@vizhub/runtime 4.0.1 → 4.0.2

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/README.md CHANGED
@@ -337,6 +337,88 @@ npm install @vizhub/runtime
337
337
 
338
338
  ### Basic Usage
339
339
 
340
+ #### createRuntime(options)
341
+
342
+ Creates a runtime environment that manages code execution in an iframe with worker-based build support.
343
+
344
+ ```typescript
345
+ const runtime = createRuntime({
346
+ iframe: HTMLIFrameElement,
347
+ worker: Worker,
348
+ setBuildErrorMessage?: (error: string | null) => void,
349
+ getLatestContent?: (vizId: string) => Promise<VizContent | null>,
350
+ resolveSlugKey?: (slugKey: string) => Promise<string | null>,
351
+ writeFile?: (fileName: string, content: string) => void
352
+ });
353
+ ```
354
+
355
+ ##### Options
356
+
357
+ - **iframe**: `HTMLIFrameElement` - The iframe element where the viz will be rendered
358
+ - **worker**: `Worker` - Web Worker instance that handles code building
359
+ - **setBuildErrorMessage**: `(error: string | null) => void` - Optional callback for handling build errors
360
+ - **getLatestContent**: `(vizId: string) => Promise<VizContent | null>` - Optional function to fetch viz content for cross-viz imports
361
+ - **resolveSlugKey**: `(slugKey: string) => Promise<string | null>` - Optional function to resolve viz slugs to IDs
362
+ - **writeFile**: `(fileName: string, content: string) => void` - Optional callback when code running in the iframe writes files
363
+
364
+ ##### Returns
365
+
366
+ Returns a `VizHubRuntime` object with methods:
367
+
368
+ - **run**: `(options: RunOptions) => void` - Executes code in the iframe
369
+ - **options.files**: `FileCollection` - Map of filenames to file contents
370
+ - **options.enableHotReloading**: `boolean` - Enable hot reloading (v3 runtime only)
371
+ - **options.enableSourcemap**: `boolean` - Enable source maps for debugging
372
+ - **options.vizId**: `string` - ID of current viz (required for v3)
373
+ - **cleanup**: `() => void` - Removes event listeners from worker and iframe
374
+ - **invalidateVizCache**: `(changedVizIds: string[]) => Promise<void>` - Invalidates cache for specified viz IDs
375
+
376
+ ##### Example
377
+
378
+ ```javascript
379
+ import { createRuntime } from "@vizhub/runtime";
380
+ import BuildWorker from "./buildWorker?worker";
381
+
382
+ // Get iframe from DOM
383
+ const iframe = document.getElementById("viz-iframe");
384
+
385
+ // Create worker
386
+ const worker = new BuildWorker();
387
+
388
+ // Initialize runtime
389
+ const runtime = createRuntime({
390
+ iframe,
391
+ worker,
392
+ setBuildErrorMessage: (error) => {
393
+ error && console.error("Build error:", error);
394
+ },
395
+ getLatestContent: async (vizId) => {
396
+ // Fetch viz content from your backend
397
+ return await fetchVizContent(vizId);
398
+ },
399
+ resolveSlugKey: async (slugKey) => {
400
+ // Resolve slug to vizId from your backend
401
+ return await resolveSlug(slugKey);
402
+ },
403
+ });
404
+
405
+ // Run code in the iframe
406
+ runtime.run({
407
+ files: {
408
+ "index.js":
409
+ 'console.log("Hello from VizHub runtime!");',
410
+ },
411
+ enableHotReloading: true,
412
+ enableSourcemap: true,
413
+ vizId: "example-viz",
414
+ });
415
+
416
+ // Clean up when done
417
+ runtime.cleanup();
418
+ ```
419
+
420
+ ### Building HTML Only
421
+
340
422
  ```javascript
341
423
  import { build } from "@vizhub/runtime";
342
424
  import { rollup } from "rollup";
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/build/build.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,EAGL,SAAS,EACT,cAAc,EAEd,QAAQ,EACT,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAUtC,eAAO,MAAM,KAAK,GAAU,oFAQzB;IAGD,KAAK,CAAC,EAAE,cAAc,CAAC;IAGvB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAQ1D,eAAe,CAAC,EAAE,OAAO,CAAC;IAI1B,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAGpB,KAAK,CAAC,EAAE,MAAM,CAAC;IAGf,SAAS,CAAC,EAAE,SAAS,CAAC;IAGtB,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC;CACnD,KAAG,OAAO,CAAC,WAAW,CAmItB,CAAC"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/build/build.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,EAGL,SAAS,EACT,cAAc,EAEd,QAAQ,EACT,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAUtC,eAAO,MAAM,KAAK,GAAU,oFAQzB;IAGD,KAAK,CAAC,EAAE,cAAc,CAAC;IAGvB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAQ1D,eAAe,CAAC,EAAE,OAAO,CAAC;IAI1B,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAGpB,KAAK,CAAC,EAAE,MAAM,CAAC;IAGf,SAAS,CAAC,EAAE,SAAS,CAAC;IAGtB,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC;CACnD,KAAG,OAAO,CAAC,WAAW,CAuItB,CAAC"}
@@ -1,6 +1,7 @@
1
1
  export type runtimeVersion = "v1" | "v2" | "v3" | "v4";
2
2
  export type BuildResult = {
3
3
  html: string;
4
+ runtimeVersion: runtimeVersion;
4
5
  css?: string;
5
6
  js?: string;
6
7
  };
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/build/types.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAGvD,MAAM,MAAM,WAAW,GAAG;IAKxB,IAAI,EAAE,MAAM,CAAC;IAIb,GAAG,CAAC,EAAE,MAAM,CAAC;IAIb,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/build/types.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAGvD,MAAM,MAAM,WAAW,GAAG;IAKxB,IAAI,EAAE,MAAM,CAAC;IAGb,cAAc,EAAE,cAAc,CAAC;IAI/B,GAAG,CAAC,EAAE,MAAM,CAAC;IAIb,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { magicSandbox as $ } from "magic-sandbox";
2
- import { isVizId as V, getFileText as L, generateVizId as D, fileCollectionToVizFiles as B, vizFilesToFileCollection as A } from "@vizhub/viz-utils";
2
+ import { isVizId as J, getFileText as L, generateVizId as D, fileCollectionToVizFiles as B, vizFilesToFileCollection as A } from "@vizhub/viz-utils";
3
3
  import { transform as q } from "sucrase";
4
4
  const Nt = () => (Math.random() + "").slice(2);
5
5
  function C(t = {}) {
@@ -54,7 +54,7 @@ const P = {
54
54
  d3: "d3",
55
55
  react: "React",
56
56
  "react-dom": "ReactDOM"
57
- }, U = (t) => {
57
+ }, V = (t) => {
58
58
  const e = G(t);
59
59
  return {
60
60
  ...Y,
@@ -219,8 +219,8 @@ export { csvParse, tsvParse };`, Q = (t) => (
219
219
  if (!s.endsWith(".js") && !s.endsWith(".css") && !s.endsWith(".csv") && !s.endsWith(".svelte") && (s += ".js"), r) {
220
220
  const {
221
221
  vizId: i,
222
- fileName: c
223
- } = b(r), a = c.split("/").slice(0, -1).join("/"), l = a ? `${a}/${s}` : s;
222
+ fileName: a
223
+ } = b(r), c = a.split("/").slice(0, -1).join("/"), l = c ? `${c}/${s}` : s;
224
224
  return `${i}/${l}`;
225
225
  }
