@vibeo/renderer 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundler.d.ts +5 -0
- package/dist/bundler.d.ts.map +1 -1
- package/dist/bundler.js +167 -1
- package/dist/bundler.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/bundler.ts +195 -1
- package/src/index.ts +1 -1
package/dist/bundler.d.ts
CHANGED
|
@@ -7,4 +7,9 @@ import type { BundleResult } from "./types.js";
|
|
|
7
7
|
* and mounts it with ReactDOM.createRoot.
|
|
8
8
|
*/
|
|
9
9
|
export declare function bundle(entryPoint: string): Promise<BundleResult>;
|
|
10
|
+
/**
|
|
11
|
+
* Bundle the user's React entry point for the visual editor.
|
|
12
|
+
* Same pattern as bundle() but renders <Editor> instead of <Player>.
|
|
13
|
+
*/
|
|
14
|
+
export declare function bundleForEditor(entryPoint: string, port?: number): Promise<BundleResult>;
|
|
10
15
|
//# sourceMappingURL=bundler.d.ts.map
|
package/dist/bundler.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundler.d.ts","sourceRoot":"","sources":["../src/bundler.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"bundler.d.ts","sourceRoot":"","sources":["../src/bundler.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AA0D/C;;;;;;GAMG;AACH,wBAAsB,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAyItE;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,MAAa,GAClB,OAAO,CAAC,YAAY,CAAC,CA6HvB"}
|
package/dist/bundler.js
CHANGED
|
@@ -1,6 +1,54 @@
|
|
|
1
1
|
import { mkdtemp, rm } from "node:fs/promises";
|
|
2
|
-
import { join, dirname } from "node:path";
|
|
2
|
+
import { join, dirname, resolve } from "node:path";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
|
+
import { existsSync } from "node:fs";
|
|
5
|
+
/**
|
|
6
|
+
* Find the monorepo root by walking up from the entry file until we find
|
|
7
|
+
* the packages/ directory. Returns null if not found.
|
|
8
|
+
*/
|
|
9
|
+
function findMonorepoRoot(startDir) {
|
|
10
|
+
let dir = startDir;
|
|
11
|
+
for (let i = 0; i < 10; i++) {
|
|
12
|
+
if (existsSync(join(dir, "packages", "core", "src", "index.ts"))) {
|
|
13
|
+
return dir;
|
|
14
|
+
}
|
|
15
|
+
const parent = dirname(dir);
|
|
16
|
+
if (parent === dir)
|
|
17
|
+
break;
|
|
18
|
+
dir = parent;
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Bun.build plugin that resolves all @vibeo/* bare-specifier imports to
|
|
24
|
+
* their source .ts/.tsx files. This prevents the bundler from pulling in
|
|
25
|
+
* BOTH the compiled dist/ AND the source for the same package, which
|
|
26
|
+
* would duplicate React contexts and break provider/consumer pairing.
|
|
27
|
+
*/
|
|
28
|
+
function vibeoSourcePlugin(monoRoot) {
|
|
29
|
+
const pkgMap = {};
|
|
30
|
+
for (const name of [
|
|
31
|
+
"core",
|
|
32
|
+
"player",
|
|
33
|
+
"audio",
|
|
34
|
+
"effects",
|
|
35
|
+
"extras",
|
|
36
|
+
"editor",
|
|
37
|
+
]) {
|
|
38
|
+
pkgMap[`@vibeo/${name}`] = resolve(monoRoot, "packages", name, "src", "index.ts");
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
name: "vibeo-source-resolver",
|
|
42
|
+
setup(build) {
|
|
43
|
+
build.onResolve({ filter: /^@vibeo\// }, (args) => {
|
|
44
|
+
const src = pkgMap[args.path];
|
|
45
|
+
if (src)
|
|
46
|
+
return { path: src };
|
|
47
|
+
return undefined;
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
4
52
|
/**
|
|
5
53
|
* Bundle the user's React entry point using Bun.build,
|
|
6
54
|
* then serve it via a local HTTP server for the headless browser to load.
|
|
@@ -71,6 +119,8 @@ root.render(React.createElement(PreviewApp));
|
|
|
71
119
|
window.vibeo_ready = true;
|
|
72
120
|
`);
|
|
73
121
|
try {
|
|
122
|
+
const monoRoot = findMonorepoRoot(entryDir);
|
|
123
|
+
const plugins = monoRoot ? [vibeoSourcePlugin(monoRoot)] : [];
|
|
74
124
|
const result = await Bun.build({
|
|
75
125
|
entrypoints: [bootstrapPath],
|
|
76
126
|
outdir: outDir,
|
|
@@ -78,6 +128,7 @@ window.vibeo_ready = true;
|
|
|
78
128
|
format: "esm",
|
|
79
129
|
minify: false,
|
|
80
130
|
splitting: false,
|
|
131
|
+
plugins,
|
|
81
132
|
define: {
|
|
82
133
|
"process.env.NODE_ENV": JSON.stringify("production"),
|
|
83
134
|
},
|
|
@@ -132,4 +183,119 @@ window.vibeo_ready = true;
|
|
|
132
183
|
await rm(bootstrapPath, { force: true });
|
|
133
184
|
}
|
|
134
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* Bundle the user's React entry point for the visual editor.
|
|
188
|
+
* Same pattern as bundle() but renders <Editor> instead of <Player>.
|
|
189
|
+
*/
|
|
190
|
+
export async function bundleForEditor(entryPoint, port = 3001) {
|
|
191
|
+
const outDir = await mkdtemp(join(tmpdir(), "vibeo-editor-bundle-"));
|
|
192
|
+
const entryDir = dirname(entryPoint);
|
|
193
|
+
const bootstrapPath = join(entryDir, "__vibeo_editor_entry.tsx");
|
|
194
|
+
await Bun.write(bootstrapPath, `import React from "react";
|
|
195
|
+
import { createRoot } from "react-dom/client";
|
|
196
|
+
import { Root } from ${JSON.stringify(entryPoint)};
|
|
197
|
+
import { Editor } from "@vibeo/editor";
|
|
198
|
+
import { VibeoRoot, useCompositionContext } from "@vibeo/core";
|
|
199
|
+
|
|
200
|
+
function EditorShell() {
|
|
201
|
+
const { compositions } = useCompositionContext();
|
|
202
|
+
|
|
203
|
+
const entries = [];
|
|
204
|
+
for (const [, comp] of compositions) {
|
|
205
|
+
entries.push({
|
|
206
|
+
id: comp.id,
|
|
207
|
+
name: comp.id,
|
|
208
|
+
component: comp.component,
|
|
209
|
+
width: comp.width,
|
|
210
|
+
height: comp.height,
|
|
211
|
+
fps: comp.fps,
|
|
212
|
+
durationInFrames: comp.durationInFrames,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (entries.length === 0) {
|
|
217
|
+
return React.createElement("div", {
|
|
218
|
+
style: { color: "#888", fontFamily: "sans-serif", padding: 40 }
|
|
219
|
+
}, "Loading compositions...");
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return React.createElement(Editor, { compositions: entries });
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function EditorApp() {
|
|
226
|
+
return React.createElement(VibeoRoot, null,
|
|
227
|
+
React.createElement(Root),
|
|
228
|
+
React.createElement(EditorShell),
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const container = document.getElementById("root");
|
|
233
|
+
const root = createRoot(container);
|
|
234
|
+
root.render(React.createElement(EditorApp));
|
|
235
|
+
|
|
236
|
+
window.vibeo_ready = true;
|
|
237
|
+
`);
|
|
238
|
+
try {
|
|
239
|
+
const monoRoot = findMonorepoRoot(entryDir);
|
|
240
|
+
const plugins = monoRoot ? [vibeoSourcePlugin(monoRoot)] : [];
|
|
241
|
+
const result = await Bun.build({
|
|
242
|
+
entrypoints: [bootstrapPath],
|
|
243
|
+
outdir: outDir,
|
|
244
|
+
target: "browser",
|
|
245
|
+
format: "esm",
|
|
246
|
+
minify: false,
|
|
247
|
+
splitting: false,
|
|
248
|
+
plugins,
|
|
249
|
+
define: {
|
|
250
|
+
"process.env.NODE_ENV": JSON.stringify("production"),
|
|
251
|
+
},
|
|
252
|
+
});
|
|
253
|
+
if (!result.success) {
|
|
254
|
+
const messages = result.logs.map((l) => l.message).join("\n");
|
|
255
|
+
throw new Error(`Editor bundle failed:\n${messages}`);
|
|
256
|
+
}
|
|
257
|
+
const bundleName = result.outputs[0]?.path.split("/").pop() ?? "__vibeo_editor_entry.js";
|
|
258
|
+
const html = `<!DOCTYPE html>
|
|
259
|
+
<html>
|
|
260
|
+
<head>
|
|
261
|
+
<meta charset="utf-8" />
|
|
262
|
+
<title>Vibeo Editor</title>
|
|
263
|
+
<style>
|
|
264
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
265
|
+
html, body, #root { width: 100%; height: 100%; overflow: hidden; }
|
|
266
|
+
</style>
|
|
267
|
+
</head>
|
|
268
|
+
<body>
|
|
269
|
+
<div id="root"></div>
|
|
270
|
+
<script type="module" src="/${bundleName}"></script>
|
|
271
|
+
</body>
|
|
272
|
+
</html>`;
|
|
273
|
+
await Bun.write(join(outDir, "index.html"), html);
|
|
274
|
+
const server = Bun.serve({
|
|
275
|
+
port,
|
|
276
|
+
async fetch(req) {
|
|
277
|
+
const url = new URL(req.url);
|
|
278
|
+
const filePath = join(outDir, url.pathname === "/" ? "index.html" : url.pathname);
|
|
279
|
+
const file = Bun.file(filePath);
|
|
280
|
+
if (await file.exists()) {
|
|
281
|
+
return new Response(file);
|
|
282
|
+
}
|
|
283
|
+
return new Response("Not found", { status: 404 });
|
|
284
|
+
},
|
|
285
|
+
});
|
|
286
|
+
const serverPort = server.port ?? port;
|
|
287
|
+
const cleanup = async () => {
|
|
288
|
+
server.stop(true);
|
|
289
|
+
await rm(outDir, { recursive: true, force: true });
|
|
290
|
+
};
|
|
291
|
+
return {
|
|
292
|
+
outDir,
|
|
293
|
+
url: `http://localhost:${serverPort}`,
|
|
294
|
+
cleanup,
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
finally {
|
|
298
|
+
await rm(bootstrapPath, { force: true });
|
|
299
|
+
}
|
|
300
|
+
}
|
|
135
301
|
//# sourceMappingURL=bundler.js.map
|
package/dist/bundler.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundler.js","sourceRoot":"","sources":["../src/bundler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"bundler.js","sourceRoot":"","sources":["../src/bundler.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type { RenderConfig, RenderProgress, Codec, ImageFormat, FrameRange, StitchOptions, AudioMuxOptions, BundleResult, } from "./types.js";
|
|
2
2
|
export { launchBrowser, closeBrowser, createPage } from "./browser.js";
|
|
3
|
-
export { bundle } from "./bundler.js";
|
|
3
|
+
export { bundle, bundleForEditor } from "./bundler.js";
|
|
4
4
|
export { seekToFrame, loadBundle } from "./seek-to-frame.js";
|
|
5
5
|
export { captureFrame } from "./capture-frame.js";
|
|
6
6
|
export { parseFrameRange, getRealFrameRange, validateFrameRange } from "./frame-range.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,YAAY,EACZ,cAAc,EACd,KAAK,EACL,WAAW,EACX,UAAU,EACV,aAAa,EACb,eAAe,EACf,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAGvE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,YAAY,EACZ,cAAc,EACd,KAAK,EACL,WAAW,EACX,UAAU,EACV,aAAa,EACb,eAAe,EACf,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAGvE,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGvD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAG7D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAG1F,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Browser lifecycle
|
|
2
2
|
export { launchBrowser, closeBrowser, createPage } from "./browser.js";
|
|
3
3
|
// Bundler
|
|
4
|
-
export { bundle } from "./bundler.js";
|
|
4
|
+
export { bundle, bundleForEditor } from "./bundler.js";
|
|
5
5
|
// Frame navigation
|
|
6
6
|
export { seekToFrame, loadBundle } from "./seek-to-frame.js";
|
|
7
7
|
// Frame capture
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAYA,oBAAoB;AACpB,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEvE,UAAU;AACV,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAYA,oBAAoB;AACpB,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEvE,UAAU;AACV,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEvD,mBAAmB;AACnB,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAE7D,gBAAgB;AAChB,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,wBAAwB;AACxB,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE1F,mBAAmB;AACnB,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,qBAAqB;AACrB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,4BAA4B;AAC5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC"}
|
package/package.json
CHANGED
package/src/bundler.ts
CHANGED
|
@@ -1,8 +1,64 @@
|
|
|
1
1
|
import { mkdtemp, rm } from "node:fs/promises";
|
|
2
|
-
import { join, dirname } from "node:path";
|
|
2
|
+
import { join, dirname, resolve } from "node:path";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import type { BundleResult } from "./types.js";
|
|
5
5
|
|
|
6
|
+
import { existsSync } from "node:fs";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Find the monorepo root by walking up from the entry file until we find
|
|
10
|
+
* the packages/ directory. Returns null if not found.
|
|
11
|
+
*/
|
|
12
|
+
function findMonorepoRoot(startDir: string): string | null {
|
|
13
|
+
let dir = startDir;
|
|
14
|
+
for (let i = 0; i < 10; i++) {
|
|
15
|
+
if (existsSync(join(dir, "packages", "core", "src", "index.ts"))) {
|
|
16
|
+
return dir;
|
|
17
|
+
}
|
|
18
|
+
const parent = dirname(dir);
|
|
19
|
+
if (parent === dir) break;
|
|
20
|
+
dir = parent;
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Bun.build plugin that resolves all @vibeo/* bare-specifier imports to
|
|
27
|
+
* their source .ts/.tsx files. This prevents the bundler from pulling in
|
|
28
|
+
* BOTH the compiled dist/ AND the source for the same package, which
|
|
29
|
+
* would duplicate React contexts and break provider/consumer pairing.
|
|
30
|
+
*/
|
|
31
|
+
function vibeoSourcePlugin(monoRoot: string): import("bun").BunPlugin {
|
|
32
|
+
const pkgMap: Record<string, string> = {};
|
|
33
|
+
for (const name of [
|
|
34
|
+
"core",
|
|
35
|
+
"player",
|
|
36
|
+
"audio",
|
|
37
|
+
"effects",
|
|
38
|
+
"extras",
|
|
39
|
+
"editor",
|
|
40
|
+
]) {
|
|
41
|
+
pkgMap[`@vibeo/${name}`] = resolve(
|
|
42
|
+
monoRoot,
|
|
43
|
+
"packages",
|
|
44
|
+
name,
|
|
45
|
+
"src",
|
|
46
|
+
"index.ts",
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
name: "vibeo-source-resolver",
|
|
52
|
+
setup(build) {
|
|
53
|
+
build.onResolve({ filter: /^@vibeo\// }, (args) => {
|
|
54
|
+
const src = pkgMap[args.path];
|
|
55
|
+
if (src) return { path: src };
|
|
56
|
+
return undefined;
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
6
62
|
/**
|
|
7
63
|
* Bundle the user's React entry point using Bun.build,
|
|
8
64
|
* then serve it via a local HTTP server for the headless browser to load.
|
|
@@ -78,6 +134,9 @@ window.vibeo_ready = true;
|
|
|
78
134
|
);
|
|
79
135
|
|
|
80
136
|
try {
|
|
137
|
+
const monoRoot = findMonorepoRoot(entryDir);
|
|
138
|
+
const plugins = monoRoot ? [vibeoSourcePlugin(monoRoot)] : [];
|
|
139
|
+
|
|
81
140
|
const result = await Bun.build({
|
|
82
141
|
entrypoints: [bootstrapPath],
|
|
83
142
|
outdir: outDir,
|
|
@@ -85,6 +144,7 @@ window.vibeo_ready = true;
|
|
|
85
144
|
format: "esm",
|
|
86
145
|
minify: false,
|
|
87
146
|
splitting: false,
|
|
147
|
+
plugins,
|
|
88
148
|
define: {
|
|
89
149
|
"process.env.NODE_ENV": JSON.stringify("production"),
|
|
90
150
|
},
|
|
@@ -144,3 +204,137 @@ window.vibeo_ready = true;
|
|
|
144
204
|
await rm(bootstrapPath, { force: true });
|
|
145
205
|
}
|
|
146
206
|
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Bundle the user's React entry point for the visual editor.
|
|
210
|
+
* Same pattern as bundle() but renders <Editor> instead of <Player>.
|
|
211
|
+
*/
|
|
212
|
+
export async function bundleForEditor(
|
|
213
|
+
entryPoint: string,
|
|
214
|
+
port: number = 3001,
|
|
215
|
+
): Promise<BundleResult> {
|
|
216
|
+
const outDir = await mkdtemp(join(tmpdir(), "vibeo-editor-bundle-"));
|
|
217
|
+
|
|
218
|
+
const entryDir = dirname(entryPoint);
|
|
219
|
+
const bootstrapPath = join(entryDir, "__vibeo_editor_entry.tsx");
|
|
220
|
+
await Bun.write(
|
|
221
|
+
bootstrapPath,
|
|
222
|
+
`import React from "react";
|
|
223
|
+
import { createRoot } from "react-dom/client";
|
|
224
|
+
import { Root } from ${JSON.stringify(entryPoint)};
|
|
225
|
+
import { Editor } from "@vibeo/editor";
|
|
226
|
+
import { VibeoRoot, useCompositionContext } from "@vibeo/core";
|
|
227
|
+
|
|
228
|
+
function EditorShell() {
|
|
229
|
+
const { compositions } = useCompositionContext();
|
|
230
|
+
|
|
231
|
+
const entries = [];
|
|
232
|
+
for (const [, comp] of compositions) {
|
|
233
|
+
entries.push({
|
|
234
|
+
id: comp.id,
|
|
235
|
+
name: comp.id,
|
|
236
|
+
component: comp.component,
|
|
237
|
+
width: comp.width,
|
|
238
|
+
height: comp.height,
|
|
239
|
+
fps: comp.fps,
|
|
240
|
+
durationInFrames: comp.durationInFrames,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (entries.length === 0) {
|
|
245
|
+
return React.createElement("div", {
|
|
246
|
+
style: { color: "#888", fontFamily: "sans-serif", padding: 40 }
|
|
247
|
+
}, "Loading compositions...");
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return React.createElement(Editor, { compositions: entries });
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function EditorApp() {
|
|
254
|
+
return React.createElement(VibeoRoot, null,
|
|
255
|
+
React.createElement(Root),
|
|
256
|
+
React.createElement(EditorShell),
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const container = document.getElementById("root");
|
|
261
|
+
const root = createRoot(container);
|
|
262
|
+
root.render(React.createElement(EditorApp));
|
|
263
|
+
|
|
264
|
+
window.vibeo_ready = true;
|
|
265
|
+
`,
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
try {
|
|
269
|
+
const monoRoot = findMonorepoRoot(entryDir);
|
|
270
|
+
const plugins = monoRoot ? [vibeoSourcePlugin(monoRoot)] : [];
|
|
271
|
+
|
|
272
|
+
const result = await Bun.build({
|
|
273
|
+
entrypoints: [bootstrapPath],
|
|
274
|
+
outdir: outDir,
|
|
275
|
+
target: "browser",
|
|
276
|
+
format: "esm",
|
|
277
|
+
minify: false,
|
|
278
|
+
splitting: false,
|
|
279
|
+
plugins,
|
|
280
|
+
define: {
|
|
281
|
+
"process.env.NODE_ENV": JSON.stringify("production"),
|
|
282
|
+
},
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
if (!result.success) {
|
|
286
|
+
const messages = result.logs.map((l) => l.message).join("\n");
|
|
287
|
+
throw new Error(`Editor bundle failed:\n${messages}`);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const bundleName =
|
|
291
|
+
result.outputs[0]?.path.split("/").pop() ?? "__vibeo_editor_entry.js";
|
|
292
|
+
const html = `<!DOCTYPE html>
|
|
293
|
+
<html>
|
|
294
|
+
<head>
|
|
295
|
+
<meta charset="utf-8" />
|
|
296
|
+
<title>Vibeo Editor</title>
|
|
297
|
+
<style>
|
|
298
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
299
|
+
html, body, #root { width: 100%; height: 100%; overflow: hidden; }
|
|
300
|
+
</style>
|
|
301
|
+
</head>
|
|
302
|
+
<body>
|
|
303
|
+
<div id="root"></div>
|
|
304
|
+
<script type="module" src="/${bundleName}"></script>
|
|
305
|
+
</body>
|
|
306
|
+
</html>`;
|
|
307
|
+
|
|
308
|
+
await Bun.write(join(outDir, "index.html"), html);
|
|
309
|
+
|
|
310
|
+
const server = Bun.serve({
|
|
311
|
+
port,
|
|
312
|
+
async fetch(req) {
|
|
313
|
+
const url = new URL(req.url);
|
|
314
|
+
const filePath = join(
|
|
315
|
+
outDir,
|
|
316
|
+
url.pathname === "/" ? "index.html" : url.pathname,
|
|
317
|
+
);
|
|
318
|
+
const file = Bun.file(filePath);
|
|
319
|
+
if (await file.exists()) {
|
|
320
|
+
return new Response(file);
|
|
321
|
+
}
|
|
322
|
+
return new Response("Not found", { status: 404 });
|
|
323
|
+
},
|
|
324
|
+
});
|
|
325
|
+
const serverPort = server.port ?? port;
|
|
326
|
+
|
|
327
|
+
const cleanup = async () => {
|
|
328
|
+
server.stop(true);
|
|
329
|
+
await rm(outDir, { recursive: true, force: true });
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
return {
|
|
333
|
+
outDir,
|
|
334
|
+
url: `http://localhost:${serverPort}`,
|
|
335
|
+
cleanup,
|
|
336
|
+
};
|
|
337
|
+
} finally {
|
|
338
|
+
await rm(bootstrapPath, { force: true });
|
|
339
|
+
}
|
|
340
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -14,7 +14,7 @@ export type {
|
|
|
14
14
|
export { launchBrowser, closeBrowser, createPage } from "./browser.js";
|
|
15
15
|
|
|
16
16
|
// Bundler
|
|
17
|
-
export { bundle } from "./bundler.js";
|
|
17
|
+
export { bundle, bundleForEditor } from "./bundler.js";
|
|
18
18
|
|
|
19
19
|
// Frame navigation
|
|
20
20
|
export { seekToFrame, loadBundle } from "./seek-to-frame.js";
|