From 1ce21abee2fda9be70661962d9d369010c7a7ef4 Mon Sep 17 00:00:00 2001 From: Miguel Angel Simon Sierra Date: Tue, 27 Oct 2026 04:21:11 -0400 Subject: [PATCH] fix(cli): audio accepts several files, as its help says --- docs/packages/cli.mdx | 1 + packages/cli/src/cli.commands.test.ts | 1 + .../utils/reject-extra-positionals.test.ts | 24 +++++++++++++++++++ .../cli/src/utils/reject-extra-positionals.ts | 1 + 4 files changed, 27 insertions(+) create mode 100644 packages/cli/src/utils/reject-extra-positionals.test.ts diff --git a/docs/packages/cli.mdx b/docs/packages/cli.mdx index 2046bf1be92..819c0dacd9e 100644 --- a/docs/packages/cli.mdx +++ b/docs/packages/cli.mdx @@ -701,6 +701,7 @@ Measure how sound moves in time, so a cut or an animation can land on it. ```bash npx hyperframes audio sfx/whoosh.mp3 # one file, in file seconds +npx hyperframes audio sfx/hit.wav sfx/whoosh.mp3 # several files, one report npx hyperframes audio sfx/hit.wav --place-at 4.2 # not in the film yet: where it lands if it starts at 4.2 s npx hyperframes audio --element '#riser' # one clip of the film, in film seconds npx hyperframes audio --at 12 # every sound playing at 12 s diff --git a/packages/cli/src/cli.commands.test.ts b/packages/cli/src/cli.commands.test.ts index db63f8f09bf..f14bc1c5b02 100644 --- a/packages/cli/src/cli.commands.test.ts +++ b/packages/cli/src/cli.commands.test.ts @@ -19,6 +19,7 @@ function commandLoaderBlock(): string { // Vite cannot resolve a template-string import, so each listed top-level command is named here. const LIST_COMMANDS: Record Promise<{ default: unknown }>> = { + audio: () => import("./commands/audio.js"), catalog: () => import("./commands/catalog.js"), compare: () => import("./commands/compare.js"), figma: () => import("./commands/figma.js"), diff --git a/packages/cli/src/utils/reject-extra-positionals.test.ts b/packages/cli/src/utils/reject-extra-positionals.test.ts new file mode 100644 index 00000000000..2c4b62761b5 --- /dev/null +++ b/packages/cli/src/utils/reject-extra-positionals.test.ts @@ -0,0 +1,24 @@ +import { afterEach, describe, expect, it, vi } from "vitest"; +import type { ArgsDef, CommandDef } from "citty"; +import audio from "../commands/audio.js"; +import { CliUsageError } from "./commandResult.js"; +import { resolveExtraPositionals } from "./reject-extra-positionals.js"; + +afterEach(() => vi.restoreAllMocks()); + +describe("resolveExtraPositionals", () => { + it("lets audio take several files, which its help promises and its analysis handles", () => { + const parsed = { _: ["a.wav", "b.wav"], files: "a.wav" }; + expect(() => + resolveExtraPositionals(audio as CommandDef, "audio", parsed), + ).not.toThrow(); + }); + + it("still rejects an extra argument for a command that reads one", () => { + vi.spyOn(console, "error").mockImplementation(() => {}); + const single = { args: { file: { type: "positional" } } } as CommandDef; + expect(() => resolveExtraPositionals(single, "single", { _: ["a", "b"], file: "a" })).toThrow( + CliUsageError, + ); + }); +}); diff --git a/packages/cli/src/utils/reject-extra-positionals.ts b/packages/cli/src/utils/reject-extra-positionals.ts index e4ea67410d2..066be0c913e 100644 --- a/packages/cli/src/utils/reject-extra-positionals.ts +++ b/packages/cli/src/utils/reject-extra-positionals.ts @@ -7,6 +7,7 @@ import { isTextFile } from "./textFile.js"; // Leaf commands that read extra positionals from `args._` on purpose, by command path. export const ACCEPTS_EXTRA_POSITIONALS = new Set([ + "audio", "compare", "figma asset", "skills update",