@scenar/cli 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/example-bundle/assets/index-DxmqjG-8.js +388 -0
- package/example-bundle/assets/style-B2sxnVVZ.css +1 -0
- package/example-bundle/embed.js +1 -1
- package/example-bundle/index.html +2 -2
- package/example-bundle/logo.png +0 -0
- package/example-bundle/pack-manifest.json +33 -9
- package/example-bundle/soundtrack/music.mp3 +0 -0
- package/example-bundle/soundtrack/sfx/click.mp3 +0 -0
- package/example-bundle/soundtrack/sfx/keystroke.mp3 +0 -0
- package/package.json +4 -4
- package/src/__tests__/collect-pack-shots.test.ts +8 -0
- package/src/__tests__/elevenlabs-provider.test.ts +187 -0
- package/src/__tests__/embed-snippet.test.ts +5 -0
- package/src/__tests__/find-authored-soundtrack.test.ts +54 -0
- package/src/__tests__/find-authored-title-cards.test.ts +65 -0
- package/src/__tests__/load-bundle.test.ts +67 -0
- package/src/__tests__/narrate-command.test.ts +65 -1
- package/src/__tests__/narration-cache.test.ts +134 -0
- package/src/__tests__/pack-bundle-contract.test.ts +2 -0
- package/src/__tests__/pack-generate-embed-entry.test.ts +95 -16
- package/src/__tests__/presenter-command.test.ts +366 -0
- package/src/__tests__/render-command.test.ts +11 -0
- package/src/__tests__/render-generate-entry.test.ts +102 -0
- package/src/__tests__/resolve-provider.test.ts +32 -3
- package/src/__tests__/scenario-validator.test.ts +174 -0
- package/src/__tests__/stage-assets.test.ts +269 -0
- package/src/commands/narrate.js +1 -1
- package/src/commands/narrate.js.map +1 -1
- package/src/commands/narrate.ts +1 -1
- package/src/commands/presenter.d.ts +3 -0
- package/src/commands/presenter.d.ts.map +1 -0
- package/src/commands/presenter.js +89 -0
- package/src/commands/presenter.js.map +1 -0
- package/src/commands/presenter.ts +107 -0
- package/src/commands/render.d.ts.map +1 -1
- package/src/commands/render.js +2 -0
- package/src/commands/render.js.map +1 -1
- package/src/commands/render.ts +6 -0
- package/src/embed/embed-snippet.d.ts +5 -0
- package/src/embed/embed-snippet.d.ts.map +1 -1
- package/src/embed/embed-snippet.js +6 -1
- package/src/embed/embed-snippet.js.map +1 -1
- package/src/embed/embed-snippet.ts +6 -1
- package/src/index.d.ts.map +1 -1
- package/src/index.js +2 -0
- package/src/index.js.map +1 -1
- package/src/index.ts +2 -0
- package/src/narrate/run-narrate.d.ts +15 -1
- package/src/narrate/run-narrate.d.ts.map +1 -1
- package/src/narrate/run-narrate.js +11 -4
- package/src/narrate/run-narrate.js.map +1 -1
- package/src/narrate/run-narrate.ts +15 -6
- package/src/pack/bundle-contract.d.ts +1 -0
- package/src/pack/bundle-contract.d.ts.map +1 -1
- package/src/pack/bundle-contract.js +3 -0
- package/src/pack/bundle-contract.js.map +1 -1
- package/src/pack/bundle-contract.ts +3 -0
- package/src/pack/collect-pack-shots.d.ts +5 -1
- package/src/pack/collect-pack-shots.d.ts.map +1 -1
- package/src/pack/collect-pack-shots.js +3 -1
- package/src/pack/collect-pack-shots.js.map +1 -1
- package/src/pack/collect-pack-shots.ts +15 -1
- package/src/pack/generate-embed-entry.d.ts +7 -0
- package/src/pack/generate-embed-entry.d.ts.map +1 -1
- package/src/pack/generate-embed-entry.js +102 -7
- package/src/pack/generate-embed-entry.js.map +1 -1
- package/src/pack/generate-embed-entry.ts +107 -7
- package/src/pack/run-pack.d.ts +1 -0
- package/src/pack/run-pack.d.ts.map +1 -1
- package/src/pack/run-pack.js +100 -9
- package/src/pack/run-pack.js.map +1 -1
- package/src/pack/run-pack.ts +133 -9
- package/src/presenter/heygen-client.d.ts +69 -0
- package/src/presenter/heygen-client.d.ts.map +1 -0
- package/src/presenter/heygen-client.js +154 -0
- package/src/presenter/heygen-client.js.map +1 -0
- package/src/presenter/heygen-client.ts +224 -0
- package/src/presenter/run-presenter.d.ts +67 -0
- package/src/presenter/run-presenter.d.ts.map +1 -0
- package/src/presenter/run-presenter.js +348 -0
- package/src/presenter/run-presenter.js.map +1 -0
- package/src/presenter/run-presenter.ts +536 -0
- package/src/render/generate-entry.d.ts +4 -0
- package/src/render/generate-entry.d.ts.map +1 -1
- package/src/render/generate-entry.js +75 -7
- package/src/render/generate-entry.js.map +1 -1
- package/src/render/generate-entry.ts +84 -7
- package/src/render/run-render.d.ts +6 -0
- package/src/render/run-render.d.ts.map +1 -1
- package/src/render/run-render.js +58 -0
- package/src/render/run-render.js.map +1 -1
- package/src/render/run-render.ts +72 -0
- package/src/render/stage-assets.d.ts +44 -0
- package/src/render/stage-assets.d.ts.map +1 -0
- package/src/render/stage-assets.js +91 -0
- package/src/render/stage-assets.js.map +1 -0
- package/src/render/stage-assets.ts +130 -0
- package/src/tts/echogarden.d.ts.map +1 -1
- package/src/tts/echogarden.js +4 -2
- package/src/tts/echogarden.js.map +1 -1
- package/src/tts/echogarden.ts +5 -2
- package/src/tts/edge-tts.d.ts.map +1 -1
- package/src/tts/edge-tts.js +2 -1
- package/src/tts/edge-tts.js.map +1 -1
- package/src/tts/edge-tts.ts +2 -1
- package/src/tts/elevenlabs.d.ts +15 -0
- package/src/tts/elevenlabs.d.ts.map +1 -0
- package/src/tts/elevenlabs.js +73 -0
- package/src/tts/elevenlabs.js.map +1 -0
- package/src/tts/elevenlabs.ts +105 -0
- package/src/tts/openai.d.ts.map +1 -1
- package/src/tts/openai.js +2 -1
- package/src/tts/openai.js.map +1 -1
- package/src/tts/openai.ts +2 -1
- package/src/tts/resolve-provider.d.ts +1 -1
- package/src/tts/resolve-provider.d.ts.map +1 -1
- package/src/tts/resolve-provider.js +10 -3
- package/src/tts/resolve-provider.js.map +1 -1
- package/src/tts/resolve-provider.ts +12 -4
- package/src/tts/types.d.ts +9 -0
- package/src/tts/types.d.ts.map +1 -1
- package/src/tts/types.ts +10 -0
- package/src/util/confirm.d.ts +11 -0
- package/src/util/confirm.d.ts.map +1 -0
- package/src/util/confirm.js +24 -0
- package/src/util/confirm.js.map +1 -0
- package/src/util/confirm.ts +23 -0
- package/src/util/load-bundle.d.ts +17 -1
- package/src/util/load-bundle.d.ts.map +1 -1
- package/src/util/load-bundle.js +19 -11
- package/src/util/load-bundle.js.map +1 -1
- package/src/util/load-bundle.ts +38 -12
- package/src/util/load-ts.d.ts +77 -0
- package/src/util/load-ts.d.ts.map +1 -1
- package/src/util/load-ts.js +125 -0
- package/src/util/load-ts.js.map +1 -1
- package/src/util/load-ts.ts +165 -0
- package/src/util/narration-cache.d.ts +13 -5
- package/src/util/narration-cache.d.ts.map +1 -1
- package/src/util/narration-cache.js +10 -8
- package/src/util/narration-cache.js.map +1 -1
- package/src/util/narration-cache.ts +22 -6
- package/src/util/presenter-cache.d.ts +44 -0
- package/src/util/presenter-cache.d.ts.map +1 -0
- package/src/util/presenter-cache.js +43 -0
- package/src/util/presenter-cache.js.map +1 -0
- package/src/util/presenter-cache.ts +101 -0
- package/src/util/scenario-assets.d.ts +47 -0
- package/src/util/scenario-assets.d.ts.map +1 -0
- package/src/util/scenario-assets.js +71 -0
- package/src/util/scenario-assets.js.map +1 -0
- package/src/util/scenario-assets.ts +111 -0
- package/src/util/soundtrack-assets.d.ts +34 -0
- package/src/util/soundtrack-assets.d.ts.map +1 -0
- package/src/util/soundtrack-assets.js +48 -0
- package/src/util/soundtrack-assets.js.map +1 -0
- package/src/util/soundtrack-assets.ts +69 -0
- package/src/validate/scenario-validator.d.ts.map +1 -1
- package/src/validate/scenario-validator.js +82 -0
- package/src/validate/scenario-validator.js.map +1 -1
- package/src/validate/scenario-validator.ts +110 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/example-bundle/assets/index-DpJUOVBT.js +0 -388
- package/example-bundle/assets/style-ix_q0zsc.css +0 -1
package/src/tts/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/tts/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,oEAAoE;IACpE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;CACnE;AAED,MAAM,WAAW,UAAU;IACzB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,qBAAqB,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/tts/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,oEAAoE;IACpE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;;;;;;OAOG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;CACnE;AAED,MAAM,WAAW,UAAU;IACzB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,qBAAqB,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd"}
|
package/src/tts/types.ts
CHANGED
|
@@ -9,6 +9,16 @@ export interface TtsProvider {
|
|
|
9
9
|
/** Human-readable name shown in logs and the narration manifest. */
|
|
10
10
|
readonly name: string;
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Cache identity: the provider name plus every piece of static
|
|
14
|
+
* configuration that changes the audio bytes (model, default voice,
|
|
15
|
+
* engine). The narration cache keys on this, so audio regenerates
|
|
16
|
+
* whenever any of those inputs change — switching providers or models
|
|
17
|
+
* must never serve stale audio from a previous configuration.
|
|
18
|
+
* Per-call inputs (requested voice, text) are hashed separately.
|
|
19
|
+
*/
|
|
20
|
+
readonly fingerprint: string;
|
|
21
|
+
|
|
12
22
|
/**
|
|
13
23
|
* Generate speech audio for the given text.
|
|
14
24
|
* Returns the raw audio bytes and the audio duration.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ask a yes/no question on stderr and read the answer from stdin.
|
|
3
|
+
* Resolves true only on an explicit yes (`y`/`yes`, case-insensitive) —
|
|
4
|
+
* the safe default for anything that spends money or overwrites work.
|
|
5
|
+
*
|
|
6
|
+
* Callers own the non-interactive policy: when stdin is not a TTY,
|
|
7
|
+
* decide (and message) before calling this — a prompt nobody can
|
|
8
|
+
* answer just hangs a pipeline.
|
|
9
|
+
*/
|
|
10
|
+
export declare function confirm(question: string): Promise<boolean>;
|
|
11
|
+
//# sourceMappingURL=confirm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confirm.d.ts","sourceRoot":"","sources":["../../../src/util/confirm.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAWhE"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createInterface } from "node:readline";
|
|
2
|
+
/**
|
|
3
|
+
* Ask a yes/no question on stderr and read the answer from stdin.
|
|
4
|
+
* Resolves true only on an explicit yes (`y`/`yes`, case-insensitive) —
|
|
5
|
+
* the safe default for anything that spends money or overwrites work.
|
|
6
|
+
*
|
|
7
|
+
* Callers own the non-interactive policy: when stdin is not a TTY,
|
|
8
|
+
* decide (and message) before calling this — a prompt nobody can
|
|
9
|
+
* answer just hangs a pipeline.
|
|
10
|
+
*/
|
|
11
|
+
export async function confirm(question) {
|
|
12
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
13
|
+
try {
|
|
14
|
+
const answer = await new Promise((resolve) => {
|
|
15
|
+
rl.question(`${question} [y/N] `, resolve);
|
|
16
|
+
});
|
|
17
|
+
const normalized = answer.trim().toLowerCase();
|
|
18
|
+
return normalized === "y" || normalized === "yes";
|
|
19
|
+
}
|
|
20
|
+
finally {
|
|
21
|
+
rl.close();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=confirm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confirm.js","sourceRoot":"","sources":["../../../src/util/confirm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,QAAgB;IAC5C,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7E,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;YACnD,EAAE,CAAC,QAAQ,CAAC,GAAG,QAAQ,SAAS,EAAE,OAAO,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QACH,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC/C,OAAO,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,KAAK,CAAC;IACpD,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createInterface } from "node:readline";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Ask a yes/no question on stderr and read the answer from stdin.
|
|
5
|
+
* Resolves true only on an explicit yes (`y`/`yes`, case-insensitive) —
|
|
6
|
+
* the safe default for anything that spends money or overwrites work.
|
|
7
|
+
*
|
|
8
|
+
* Callers own the non-interactive policy: when stdin is not a TTY,
|
|
9
|
+
* decide (and message) before calling this — a prompt nobody can
|
|
10
|
+
* answer just hangs a pipeline.
|
|
11
|
+
*/
|
|
12
|
+
export async function confirm(question: string): Promise<boolean> {
|
|
13
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
14
|
+
try {
|
|
15
|
+
const answer = await new Promise<string>((resolve) => {
|
|
16
|
+
rl.question(`${question} [y/N] `, resolve);
|
|
17
|
+
});
|
|
18
|
+
const normalized = answer.trim().toLowerCase();
|
|
19
|
+
return normalized === "y" || normalized === "yes";
|
|
20
|
+
} finally {
|
|
21
|
+
rl.close();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
import { type AuthoredSoundtrack, type AuthoredTitleCards } from "./load-ts.js";
|
|
1
2
|
/**
|
|
2
3
|
* Lightweight bundle shape for CLI use. Mirrors the @scenar/core
|
|
3
4
|
* ScenarioBundle interface but uses plain objects (the CLI does not
|
|
4
5
|
* import @scenar/core at runtime to stay lightweight).
|
|
6
|
+
*
|
|
7
|
+
* Carries the AUTHORED shape: steps as written, title cards as config.
|
|
8
|
+
* Card-step synthesis (`applyTitleCards`) happens in the generated
|
|
9
|
+
* render/pack entries — the true bundle-assembly seam — never here; the
|
|
10
|
+
* CLI consumes this bundle for staging and inspection only.
|
|
5
11
|
*/
|
|
6
12
|
export interface CliBundle {
|
|
7
13
|
id: string;
|
|
@@ -15,11 +21,21 @@ export interface CliBundle {
|
|
|
15
21
|
durationMs: number;
|
|
16
22
|
} | null>;
|
|
17
23
|
};
|
|
24
|
+
presenterManifest?: {
|
|
25
|
+
steps: Array<{
|
|
26
|
+
src: string;
|
|
27
|
+
durationMs: number;
|
|
28
|
+
} | null>;
|
|
29
|
+
};
|
|
30
|
+
soundtrack?: AuthoredSoundtrack;
|
|
31
|
+
titleCards?: AuthoredTitleCards;
|
|
18
32
|
}
|
|
19
33
|
/**
|
|
20
34
|
* Load a scenario bundle from a directory. Expects:
|
|
21
|
-
* <dir>/steps.ts — required (step definitions
|
|
35
|
+
* <dir>/steps.ts — required (step definitions, optional
|
|
36
|
+
* `soundtrack` named export)
|
|
22
37
|
* <dir>/narration/manifest.json — optional (narration manifest)
|
|
38
|
+
* <dir>/presenter/manifest.json — optional (presenter manifest)
|
|
23
39
|
*
|
|
24
40
|
* The scenario id defaults to the directory base name.
|
|
25
41
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-bundle.d.ts","sourceRoot":"","sources":["../../../src/util/load-bundle.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"load-bundle.d.ts","sourceRoot":"","sources":["../../../src/util/load-bundle.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACxB,MAAM,cAAc,CAAC;AAEtB;;;;;;;;;GASG;AACH,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtD,iBAAiB,CAAC,EAAE;QAClB,KAAK,EAAE,KAAK,CAAC;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAC,CAAC;KAC1D,CAAC;IACF,iBAAiB,CAAC,EAAE;QAClB,KAAK,EAAE,KAAK,CAAC;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAC,CAAC;KAC1D,CAAC;IACF,UAAU,CAAC,EAAE,kBAAkB,CAAC;IAChC,UAAU,CAAC,EAAE,kBAAkB,CAAC;CACjC;AAED;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAehE"}
|
package/src/util/load-bundle.js
CHANGED
|
@@ -1,30 +1,38 @@
|
|
|
1
1
|
import { readFile, access } from "node:fs/promises";
|
|
2
2
|
import { join, basename } from "node:path";
|
|
3
|
-
import { loadStepsFromTs } from "./load-ts.js";
|
|
3
|
+
import { loadSoundtrackFromTs, loadStepsFromTs, loadTitleCardsFromTs, } from "./load-ts.js";
|
|
4
4
|
/**
|
|
5
5
|
* Load a scenario bundle from a directory. Expects:
|
|
6
|
-
* <dir>/steps.ts — required (step definitions
|
|
6
|
+
* <dir>/steps.ts — required (step definitions, optional
|
|
7
|
+
* `soundtrack` named export)
|
|
7
8
|
* <dir>/narration/manifest.json — optional (narration manifest)
|
|
9
|
+
* <dir>/presenter/manifest.json — optional (presenter manifest)
|
|
8
10
|
*
|
|
9
11
|
* The scenario id defaults to the directory base name.
|
|
10
12
|
*/
|
|
11
13
|
export async function loadBundle(dir) {
|
|
12
14
|
const stepsPath = join(dir, "steps.ts");
|
|
13
|
-
const manifestPath = join(dir, "narration", "manifest.json");
|
|
14
15
|
const steps = await loadStepsFromTs(stepsPath);
|
|
15
|
-
|
|
16
|
+
const soundtrack = await loadSoundtrackFromTs(stepsPath);
|
|
17
|
+
const titleCards = await loadTitleCardsFromTs(stepsPath);
|
|
18
|
+
return {
|
|
19
|
+
id: basename(dir),
|
|
20
|
+
steps,
|
|
21
|
+
narrationManifest: await readPositionalManifest(join(dir, "narration", "manifest.json")),
|
|
22
|
+
presenterManifest: await readPositionalManifest(join(dir, "presenter", "manifest.json")),
|
|
23
|
+
soundtrack: soundtrack ?? undefined,
|
|
24
|
+
titleCards: titleCards ?? undefined,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** Read a positional clip manifest, or undefined when none exists. */
|
|
28
|
+
async function readPositionalManifest(manifestPath) {
|
|
16
29
|
try {
|
|
17
30
|
await access(manifestPath);
|
|
18
31
|
const raw = await readFile(manifestPath, "utf-8");
|
|
19
|
-
|
|
32
|
+
return JSON.parse(raw);
|
|
20
33
|
}
|
|
21
34
|
catch {
|
|
22
|
-
// No manifest — scenario plays without
|
|
35
|
+
return undefined; // No manifest — the scenario plays without this track.
|
|
23
36
|
}
|
|
24
|
-
return {
|
|
25
|
-
id: basename(dir),
|
|
26
|
-
steps,
|
|
27
|
-
narrationManifest,
|
|
28
|
-
};
|
|
29
37
|
}
|
|
30
38
|
//# sourceMappingURL=load-bundle.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-bundle.js","sourceRoot":"","sources":["../../../src/util/load-bundle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,
|
|
1
|
+
{"version":3,"file":"load-bundle.js","sourceRoot":"","sources":["../../../src/util/load-bundle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,oBAAoB,GAGrB,MAAM,cAAc,CAAC;AAyBtB;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW;IAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAExC,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,MAAM,oBAAoB,CAAC,SAAS,CAAC,CAAC;IACzD,MAAM,UAAU,GAAG,MAAM,oBAAoB,CAAC,SAAS,CAAC,CAAC;IAEzD,OAAO;QACL,EAAE,EAAE,QAAQ,CAAC,GAAG,CAAC;QACjB,KAAK;QACL,iBAAiB,EAAE,MAAM,sBAAsB,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC;QACxF,iBAAiB,EAAE,MAAM,sBAAsB,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC;QACxF,UAAU,EAAE,UAAU,IAAI,SAAS;QACnC,UAAU,EAAE,UAAU,IAAI,SAAS;KACpC,CAAC;AACJ,CAAC;AAED,sEAAsE;AACtE,KAAK,UAAU,sBAAsB,CACnC,YAAoB;IAEpB,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QAC3B,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAmC,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC,CAAC,uDAAuD;IAC3E,CAAC;AACH,CAAC"}
|
package/src/util/load-bundle.ts
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
import { readFile, access } from "node:fs/promises";
|
|
2
2
|
import { join, basename } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
loadSoundtrackFromTs,
|
|
5
|
+
loadStepsFromTs,
|
|
6
|
+
loadTitleCardsFromTs,
|
|
7
|
+
type AuthoredSoundtrack,
|
|
8
|
+
type AuthoredTitleCards,
|
|
9
|
+
} from "./load-ts.js";
|
|
4
10
|
|
|
5
11
|
/**
|
|
6
12
|
* Lightweight bundle shape for CLI use. Mirrors the @scenar/core
|
|
7
13
|
* ScenarioBundle interface but uses plain objects (the CLI does not
|
|
8
14
|
* import @scenar/core at runtime to stay lightweight).
|
|
15
|
+
*
|
|
16
|
+
* Carries the AUTHORED shape: steps as written, title cards as config.
|
|
17
|
+
* Card-step synthesis (`applyTitleCards`) happens in the generated
|
|
18
|
+
* render/pack entries — the true bundle-assembly seam — never here; the
|
|
19
|
+
* CLI consumes this bundle for staging and inspection only.
|
|
9
20
|
*/
|
|
10
21
|
export interface CliBundle {
|
|
11
22
|
id: string;
|
|
@@ -13,33 +24,48 @@ export interface CliBundle {
|
|
|
13
24
|
narrationManifest?: {
|
|
14
25
|
steps: Array<{ src: string; durationMs: number } | null>;
|
|
15
26
|
};
|
|
27
|
+
presenterManifest?: {
|
|
28
|
+
steps: Array<{ src: string; durationMs: number } | null>;
|
|
29
|
+
};
|
|
30
|
+
soundtrack?: AuthoredSoundtrack;
|
|
31
|
+
titleCards?: AuthoredTitleCards;
|
|
16
32
|
}
|
|
17
33
|
|
|
18
34
|
/**
|
|
19
35
|
* Load a scenario bundle from a directory. Expects:
|
|
20
|
-
* <dir>/steps.ts — required (step definitions
|
|
36
|
+
* <dir>/steps.ts — required (step definitions, optional
|
|
37
|
+
* `soundtrack` named export)
|
|
21
38
|
* <dir>/narration/manifest.json — optional (narration manifest)
|
|
39
|
+
* <dir>/presenter/manifest.json — optional (presenter manifest)
|
|
22
40
|
*
|
|
23
41
|
* The scenario id defaults to the directory base name.
|
|
24
42
|
*/
|
|
25
43
|
export async function loadBundle(dir: string): Promise<CliBundle> {
|
|
26
44
|
const stepsPath = join(dir, "steps.ts");
|
|
27
|
-
const manifestPath = join(dir, "narration", "manifest.json");
|
|
28
45
|
|
|
29
46
|
const steps = await loadStepsFromTs(stepsPath);
|
|
47
|
+
const soundtrack = await loadSoundtrackFromTs(stepsPath);
|
|
48
|
+
const titleCards = await loadTitleCardsFromTs(stepsPath);
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
id: basename(dir),
|
|
52
|
+
steps,
|
|
53
|
+
narrationManifest: await readPositionalManifest(join(dir, "narration", "manifest.json")),
|
|
54
|
+
presenterManifest: await readPositionalManifest(join(dir, "presenter", "manifest.json")),
|
|
55
|
+
soundtrack: soundtrack ?? undefined,
|
|
56
|
+
titleCards: titleCards ?? undefined,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
30
59
|
|
|
31
|
-
|
|
60
|
+
/** Read a positional clip manifest, or undefined when none exists. */
|
|
61
|
+
async function readPositionalManifest(
|
|
62
|
+
manifestPath: string,
|
|
63
|
+
): Promise<CliBundle["narrationManifest"]> {
|
|
32
64
|
try {
|
|
33
65
|
await access(manifestPath);
|
|
34
66
|
const raw = await readFile(manifestPath, "utf-8");
|
|
35
|
-
|
|
67
|
+
return JSON.parse(raw) as CliBundle["narrationManifest"];
|
|
36
68
|
} catch {
|
|
37
|
-
// No manifest — scenario plays without
|
|
69
|
+
return undefined; // No manifest — the scenario plays without this track.
|
|
38
70
|
}
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
id: basename(dir),
|
|
42
|
-
steps,
|
|
43
|
-
narrationManifest,
|
|
44
|
-
};
|
|
45
71
|
}
|
package/src/util/load-ts.d.ts
CHANGED
|
@@ -41,6 +41,69 @@ export interface AuthoredViewport {
|
|
|
41
41
|
* wins, because its viewport is inseparable from the steps it sizes.
|
|
42
42
|
*/
|
|
43
43
|
export declare function findAuthoredViewport(exports: Record<string, unknown>): AuthoredViewport | null;
|
|
44
|
+
/**
|
|
45
|
+
* A scenario-authored soundtrack, mirroring the proto `SoundtrackConfig`
|
|
46
|
+
* in camelCase (the same shape as `@scenar/core`'s `Soundtrack`).
|
|
47
|
+
*/
|
|
48
|
+
export interface AuthoredSoundtrack {
|
|
49
|
+
musicSrc?: string;
|
|
50
|
+
musicVolume?: number;
|
|
51
|
+
duckingVolume?: number;
|
|
52
|
+
sfx?: boolean;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Find the scenario's authored soundtrack in a loaded module's exports,
|
|
56
|
+
* or null when the module authors none.
|
|
57
|
+
*
|
|
58
|
+
* Mirrors {@link findAuthoredViewport}'s two authored forms and
|
|
59
|
+
* precedence exactly:
|
|
60
|
+
*
|
|
61
|
+
* 1. A scenario-shaped export — an object carrying both a `soundtrack`
|
|
62
|
+
* and a delayMs-bearing `steps` array (what `createScenario()`
|
|
63
|
+
* returns when the author passes a soundtrack).
|
|
64
|
+
* 2. An export *named* `soundtrack` — the directory-form counterpart,
|
|
65
|
+
* for authors of a raw steps array.
|
|
66
|
+
*
|
|
67
|
+
* Field validity (volume ranges, non-empty musicSrc) is the validator's
|
|
68
|
+
* concern, not discovery's — this only locates the authored object.
|
|
69
|
+
*/
|
|
70
|
+
export declare function findAuthoredSoundtrack(exports: Record<string, unknown>): AuthoredSoundtrack | null;
|
|
71
|
+
/**
|
|
72
|
+
* A scenario-authored title card, mirroring the proto `TitleCard`
|
|
73
|
+
* in camelCase (the same shape as `@scenar/core`'s `TitleCard`).
|
|
74
|
+
*/
|
|
75
|
+
export interface AuthoredTitleCard {
|
|
76
|
+
title?: string;
|
|
77
|
+
subtitle?: string;
|
|
78
|
+
logoSrc?: string;
|
|
79
|
+
ctaText?: string;
|
|
80
|
+
durationMs?: number;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* A scenario-authored title-cards config, mirroring the proto
|
|
84
|
+
* `TitleCardsConfig` in camelCase.
|
|
85
|
+
*/
|
|
86
|
+
export interface AuthoredTitleCards {
|
|
87
|
+
intro?: AuthoredTitleCard;
|
|
88
|
+
outro?: AuthoredTitleCard;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Find the scenario's authored title cards in a loaded module's exports,
|
|
92
|
+
* or null when the module authors none.
|
|
93
|
+
*
|
|
94
|
+
* Mirrors {@link findAuthoredSoundtrack}'s two authored forms and
|
|
95
|
+
* precedence exactly:
|
|
96
|
+
*
|
|
97
|
+
* 1. A scenario-shaped export — an object carrying both a `titleCards`
|
|
98
|
+
* and a delayMs-bearing `steps` array (what `createScenario()`
|
|
99
|
+
* returns when the author passes title cards).
|
|
100
|
+
* 2. An export *named* `titleCards` — the directory-form counterpart,
|
|
101
|
+
* for authors of a raw steps array.
|
|
102
|
+
*
|
|
103
|
+
* Field validity (non-empty title, positive duration) is the validator's
|
|
104
|
+
* concern, not discovery's — this only locates the authored object.
|
|
105
|
+
*/
|
|
106
|
+
export declare function findAuthoredTitleCards(exports: Record<string, unknown>): AuthoredTitleCards | null;
|
|
44
107
|
/**
|
|
45
108
|
* Dynamically import a TypeScript steps file and extract the
|
|
46
109
|
* steps array by duck-typing ({@link findStepsArray}).
|
|
@@ -50,4 +113,18 @@ export declare function findAuthoredViewport(exports: Record<string, unknown>):
|
|
|
50
113
|
* on any TS compilation tool.
|
|
51
114
|
*/
|
|
52
115
|
export declare function loadStepsFromTs(filePath: string): Promise<ImportedStep[]>;
|
|
116
|
+
/**
|
|
117
|
+
* Dynamically import a TypeScript steps file and extract the authored
|
|
118
|
+
* soundtrack ({@link findAuthoredSoundtrack}), or null when the module
|
|
119
|
+
* authors none. Node caches the module, so calling this alongside
|
|
120
|
+
* {@link loadStepsFromTs} costs one import.
|
|
121
|
+
*/
|
|
122
|
+
export declare function loadSoundtrackFromTs(filePath: string): Promise<AuthoredSoundtrack | null>;
|
|
123
|
+
/**
|
|
124
|
+
* Dynamically import a TypeScript steps file and extract the authored
|
|
125
|
+
* title cards ({@link findAuthoredTitleCards}), or null when the module
|
|
126
|
+
* authors none. Node caches the module, so calling this alongside
|
|
127
|
+
* {@link loadStepsFromTs} costs one import.
|
|
128
|
+
*/
|
|
129
|
+
export declare function loadTitleCardsFromTs(filePath: string): Promise<AuthoredTitleCards | null>;
|
|
53
130
|
//# sourceMappingURL=load-ts.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-ts.d.ts","sourceRoot":"","sources":["../../../src/util/load-ts.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,YAAY,EAAE,GAAG,IAAI,CAatF;AAED,6DAA6D;AAC7D,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAyBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,gBAAgB,GAAG,IAAI,CAc9F;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAO/E"}
|
|
1
|
+
{"version":3,"file":"load-ts.d.ts","sourceRoot":"","sources":["../../../src/util/load-ts.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,YAAY,EAAE,GAAG,IAAI,CAatF;AAED,6DAA6D;AAC7D,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAyBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,gBAAgB,GAAG,IAAI,CAc9F;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAeD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,kBAAkB,GAAG,IAAI,CAY3B;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,KAAK,CAAC,EAAE,iBAAiB,CAAC;CAC3B;AAgCD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,kBAAkB,GAAG,IAAI,CAY3B;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAO/E;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAGpC;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAGpC"}
|
package/src/util/load-ts.js
CHANGED
|
@@ -72,6 +72,111 @@ export function findAuthoredViewport(exports) {
|
|
|
72
72
|
}
|
|
73
73
|
return null;
|
|
74
74
|
}
|
|
75
|
+
/** The soundtrack's known field names — used to pick a clean copy. */
|
|
76
|
+
const SOUNDTRACK_FIELDS = ["musicSrc", "musicVolume", "duckingVolume", "sfx"];
|
|
77
|
+
function pickSoundtrack(value) {
|
|
78
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
79
|
+
return null;
|
|
80
|
+
const record = value;
|
|
81
|
+
const soundtrack = {};
|
|
82
|
+
for (const field of SOUNDTRACK_FIELDS) {
|
|
83
|
+
if (record[field] !== undefined)
|
|
84
|
+
soundtrack[field] = record[field];
|
|
85
|
+
}
|
|
86
|
+
return soundtrack;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Find the scenario's authored soundtrack in a loaded module's exports,
|
|
90
|
+
* or null when the module authors none.
|
|
91
|
+
*
|
|
92
|
+
* Mirrors {@link findAuthoredViewport}'s two authored forms and
|
|
93
|
+
* precedence exactly:
|
|
94
|
+
*
|
|
95
|
+
* 1. A scenario-shaped export — an object carrying both a `soundtrack`
|
|
96
|
+
* and a delayMs-bearing `steps` array (what `createScenario()`
|
|
97
|
+
* returns when the author passes a soundtrack).
|
|
98
|
+
* 2. An export *named* `soundtrack` — the directory-form counterpart,
|
|
99
|
+
* for authors of a raw steps array.
|
|
100
|
+
*
|
|
101
|
+
* Field validity (volume ranges, non-empty musicSrc) is the validator's
|
|
102
|
+
* concern, not discovery's — this only locates the authored object.
|
|
103
|
+
*/
|
|
104
|
+
export function findAuthoredSoundtrack(exports) {
|
|
105
|
+
for (const value of Object.values(exports)) {
|
|
106
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
107
|
+
continue;
|
|
108
|
+
const record = value;
|
|
109
|
+
if (record["soundtrack"] !== undefined && isStepsShape(record["steps"])) {
|
|
110
|
+
return pickSoundtrack(record["soundtrack"]);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (exports["soundtrack"] !== undefined) {
|
|
114
|
+
return pickSoundtrack(exports["soundtrack"]);
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
/** The card's known field names — used to pick a clean copy. */
|
|
119
|
+
const TITLE_CARD_FIELDS = [
|
|
120
|
+
"title",
|
|
121
|
+
"subtitle",
|
|
122
|
+
"logoSrc",
|
|
123
|
+
"ctaText",
|
|
124
|
+
"durationMs",
|
|
125
|
+
];
|
|
126
|
+
function pickTitleCard(value) {
|
|
127
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
128
|
+
return null;
|
|
129
|
+
const record = value;
|
|
130
|
+
const card = {};
|
|
131
|
+
for (const field of TITLE_CARD_FIELDS) {
|
|
132
|
+
if (record[field] !== undefined)
|
|
133
|
+
card[field] = record[field];
|
|
134
|
+
}
|
|
135
|
+
return card;
|
|
136
|
+
}
|
|
137
|
+
function pickTitleCards(value) {
|
|
138
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
139
|
+
return null;
|
|
140
|
+
const record = value;
|
|
141
|
+
const cards = {};
|
|
142
|
+
const intro = pickTitleCard(record["intro"]);
|
|
143
|
+
const outro = pickTitleCard(record["outro"]);
|
|
144
|
+
if (intro)
|
|
145
|
+
cards.intro = intro;
|
|
146
|
+
if (outro)
|
|
147
|
+
cards.outro = outro;
|
|
148
|
+
return cards;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Find the scenario's authored title cards in a loaded module's exports,
|
|
152
|
+
* or null when the module authors none.
|
|
153
|
+
*
|
|
154
|
+
* Mirrors {@link findAuthoredSoundtrack}'s two authored forms and
|
|
155
|
+
* precedence exactly:
|
|
156
|
+
*
|
|
157
|
+
* 1. A scenario-shaped export — an object carrying both a `titleCards`
|
|
158
|
+
* and a delayMs-bearing `steps` array (what `createScenario()`
|
|
159
|
+
* returns when the author passes title cards).
|
|
160
|
+
* 2. An export *named* `titleCards` — the directory-form counterpart,
|
|
161
|
+
* for authors of a raw steps array.
|
|
162
|
+
*
|
|
163
|
+
* Field validity (non-empty title, positive duration) is the validator's
|
|
164
|
+
* concern, not discovery's — this only locates the authored object.
|
|
165
|
+
*/
|
|
166
|
+
export function findAuthoredTitleCards(exports) {
|
|
167
|
+
for (const value of Object.values(exports)) {
|
|
168
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
169
|
+
continue;
|
|
170
|
+
const record = value;
|
|
171
|
+
if (record["titleCards"] !== undefined && isStepsShape(record["steps"])) {
|
|
172
|
+
return pickTitleCards(record["titleCards"]);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (exports["titleCards"] !== undefined) {
|
|
176
|
+
return pickTitleCards(exports["titleCards"]);
|
|
177
|
+
}
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
75
180
|
/**
|
|
76
181
|
* Dynamically import a TypeScript steps file and extract the
|
|
77
182
|
* steps array by duck-typing ({@link findStepsArray}).
|
|
@@ -88,4 +193,24 @@ export async function loadStepsFromTs(filePath) {
|
|
|
88
193
|
}
|
|
89
194
|
return steps;
|
|
90
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* Dynamically import a TypeScript steps file and extract the authored
|
|
198
|
+
* soundtrack ({@link findAuthoredSoundtrack}), or null when the module
|
|
199
|
+
* authors none. Node caches the module, so calling this alongside
|
|
200
|
+
* {@link loadStepsFromTs} costs one import.
|
|
201
|
+
*/
|
|
202
|
+
export async function loadSoundtrackFromTs(filePath) {
|
|
203
|
+
const mod = await import(pathToFileURL(filePath).href);
|
|
204
|
+
return findAuthoredSoundtrack(mod.default ?? mod);
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Dynamically import a TypeScript steps file and extract the authored
|
|
208
|
+
* title cards ({@link findAuthoredTitleCards}), or null when the module
|
|
209
|
+
* authors none. Node caches the module, so calling this alongside
|
|
210
|
+
* {@link loadStepsFromTs} costs one import.
|
|
211
|
+
*/
|
|
212
|
+
export async function loadTitleCardsFromTs(filePath) {
|
|
213
|
+
const mod = await import(pathToFileURL(filePath).href);
|
|
214
|
+
return findAuthoredTitleCards(mod.default ?? mod);
|
|
215
|
+
}
|
|
91
216
|
//# sourceMappingURL=load-ts.js.map
|
package/src/util/load-ts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-ts.js","sourceRoot":"","sources":["../../../src/util/load-ts.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"load-ts.js","sourceRoot":"","sources":["../../../src/util/load-ts.ts"],"names":[],"mappings":"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"}
|