@scenar/cli 0.1.20 → 0.2.1

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.
Files changed (112) hide show
  1. package/example-bundle/assets/index-BLQ14SEo.js +147 -0
  2. package/example-bundle/assets/logo-f-5LjVqJ.png +0 -0
  3. package/example-bundle/assets/style-Dnzx_jUO.css +1 -0
  4. package/example-bundle/index.html +13 -0
  5. package/example-bundle/pack-manifest.json +36 -0
  6. package/example-bundle/scenario.json +9 -0
  7. package/package.json +17 -5
  8. package/src/__tests__/pack-generate-embed-entry.test.ts +59 -6
  9. package/src/__tests__/publish-command.test.ts +46 -0
  10. package/src/__tests__/publish-flow.test.ts +220 -0
  11. package/src/__tests__/read-viewport.test.ts +45 -0
  12. package/src/__tests__/run-publish.test.ts +92 -0
  13. package/src/__tests__/serve-command.test.ts +44 -0
  14. package/src/__tests__/serve-request-path.test.ts +67 -0
  15. package/src/__tests__/serve-static-server.test.ts +88 -0
  16. package/src/__tests__/try-command.test.ts +21 -0
  17. package/src/api.d.ts +31 -0
  18. package/src/api.d.ts.map +1 -0
  19. package/src/api.js +28 -0
  20. package/src/api.js.map +1 -0
  21. package/src/api.ts +55 -0
  22. package/src/bundle/read-viewport.d.ts +23 -0
  23. package/src/bundle/read-viewport.d.ts.map +1 -0
  24. package/src/bundle/read-viewport.js +25 -0
  25. package/src/bundle/read-viewport.js.map +1 -0
  26. package/src/bundle/read-viewport.ts +36 -0
  27. package/src/commands/deploy.d.ts.map +1 -1
  28. package/src/commands/deploy.js +8 -24
  29. package/src/commands/deploy.js.map +1 -1
  30. package/src/commands/deploy.ts +10 -28
  31. package/src/commands/narrate.d.ts.map +1 -1
  32. package/src/commands/narrate.js +39 -170
  33. package/src/commands/narrate.js.map +1 -1
  34. package/src/commands/narrate.ts +48 -289
  35. package/src/commands/pack.d.ts.map +1 -1
  36. package/src/commands/pack.js +12 -112
  37. package/src/commands/pack.js.map +1 -1
  38. package/src/commands/pack.ts +12 -128
  39. package/src/commands/publish.d.ts +3 -0
  40. package/src/commands/publish.d.ts.map +1 -0
  41. package/src/commands/publish.js +64 -0
  42. package/src/commands/publish.js.map +1 -0
  43. package/src/commands/publish.ts +86 -0
  44. package/src/commands/render.d.ts.map +1 -1
  45. package/src/commands/render.js +12 -194
  46. package/src/commands/render.js.map +1 -1
  47. package/src/commands/render.ts +19 -286
  48. package/src/commands/serve.d.ts +3 -0
  49. package/src/commands/serve.d.ts.map +1 -0
  50. package/src/commands/serve.js +91 -0
  51. package/src/commands/serve.js.map +1 -0
  52. package/src/commands/serve.ts +112 -0
  53. package/src/commands/try.d.ts +3 -0
  54. package/src/commands/try.d.ts.map +1 -0
  55. package/src/commands/try.js +99 -0
  56. package/src/commands/try.js.map +1 -0
  57. package/src/commands/try.ts +122 -0
  58. package/src/index.d.ts.map +1 -1
  59. package/src/index.js +6 -0
  60. package/src/index.js.map +1 -1
  61. package/src/index.ts +6 -0
  62. package/src/narrate/run-narrate.d.ts +43 -0
  63. package/src/narrate/run-narrate.d.ts.map +1 -0
  64. package/src/narrate/run-narrate.js +174 -0
  65. package/src/narrate/run-narrate.js.map +1 -0
  66. package/src/narrate/run-narrate.ts +298 -0
  67. package/src/pack/generate-embed-entry.d.ts +11 -0
  68. package/src/pack/generate-embed-entry.d.ts.map +1 -1
  69. package/src/pack/generate-embed-entry.js +81 -10
  70. package/src/pack/generate-embed-entry.js.map +1 -1
  71. package/src/pack/generate-embed-entry.ts +81 -10
  72. package/src/pack/run-pack.d.ts +34 -0
  73. package/src/pack/run-pack.d.ts.map +1 -0
  74. package/src/pack/run-pack.js +117 -0
  75. package/src/pack/run-pack.js.map +1 -0
  76. package/src/pack/run-pack.ts +163 -0
  77. package/src/publish/github.d.ts +11 -0
  78. package/src/publish/github.d.ts.map +1 -0
  79. package/src/publish/github.js +197 -0
  80. package/src/publish/github.js.map +1 -0
  81. package/src/publish/github.ts +216 -0
  82. package/src/publish/publish-flow.d.ts +110 -0
  83. package/src/publish/publish-flow.d.ts.map +1 -0
  84. package/src/publish/publish-flow.js +117 -0
  85. package/src/publish/publish-flow.js.map +1 -0
  86. package/src/publish/publish-flow.ts +199 -0
  87. package/src/publish/run-publish.d.ts +41 -0
  88. package/src/publish/run-publish.d.ts.map +1 -0
  89. package/src/publish/run-publish.js +77 -0
  90. package/src/publish/run-publish.js.map +1 -0
  91. package/src/publish/run-publish.ts +131 -0
  92. package/src/render/run-render.d.ts +31 -0
  93. package/src/render/run-render.d.ts.map +1 -0
  94. package/src/render/run-render.js +196 -0
  95. package/src/render/run-render.js.map +1 -0
  96. package/src/render/run-render.ts +287 -0
  97. package/src/serve/request-path.d.ts +23 -0
  98. package/src/serve/request-path.d.ts.map +1 -0
  99. package/src/serve/request-path.js +52 -0
  100. package/src/serve/request-path.js.map +1 -0
  101. package/src/serve/request-path.ts +55 -0
  102. package/src/serve/run-serve.d.ts +31 -0
  103. package/src/serve/run-serve.d.ts.map +1 -0
  104. package/src/serve/run-serve.js +35 -0
  105. package/src/serve/run-serve.js.map +1 -0
  106. package/src/serve/run-serve.ts +68 -0
  107. package/src/serve/static-server.d.ts +38 -0
  108. package/src/serve/static-server.d.ts.map +1 -0
  109. package/src/serve/static-server.js +91 -0
  110. package/src/serve/static-server.js.map +1 -0
  111. package/src/serve/static-server.ts +118 -0
  112. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,41 @@
