demofly 0.1.3 → 0.1.5

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 (71) hide show
  1. package/dist/commands/auth/login.js +1 -1
  2. package/dist/commands/auth/login.js.map +1 -1
  3. package/dist/commands/demos/delete.d.ts +3 -0
  4. package/dist/commands/demos/delete.d.ts.map +1 -0
  5. package/dist/commands/demos/delete.js +41 -0
  6. package/dist/commands/demos/delete.js.map +1 -0
  7. package/dist/commands/demos/get.d.ts +3 -0
  8. package/dist/commands/demos/get.d.ts.map +1 -0
  9. package/dist/commands/demos/get.js +30 -0
  10. package/dist/commands/demos/get.js.map +1 -0
  11. package/dist/commands/demos/index.d.ts +3 -0
  12. package/dist/commands/demos/index.d.ts.map +1 -0
  13. package/dist/commands/demos/index.js +17 -0
  14. package/dist/commands/demos/index.js.map +1 -0
  15. package/dist/commands/demos/list.d.ts +3 -0
  16. package/dist/commands/demos/list.d.ts.map +1 -0
  17. package/dist/commands/demos/list.js +117 -0
  18. package/dist/commands/demos/list.js.map +1 -0
  19. package/dist/commands/demos/open.d.ts +3 -0
  20. package/dist/commands/demos/open.d.ts.map +1 -0
  21. package/dist/commands/demos/open.js +45 -0
  22. package/dist/commands/demos/open.js.map +1 -0
  23. package/dist/commands/demos/update.d.ts +3 -0
  24. package/dist/commands/demos/update.d.ts.map +1 -0
  25. package/dist/commands/demos/update.js +31 -0
  26. package/dist/commands/demos/update.js.map +1 -0
  27. package/dist/commands/generate.d.ts +6 -0
  28. package/dist/commands/generate.d.ts.map +1 -1
  29. package/dist/commands/generate.js +75 -19
  30. package/dist/commands/generate.js.map +1 -1
  31. package/dist/commands/push.d.ts.map +1 -1
  32. package/dist/commands/push.js +12 -9
  33. package/dist/commands/push.js.map +1 -1
  34. package/dist/commands/render.d.ts +11 -0
  35. package/dist/commands/render.d.ts.map +1 -0
  36. package/dist/commands/render.js +161 -0
  37. package/dist/commands/render.js.map +1 -0
  38. package/dist/index.js +10 -3
  39. package/dist/index.js.map +1 -1
  40. package/dist/lib/api-client.d.ts +2 -1
  41. package/dist/lib/api-client.d.ts.map +1 -1
  42. package/dist/lib/api-client.js +22 -10
  43. package/dist/lib/api-client.js.map +1 -1
  44. package/dist/lib/audio-stitching.d.ts +64 -0
  45. package/dist/lib/audio-stitching.d.ts.map +1 -0
  46. package/dist/lib/audio-stitching.js +260 -0
  47. package/dist/lib/audio-stitching.js.map +1 -0
  48. package/dist/lib/credentials.d.ts.map +1 -1
  49. package/dist/lib/credentials.js +2 -0
  50. package/dist/lib/credentials.js.map +1 -1
  51. package/dist/lib/demo-scanner.d.ts +17 -0
  52. package/dist/lib/demo-scanner.d.ts.map +1 -0
  53. package/dist/lib/demo-scanner.js +70 -0
  54. package/dist/lib/demo-scanner.js.map +1 -0
  55. package/dist/lib/enhancement-client.d.ts +17 -0
  56. package/dist/lib/enhancement-client.d.ts.map +1 -0
  57. package/dist/lib/enhancement-client.js +129 -0
  58. package/dist/lib/enhancement-client.js.map +1 -0
  59. package/dist/lib/hybrid-rendering.d.ts +52 -0
  60. package/dist/lib/hybrid-rendering.d.ts.map +1 -0
  61. package/dist/lib/hybrid-rendering.js +161 -0
  62. package/dist/lib/hybrid-rendering.js.map +1 -0
  63. package/dist/lib/logger.d.ts +7 -0
  64. package/dist/lib/logger.d.ts.map +1 -0
  65. package/dist/lib/logger.js +19 -0
  66. package/dist/lib/logger.js.map +1 -0
  67. package/dist/lib/tts.d.ts +12 -0
  68. package/dist/lib/tts.d.ts.map +1 -1
  69. package/dist/lib/tts.js +64 -28
  70. package/dist/lib/tts.js.map +1 -1
  71. package/package.json +1 -1
