From 42cf6ed71a81e551db9e3bde2eef8f9ce39c4b38 Mon Sep 17 00:00:00 2001 From: Miguel Angel Simon Sierra Date: Fri, 30 Oct 2026 01:14:01 -0400 Subject: [PATCH] fix(cli): split add's per-item install, and keep soundfx folders as sfx --- packages/cli/src/commands/add.ts | 61 +++++++++++-------- packages/cli/src/media-use/lib/adopt.mjs | 3 +- packages/cli/src/media-use/lib/adopt.test.mjs | 2 + 3 files changed, 38 insertions(+), 28 deletions(-) diff --git a/packages/cli/src/commands/add.ts b/packages/cli/src/commands/add.ts index efa7d5148e..8ca51d9277 100644 --- a/packages/cli/src/commands/add.ts +++ b/packages/cli/src/commands/add.ts @@ -173,36 +173,43 @@ export function severalAddJson( return installJson(results, errors); } -async function installEach( - names: readonly string[], - context: { - projectDir: string; - force: boolean | undefined; - vars: string | undefined; - json: boolean; - }, -) { +interface InstallContext { + projectDir: string; + force: boolean | undefined; + vars: string | undefined; + json: boolean; +} + +type InstallOutcome = { result: RunAddResult } | { name: string; error: string }; + +async function installOne(name: string, context: InstallContext): Promise { + try { + const result = await runAdd({ + name, + projectDir: context.projectDir, + skipClipboard: true, + force: context.force, + vars: context.vars, + }); + if (!context.json) { + for (const warning of result.warnings) console.log(` ${c.warn("Warning:")} ${warning}`); + console.log(` ${c.success("✓")} ${result.name}`); + } + return { result }; + } catch (err) { + const reason = err instanceof Error ? err.message : String(err); + if (!context.json) console.log(` ${c.error("✗")} ${name} (skipped: ${reason})`); + return { name, error: reason }; + } +} + +async function installEach(names: readonly string[], context: InstallContext) { const results: RunAddResult[] = []; const errors: Array<{ name: string; error: string }> = []; for (const name of names) { - try { - const result = await runAdd({ - name, - projectDir: context.projectDir, - skipClipboard: true, - force: context.force, - vars: context.vars, - }); - results.push(result); - for (const warning of result.warnings) { - if (!context.json) console.log(` ${c.warn("Warning:")} ${warning}`); - } - if (!context.json) console.log(` ${c.success("✓")} ${result.name}`); - } catch (err) { - const reason = err instanceof Error ? err.message : String(err); - errors.push({ name, error: reason }); - if (!context.json) console.log(` ${c.error("✗")} ${name} (skipped: ${reason})`); - } + const outcome = await installOne(name, context); + if ("result" in outcome) results.push(outcome.result); + else errors.push(outcome); } return { results, errors }; } diff --git a/packages/cli/src/media-use/lib/adopt.mjs b/packages/cli/src/media-use/lib/adopt.mjs index ffa7122329..e9950ffbf0 100644 --- a/packages/cli/src/media-use/lib/adopt.mjs +++ b/packages/cli/src/media-use/lib/adopt.mjs @@ -13,7 +13,8 @@ function audioKind(filePath) { const words = filePath.toLowerCase().split(/[^a-z0-9]+/); const has = (test) => words.some(test); if (has((w) => w === "bgm" || w === "music" || w === "soundtrack")) return "bgm"; - if (has((w) => w === "sfx" || w === "fx" || w === "sound" || w === "sounds")) return "sfx"; + if (has((w) => w === "sfx" || w === "fx" || (w.startsWith("sound") && w !== "soundtrack"))) + return "sfx"; if (has((w) => w.startsWith("voice") || w.startsWith("narrat"))) return "voice"; return "bgm"; } diff --git a/packages/cli/src/media-use/lib/adopt.test.mjs b/packages/cli/src/media-use/lib/adopt.test.mjs index 2d8c23acab..9e9484380b 100644 --- a/packages/cli/src/media-use/lib/adopt.test.mjs +++ b/packages/cli/src/media-use/lib/adopt.test.mjs @@ -81,6 +81,7 @@ function runTests() { drop("narration.mp3"); drop("soundtrack/main.mp3"); drop("track.mp3"); + drop("soundfx/pop.mp3"); const types = Object.fromEntries( adoptExistingAssets(tmp).map((record) => [record.path, record.type]), ); @@ -90,6 +91,7 @@ function runTests() { "assets/narration.mp3": "voice", "assets/soundtrack/main.mp3": "bgm", "assets/track.mp3": "bgm", + "assets/soundfx/pop.mp3": "sfx", }); cleanup(); });