refactor: consolidate upload helpers
This commit is contained in:
@@ -2,6 +2,7 @@ import { NextRequest, NextResponse } from 'next/server'
|
||||
import { validateUploadSecret } from '@/lib/auth'
|
||||
import { getRemoteFolder } from '@/lib/github'
|
||||
import { classifyFileChanges } from '@/lib/diff-files'
|
||||
import { getModelFolderPath } from '@/lib/model-paths'
|
||||
import { ensurePreparedStagingAssets } from '@/lib/upload-staging'
|
||||
|
||||
export const runtime = 'nodejs'
|
||||
@@ -30,7 +31,7 @@ export async function POST(req: NextRequest) {
|
||||
|
||||
try {
|
||||
const { folderName, filesToPush } = await ensurePreparedStagingAssets(stagingId)
|
||||
const folderPath = `public/models/${folderName}`
|
||||
const folderPath = getModelFolderPath(folderName)
|
||||
const { exists, files } = await getRemoteFolder(folderPath)
|
||||
|
||||
if (exists) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { validateUploadSecret } from '@/lib/auth'
|
||||
import { getRemoteFolder, pushAllToGitHub } from '@/lib/github'
|
||||
import { buildCommitMessage } from '@/lib/commit-message'
|
||||
import { classifyFileChanges } from '@/lib/diff-files'
|
||||
import { getModelFolderPath } from '@/lib/model-paths'
|
||||
import { cleanupStagingUpload, ensurePreparedStagingAssets, readStagedManifest } from '@/lib/upload-staging'
|
||||
import { acquireUploadLock, releaseUploadLock } from '@/lib/upload-lock'
|
||||
|
||||
@@ -52,7 +53,7 @@ export async function POST(req: NextRequest) {
|
||||
} = await ensurePreparedStagingAssets(stagingId)
|
||||
|
||||
// --- Detect existing files and classify changes ---
|
||||
const folderPath = `public/models/${folderName}`
|
||||
const folderPath = getModelFolderPath(folderName)
|
||||
let remoteFileMap: Map<string, number>
|
||||
|
||||
try {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import type { FolderEntry } from '@/lib/client-types'
|
||||
import { revokeEntryUrls } from '@/lib/client-object-urls'
|
||||
import { useSecret } from '@/hooks/useSecret'
|
||||
import { useFolderEntries } from '@/hooks/useFolderEntries'
|
||||
import { useUploadOrchestrator } from '@/hooks/useUploadOrchestrator'
|
||||
@@ -60,12 +61,7 @@ export default function UploadZone() {
|
||||
})
|
||||
|
||||
const handleFolderSelected = (entry: FolderEntry) => {
|
||||
entries.forEach((current) => {
|
||||
const urls = new Set<string>()
|
||||
if (current.modelUrl) urls.add(current.modelUrl)
|
||||
Object.values(current.assetUrls || {}).forEach((url) => urls.add(url))
|
||||
urls.forEach((url) => URL.revokeObjectURL(url))
|
||||
})
|
||||
entries.forEach(revokeEntryUrls)
|
||||
setGlobalError(null)
|
||||
setEntries([entry])
|
||||
}
|
||||
|
||||
@@ -2,13 +2,7 @@
|
||||
|
||||
import { useState, useCallback } from 'react'
|
||||
import type { FolderEntry } from '@/lib/client-types'
|
||||
|
||||
function revokeEntryUrls(entry: FolderEntry) {
|
||||
const urls = new Set<string>()
|
||||
if (entry.modelUrl) urls.add(entry.modelUrl)
|
||||
Object.values(entry.assetUrls || {}).forEach((url) => urls.add(url))
|
||||
urls.forEach((url) => URL.revokeObjectURL(url))
|
||||
}
|
||||
import { revokeEntryUrls } from '@/lib/client-object-urls'
|
||||
|
||||
export function useFolderEntries() {
|
||||
const [entries, setEntries] = useState<FolderEntry[]>([])
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import type { FolderEntry } from '@/lib/client-types'
|
||||
|
||||
export function revokeEntryUrls(entry: FolderEntry) {
|
||||
const urls = new Set<string>()
|
||||
|
||||
if (entry.modelUrl) urls.add(entry.modelUrl)
|
||||
Object.values(entry.assetUrls || {}).forEach((url) => urls.add(url))
|
||||
urls.forEach((url) => URL.revokeObjectURL(url))
|
||||
}
|
||||
+1
-6
@@ -3,12 +3,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
import { MODEL_EXTENSIONS } from './constants'
|
||||
import type { FileChange } from './types'
|
||||
|
||||
interface PushFile {
|
||||
path: string
|
||||
contentBase64: string
|
||||
}
|
||||
import type { FileChange, PushFile } from './types'
|
||||
|
||||
export interface DiffResult {
|
||||
/** Map of lowercase filename → change status (for commit message) */
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
import { createHash } from 'crypto'
|
||||
import { Octokit } from '@octokit/rest'
|
||||
import { LFS_EXTENSIONS } from './constants'
|
||||
import type { RemoteFile } from './types'
|
||||
import type { PushFile, RemoteFile } from './types'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Octokit helpers
|
||||
@@ -237,7 +237,7 @@ export async function getRemoteFolder(
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export async function pushAllToGitHub(
|
||||
files: { path: string; contentBase64: string }[],
|
||||
files: PushFile[],
|
||||
deletePaths: string[],
|
||||
commitMessage: string,
|
||||
): Promise<{ commitUrl: string }> {
|
||||
@@ -247,7 +247,7 @@ export async function pushAllToGitHub(
|
||||
|
||||
// --- Separate LFS files from regular files ---
|
||||
const lfsFiles: { path: string; contentBase64: string; oid: string; size: number }[] = []
|
||||
const regularFiles: { path: string; contentBase64: string }[] = []
|
||||
const regularFiles: PushFile[] = []
|
||||
|
||||
for (const f of files) {
|
||||
if (isLfsFile(f.path)) {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
export function getModelFolderPath(folderName: string) {
|
||||
return `public/models/${folderName}`
|
||||
}
|
||||
|
||||
export function getModelAssetPath(folderName: string, filename: string) {
|
||||
return `${getModelFolderPath(folderName)}/${filename}`
|
||||
}
|
||||
@@ -1,11 +1,7 @@
|
||||
import { compressTextureBuffer } from '@/lib/texture-compression'
|
||||
import { classifyAssetCategory } from '@/lib/asset-classification'
|
||||
import type { ParsedFile, PreparedAssetSummary } from '@/lib/types'
|
||||
|
||||
interface PushFile {
|
||||
path: string
|
||||
contentBase64: string
|
||||
}
|
||||
import { getModelAssetPath } from '@/lib/model-paths'
|
||||
import type { ParsedFile, PreparedAssetSummary, PushFile } from '@/lib/types'
|
||||
|
||||
interface PrepareGitAssetsParams {
|
||||
folderName: string
|
||||
@@ -61,7 +57,7 @@ export async function prepareGitAssets({
|
||||
}
|
||||
|
||||
filesToPush.push({
|
||||
path: `public/models/${folderName}/${pf.filename}`,
|
||||
path: getModelAssetPath(folderName, pf.filename),
|
||||
contentBase64: content.toString('base64'),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -10,6 +10,11 @@ export interface ParsedFile {
|
||||
isModel: boolean
|
||||
}
|
||||
|
||||
export interface PushFile {
|
||||
path: string
|
||||
contentBase64: string
|
||||
}
|
||||
|
||||
export type FileChange = 'new' | 'changed' | 'unchanged'
|
||||
|
||||
export interface FileDiff {
|
||||
|
||||
@@ -3,8 +3,9 @@ import { dirname, join } from 'path'
|
||||
import { mkdir, readdir, readFile, rm, writeFile } from 'fs/promises'
|
||||
import { existsSync } from 'fs'
|
||||
import { TMP_DIR } from '@/lib/constants'
|
||||
import { getModelAssetPath } from '@/lib/model-paths'
|
||||
import { prepareGitAssets } from '@/lib/prepare-git-assets'
|
||||
import type { ParsedFile, PreparedAssetSummary } from '@/lib/types'
|
||||
import type { ParsedFile, PreparedAssetSummary, PushFile } from '@/lib/types'
|
||||
|
||||
const STAGING_ROOT = join(TMP_DIR, 'staging')
|
||||
const STAGING_TTL_MS = 60 * 60 * 1000
|
||||
@@ -30,11 +31,6 @@ interface StagingManifest {
|
||||
prepared?: StagedPreparedData
|
||||
}
|
||||
|
||||
interface PushFile {
|
||||
path: string
|
||||
contentBase64: string
|
||||
}
|
||||
|
||||
interface PreparedStageAssetsResult {
|
||||
folderName: string
|
||||
filesToPush: PushFile[]
|
||||
@@ -148,7 +144,7 @@ async function buildPreparedPushFiles(stagingId: string, manifest: StagingManife
|
||||
manifest.originals.map(async (file) => {
|
||||
const buffer = await readFile(join(preparedDir, file.filename))
|
||||
return {
|
||||
path: `public/models/${manifest.folderName}/${file.filename}`,
|
||||
path: getModelAssetPath(manifest.folderName, file.filename),
|
||||
contentBase64: buffer.toString('base64'),
|
||||
}
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user