@@ -3,7 +3,7 @@ import { createServer } from "node:http";
3
3
  import { execFileSync } from "node:child_process";
4
4
  import { setToken } from "../../lib/credentials.js";
5
5
  const CLIENT_ID = "demofly-cli";
6
- const AUTH_BASE = "https://app.demofly.dev/oauth";
6
+ const AUTH_BASE = `${process.env.DEMOFLY_URL || "https://demofly.ai"}/oauth`;
7
7
  const LOGIN_TIMEOUT_MS = 120_000;
8
8
  function openBrowser(url) {
9
9
  const platform = process.platform;
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/commands/auth/login.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/commands/auth/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type Command } from "commander";
2
+ export declare function registerDeleteCommand(demos: Command): void;
3
+ //# sourceMappingURL=delete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../../src/commands/demos/delete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBzC,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAgC1D"}
@@ -0,0 +1,41 @@
1
+ import {} from "commander";
2
+ import { createInterface } from "node:readline";
3
+ import { createApiClient, requireAuth } from "../../lib/api-client.js";
4
+ function confirm(message) {
5
+ return new Promise((resolve) => {
6
+ const rl = createInterface({
7
+ input: process.stdin,
8
+ output: process.stdout,
9
+ });
10
+ rl.question(`${message} (y/N) `, (answer) => {
11
+ rl.close();
12
+ resolve(answer.trim().toLowerCase() === "y");
13
+ });
14
+ });
15
+ }
16
+ export function registerDeleteCommand(demos) {
17
+ demos
18
+ .command("delete <name>")
19
+ .description("Delete a demo")
20
+ .option("-f, --force", "Skip confirmation prompt")
21
+ .action(async (name, opts) => {
22
+ const token = await requireAuth();
23
+ if (!opts.force) {
24
+ const confirmed = await confirm(`Are you sure you want to delete demo '${name}'?`);
25
+ if (!confirmed) {
26
+ console.log("Cancelled.");
27
+ return;
28
+ }
29
+ }
30
+ const client = createApiClient(token);
31
+ try {
32
+ await client.delete(`/demos/${encodeURIComponent(name)}`);
33
+ console.log(`Deleted demo '${name}'.`);
34
+ }
35
+ catch (error) {
36
+ console.error(`Failed to delete demo: ${error instanceof Error ? error.message : String(error)}`);
37
+ process.exit(1);
38
+ }
39
+ });
40
+ }
41
+ //# sourceMappingURL=delete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.js","sourceRoot":"","sources":["../../../src/commands/demos/delete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEvE,SAAS,OAAO,CAAC,OAAe;IAC9B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,EAAE,GAAG,eAAe,CAAC;YACzB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QAEH,EAAE,CAAC,QAAQ,CAAC,GAAG,OAAO,SAAS,EAAE,CAAC,MAAM,EAAE,EAAE;YAC1C,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAc;IAClD,KAAK;SACF,OAAO,CAAC,eAAe,CAAC;SACxB,WAAW,CAAC,eAAe,CAAC;SAC5B,MAAM,CAAC,aAAa,EAAE,0BAA0B,CAAC;SACjD,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,IAAyB,EAAE,EAAE;QACxD,MAAM,KAAK,GAAG,MAAM,WAAW,EAAE,CAAC;QAElC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAChB,MAAM,SAAS,GAAG,MAAM,OAAO,CAC7B,yCAAyC,IAAI,IAAI,CAClD,CAAC;YACF,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;gBAC1B,OAAO;YACT,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QAEtC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,MAAM,CACjB,UAAU,kBAAkB,CAAC,IAAI,CAAC,EAAE,CACrC,CAAC;YACF,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,IAAI,CAAC,CAAC;QACzC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CACX,0BAA0B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACnF,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type Command } from "commander";
2
+ export declare function registerGetCommand(demos: Command): void;
3
+ //# sourceMappingURL=get.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get.d.ts","sourceRoot":"","sources":["../../../src/commands/demos/get.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAYzC,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAgCvD"}
@@ -0,0 +1,30 @@
1
+ import {} from "commander";
2
+ import { createApiClient, requireAuth } from "../../lib/api-client.js";
3
+ export function registerGetCommand(demos) {
4
+ demos
5
+ .command("get <name>")
6
+ .description("Get details of a demo")
7
+ .action(async (name) => {
8
+ const token = await requireAuth();
9
+ const client = createApiClient(token);
10
+ try {
11
+ const demo = await client.get(`/demos/${encodeURIComponent(name)}`);
12
+ console.log(`Name: ${demo.name}`);
13
+ console.log(`Status: ${demo.status}`);
14
+ console.log(`Created: ${demo.created}`);
15
+ console.log(`Updated: ${demo.updated}`);
16
+ console.log(`URL: ${demo.url}`);
17
+ if (demo.exports && demo.exports.length > 0) {
18
+ console.log(`Exports:`);
19
+ for (const exp of demo.exports) {
20
+ console.log(` - ${exp}`);
21
+ }
22
+ }
23
+ }
24
+ catch (error) {
25
+ console.error(`Demo '${name}' not found. ${error instanceof Error ? error.message : String(error)}`);
26
+ process.exit(1);
27
+ }
28
+ });
29
+ }
30
+ //# sourceMappingURL=get.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get.js","sourceRoot":"","sources":["../../../src/commands/demos/get.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAWvE,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,KAAK;SACF,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,CAAC,uBAAuB,CAAC;SACpC,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,MAAM,WAAW,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QAEtC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAC3B,UAAU,kBAAkB,CAAC,IAAI,CAAC,EAAE,CACrC,CAAC;YAEF,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YACzC,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;YAC1C,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;YAC1C,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;YAEtC,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC5C,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;gBACxB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;oBAC/B,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;gBAC5B,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CACX,SAAS,IAAI,gBAAgB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACtF,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type Command } from "commander";
2
+ export declare function registerDemosCommands(program: Command): void;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/demos/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAOzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAU5D"}
@@ -0,0 +1,17 @@
1
+ import {} from "commander";
2
+ import { registerListCommand } from "./list.js";
3
+ import { registerGetCommand } from "./get.js";
4
+ import { registerUpdateCommand } from "./update.js";
5
+ import { registerDeleteCommand } from "./delete.js";
6
+ import { registerOpenCommand } from "./open.js";
7
+ export function registerDemosCommands(program) {
8
+ const demos = program
9
+ .command("demos")
10
+ .description("List and manage demofly demos");
11
+ registerListCommand(demos);
12
+ registerGetCommand(demos);
13
+ registerUpdateCommand(demos);
14
+ registerDeleteCommand(demos);
15
+ registerOpenCommand(demos);
16
+ }
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/demos/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAEhD,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,MAAM,KAAK,GAAG,OAAO;SAClB,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,+BAA+B,CAAC,CAAC;IAEhD,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAC3B,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC1B,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAC7B,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAC7B,mBAAmB,CAAC,KAAK,CAAC,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type Command } from "commander";
2
+ export declare function registerListCommand(demos: Command): void;
3
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/demos/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAyHzC,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CA6BxD"}
@@ -0,0 +1,117 @@
1
+ import {} from "commander";
2
+ import { createApiClient } from "../../lib/api-client.js";
3
+ import { getToken } from "../../lib/credentials.js";
4
+ import { scanLocalDemos } from "../../lib/demo-scanner.js";
5
+ import { debug } from "../../lib/logger.js";
6
+ function formatDuration(ms) {
7
+ const totalSeconds = Math.floor(ms / 1000);
8
+ const minutes = Math.floor(totalSeconds / 60);
9
+ const seconds = totalSeconds % 60;
10
+ if (minutes > 0)
11
+ return `${minutes}m ${seconds}s`;
12
+ return `${seconds}s`;
13
+ }
14
+ async function fetchCloudDemos(token) {
15
+ try {
16
+ const client = createApiClient(token);
17
+ return await client.get("/demos");
18
+ }
19
+ catch {
20
+ return [];
21
+ }
22
+ }
23
+ function mergeResults(local, cloud) {
24
+ const merged = new Map();
25
+ for (const demo of local) {
26
+ merged.set(demo.name, {
27
+ name: demo.name,
28
+ phase: demo.phase,
29
+ cloud: cloud ? "\u2014" : "",
30
+ duration: demo.durationMs ? formatDuration(demo.durationMs) : "\u2014",
31
+ });
32
+ }
33
+ if (cloud) {
34
+ const cloudNames = new Set(cloud.map((c) => c.name));
35
+ for (const demo of local) {
36
+ if (cloudNames.has(demo.name)) {
37
+ merged.get(demo.name).cloud = "synced";
38
+ }
39
+ }
40
+ for (const c of cloud) {
41
+ if (!merged.has(c.name)) {
42
+ merged.set(c.name, {
43
+ name: c.name,
44
+ phase: "\u2014",
45
+ cloud: "cloud",
46
+ duration: "\u2014",
47
+ });
48
+ }
49
+ }
50
+ }
51
+ return [...merged.values()].sort((a, b) => a.name.localeCompare(b.name));
52
+ }
53
+ function printTable(demos, hasCloud) {
54
+ const columns = hasCloud
55
+ ? ["name", "phase", "cloud", "duration"]
56
+ : ["name", "phase", "duration"];
57
+ const headers = {
58
+ name: "DEMO",
59
+ phase: "PHASE",
60
+ cloud: "CLOUD",
61
+ duration: "DURATION",
62
+ };
63
+ const widths = {};
64
+ for (const col of columns) {
65
+ widths[col] = Math.max(headers[col].length, ...demos.map((d) => d[col].length));
66
+ }
67
+ const header = columns.map((c) => headers[c].padEnd(widths[c])).join(" ");
68
+ console.log(header);
69
+ console.log(columns.map((c) => "\u2014".repeat(widths[c])).join(" "));
70
+ for (const demo of demos) {
71
+ const row = columns.map((c) => demo[c].padEnd(widths[c])).join(" ");
72
+ console.log(row);
73
+ }
74
+ }
75
+ function printSummary(demos, hasCloud) {
76
+ const total = demos.length;
77
+ if (!hasCloud) {
78
+ console.log(`\n${total} demo${total === 1 ? "" : "s"}`);
79
+ return;
80
+ }
81
+ const synced = demos.filter((d) => d.cloud === "synced").length;
82
+ const cloudOnly = demos.filter((d) => d.cloud === "cloud").length;
83
+ const parts = [`${total} demo${total === 1 ? "" : "s"}`];
84
+ if (synced > 0)
85
+ parts.push(`${synced} synced`);
86
+ if (cloudOnly > 0)
87
+ parts.push(`${cloudOnly} cloud-only`);
88
+ console.log(`\n${parts.join(", ")}`);
89
+ }
90
+ export function registerListCommand(demos) {
91
+ demos
92
+ .command("list")
93
+ .description("List demos (local and cloud)")
94
+ .action(async () => {
95
+ const localDemos = scanLocalDemos(process.cwd());
96
+ debug(`Local scan: ${localDemos.length} demo(s) found`);
97
+ const token = await getToken();
98
+ let cloudDemos = null;
99
+ if (token) {
100
+ debug("Fetching cloud demos");
101
+ cloudDemos = await fetchCloudDemos(token);
102
+ debug(`Cloud fetch: ${cloudDemos.length} demo(s) found`);
103
+ }
104
+ else {
105
+ debug("No auth token, skipping cloud fetch");
106
+ }
107
+ const merged = mergeResults(localDemos, cloudDemos);
108
+ if (merged.length === 0) {
109
+ console.log("No demos found. Create one with: demofly init");
110
+ return;
111
+ }
112
+ const hasCloud = cloudDemos !== null;
113
+ printTable(merged, hasCloud);
114
+ printSummary(merged, hasCloud);
115
+ });
116
+ }
117
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/demos/list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type Command } from "commander";
2
+ export declare function registerOpenCommand(demos: Command): void;
3
+ //# sourceMappingURL=open.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open.d.ts","sourceRoot":"","sources":["../../../src/commands/demos/open.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAgCzC,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAsBxD"}
@@ -0,0 +1,45 @@
1
+ import {} from "commander";
2
+ import { execFile } from "node:child_process";
3
+ import { createApiClient, requireAuth } from "../../lib/api-client.js";
4
+ function openUrl(url) {
5
+ const platform = process.platform;
6
+ let cmd;
7
+ let args;
8
+ if (platform === "darwin") {
9
+ cmd = "open";
10
+ args = [url];
11
+ }
12
+ else if (platform === "win32") {
13
+ cmd = "cmd";
14
+ args = ["/c", "start", "", url];
15
+ }
16
+ else {
17
+ cmd = "xdg-open";
18
+ args = [url];
19
+ }
20
+ execFile(cmd, args, (error) => {
21
+ if (error) {
22
+ console.error(`Failed to open browser: ${error.message}`);
23
+ console.log(`Open manually: ${url}`);
24
+ }
25
+ });
26
+ }
27
+ export function registerOpenCommand(demos) {
28
+ demos
29
+ .command("open <name>")
30
+ .description("Open a demo in the browser")
31
+ .action(async (name) => {
32
+ const token = await requireAuth();
33
+ const client = createApiClient(token);
34
+ try {
35
+ const demo = await client.get(`/demos/${encodeURIComponent(name)}`);
36
+ console.log(`Opening ${demo.url}`);
37
+ openUrl(demo.url);
38
+ }
39
+ catch (error) {
40
+ console.error(`Failed to open demo: ${error instanceof Error ? error.message : String(error)}`);
41
+ process.exit(1);
42
+ }
43
+ });
44
+ }
45
+ //# sourceMappingURL=open.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open.js","sourceRoot":"","sources":["../../../src/commands/demos/open.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAMvE,SAAS,OAAO,CAAC,GAAW;IAC1B,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAClC,IAAI,GAAW,CAAC;IAChB,IAAI,IAAc,CAAC;IAEnB,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,GAAG,GAAG,MAAM,CAAC;QACb,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACf,CAAC;SAAM,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QAChC,GAAG,GAAG,KAAK,CAAC;QACZ,IAAI,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;IAClC,CAAC;SAAM,CAAC;QACN,GAAG,GAAG,UAAU,CAAC;QACjB,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACf,CAAC;IAED,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE;QAC5B,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,KAAK,CAAC,2BAA2B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC1D,OAAO,CAAC,GAAG,CAAC,kBAAkB,GAAG,EAAE,CAAC,CAAC;QACvC,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,KAAK;SACF,OAAO,CAAC,aAAa,CAAC;SACtB,WAAW,CAAC,4BAA4B,CAAC;SACzC,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,MAAM,WAAW,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QAEtC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAC3B,UAAU,kBAAkB,CAAC,IAAI,CAAC,EAAE,CACrC,CAAC;YAEF,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;YACnC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CACX,wBAAwB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACjF,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type Command } from "commander";
2
+ export declare function registerUpdateCommand(demos: Command): void;
3
+ //# sourceMappingURL=update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../src/commands/demos/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAazC,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAuC1D"}
@@ -0,0 +1,31 @@
1
+ import {} from "commander";
2
+ import { createApiClient, requireAuth } from "../../lib/api-client.js";
3
+ export function registerUpdateCommand(demos) {
4
+ demos
5
+ .command("update <name>")
6
+ .description("Update a demo")
7
+ .option("--name <newName>", "New demo name")
8
+ .option("--description <description>", "New demo description")
9
+ .action(async (name, opts) => {
10
+ if (!opts.name && !opts.description) {
11
+ console.error("No updates specified. Use --name or --description.");
12
+ process.exit(1);
13
+ }
14
+ const token = await requireAuth();
15
+ const client = createApiClient(token);
16
+ const payload = {};
17
+ if (opts.name)
18
+ payload.name = opts.name;
19
+ if (opts.description)
20
+ payload.description = opts.description;
21
+ try {
22
+ const result = await client.put(`/demos/${encodeURIComponent(name)}`, payload);
23
+ console.log(`Updated demo '${result.name}'.`);
24
+ }
25
+ catch (error) {
26
+ console.error(`Failed to update demo: ${error instanceof Error ? error.message : String(error)}`);
27
+ process.exit(1);
28
+ }
29
+ });
30
+ }
31
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../../src/commands/demos/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAYvE,MAAM,UAAU,qBAAqB,CAAC,KAAc;IAClD,KAAK;SACF,OAAO,CAAC,eAAe,CAAC;SACxB,WAAW,CAAC,eAAe,CAAC;SAC5B,MAAM,CAAC,kBAAkB,EAAE,eAAe,CAAC;SAC3C,MAAM,CAAC,6BAA6B,EAAE,sBAAsB,CAAC;SAC7D,MAAM,CACL,KAAK,EACH,IAAY,EACZ,IAA6C,EAC7C,EAAE;QACF,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACpC,OAAO,CAAC,KAAK,CACX,oDAAoD,CACrD,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,WAAW,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QAEtC,MAAM,OAAO,GAAkB,EAAE,CAAC;QAClC,IAAI,IAAI,CAAC,IAAI;YAAE,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACxC,IAAI,IAAI,CAAC,WAAW;YAAE,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QAE7D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAC7B,UAAU,kBAAkB,CAAC,IAAI,CAAC,EAAE,EACpC,OAAO,CACR,CAAC;YACF,OAAO,CAAC,GAAG,CAAC,iBAAiB,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;QAChD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CACX,0BAA0B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACnF,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CACF,CAAC;AACN,CAAC"}
@@ -1,6 +1,12 @@
1
1
  import type { Command } from "commander";
