From 1ba82cf1b2cabc80f362391765b34a9a434ebd7e Mon Sep 17 00:00:00 2001 From: Dante Barbieri Date: Wed, 22 Apr 2026 15:28:52 -0500 Subject: [PATCH] fix(assimp): pass -f so non-extension targets work (#557) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(assimp): pass -f so non-extension targets work The assimp converter invokes `assimp export ` and relies on assimp's extension-based format inference to pick the output format. That works for targets whose id happens to match a real file extension (glb, gltf, obj, stl, ply, etc.) but silently fails for every target whose assimp id is not a conventional filename extension: glb2, gltf2, objnomtl, stlb, plyb, fbxa, assbin, assxml, pbrt, assjson Picking any of those in the UI aborts the job with: assimp export: no output format specified and I failed to guess it assimp_cmd's `-f` flag overrides extension inference, and the values in `properties.to.object` already correspond 1:1 to assimp's format ids (verified against `assimp listexport`). Passing `-f${convertTo}` makes every advertised target work without changing anything else. Reproduction: upload any .stl, convert to glb2. Before: ENOENT on the nonexistent output file. After: valid binary glTF 2.0. * fix(assimp): write real file extensions for non-extension format ids Follow-up to the previous commit. With `-f` now passed to assimp, every advertised target exports successfully — but seven of them still produce files with assimp's internal format id as the extension, which no third-party viewer recognises: glb2 → .glb2 (really binary glTF 2.0, should be .glb) gltf2 → .gltf2 (text glTF 2.0, should be .gltf) objnomtl → .objnomtl (OBJ without .mtl, should be .obj) stlb → .stlb (binary STL, should be .stl) plyb → .plyb (binary PLY, should be .ply) fbxa → .fbxa (ASCII FBX, should be .fbx) assjson → .assjson (JSON dump, should be .json) Map these in `normalizeOutputFiletype`, the same helper that already handles jpeg→jpg, latex→tex, markdown→md. The format id on `convertTo` is untouched, so `assimp -f` still selects the correct encoding/variant — only the output filename changes. assbin, assxml, and pbrt are both the format id and the canonical extension, so they need no mapping. * style(assimp): fix prettier formatting --- src/converters/assimp.ts | 28 ++++++++++++++++------------ src/helpers/normalizeFiletype.ts | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/converters/assimp.ts b/src/converters/assimp.ts index 69f3258..42e1b6f 100644 --- a/src/converters/assimp.ts +++ b/src/converters/assimp.ts @@ -121,20 +121,24 @@ export async function convert( execFile: ExecFileFn = execFileOriginal, // to make it mockable ): Promise { return new Promise((resolve, reject) => { - execFile("assimp", ["export", filePath, targetPath], (error, stdout, stderr) => { - if (error) { - reject(`error: ${error}`); - } + execFile( + "assimp", + ["export", filePath, targetPath, `-f${convertTo}`], + (error, stdout, stderr) => { + if (error) { + reject(`error: ${error}`); + } - if (stdout) { - console.log(`stdout: ${stdout}`); - } + if (stdout) { + console.log(`stdout: ${stdout}`); + } - if (stderr) { - console.error(`stderr: ${stderr}`); - } + if (stderr) { + console.error(`stderr: ${stderr}`); + } - resolve("Done"); - }); + resolve("Done"); + }, + ); }); } diff --git a/src/helpers/normalizeFiletype.ts b/src/helpers/normalizeFiletype.ts index cf9389a..dcdce29 100644 --- a/src/helpers/normalizeFiletype.ts +++ b/src/helpers/normalizeFiletype.ts @@ -31,6 +31,24 @@ export const normalizeOutputFiletype = (filetype: string): string => { case "markdown_mmd": case "markdown": return "md"; + // assimp format ids that aren't real file extensions — map to the + // canonical extension for the underlying format so the output file + // opens in third-party viewers. The format id is still passed to + // `assimp export -f` so the right encoding/variant is produced. + case "glb2": + return "glb"; + case "gltf2": + return "gltf"; + case "objnomtl": + return "obj"; + case "stlb": + return "stl"; + case "plyb": + return "ply"; + case "fbxa": + return "fbx"; + case "assjson": + return "json"; default: return lowercaseFiletype; }