demofly 0.1.3 → 0.1.4
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/dist/commands/auth/login.js +1 -1
- package/dist/commands/auth/login.js.map +1 -1
- package/dist/commands/demos/delete.d.ts +3 -0
- package/dist/commands/demos/delete.d.ts.map +1 -0
- package/dist/commands/demos/delete.js +41 -0
- package/dist/commands/demos/delete.js.map +1 -0
- package/dist/commands/demos/get.d.ts +3 -0
- package/dist/commands/demos/get.d.ts.map +1 -0
- package/dist/commands/demos/get.js +30 -0
- package/dist/commands/demos/get.js.map +1 -0
- package/dist/commands/demos/index.d.ts +3 -0
- package/dist/commands/demos/index.d.ts.map +1 -0
- package/dist/commands/demos/index.js +17 -0
- package/dist/commands/demos/index.js.map +1 -0
- package/dist/commands/demos/list.d.ts +3 -0
- package/dist/commands/demos/list.d.ts.map +1 -0
- package/dist/commands/demos/list.js +117 -0
- package/dist/commands/demos/list.js.map +1 -0
- package/dist/commands/demos/open.d.ts +3 -0
- package/dist/commands/demos/open.d.ts.map +1 -0
- package/dist/commands/demos/open.js +45 -0
- package/dist/commands/demos/open.js.map +1 -0
- package/dist/commands/demos/update.d.ts +3 -0
- package/dist/commands/demos/update.d.ts.map +1 -0
- package/dist/commands/demos/update.js +31 -0
- package/dist/commands/demos/update.js.map +1 -0
- package/dist/commands/generate.d.ts +6 -0
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +73 -17
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/push.d.ts.map +1 -1
- package/dist/commands/push.js +12 -9
- package/dist/commands/push.js.map +1 -1
- package/dist/commands/render.d.ts +11 -0
- package/dist/commands/render.d.ts.map +1 -0
- package/dist/commands/render.js +161 -0
- package/dist/commands/render.js.map +1 -0
- package/dist/index.js +10 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/api-client.d.ts +2 -1
- package/dist/lib/api-client.d.ts.map +1 -1
- package/dist/lib/api-client.js +22 -10
- package/dist/lib/api-client.js.map +1 -1
- package/dist/lib/audio-stitching.d.ts +64 -0
- package/dist/lib/audio-stitching.d.ts.map +1 -0
- package/dist/lib/audio-stitching.js +260 -0
- package/dist/lib/audio-stitching.js.map +1 -0
- package/dist/lib/credentials.d.ts.map +1 -1
- package/dist/lib/credentials.js +2 -0
- package/dist/lib/credentials.js.map +1 -1
- package/dist/lib/demo-scanner.d.ts +17 -0
- package/dist/lib/demo-scanner.d.ts.map +1 -0
- package/dist/lib/demo-scanner.js +70 -0
- package/dist/lib/demo-scanner.js.map +1 -0
- package/dist/lib/enhancement-client.d.ts +17 -0
- package/dist/lib/enhancement-client.d.ts.map +1 -0
- package/dist/lib/enhancement-client.js +129 -0
- package/dist/lib/enhancement-client.js.map +1 -0
- package/dist/lib/hybrid-rendering.d.ts +52 -0
- package/dist/lib/hybrid-rendering.d.ts.map +1 -0
- package/dist/lib/hybrid-rendering.js +161 -0
- package/dist/lib/hybrid-rendering.js.map +1 -0
- package/dist/lib/logger.d.ts +7 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +19 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/tts.d.ts +12 -0
- package/dist/lib/tts.d.ts.map +1 -1
- package/dist/lib/tts.js +64 -28
- package/dist/lib/tts.js.map +1 -1
- 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://
|
|
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":"AAAA,OAAO,EAAgB,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,YAAY,EAA6C,MAAM,WAAW,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD,MAAM,SAAS,GAAG,aAAa,CAAC;AAChC,MAAM,SAAS,GAAG
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/commands/auth/login.ts"],"names":[],"mappings":"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"}
|
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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;
|
|
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"}
|
|
@@ -3,31 +3,33 @@ import { existsSync, mkdirSync, readdirSync, writeFileSync, readFileSync, copyFi
|
|
|
3
3
|
import { resolve, basename, extname } from "node:path";
|
|
4
4
|
import * as readline from "node:readline";
|
|
5
5
|
import { parseTimingMarkers } from "../lib/timing.js";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
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/${
|
|
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/${
|
|
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(
|
|
21
|
-
const specPath = `demofly/${
|
|
22
|
-
const configPath = `demofly/${
|
|
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(
|
|
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(
|
|
49
|
-
const recordingsDir = resolve(
|
|
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(
|
|
61
|
-
const testResultsDir = resolve(
|
|
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(
|
|
84
|
-
const audioDir = resolve(
|
|
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 (!
|
|
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")
|
|
@@ -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`);
|