2
2
  import type { TimingData } from "../lib/timing.js";
3
3
  export declare function splitScenes(videoPath: string, timingData: TimingData, recordingsDir: string): string[];
4
+ /**
5
+ * Mux audio files into per-scene video clips.
6
+ * Takes the split video.webm files and corresponding audio files,
7
+ * produces video clips with embedded audio tracks.
8
+ */
9
+ export declare function muxSceneAudio(timingData: TimingData, recordingsDir: string, audioDir: string): string[];
4
10
  export declare function extractThumbnails(videoPath: string, timingData: TimingData, recordingsDir: string): string[];
5
11
  export declare function registerGenerateCommand(program: Command): void;
6
12
  //# sourceMappingURL=generate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/commands/generate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAazC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AA6NnD,wBAAgB,WAAW,CACzB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,UAAU,EACtB,aAAa,EAAE,MAAM,GACpB,MAAM,EAAE,CA4BV;AAED,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,UAAU,EACtB,aAAa,EAAE,MAAM,GACpB,MAAM,EAAE,CA6BV;AA0ED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuL9D"}
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/commands/generate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAazC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AA+NnD,wBAAgB,WAAW,CACzB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,UAAU,EACtB,aAAa,EAAE,MAAM,GACpB,MAAM,EAAE,CA4BV;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE,UAAU,EACtB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GACf,MAAM,EAAE,CA0CV;AAED,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,UAAU,EACtB,aAAa,EAAE,MAAM,GACpB,MAAM,EAAE,CA6BV;AA0ED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAkM9D"}
@@ -2,32 +2,34 @@ import { execSync } from "node:child_process";
2
2
  import { existsSync, mkdirSync, readdirSync, writeFileSync, readFileSync, copyFileSync, } from "node:fs";
