fix(nitro): normalise attached and recovered .nitro bundles too
Gitea Actions Runner Test / test-job (push) Successful in 1s
CI / check (push) Successful in 40s
CI / tests-unit (push) Successful in 1m45s
CI / tests-integration (push) Successful in 1m55s
CI / tests-ui (push) Successful in 2m37s
CI / preflight (push) Skipped
CI / deploy (push) Failing after 1m53s

Two more .nitro entry points in the main import path still wrote the
supplied buffer verbatim: an attached `providedNitro` and a bundle pulled
back by `resolveMissingNitro`. Both are real furniture imports, so they
could still land a PNG texture while the SWF, clone and upload paths
produced WebP.

Route both through the same normalisation, falling back to the original
bytes with a warning if the texture cannot be decoded.
This commit is contained in:
openhands committed 2026-09-27 16:00:44 +02:00
1 parent b26e2e0de4
commit 9ee22db8ba
1 file changed
+31 -2
+31 -2
View File
@@ -218,6 +218,26 @@ import { classifyFurni } from "@/lib/furni/auto-catalog";
export { autoPriceFurni } from "@/lib/furni/auto-catalog";
import { autoPriceFurni } from "@/lib/furni/auto-catalog";
import { toWebpLosslessBundle } from "@/lib/services/swf/nitro-builder";
/**
* Store an incoming .nitro as WebP Lossless, whatever format it arrived in, so
* every import path ends up with the same on-disk format as the SWF importer.
* A texture that cannot be decoded is kept as-is with a warning: the bundle
* itself is valid, and dropping a furniture item over a codec edge case is
* worse than a slightly larger texture.
*/
async function toWebpLosslessOrKeep(
bundle: Buffer,
warnings: string[],
): Promise<Buffer> {
try {
return await toWebpLosslessBundle(bundle);
} catch {
warnings.push("texture kept in its original format");
return bundle;
}
}
/** Get or create a category sub-page under the imported parent page.
* Caches category page IDs in-memory for CATEGORY_CACHE_TTL_MS to avoid
@@ -654,7 +674,11 @@ export async function importSingleFurni(params: {
const mirrorNitroDirs = assetTargets.mirrorDirs.map((d) => d.nitroDir);
if (params.providedNitro && !existsSync(nitroPath)) {
await fs.writeFile(nitroPath, params.providedNitro, { flag: "wx" });
await fs.writeFile(
nitroPath,
await toWebpLosslessOrKeep(params.providedNitro, warnings),
{ flag: "wx" },
);
}
// ── Download assets in parallel (with retry + validation) ────────
@@ -816,7 +840,12 @@ 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" });
if (recovered)
await fs.writeFile(
nitroPath,
await toWebpLosslessOrKeep(recovered, warnings),
{ flag: "wx" },
);
else
warnings.push(
"No matching bundle was recovered from the checked sources. Review source availability or attach the original .nitro file.",