refactor: clean upload pipeline and restore draco delivery
This commit is contained in:
+80
-24
@@ -1,23 +1,22 @@
|
||||
import { extname } from 'path'
|
||||
import { randomUUID } from 'crypto'
|
||||
import { existsSync } from 'fs'
|
||||
import { mkdir, readFile, rm, writeFile } from 'fs/promises'
|
||||
import { extname, join } from 'path'
|
||||
import { compressWithBlender } from '@/lib/blender'
|
||||
import { compressTextureBuffer } from '@/lib/texture-compression'
|
||||
import { classifyAssetCategory } from '@/lib/asset-classification'
|
||||
import { normalizeTextureFilename } from '@/lib/asset-naming'
|
||||
import { TEXTURE_EXTENSIONS } from '@/lib/constants'
|
||||
import { TEXTURE_EXTENSIONS, TMP_DIR } from '@/lib/constants'
|
||||
import { getModelAssetPath } from '@/lib/model-paths'
|
||||
import type { ParsedFile, PreparedAssetSummary, PushFile } from '@/lib/types'
|
||||
import type { GitModelMode, ParsedFile, PreparedAssetSummary, PreparedGitAssetsResult, PushFile } from '@/lib/types'
|
||||
|
||||
interface PrepareGitAssetsParams {
|
||||
folderName: string
|
||||
parsedFiles: ParsedFile[]
|
||||
gitModelMode: GitModelMode
|
||||
}
|
||||
|
||||
interface PrepareGitAssetsResult {
|
||||
filesToPush: PushFile[]
|
||||
modelFilename: string
|
||||
assetSummaries: PreparedAssetSummary[]
|
||||
compressed: boolean
|
||||
compressionError?: string
|
||||
}
|
||||
type JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue }
|
||||
|
||||
function getTextureFilenameMap(parsedFiles: ParsedFile[]) {
|
||||
const filenameMap = new Map<string, string>()
|
||||
@@ -51,14 +50,14 @@ function getReferencedFilename(uri: string) {
|
||||
return cleanUri.split(/[\\/]/).pop()?.toLowerCase()
|
||||
}
|
||||
|
||||
function rewriteGltfUris(value: unknown, filenameMap: Map<string, string>): unknown {
|
||||
function rewriteGltfUris(value: JsonValue, filenameMap: Map<string, string>): JsonValue {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map((entry) => rewriteGltfUris(entry, filenameMap))
|
||||
}
|
||||
|
||||
if (!value || typeof value !== 'object') return value
|
||||
|
||||
const rewritten: Record<string, unknown> = {}
|
||||
const rewritten: Record<string, JsonValue> = {}
|
||||
|
||||
for (const [key, entry] of Object.entries(value)) {
|
||||
if (key === 'uri' && typeof entry === 'string') {
|
||||
@@ -76,20 +75,20 @@ function rewriteGltfUris(value: unknown, filenameMap: Map<string, string>): unkn
|
||||
function prepareModelBuffer(buffer: Buffer, filenameMap: Map<string, string>) {
|
||||
if (filenameMap.size === 0) return buffer
|
||||
|
||||
const parsed: unknown = JSON.parse(buffer.toString('utf-8'))
|
||||
const parsed = JSON.parse(buffer.toString('utf-8')) as JsonValue
|
||||
return Buffer.from(JSON.stringify(rewriteGltfUris(parsed, filenameMap), null, 2), 'utf-8')
|
||||
}
|
||||
|
||||
export async function prepareGitAssets({
|
||||
folderName,
|
||||
parsedFiles,
|
||||
}: PrepareGitAssetsParams): Promise<PrepareGitAssetsResult> {
|
||||
async function prepareSeparateFiles(
|
||||
folderName: string,
|
||||
parsedFiles: ParsedFile[],
|
||||
textureFilenameMap: Map<string, string>,
|
||||
) {
|
||||
const filesToPush: PushFile[] = []
|
||||
const assetSummaries: PreparedAssetSummary[] = []
|
||||
let modelFilename = ''
|
||||
let compressed = false
|
||||
let compressionError: string | undefined
|
||||
const textureFilenameMap = getTextureFilenameMap(parsedFiles)
|
||||
|
||||
for (const pf of parsedFiles) {
|
||||
let content = pf.buffer
|
||||
@@ -131,11 +130,68 @@ export async function prepareGitAssets({
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
filesToPush,
|
||||
modelFilename,
|
||||
assetSummaries,
|
||||
compressed,
|
||||
compressionError,
|
||||
return { filesToPush, modelFilename, assetSummaries, compressed, compressionError }
|
||||
}
|
||||
|
||||
async function prepareDracoGlb(
|
||||
folderName: string,
|
||||
parsedFiles: ParsedFile[],
|
||||
textureFilenameMap: Map<string, string>,
|
||||
): Promise<PreparedGitAssetsResult> {
|
||||
const tmpFolder = join(TMP_DIR, 'blender', `${folderName}-${randomUUID()}`)
|
||||
const inputModelPath = join(tmpFolder, 'model.gltf')
|
||||
const outputModelPath = join(tmpFolder, 'model.glb')
|
||||
|
||||
await mkdir(tmpFolder, { recursive: true })
|
||||
|
||||
try {
|
||||
for (const pf of parsedFiles) {
|
||||
if (pf.isModel) {
|
||||
await writeFile(inputModelPath, prepareModelBuffer(pf.buffer, textureFilenameMap))
|
||||
continue
|
||||
}
|
||||
|
||||
const filename = textureFilenameMap.get(pf.filename.toLowerCase()) || pf.filename
|
||||
const ext = extname(filename).toLowerCase()
|
||||
const content = TEXTURE_EXTENSIONS.has(ext)
|
||||
? (await compressTextureBuffer(filename, pf.buffer)).buffer
|
||||
: pf.buffer
|
||||
|
||||
await writeFile(join(tmpFolder, filename), content)
|
||||
}
|
||||
|
||||
const result = await compressWithBlender(inputModelPath, outputModelPath)
|
||||
if (!result.success || !existsSync(outputModelPath)) {
|
||||
throw new Error(result.error || 'Compression Blender echouee')
|
||||
}
|
||||
|
||||
const content = await readFile(outputModelPath)
|
||||
const modelFilename = 'model.glb'
|
||||
|
||||
return {
|
||||
filesToPush: [{
|
||||
path: getModelAssetPath(folderName, modelFilename),
|
||||
contentBase64: content.toString('base64'),
|
||||
}],
|
||||
modelFilename,
|
||||
assetSummaries: [{ filename: modelFilename, kind: 'model', compressed: true }],
|
||||
compressed: true,
|
||||
}
|
||||
} finally {
|
||||
await rm(tmpFolder, { recursive: true, force: true }).catch(() => {})
|
||||
}
|
||||
}
|
||||
|
||||
export async function prepareGitAssets({
|
||||
folderName,
|
||||
parsedFiles,
|
||||
gitModelMode,
|
||||
}: PrepareGitAssetsParams): Promise<PreparedGitAssetsResult> {
|
||||
const textureFilenameMap = getTextureFilenameMap(parsedFiles)
|
||||
|
||||
if (gitModelMode === 'keep-gltf') {
|
||||
return prepareSeparateFiles(folderName, parsedFiles, textureFilenameMap)
|
||||
}
|
||||
|
||||
return prepareDracoGlb(folderName, parsedFiles, textureFilenameMap)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user