3
3
  import { resolve, basename, extname } from "node:path";
4
4
  import * as readline from "node:readline";
5
- import { parseTimingMarkers } from "../lib/timing.js";
6
- function validateProjectArtifacts(projectDir, project) {
7
- const specPath = resolve(projectDir, "demo.spec.ts");
8
- const configPath = resolve(projectDir, "playwright.config.ts");
5
+ import { parseTimingMarkers, normalizeTimingData } from "../lib/timing.js";
6
+ import { debug } from "../lib/logger.js";
7
+ function validateDemoArtifacts(demoDir, demo) {
8
+ const specPath = resolve(demoDir, "demo.spec.ts");
9
+ const configPath = resolve(demoDir, "playwright.config.ts");
9
10
  let valid = true;
10
11
  if (!existsSync(specPath)) {
11
- console.error(`No demo.spec.ts found in demofly/${project}/. Create one with /demofly:create ${project} in Claude Code.`);
12
+ console.error(`No demo.spec.ts found in demofly/${demo}/. Create one with /demofly:create ${demo} in Claude Code.`);
12
13
  valid = false;
13
14
  }
14
15
  if (!existsSync(configPath)) {
15
- console.error(`No playwright.config.ts found in demofly/${project}/. Create one with /demofly:create ${project} in Claude Code.`);
16
+ console.error(`No playwright.config.ts found in demofly/${demo}/. Create one with /demofly:create ${demo} in Claude Code.`);
16
17
  valid = false;
17
18
  }
18
19
  return valid;
19
20
  }
20
- function runPlaywrightTest(projectDir, project) {
21
- const specPath = `demofly/${project}/demo.spec.ts`;
22
- const configPath = `demofly/${project}/playwright.config.ts`;
21
+ function runPlaywrightTest(demoDir, demo) {
22
+ const specPath = `demofly/${demo}/demo.spec.ts`;
23
+ const configPath = `demofly/${demo}/playwright.config.ts`;
23
24
  const cmd = `npx playwright test ${specPath} --config ${configPath}`;
25
+ debug(`Playwright command: ${cmd}`);
24
26
  console.log(`Running: ${cmd}\n`);
25
27
  try {
26
28
  const output = execSync(cmd, {
27
29
  encoding: "utf-8",
28
30
  timeout: 600_000,
29
31
  stdio: ["pipe", "pipe", "pipe"],
30
- cwd: resolve(projectDir, "..", ".."),
32
+ cwd: resolve(demoDir, "..", ".."),
31
33
  });
32
34
  return output;
33
35
  }
@@ -45,8 +47,8 @@ function runPlaywrightTest(projectDir, project) {
45
47
  process.exit(1);
46
48
  }
47
49
  }
48
- function ensureRecordingsDir(projectDir) {
49
- const recordingsDir = resolve(projectDir, "recordings");
50
+ function ensureRecordingsDir(demoDir) {
51
+ const recordingsDir = resolve(demoDir, "recordings");
50
52
  if (!existsSync(recordingsDir)) {
51
53
  mkdirSync(recordingsDir, { recursive: true });
52
54
  }
@@ -57,8 +59,8 @@ function writeTimingJson(recordingsDir, timingData) {
57
59
  writeFileSync(timingPath, JSON.stringify(timingData, null, 2), "utf-8");
58
60
  return timingPath;
59
61
  }
60
- function findRecordedVideo(projectDir) {
61
- const testResultsDir = resolve(projectDir, "..", "..", "test-results");
62
+ function findRecordedVideo(demoDir) {
63
+ const testResultsDir = resolve(demoDir, "..", "..", "test-results");
62
64
  if (!existsSync(testResultsDir)) {
63
65
  return null;
64
66
  }
@@ -80,8 +82,8 @@ function findVideoRecursive(dir) {
80
82
  }
81
83
  return null;
82
84
  }
83
- function findAudioFiles(projectDir, timingData) {
84
- const audioDir = resolve(projectDir, "audio");
85
+ function findAudioFiles(demoDir, timingData) {
86
+ const audioDir = resolve(demoDir, "audio");
85
87
  if (!existsSync(audioDir)) {
86
88
  return { matched: [], missing: [] };
87
89
  }
@@ -193,6 +195,50 @@ export function splitScenes(videoPath, timingData, recordingsDir) {
193
195
  }
194
196
  return outputs;
195
197
  }
198
+ /**
199
+ * Mux audio files into per-scene video clips.
200
+ * Takes the split video.webm files and corresponding audio files,
201
+ * produces video clips with embedded audio tracks.
202
+ */
203
+ export function muxSceneAudio(timingData, recordingsDir, audioDir) {
204
+ const scenesDir = resolve(recordingsDir, "scenes");
205
+ const outputs = [];
206
+ for (const scene of timingData.scenes) {
207
+ const sceneDir = resolve(scenesDir, scene.sceneId);
208
+ const videoPath = resolve(sceneDir, "video.webm");
209
+ if (!existsSync(videoPath))
210
+ continue;
211
+ // Find matching audio file (try .wav then .mp3)
212
+ const audioWav = resolve(audioDir, `${scene.sceneId}.wav`);
213
+ const audioMp3 = resolve(audioDir, `${scene.sceneId}.mp3`);
214
+ const audioPath = existsSync(audioWav) ? audioWav : existsSync(audioMp3) ? audioMp3 : null;
215
+ if (!audioPath)
216
+ continue;
217
+ const muxedPath = resolve(sceneDir, "video-muxed.webm");
218
+ try {
219
+ execSync(`ffmpeg -y -i "${videoPath}" -i "${audioPath}" -c:v copy -c:a libopus -shortest "${muxedPath}"`, { encoding: "utf-8", timeout: 300_000, stdio: ["pipe", "pipe", "pipe"] });
220
+ // Replace the original with the muxed version
221
+ execSync(`mv "${muxedPath}" "${videoPath}"`, {
222
+ encoding: "utf-8",
223
+ stdio: ["pipe", "pipe", "pipe"],
224
+ });
225
+ outputs.push(videoPath);
226
+ }
227
+ catch (error) {
228
+ const execError = error;
229
+ console.warn(`Warning: Failed to mux audio for ${scene.sceneId}:`);
230
+ if (execError.stderr) {
231
+ console.warn(execError.stderr);
232
+ }
233
+ // Clean up partial file
234
+ try {
235
+ execSync(`rm -f "${muxedPath}"`, { stdio: "pipe" });
236
+ }
237
+ catch { }
238
+ }
239
+ }
240
+ return outputs;
241
+ }
196
242
  export function extractThumbnails(videoPath, timingData, recordingsDir) {
197
243
  const scenesDir = resolve(recordingsDir, "scenes");
198
244
  const outputs = [];
@@ -289,8 +335,9 @@ export function registerGenerateCommand(program) {
289
335
  process.exit(1);
290
336
  }
291
337
  const projectDir = resolve(process.cwd(), "demofly", project);
338
+ debug(`Resolved demo directory: ${projectDir}`);
292
339
  // Step 1: Validate artifacts exist
293
- if (!validateProjectArtifacts(projectDir, project)) {
340
+ if (!validateDemoArtifacts(projectDir, project)) {
294
341
  process.exit(1);
295
342
  }
296
343
  const recordingsDir = ensureRecordingsDir(projectDir);
@@ -299,6 +346,7 @@ export function registerGenerateCommand(program) {
299
346
  let timingPath;
300
347
  // Step 2: Record or use existing artifacts
301
348
  if (opts.record) {
349
+ debug("Recording mode: running Playwright test");
302
350
  const result = recordDemo(projectDir, project);
303
351
  videoPath = result.videoPath
304
352
  ? resolve(recordingsDir, "video.webm")
@@ -354,7 +402,7 @@ export function registerGenerateCommand(program) {
354
402
  // If we didn't record (existing artifacts found), load from disk
355
403
  if (!videoPath) {
356
404
  videoPath = existingVideo;
357
- timingData = JSON.parse(readFileSync(existingTiming, "utf-8"));
405
+ timingData = normalizeTimingData(JSON.parse(readFileSync(existingTiming, "utf-8")));
358
406
  timingPath = existingTiming;
359
407
  }
360
408
  else {
@@ -365,6 +413,7 @@ export function registerGenerateCommand(program) {
365
413
  }
366
414
  // Step 3: Find audio files and check ffmpeg
367
415
  const { matched, missing } = findAudioFiles(projectDir, timingData);
416
+ debug(`Audio files: ${matched.length} matched, ${missing.length} missing`);
368
417
  let finalPath = null;
369
418
  if (matched.length > 0) {
370
419
  if (!hasFfmpeg()) {
@@ -402,7 +451,7 @@ export function registerGenerateCommand(program) {
402
451
  finalPath = outputPath;
403
452
  }
404
453
  }
405
- else {
454
+ else if (!videoPath) {
406
455
  console.warn("Warning: No recorded video found. Skipping assembly.");
407
456
  }
408
457
  // Step 4: Split scenes and extract thumbnails
@@ -410,6 +459,13 @@ export function registerGenerateCommand(program) {
410
459
  console.log("Splitting video into per-scene clips...\n");
411
460
  const sceneClips = splitScenes(videoPath, timingData, recordingsDir);
412
461
  console.log(` Split ${sceneClips.length} scene clip(s)`);
462
+ // Mux audio into scene clips
463
+ const audioDir = resolve(projectDir, "audio");
464
+ if (existsSync(audioDir)) {
465
+ console.log("Muxing audio into scene clips...\n");
466
+ const muxed = muxSceneAudio(timingData, recordingsDir, audioDir);
467
+ console.log(` Muxed audio into ${muxed.length} clip(s)`);
468
+ }
413
469
  console.log("Extracting thumbnails...\n");
414
470
  const thumbnails = extractThumbnails(videoPath, timingData, recordingsDir);
415
471
  console.log(` Extracted ${thumbnails.length} thumbnail(s)\n`);