226
226
  return t + "/" + s;
@@ -228,7 +228,7 @@ export { csvParse, tsvParse };`, Q = (t) => (
228
228
  const o = Z(n);
229
229
  if (o) {
230
230
  let s;
231
- if (V(o.idOrSlug))
231
+ if (J(o.idOrSlug))
232
232
  s = o.idOrSlug;
233
233
  else {
234
234
  if (!e)
@@ -252,21 +252,21 @@ export { csvParse, tsvParse };`, Q = (t) => (
252
252
  // `id` here is of the form
253
253
  // `{vizId}/{fileName}`
254
254
  load: async (o) => {
255
- const s = b(o), i = s.vizId, c = s.fileName;
256
- if (c.endsWith(".css"))
255
+ const s = b(o), i = s.vizId, a = s.fileName;
256
+ if (a.endsWith(".css"))
257
257
  return e(o), "";
258
- let a = null;
258
+ let c = null;
259
259
  if (i === n && r)
260
- a = r[c] || null;
260
+ c = r[a] || null;
261
261
  else {
262
262
  const l = await t.get(i);
263
- a = L(l, c);
263
+ c = L(l, a);
264
264
  }
265
- if (a === null)
265
+ if (c === null)
266
266
  throw new Error(
267
- `Imported file "${c}" not found.`
267
+ `Imported file "${a}" not found.`
268
268
  );
269
- return a;
269
+ return c;
270
270
  }
271
271
  }), M = /* @__PURE__ */ new Map();