1
+ import type { Viewport } from "../pack/viewport.js";
2
+ import { type PublishFlowDeps, type PublishResult } from "./publish-flow.js";
3
+ /** Options for {@link runPublish}. */
4
+ export interface RunPublishOptions {
5
+ readonly bundleDir: string;
6
+ /** Target repository name (default: {@link DEFAULT_REPO}). */
7
+ readonly repo?: string;
8
+ /**
9
+ * Subdirectory within the repo (default: the packed scenario slug). Pass "/"
10
+ * or "" to publish at the repo root (a dedicated single-tour repo).
11
+ */
12
+ readonly path?: string;
13
+ /** Target GitHub org (default: the authenticated user). */
14
+ readonly org?: string;
15
+ /** Create the repo private (GitHub Pages needs Pro for private repos). */
16
+ readonly private?: boolean;
17
+ /** Commit message for the published snapshot. */
18
+ readonly message?: string;
19
+ /** Progress sink for flow messages. */
20
+ readonly onLog?: (message: string) => void;
21
+ /**
22
+ * Override the publish backend (the gh/git deps). Defaults to the real
23
+ * {@link createGithubPublisher}; tests inject a fake to avoid live calls.
24
+ */
25
+ readonly deps?: Omit<PublishFlowDeps, "log">;
26
+ }
27
+ /** The published location plus the derived embed snippet. */
28
+ export interface PublishRunResult {
29
+ readonly result: PublishResult;
30
+ readonly viewport: Viewport;
31
+ readonly recordedViewport: boolean;
32
+ readonly snippet: string;
33
+ }
34
+ /**
35
+ * Validate a packed bundle and publish it to GitHub Pages — the orchestration
36
+ * behind `scenar publish`, with no process/exit coupling. Resolves the default
37
+ * repo name, runs the publish flow, and builds the embed snippet. Throws on an
38
+ * invalid bundle, an invalid repo name, or any flow failure.
39
+ */
40
+ export declare function runPublish(options: RunPublishOptions): Promise<PublishRunResult>;
41
+ //# sourceMappingURL=run-publish.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-publish.d.ts","sourceRoot":"","sources":["../../../src/publish/run-publish.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAKL,KAAK,eAAe,EACpB,KAAK,aAAa,EACnB,MAAM,mBAAmB,CAAC;AAc3B,sCAAsC;AACtC,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,2DAA2D;IAC3D,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,0EAA0E;IAC1E,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,uCAAuC;IACvC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;CAC9C;AAED,6DAA6D;AAC7D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA+CtF"}
@@ -0,0 +1,77 @@
1
+ import { resolve, join, basename } from "node:path";
2
+ import { stat, readFile } from "node:fs/promises";
3
+ import { PACK_MANIFEST_FILE } from "../pack/pack-manifest.js";
4
+ import { buildEmbedSnippet } from "../deploy/embed-snippet.js";
5
+ import { readBundleViewport } from "../bundle/read-viewport.js";
6
+ import { createGithubPublisher } from "./github.js";
7
+ import { runPublishFlow, validateRepoName, validatePublishPath, normalizePath, } from "./publish-flow.js";
8
+ /** The servable entry every packed bundle contains at its root. */
9
+ const INDEX_FILE = "index.html";
10
+ /** Repo-name rule for the default (same shape as scenario slugs). */
11
+ const REPO_FALLBACK_PATTERN = /^[a-z][a-z0-9-]*[a-z0-9]$/;
12
+ /**
13
+ * Default shared repo for embeds. Many tours live here, each under its own slug
14
+ * path, so previews never land in the user's source repo. Override with --repo.
15
+ */
16
+ const DEFAULT_REPO = "scenar-embeds";
17
+ /**
18
+ * Validate a packed bundle and publish it to GitHub Pages — the orchestration
19
+ * behind `scenar publish`, with no process/exit coupling. Resolves the default
20
+ * repo name, runs the publish flow, and builds the embed snippet. Throws on an
21
+ * invalid bundle, an invalid repo name, or any flow failure.
22
+ */
23
+ export async function runPublish(options) {
24
+ const onLog = options.onLog ?? (() => { });
25
+ const resolvedDir = resolve(options.bundleDir);
26
+ const info = await stat(resolvedDir).catch(() => null);
27
+ if (!info || !info.isDirectory()) {
28
+ throw new Error(`${options.bundleDir} is not a directory. Pass a bundle produced by \`scenar pack\`.`);
29
+ }
30
+ const indexInfo = await stat(join(resolvedDir, INDEX_FILE)).catch(() => null);
31
+ if (!indexInfo || !indexInfo.isFile()) {
32
+ throw new Error(`no ${INDEX_FILE} in ${options.bundleDir}. Run \`scenar pack\` to produce a servable bundle first.`);
33
+ }
34
+ const slug = await scenarioSlug(resolvedDir);
35
+ const repo = options.repo ?? DEFAULT_REPO;
36
+ const repoError = validateRepoName(repo);
37
+ if (repoError) {
38
+ throw new Error(`${repoError}. Pass --repo <name> to override.`);
39
+ }
40
+ // Path defaults to the scenario slug so tours coexist in one repo; an explicit
41
+ // "/" (or "") publishes at the repo root.
42
+ const path = normalizePath(options.path ?? slug);
43
+ const pathError = validatePublishPath(path);
44
+ if (pathError) {
45
+ throw new Error(`${pathError}. Pass --path <subpath> to override.`);
46
+ }
47
+ const deps = { ...(options.deps ?? createGithubPublisher()), log: onLog };
48
+ const result = await runPublishFlow(deps, {
49
+ bundleDir: resolvedDir,
50
+ repo,
51
+ path,
52
+ org: options.org,
53
+ private: Boolean(options.private),
54
+ message: options.message ?? "Publish Scenar embed",
55
+ });
56
+ const { viewport, recorded } = await readBundleViewport(resolvedDir);
57
+ const snippet = buildEmbedSnippet({ embedUrl: result.pagesUrl, viewport });
58
+ return { result, viewport, recordedViewport: recorded, snippet };
59
+ }
60
+ /**
61
+ * The packed scenario slug (from pack-manifest.json), falling back to the bundle
62
+ * directory's base name. Used as the default publish subpath. The downstream
63
+ * validatePublishPath guards the result.
64
+ */
65
+ async function scenarioSlug(bundleDir) {
66
+ try {
67
+ const raw = await readFile(join(bundleDir, PACK_MANIFEST_FILE), "utf-8");
68
+ const id = JSON.parse(raw).scenarioId;
69
+ if (typeof id === "string" && REPO_FALLBACK_PATTERN.test(id))
70
+ return id;
71
+ }
72
+ catch {
73
+ // No/invalid manifest — fall back to the directory name.
74
+ }
75
+ return basename(bundleDir);
76
+ }
77
+ //# sourceMappingURL=run-publish.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-publish.js","sourceRoot":"","sources":["../../../src/publish/run-publish.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,131 @@
1
+ import { resolve, join, basename } from "node:path";
2
+ import { stat, readFile } from "node:fs/promises";
3
+ import { PACK_MANIFEST_FILE } from "../pack/pack-manifest.js";
4
+ import { buildEmbedSnippet } from "../deploy/embed-snippet.js";
5
+ import { readBundleViewport } from "../bundle/read-viewport.js";
6
+ import type { Viewport } from "../pack/viewport.js";
7
+ import { createGithubPublisher } from "./github.js";
8
+ import {
9
+ runPublishFlow,
10
+ validateRepoName,
11
+ validatePublishPath,
12
+ normalizePath,
13
+ type PublishFlowDeps,
14
+ type PublishResult,
15
+ } from "./publish-flow.js";
16
+
17
+ /** The servable entry every packed bundle contains at its root. */
18
+ const INDEX_FILE = "index.html";
19
+
20
+ /** Repo-name rule for the default (same shape as scenario slugs). */
21
+ const REPO_FALLBACK_PATTERN = /^[a-z][a-z0-9-]*[a-z0-9]$/;
22
+
23
+ /**
24
+ * Default shared repo for embeds. Many tours live here, each under its own slug
25
+ * path, so previews never land in the user's source repo. Override with --repo.
26
+ */
27
+ const DEFAULT_REPO = "scenar-embeds";
28
+
29
+ /** Options for {@link runPublish}. */
30
+ export interface RunPublishOptions {
31
+ readonly bundleDir: string;
32
+ /** Target repository name (default: {@link DEFAULT_REPO}). */
33
+ readonly repo?: string;
34
+ /**
35
+ * Subdirectory within the repo (default: the packed scenario slug). Pass "/"
36
+ * or "" to publish at the repo root (a dedicated single-tour repo).
37
+ */
38
+ readonly path?: string;
39
+ /** Target GitHub org (default: the authenticated user). */
40
+ readonly org?: string;
41
+ /** Create the repo private (GitHub Pages needs Pro for private repos). */
42
+ readonly private?: boolean;
43
+ /** Commit message for the published snapshot. */
44
+ readonly message?: string;
45
+ /** Progress sink for flow messages. */
46
+ readonly onLog?: (message: string) => void;
47
+ /**
48
+ * Override the publish backend (the gh/git deps). Defaults to the real
49
+ * {@link createGithubPublisher}; tests inject a fake to avoid live calls.
50
+ */
51
+ readonly deps?: Omit<PublishFlowDeps, "log">;
52
+ }
53
+
54
+ /** The published location plus the derived embed snippet. */
55
+ export interface PublishRunResult {
56
+ readonly result: PublishResult;
57
+ readonly viewport: Viewport;
58
+ readonly recordedViewport: boolean;
59
+ readonly snippet: string;
60
+ }
61
+
62
+ /**
63
+ * Validate a packed bundle and publish it to GitHub Pages — the orchestration
64
+ * behind `scenar publish`, with no process/exit coupling. Resolves the default
65
+ * repo name, runs the publish flow, and builds the embed snippet. Throws on an
66
+ * invalid bundle, an invalid repo name, or any flow failure.
67
+ */
68
+ export async function runPublish(options: RunPublishOptions): Promise<PublishRunResult> {
69
+ const onLog = options.onLog ?? (() => {});
70
+ const resolvedDir = resolve(options.bundleDir);
71
+
72
+ const info = await stat(resolvedDir).catch(() => null);
73
+ if (!info || !info.isDirectory()) {
74
+ throw new Error(
75
+ `${options.bundleDir} is not a directory. Pass a bundle produced by \`scenar pack\`.`,
76
+ );
77
+ }
78
+ const indexInfo = await stat(join(resolvedDir, INDEX_FILE)).catch(() => null);
79
+ if (!indexInfo || !indexInfo.isFile()) {
80
+ throw new Error(
81
+ `no ${INDEX_FILE} in ${options.bundleDir}. Run \`scenar pack\` to produce a servable bundle first.`,
82
+ );
83
+ }
84
+
85
+ const slug = await scenarioSlug(resolvedDir);
86
+
87
+ const repo = options.repo ?? DEFAULT_REPO;
88
+ const repoError = validateRepoName(repo);
89
+ if (repoError) {
90
+ throw new Error(`${repoError}. Pass --repo <name> to override.`);
91
+ }
92
+
93
+ // Path defaults to the scenario slug so tours coexist in one repo; an explicit
94
+ // "/" (or "") publishes at the repo root.
95
+ const path = normalizePath(options.path ?? slug);
96
+ const pathError = validatePublishPath(path);
97
+ if (pathError) {
98
+ throw new Error(`${pathError}. Pass --path <subpath> to override.`);
99
+ }
100
+
101
+ const deps: PublishFlowDeps = { ...(options.deps ?? createGithubPublisher()), log: onLog };
102
+ const result = await runPublishFlow(deps, {
103
+ bundleDir: resolvedDir,
104
+ repo,
105
+ path,
106
+ org: options.org,
107
+ private: Boolean(options.private),
108
+ message: options.message ?? "Publish Scenar embed",
109
+ });
110
+
111
+ const { viewport, recorded } = await readBundleViewport(resolvedDir);
112
+ const snippet = buildEmbedSnippet({ embedUrl: result.pagesUrl, viewport });
113
+
114
+ return { result, viewport, recordedViewport: recorded, snippet };
115
+ }
116
+
117
+ /**
118
+ * The packed scenario slug (from pack-manifest.json), falling back to the bundle
119
+ * directory's base name. Used as the default publish subpath. The downstream
120
+ * validatePublishPath guards the result.
121
+ */
122
+ async function scenarioSlug(bundleDir: string): Promise<string> {
123
+ try {
124
+ const raw = await readFile(join(bundleDir, PACK_MANIFEST_FILE), "utf-8");
125
+ const id = (JSON.parse(raw) as { scenarioId?: unknown }).scenarioId;
126
+ if (typeof id === "string" && REPO_FALLBACK_PATTERN.test(id)) return id;
127
+ } catch {
128
+ // No/invalid manifest — fall back to the directory name.
129
+ }
130
+ return basename(bundleDir);
131
+ }
@@ -0,0 +1,31 @@
1
+ /** Options for {@link runRender}. Paths may be relative; resolved here. */
2
+ export interface RunRenderOptions {
3
+ readonly scenarioDir: string;
4
+ readonly out?: string;
5
+ readonly fps?: number;
6
+ readonly width?: number;
7
+ readonly height?: number;
8
+ readonly compositionId?: string;
9
+ readonly entry?: string;
10
+ readonly webpackOverride?: string;
11
+ readonly onLog?: (message: string) => void;
12
+ }
13
+ /** The outcome of a successful render. */
14
+ export interface RenderResult {
15
+ readonly scenarioId: string;
16
+ readonly outputPath: string;
17
+ readonly steps: number;
18
+ readonly hasNarration: boolean;
19
+ readonly entryAutoGenerated: boolean;
20
+ readonly fps: number;
21
+ readonly width: number;
22
+ readonly height: number;
23
+ }
24
+ /**
25
+ * Render a scenario directory to an MP4 via Remotion — the pure orchestration
26
+ * behind `scenar render`, with no process/exit coupling. Throws on any failure
27
+ * (missing directory, missing Remotion peer deps, render error). The caller
28
+ * formats the result/error.
29
+ */
30
+ export declare function runRender(options: RunRenderOptions): Promise<RenderResult>;
31
+ //# sourceMappingURL=run-render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-render.d.ts","sourceRoot":"","sources":["../../../src/render/run-render.ts"],"names":[],"mappings":"AAQA,2EAA2E;AAC3E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AAED,0CAA0C;AAC1C,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;IACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CAkFhF"}
@@ -0,0 +1,196 @@
1
+ import { resolve, join } from "node:path";
2
+ import { stat, mkdir, access, writeFile, rm } from "node:fs/promises";
3
+ import { pathToFileURL } from "node:url";
4
+ import { loadBundle } from "../util/load-bundle.js";
5
+ import { generateRemotionEntry } from "./generate-entry.js";
6
+ import { resolveProvidersPath } from "./resolve-providers.js";
7
+ import { detectRenderExport } from "./detect-render-export.js";
8
+ /**
9
+ * Render a scenario directory to an MP4 via Remotion — the pure orchestration
10
+ * behind `scenar render`, with no process/exit coupling. Throws on any failure
11
+ * (missing directory, missing Remotion peer deps, render error). The caller
12
+ * formats the result/error.
13
+ */
14
+ export async function runRender(options) {
15
+ const onLog = options.onLog ?? (() => { });
16
+ const scenarioDir = resolve(options.scenarioDir);
17
+ const info = await stat(scenarioDir).catch(() => null);
18
+ if (!info) {
19
+ throw new Error(`${options.scenarioDir} does not exist.`);
20
+ }
21
+ if (!info.isDirectory()) {
22
+ throw new Error(`${options.scenarioDir} is not a directory. ` +
23
+ "The render command requires a scenario directory (with steps.ts).");
24
+ }
25
+ const fps = options.fps ?? 30;
26
+ const width = options.width ?? 1920;
27
+ const height = options.height ?? 1080;
28
+ let tempDir;
29
+ try {
30
+ const bundle = await loadBundle(scenarioDir);
31
+ const scenarioId = bundle.id;
32
+ const compositionId = options.compositionId ?? scenarioId;
33
+ const outputPath = resolveOutputPath(options.out, scenarioId);
34
+ const { entryPoint, generated } = await resolveEntryPoint({
35
+ entryOption: options.entry,
36
+ scenarioDir,
37
+ scenarioId,
38
+ compositionId,
39
+ hasNarration: !!bundle.narrationManifest,
40
+ fps,
41
+ width,
42
+ height,
43
+ });
44
+ tempDir = generated?.tempDir;
45
+ const webpackOverride = options.webpackOverride
46
+ ? await loadWebpackOverride(options.webpackOverride)
47
+ : undefined;
48
+ onLog(`Scenario: ${scenarioId}`);
49
+ onLog(`Steps: ${bundle.steps.length}`);
50
+ onLog(`Audio: ${bundle.narrationManifest ? "yes (manifest found)" : "none"}`);
51
+ onLog(`Entry: ${generated ? "(auto-generated)" : entryPoint}`);
52
+ if (generated?.providersPath) {
53
+ onLog(`Providers: ${generated.providersPath}`);
54
+ }
55
+ if (webpackOverride) {
56
+ onLog("Webpack: custom override loaded");
57
+ }
58
+ onLog(`Output: ${outputPath}`);
59
+ onLog(`Config: ${width}x${height} @ ${fps}fps`);
60
+ await renderScenario({
61
+ bundle,
62
+ entryPoint,
63
+ compositionId,
64
+ outputPath,
65
+ fps,
66
+ width,
67
+ height,
68
+ webpackOverride,
69
+ onLog,
70
+ });
71
+ return {
72
+ scenarioId,
73
+ outputPath,
74
+ steps: bundle.steps.length,
75
+ hasNarration: !!bundle.narrationManifest,
76
+ entryAutoGenerated: !!generated,
77
+ fps,
78
+ width,
79
+ height,
80
+ };
81
+ }
82
+ finally {
83
+ if (tempDir) {
84
+ await rm(tempDir, { recursive: true, force: true }).catch(() => { });
85
+ }
86
+ }
87
+ }
88
+ function resolveOutputPath(outOption, scenarioId) {
89
+ if (!outOption) {
90
+ return resolve(`./${scenarioId}.mp4`);
91
+ }
92
+ if (outOption.endsWith(".mp4")) {
93
+ return resolve(outOption);
94
+ }
95
+ return resolve(join(outOption, `${scenarioId}.mp4`));
96
+ }
97
+ async function resolveEntryPoint(input) {
98
+ // Explicit --entry: use as-is, no generation.
99
+ if (input.entryOption) {
100
+ const resolved = resolve(input.entryOption);
101
+ try {
102
+ await access(resolved);
103
+ }
104
+ catch {
105
+ throw new Error(`Remotion entry point not found: ${input.entryOption}`);
106
+ }
107
+ return { entryPoint: resolved };
108
+ }
109
+ // Auto-generate: detect renderStep export, find providers, write temp entry.
110
+ const renderFilePath = await detectRenderExport(input.scenarioDir);
111
+ const providersPath = await resolveProvidersPath(input.scenarioDir);
112
+ const entrySource = generateRemotionEntry({
113
+ scenarioDir: input.scenarioDir,
114
+ renderFilePath,
115
+ scenarioId: input.scenarioId,
116
+ hasNarration: input.hasNarration,
117
+ providersPath,
118
+ fps: input.fps,
119
+ width: input.width,
120
+ height: input.height,
121
+ compositionId: input.compositionId,
122
+ });
123
+ // Write the entry inside the scenario directory so webpack's standard
124
+ // node_modules resolution walks up from here into the consumer project.
125
+ // A /tmp/ location would fail because no node_modules exist there.
126
+ const tempDir = join(input.scenarioDir, ".scenar-render");
127
+ await mkdir(tempDir, { recursive: true });
128
+ const entryPath = join(tempDir, "index.tsx");
129
+ await writeFile(entryPath, entrySource, "utf-8");
130
+ return { entryPoint: entryPath, generated: { tempDir, providersPath } };
131
+ }
132
+ async function loadWebpackOverride(overridePath) {
133
+ const resolved = resolve(overridePath);
134
+ try {
135
+ await access(resolved);
136
+ }
137
+ catch {
138
+ throw new Error(`Webpack override file not found: ${overridePath}`);
139
+ }
140
+ let mod;
141
+ try {
142
+ mod = (await import(pathToFileURL(resolved).href));
143
+ }
144
+ catch (err) {
145
+ const detail = err instanceof Error ? err.message : String(err);
146
+ throw new Error(`Failed to import webpack override from ${overridePath}:\n${detail}`);
147
+ }
148
+ const override = (mod.default ?? mod.webpackOverride);
149
+ if (typeof override !== "function") {
150
+ throw new Error(`${overridePath} does not export a webpack override function.\n\n` +
151
+ "Expected a default export or named 'webpackOverride' export:\n\n" +
152
+ ' import type { WebpackOverrideFn } from "@remotion/bundler";\n\n' +
153
+ " const webpackOverride: WebpackOverrideFn = (config) => ({\n" +
154
+ " ...config,\n" +
155
+ " // your overrides\n" +
156
+ " });\n\n" +
157
+ " export default webpackOverride;\n");
158
+ }
159
+ return override;
160
+ }
161
+ async function renderScenario(config) {
162
+ const bundler = await import("@remotion/bundler").catch(() => {
163
+ throw new Error("Could not load @remotion/bundler.\nInstall it: pnpm add @remotion/bundler@4.0.448");
164
+ });
165
+ const renderer = await import("@remotion/renderer").catch(() => {
166
+ throw new Error("Could not load @remotion/renderer.\nInstall it: pnpm add @remotion/renderer@4.0.448");
167
+ });
168
+ config.onLog("Bundling Remotion project...");
169
+ const bundleOptions = { entryPoint: config.entryPoint };
170
+ if (config.webpackOverride) {
171
+ bundleOptions.webpackOverride = config.webpackOverride;
172
+ }
173
+ const serveUrl = await bundler.bundle(bundleOptions);
174
+ config.onLog(`Selecting composition: ${config.compositionId}`);
175
+ const composition = await renderer.selectComposition({
176
+ serveUrl,
177
+ id: config.compositionId,
178
+ });
179
+ config.onLog(`Composition: ${composition.width}x${composition.height} @ ${composition.fps}fps, ` +
180
+ `${composition.durationInFrames} frames ` +
181
+ `(${(composition.durationInFrames / composition.fps).toFixed(1)}s)`);
182
+ const outDir = resolve(config.outputPath, "..");
183
+ await mkdir(outDir, { recursive: true });
184
+ config.onLog("Rendering...");
185
+ await renderer.renderMedia({
186
+ composition,
187
+ serveUrl,
188
+ codec: "h264",
189
+ outputLocation: config.outputPath,
190
+ onProgress: ({ progress }) => {
191
+ const pct = Math.round(progress * 100);
192
+ config.onLog(` Progress: ${pct}%`);
193
+ },
194
+ });
195
+ }
196
+ //# sourceMappingURL=run-render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-render.js","sourceRoot":"","sources":["../../../src/render/run-render.ts"],"names":[],"mappings":"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"}