feat(studio): recover matching Nitro sources and persist import phases
CI / check (push) Successful in 2m5s
CI / deploy (push) Successful in 1m8s
CI / publish-container (push) Successful in 1m4s

This commit is contained in:
Simo committed 2026-09-11 10:22:06 +02:00
1 parent 00e33623f7
commit 13bd3695cb
45 files changed
+903 -28

No files matched your search

+16 -4
View File
@@ -517,7 +517,8 @@ export async function importSingleFurni(params: {
preserveAssets?: boolean;
/** Validated matching bundle supplied by a queued import. */
providedNitro?: Buffer;
onProgress?: (status: string) => void;
onProgress?: (status: string) => void | Promise<void>;
resolveMissingNitro?: (revision: number) => Promise<Buffer | undefined>;
/** Per-source SWF download base URL (e.g. "https://virtualc.nl/dcr"). */
sourceSwfBaseUrl?: string;
/** Per-source nitro bundle + icon base URL. */
@@ -660,7 +661,7 @@ export async function importSingleFurni(params: {
// For color variants (classname has `*`): try color-specific first,
// fall back to base-classname icon (Nitro reuses base for all colors
// when no color-specific icon exists).
onProgress?.("downloading");
await onProgress?.("downloading");
const iconColorAware = classname.replace(/\*/g, "_");
@@ -770,7 +771,7 @@ export async function importSingleFurni(params: {
warnings.push(`SWF download failed: ${swfFailure || "unknown cause"}`);
// ── Convert SWF to Nitro ──────────────────────────────────────────
onProgress?.("converting");
await onProgress?.("converting");
let conversionResult: ConversionResult | null = null;
if (existsSync(/*turbopackIgnore: true*/ nitroPath)) {
@@ -803,6 +804,16 @@ export async function importSingleFurni(params: {
}
}
if (!existsSync(nitroPath) && params.resolveMissingNitro) {
await onProgress?.("checking_sources");
const recovered = await params.resolveMissingNitro(rev);
if (recovered) await fs.writeFile(nitroPath, recovered, { flag: "wx" });
else
warnings.push(
"No matching bundle was recovered from the checked sources. Review source availability or attach the original .nitro file.",
);
}
if (!iconOk && existsSync(nitroPath)) {
try {
const icon = extractFurniIconPng(await fs.readFile(nitroPath));
@@ -847,7 +858,7 @@ export async function importSingleFurni(params: {
}
// ── Insert into DB with enriched data ──────────────────────────────
onProgress?.("writing_db");
await onProgress?.("writing_db");
try {
if (preservingExisting) {
warnings.push(
@@ -1032,6 +1043,7 @@ export async function importSingleFurni(params: {
// Batch mode: return the entry so the caller writes once at the end
} else {
try {
await onProgress?.("writing_furnidata");
await appendFurniEntry(furniEntry, itemType);
} catch (err) {
logger.warn("[import-furni] Failed to update FurnitureData.json", {