272
272
  let I;
@@ -321,8 +321,8 @@ const x = "https://cdn.jsdelivr.net/npm/svelte@4.2.9", Ct = `${x}/compiler.cjs`,
321
321
  slugCache: s,
322
322
  getSvelteCompiler: i
323
323
  }) => {
324
- const c = /* @__PURE__ */ new Set(), a = (d) => {
325
- c.add(d);
324
+ const a = /* @__PURE__ */ new Set(), c = (d) => {
325
+ a.add(d);
326
326
  };
327
327
  if (!t["index.js"])
328
328
  throw new Error("Missing index.js");
@@ -336,7 +336,7 @@ const x = "https://cdn.jsdelivr.net/npm/svelte@4.2.9", Ct = `${x}/compiler.cjs`,
336
336
  ...r ? [
337
337
  tt({
338
338
  vizCache: r,
339
- trackCSSImport: a,
339
+ trackCSSImport: c,
340
340
  vizId: o,
341
341
  files: t
342
342
  })
@@ -352,13 +352,13 @@ const x = "https://cdn.jsdelivr.net/npm/svelte@4.2.9", Ct = `${x}/compiler.cjs`,
352
352
  compact: !0
353
353
  }, w = S(t);
354
354
  if (w) {
355
- const d = U(w);
355
+ const d = V(w);
356
356
  d && (u.external = Object.keys(d), m.globals = d);
357
357
  }
358
358
  const y = await e(u), { output: f } = await y.generate(m);
359
359
  return {
360
360
  src: f[0].code,
361
- cssFiles: Array.from(c)
361
+ cssFiles: Array.from(a)
362
362
  };
363
363
  };
364
364
  function rt() {
@@ -458,7 +458,7 @@ const st = ({
458
458
  slugCache: s,
459
459
  getSvelteCompiler: i
460
460
  }) => {
461
- const { src: c, cssFiles: a } = await nt({
461
+ const { src: a, cssFiles: c } = await nt({
462
462
  files: t,
463
463
  rollup: e,
464
464
  enableSourcemap: n,
@@ -468,15 +468,15 @@ const st = ({
468
468
  getSvelteCompiler: i
469
469
  });
470
470
  let l = [];
471
- if (a.length > 0)
472
- for (let f = 0; f < a.length; f++) {
473
- const d = a[f], h = b(d), E = h.vizId, j = h.fileName;
471
+ if (c.length > 0)
472
+ for (let f = 0; f < c.length; f++) {
473
+ const d = c[f], h = b(d), E = h.vizId, j = h.fileName;
474
474
  let v = null;
475
475
  if (E === o && t)
476
476
  v = t[j] || null;
477
477
  else {
478
- const J = await r.get(E);
479
- v = L(J, j);
478
+ const z = await r.get(E);
479
+ v = L(z, j);
480
480
  }
481
481
  v && l.push(v);
482
482
  }
@@ -499,9 +499,10 @@ const st = ({
499
499
  }).join("");
500
500
  }
501
501
  return {
502
- html: st({ cdn: w, src: c, styles: m }),
502
+ html: st({ cdn: w, src: a, styles: m }),
503
503
  css: u,
504
- js: c
504
+ js: a,
505
+ runtimeVersion: "v3"
505
506
  };
506
507
  }, it = ({
507
508
  initialContents: t,
@@ -511,16 +512,16 @@ const st = ({
511
512
  t.map((i) => [i.id, i])
512
513
  );
513
514
  return { get: async (i) => {
514
- const c = n.get(i);
515
- if (c !== void 0)
516
- return c;
515
+ const a = n.get(i);
516
+ if (a !== void 0)
517
+ return a;
517
518
  if (!e)
518
519
  throw new Error(
519
520
  `Unresolved import from vizId ${i}, cache miss handler not provided.`
520
521
  );
521
- const a = await e(i);
522
- if (a)
523
- return n.set(i, a), a;
522
+ const c = await e(i);
523
+ if (c)
524
+ return n.set(i, c), c;
524
525
  throw new Error(
525
526
  `Unresolved import from vizId ${i}`
526
527
  );
@@ -540,9 +541,9 @@ const st = ({
540
541
  throw new Error(
541
542
  `Unresolved slug ${s}, cache miss handler not provided.`
542
543
  );
543
- const c = await e(s);
544
- if (c)
545
- return t[s] = c, c;
544
+ const a = await e(s);
545
+ if (a)
546
+ return t[s] = a, a;
546
547
  throw new Error(`Unresolved slug ${s}`);
547
548
  }, set: (s, i) => {
548
549
  t[s] = i;
@@ -574,12 +575,12 @@ const st = ({
574
575
  const r = Object.entries(R(e));
575
576
  if (r.length) {
576
577
  const s = T(e);
577
- r.forEach(([c]) => {
578
- n = ut(n, new RegExp(`${c}@`));
578
+ r.forEach(([a]) => {
579
+ n = ut(n, new RegExp(`${a}@`));
579
580
  });
580
581
  const i = r.map(
581
- ([c, a]) => F({ name: c, version: a }, s)
582
- ).map((c) => `<script src="${c}"><\/script>`).join(`
582
+ ([a, c]) => F({ name: a, version: c }, s)
583
+ ).map((a) => `<script src="${a}"><\/script>`).join(`
583
584
  `);
584
585
  n = W(
585
586
  n,
@@ -589,9 +590,9 @@ const st = ({
589
590
  );
590
591
  }
591
592
  if (e["bundle.js"] !== void 0 || e["index.js"] !== void 0) {
592
- const s = '<script src="bundle.js"><\/script>', i = /<script\b[^>]*\bsrc=["']bundle\.js["'][^>]*>\s*<\/script>/gi, c = [...n.matchAll(i)];
593
- c.length === 1 && (() => {
594
- const l = c[0].index ?? -1;
593
+ const s = '<script src="bundle.js"><\/script>', i = /<script\b[^>]*\bsrc=["']bundle\.js["'][^>]*>\s*<\/script>/gi, a = [...n.matchAll(i)];
594
+ a.length === 1 && (() => {
595
+ const l = a[0].index ?? -1;
595
596
  if (l === -1) return !1;
596
597
  const u = n.search(/<body\b[^>]*>/i), m = n.search(/<\/body>/i);
597
598
  return u !== -1 && m !== -1 && l > u && l < m;
@@ -609,7 +610,7 @@ const st = ({
609
610
  for (const s of r)
610
611
  s === ".." ? o.pop() : s !== "." && s !== "" && o.push(s);
611
612
  return o.join("/");
612
- }, z = (t) => ({
613
+ }, U = (t) => ({
613
614
  name: "virtual-file-system",
614
615
  resolveId(e, n) {
615
616
  const r = n != null && n.startsWith(
@@ -620,10 +621,10 @@ const st = ({
620
621
  if (t[s])
621
622
  return p + s;
622
623
  const i = [".js", ".jsx", ".ts", ".tsx"];
623
- for (const c of i) {
624
- const a = s + c;
625
- if (t[a])
626
- return p + a;
624
+ for (const a of i) {
625
+ const c = s + a;
626
+ if (t[c])
627
+ return p + c;
627
628
  }
628
629
  }
629
630
  if (t[e])
@@ -656,19 +657,19 @@ const st = ({
656
657
  );
657
658
  const s = {
658
659
  input: "./" + r,
659
- plugins: [z(t), C()],
660
+ plugins: [U(t), C()],
660
661
  onwarn(u, m) {
661
662
  u.code !== "UNRESOLVED_IMPORT" && m(u);
662
663
  }
663
664
  }, i = {
664
665
  format: "iife",
665
666
  sourcemap: n
666
- }, c = S(t);
667
- if (c) {
668
- const u = U(c);
667
+ }, a = S(t);
668
+ if (a) {
669
+ const u = V(a);
669
670
  u && (s.external = Object.keys(u), i.globals = u);
670
671
  }
671
- const a = await e(s), { output: l } = await a.generate(i);
672
+ const c = await e(s), { output: l } = await c.generate(i);
672
673
  return l[0].code;
673
674
  }, ht = async ({
674
675
  files: t,
@@ -709,7 +710,7 @@ const st = ({
709
710
  const s = {
710
711
  input: t.startsWith("./") ? t : `./${t}`,
711
712
  plugins: [
712
- z(e),
713
+ U(e),
713
714
  C({
714
715
  // Enable JSX runtime
715
716
  // so we don't need to import React
@@ -728,13 +729,13 @@ const st = ({
728
729
  // DEBUG && console.log("isExternal", isExternal);
729
730
  // return isExternal;
730
731
  // },
731
- onwarn(a, l) {
732
+ onwarn(c, l) {
732
733
  }
733
- }, i = await n(s), { output: c } = await i.generate({
734
+ }, i = await n(s), { output: a } = await i.generate({
734
735
  format: "es",
735
736
  sourcemap: r
736
737
  });
737
- return c[0].code;
738
+ return a[0].code;
738
739
  }, N = (t, e) => new RegExp(`<${e}\\b`, "i").test(t) && new RegExp(`</${e}>`, "i").test(t), xt = (t) => {
739
740
  const e = t.trim();
740
741
  return N(e, "html") && N(e, "head") && N(e, "body") ? e : `<html><head></head><body>${e}</body></html>`;
@@ -790,14 +791,14 @@ ${r}
790
791
  if (o.length === 0)
791
792
  return t;
792
793
  const s = /* @__PURE__ */ new Map();
793
- for (const c of o) {
794
- const a = await gt({
795
- entryPoint: c,
794
+ for (const a of o) {
795
+ const c = await gt({
796
+ entryPoint: a,
796
797
  files: t,
797
798
  rollup: e,
798
799
  enableSourcemap: n
799
800
  });
800
- s.set(c, a);
801
+ s.set(a, c);
801
802
  }
802
803
  const i = jt(t, s);
803
804
  return {
@@ -813,7 +814,7 @@ ${r}
813
814
  slugCache: s,
814
815
  getSvelteCompiler: i
815
816
  }) => {
816
- var c;
817
+ var a;
817
818
  try {
818
819
  if (g && console.log(
819
820
  "[build] files:",
@@ -827,15 +828,16 @@ ${r}
827
828
  "vizId is required when using vizCache"
828
829
  );
829
830
  if (!t && r && o && (t = A(
830
- (c = await r.get(o)) == null ? void 0 : c.files
831
+ (a = await r.get(o)) == null ? void 0 : a.files
831
832
  )), !t)
832
833
  throw new Error("Upable to extract viz files");
833
- const a = at(t);
834
- if (g && console.log("[build] version:", a), a === "v1")
834
+ const c = at(t);
835
+ if (g && console.log("[build] version:", c), c === "v1")
835
836
  return {
836
- html: $(t)
837
+ html: $(t),
838
+ runtimeVersion: c
837
839
  };
838
- if (a === "v2") {
840
+ if (c === "v2") {
839
841
  if (!e)
840
842
  throw new Error(
841
843
  "Rollup is required for v2 runtime"
@@ -843,10 +845,11 @@ ${r}
843
845
  return {
844
846
  html: $(
845
847
  await ht({ files: t, rollup: e, enableSourcemap: n })
846
- )
848
+ ),
849
+ runtimeVersion: c
847
850
  };
848
851
  }
849
- if (a === "v3") {
852
+ if (c === "v3") {
850
853
  if (!e)
851
854
  throw new Error(
852
855
  "Rollup is required for v3 runtime"
@@ -879,7 +882,7 @@ ${r}
879
882
  getSvelteCompiler: i
880
883
  });
881
884
  }
882
- if (a === "v4") {
885
+ if (c === "v4") {
883
886
  if (!e)
884
887
  throw new Error(
885
888
  "Rollup is required for v4 runtime"
@@ -891,17 +894,18 @@ ${r}
891
894
  }), {
892
895
  html: $(
893
896
  await St({ files: t, rollup: e, enableSourcemap: n })
894
- )
897
+ ),
898
+ runtimeVersion: c
895
899
  };
896
900
  }
897
901
  throw new Error(
898
- `Unsupported runtime version: ${a}`
902
+ `Unsupported runtime version: ${c}`
899
903
  );
900
- } catch (a) {
901
- throw a instanceof Error && a.message.indexOf(p) && (a.message = a.message.replace(
904
+ } catch (c) {
905
+ throw c instanceof Error && c.message.indexOf(p) && (c.message = c.message.replace(
902
906
  p,
903
907
  ""
904
- )), a;
908
+ )), c;
905
909
  }
906
910
  };
907
911
  export {
@@ -915,4 +919,4 @@ export {
915
919
  Ct as s,
916
920
  ot as v
917
921
  };
918
- //# sourceMappingURL=build-C3ij8Dz4.js.map
922
+ //# sourceMappingURL=build-B0moD9Cl.js.map