@aprovan/patchwork-compiler 0.1.2-dev.ba8f277 → 0.1.2-dev.c1ac1dc

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/index.js CHANGED
@@ -1,48 +1,6 @@
1
1
  // src/compiler.ts
2
2
  import * as esbuild from "esbuild-wasm";
3
3
 
4
- // src/vfs/project.ts
5
- function createProjectFromFiles(files, id = crypto.randomUUID()) {
6
- const fileMap = /* @__PURE__ */ new Map();
7
- for (const file of files) {
8
- fileMap.set(file.path, file);
9
- }
10
- return { id, entry: resolveEntry(fileMap), files: fileMap };
11
- }
12
- function resolveEntry(files) {
13
- const paths = Array.from(files.keys());
14
- const mainFile = paths.find((p) => /\bmain\.(tsx?|jsx?)$/.test(p));
15
- if (mainFile) return mainFile;
16
- const indexFile = paths.find((p) => /\bindex\.(tsx?|jsx?)$/.test(p));
17
- if (indexFile) return indexFile;
18
- const firstTsx = paths.find((p) => /\.(tsx|jsx)$/.test(p));
19
- if (firstTsx) return firstTsx;
20
- return paths[0] || "main.tsx";
21
- }
22
- function detectMainFile(language) {
23
- switch (language) {
24
- case "tsx":
25
- case "typescript":
26
- return "main.tsx";
27
- case "jsx":
28
- case "javascript":
29
- return "main.jsx";
30
- case "ts":
31
- return "main.ts";
32
- case "js":
33
- return "main.js";
34
- default:
35
- return "main.tsx";
36
- }
37
- }
38
- function createSingleFileProject(content, entry = "main.tsx", id = "inline") {
39
- return {
40
- id,
41
- entry,
42
- files: /* @__PURE__ */ new Map([[entry, { path: entry, content }]])
43
- };
44
- }
45
-
46
4
  // src/schemas.ts
47
5
  import { z } from "zod";
48
6
  var PlatformSchema = z.enum(["browser", "cli"]);
@@ -333,381 +291,23 @@ var ImageRegistry = class {
333
291
  getLoadedNames() {
334
292
  return Array.from(this.images.keys());
335
293
  }
336
- };
337
- var globalRegistry = null;
338
- function getImageRegistry() {
339
- if (!globalRegistry) {
340
- globalRegistry = new ImageRegistry();
341
- }
342
- return globalRegistry;
343
- }
344
- function createImageRegistry() {
345
- return new ImageRegistry();
346
- }
347
-
348
- // src/transforms/cdn.ts
349
- var DEFAULT_CDN_BASE2 = "https://esm.sh";
350
- var cdnBaseUrl2 = DEFAULT_CDN_BASE2;
351
- function setCdnBaseUrl2(url) {
352
- cdnBaseUrl2 = url;
353
- }
354
- var EXTERNAL_PACKAGES = /* @__PURE__ */ new Set(["react", "react-dom", "ink"]);
355
- var NODE_BUILTINS = /* @__PURE__ */ new Set([
356
- "assert",
357
- "buffer",
358
- "child_process",
359
- "cluster",
360
- "crypto",
361
- "dgram",
362
- "dns",
363
- "events",
364
- "fs",
365
- "http",
366
- "http2",
367
- "https",
368
- "net",
369
- "os",
370
- "path",
371
- "perf_hooks",
372
- "process",
373
- "querystring",
374
- "readline",
375
- "stream",
376
- "string_decoder",
377
- "timers",
378
- "tls",
379
- "tty",
380
- "url",
381
- "util",
382
- "v8",
383
- "vm",
384
- "worker_threads",
385
- "zlib"
386
- ]);
387
- function toEsmShUrl(packageName, version, subpath, deps) {
388
- let url = `${cdnBaseUrl2}/${packageName}`;
389
- if (version) {
390
- url += `@${version}`;
391
- }
392
- if (subpath) {
393
- url += `/${subpath}`;
394
- }
395
- if (deps && Object.keys(deps).length > 0) {
396
- const depsStr = Object.entries(deps).map(([name, ver]) => `${name}@${ver}`).join(",");
397
- url += `?deps=${depsStr}`;
398
- }
399
- return url;
400
- }
401
- function isBareImport(path) {
402
- if (path.startsWith(".") || path.startsWith("/") || path.startsWith("http://") || path.startsWith("https://")) {
403
- return false;
404
- }
405
- return true;
406
- }
407
- function parseImportPath(importPath) {
408
- if (importPath.startsWith("@")) {
409
- const parts2 = importPath.split("/");
410
- if (parts2.length >= 2) {
411
- const packageName2 = `${parts2[0]}/${parts2[1]}`;
412
- const subpath2 = parts2.slice(2).join("/");
413
- return { packageName: packageName2, subpath: subpath2 || void 0 };
414
- }
415
- }
416
- const parts = importPath.split("/");
417
- const packageName = parts[0];
418
- const subpath = parts.slice(1).join("/");
419
- return { packageName, subpath: subpath || void 0 };
420
- }
421
- function matchAlias(importPath, aliases) {
422
- for (const [pattern, target] of Object.entries(aliases)) {
423
- if (pattern.endsWith("/*")) {
424
- const prefix = pattern.slice(0, -2);
425
- if (importPath === prefix || importPath.startsWith(prefix + "/")) {
426
- return target;
427
- }
428
- }
429
- if (importPath === pattern) {
430
- return target;
431
- }
432
- }
433
- return null;
434
- }
435
- function cdnTransformPlugin(options = {}) {
436
- const {
437
- packages = {},
438
- external = [],
439
- bundle = false,
440
- globals = {},
441
- deps = {},
442
- aliases = {}
443
- } = options;
444
- const externalSet = /* @__PURE__ */ new Set([...EXTERNAL_PACKAGES, ...external]);
445
- const globalsSet = new Set(Object.keys(globals));
446
- return {
447
- name: "cdn-transform",
448
- setup(build2) {
449
- build2.onResolve({ filter: /.*/ }, (args) => {
450
- const aliasTarget = matchAlias(args.path, aliases);
451
- if (aliasTarget) {
452
- const { packageName, subpath } = parseImportPath(aliasTarget);
453
- if (globalsSet.has(packageName)) {
454
- return {
455
- path: aliasTarget,
456
- namespace: "global-inject"
457
- };
458
- }
459
- const version = packages[packageName];
460
- let url = toEsmShUrl(
461
- packageName,
462
- version,
463
- subpath,
464
- Object.keys(deps).length > 0 ? deps : void 0
465
- );
466
- if (bundle) {
467
- url += url.includes("?") ? "&bundle" : "?bundle";
468
- }
469
- return {
470
- path: url,
471
- external: true
472
- };
473
- }
474
- return null;
475
- });
476
- build2.onResolve({ filter: /.*/ }, (args) => {
477
- if (!isBareImport(args.path)) {
478
- return null;
479
- }
480
- const { packageName } = parseImportPath(args.path);
481
- if (globalsSet.has(packageName)) {
482
- return {
483
- path: args.path,
484
- namespace: "global-inject"
485
- };
486
- }
487
- return null;
488
- });
489
- build2.onLoad({ filter: /.*/, namespace: "global-inject" }, (args) => {
490
- const { packageName, subpath } = parseImportPath(args.path);
491
- const globalName = globals[packageName];
492
- if (!globalName) return null;
493
- if (subpath) {
494
- return {
495
- contents: `export * from '${packageName}'; export { default } from '${packageName}';`,
496
- loader: "js"
497
- };
498
- }
499
- const contents = `
500
- const mod = window.${globalName};
501
- export default mod;
502
- // Re-export all properties as named exports
503
- const { ${getCommonExports(packageName).join(", ")} } = mod;
504
- export { ${getCommonExports(packageName).join(", ")} };
505
- `;
506
- return {
507
- contents,
508
- loader: "js"
509
- };
510
- });
511
- build2.onResolve({ filter: /.*/ }, (args) => {
512
- if (!isBareImport(args.path)) {
513
- return null;
514
- }
515
- if (NODE_BUILTINS.has(args.path)) {
516
- return { external: true };
517
- }
518
- const { packageName, subpath } = parseImportPath(args.path);
519
- if (globalsSet.has(packageName)) {
520
- return null;
521
- }
522
- if (externalSet.has(packageName)) {
523
- return { external: true };
524
- }
525
- const version = packages[packageName];
526
- let url = toEsmShUrl(
527
- packageName,
528
- version,
529
- subpath,
530
- Object.keys(deps).length > 0 ? deps : void 0
531
- );
532
- if (bundle) {
533
- url += url.includes("?") ? "&bundle" : "?bundle";
534
- }
535
- return {
536
- path: url,
537
- external: true
538
- };
539
- });
540
- }
541
- };
542
- }
543
- function getCommonExports(packageName) {
544
- const exports = {
545
- react: [
546
- "useState",
547
- "useEffect",
548
- "useCallback",
549
- "useMemo",
550
- "useRef",
551
- "useContext",
552
- "useReducer",
553
- "useLayoutEffect",
554
- "useId",
555
- "createContext",
556
- "createElement",
557
- "cloneElement",
558
- "createRef",
559
- "forwardRef",
560
- "lazy",
561
- "memo",
562
- "Fragment",
563
- "Suspense",
564
- "StrictMode",
565
- "Component",
566
- "PureComponent",
567
- "Children",
568
- "isValidElement"
569
- ],
570
- "react-dom": [
571
- "createPortal",
572
- "flushSync",
573
- "render",
574
- "hydrate",
575
- "unmountComponentAtNode"
576
- ]
577
- };
578
- return exports[packageName] || [];
579
- }
580
- function generateImportMap(packages) {
581
- const imports = {};
582
- for (const [name, version] of Object.entries(packages)) {
583
- imports[name] = toEsmShUrl(name, version);
584
- }
585
- return imports;
586
- }
587
-
588
- // src/transforms/vfs.ts
589
- function dirname(path) {
590
- const idx = path.lastIndexOf("/");
591
- return idx === -1 ? "." : path.slice(0, idx) || ".";
592
- }
593
- function normalizePath(path) {
594
- const parts = [];
595
- for (const segment of path.split("/")) {
596
- if (segment === "..") parts.pop();
597
- else if (segment && segment !== ".") parts.push(segment);
598
- }
599
- return parts.join("/");
600
- }
601
- function inferLoader(path, language) {
602
- if (language) {
603
- switch (language) {
604
- case "typescript":
605
- case "ts":
606
- return "ts";
607
- case "tsx":
608
- return "tsx";
609
- case "javascript":
610
- case "js":
611
- return "js";
612
- case "jsx":
613
- return "jsx";
614
- case "json":
615
- return "json";
616
- case "css":
617
- return "css";
618
- }
619
- }
620
- const ext = path.split(".").pop();
621
- switch (ext) {
622
- case "ts":
623
- return "ts";
624
- case "tsx":
625
- return "tsx";
626
- case "js":
627
- return "js";
628
- case "jsx":
629
- return "jsx";
630
- case "json":
631
- return "json";
632
- case "css":
633
- return "css";
634
- default:
635
- return "tsx";
636
- }
637
- }
638
- function normalizeVFSPath(path) {
639
- if (path.startsWith("@/")) {
640
- return path.slice(2);
641
- }
642
- return path;
643
- }
644
- function resolveRelativePath(importer, target) {
645
- const importerDir = dirname(normalizeVFSPath(importer));
646
- const combined = importerDir === "." ? target : `${importerDir}/${target}`;
647
- return normalizePath(combined);
648
- }
649
- function matchAlias2(importPath, aliases) {
650
- if (!aliases) return null;
651
- for (const [pattern, target] of Object.entries(aliases)) {
652
- if (pattern.endsWith("/*")) {
653
- const prefix = pattern.slice(0, -2);
654
- if (importPath === prefix || importPath.startsWith(prefix + "/")) {
655
- return target;
656
- }
657
- }
658
- if (importPath === pattern) {
659
- return target;
660
- }
661
- }
662
- return null;
663
- }
664
- function findFile(project, path) {
665
- if (project.files.has(path)) return path;
666
- const extensions = [".tsx", ".ts", ".jsx", ".js", ".json"];
667
- for (const ext of extensions) {
668
- if (project.files.has(path + ext)) return path + ext;
669
- }
670
- for (const ext of extensions) {
671
- const indexPath = `${path}/index${ext}`;
672
- if (project.files.has(indexPath)) return indexPath;
294
+ };
295
+ var globalRegistry = null;
296
+ function getImageRegistry() {
297
+ if (!globalRegistry) {
298
+ globalRegistry = new ImageRegistry();
673
299
  }
674
- return null;
300
+ return globalRegistry;
675
301
  }
676
- function vfsPlugin(project, options = {}) {
677
- return {
678
- name: "patchwork-vfs",
679
- setup(build2) {
680
- build2.onResolve({ filter: /^@\// }, (args) => {
681
- const aliased = matchAlias2(args.path, options.aliases);
682
- if (aliased) return null;
683
- return { path: args.path, namespace: "vfs" };
684
- });
685
- build2.onResolve({ filter: /^\./ }, (args) => {
686
- if (args.namespace !== "vfs") return null;
687
- const resolved = resolveRelativePath(args.importer, args.path);
688
- return { path: resolved, namespace: "vfs" };
689
- });
690
- build2.onLoad({ filter: /.*/, namespace: "vfs" }, (args) => {
691
- const normalPath = normalizeVFSPath(args.path);
692
- const filePath = findFile(project, normalPath);
693
- if (!filePath) {
694
- throw new Error(`File not found in VFS: ${args.path}`);
695
- }
696
- const file = project.files.get(filePath);
697
- return {
698
- contents: file.content,
699
- loader: inferLoader(filePath, file.language)
700
- };
701
- });
702
- }
703
- };
302
+ function createImageRegistry() {
303
+ return new ImageRegistry();
704
304
  }
705
305
 
706
306
  // src/mount/bridge.ts
707
307
  function generateMessageId() {
708
308
  return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
709
309
  }
710
- function createHttpServiceProxy(proxyUrl) {
310
+ function createHttpProxy(proxyUrl) {
711
311
  return {
712
312
  async call(namespace, procedure, args) {
713
313
  const url = `${proxyUrl}/${namespace}/${procedure}`;
@@ -851,7 +451,7 @@ var ParentBridge = class {
851
451
  this.pendingCalls.clear();
852
452
  }
853
453
  };
854
- function createIframeServiceProxy() {
454
+ function createIframeProxy() {
855
455
  const pendingCalls = /* @__PURE__ */ new Map();
856
456
  if (typeof window !== "undefined") {
857
457
  window.addEventListener("message", (event) => {
@@ -1105,48 +705,288 @@ async function mountEmbedded(widget, options, image, proxy) {
1105
705
  if (typeof root.unmount === "function") {
1106
706
  moduleCleanup = () => root.unmount();
1107
707
  }
1108
- } else if (createElement && renderer?.kind === "render") {
1109
- renderer.render(createElement(Component, inputs), container);
1110
- } else {
1111
- const result = Component(inputs);
1112
- if (result instanceof HTMLElement) {
1113
- container.appendChild(result);
1114
- } else if (typeof result === "string") {
1115
- container.innerHTML = result;
708
+ } else if (createElement && renderer?.kind === "render") {
709
+ renderer.render(createElement(Component, inputs), container);
710
+ } else {
711
+ const result = Component(inputs);
712
+ if (result instanceof HTMLElement) {
713
+ container.appendChild(result);
714
+ } else if (typeof result === "string") {
715
+ container.innerHTML = result;
716
+ }
717
+ }
718
+ }
719
+ } finally {
720
+ URL.revokeObjectURL(scriptUrl);
721
+ }
722
+ const unmount = () => {
723
+ if (moduleCleanup) {
724
+ moduleCleanup();
725
+ }
726
+ removeNamespaceGlobals(window, namespaceNames);
727
+ const style = document.getElementById(`${mountId}-style`);
728
+ if (style) {
729
+ style.remove();
730
+ }
731
+ container.remove();
732
+ };
733
+ return {
734
+ id: mountId,
735
+ widget,
736
+ mode: "embedded",
737
+ target,
738
+ inputs,
739
+ unmount
740
+ };
741
+ }
742
+ async function reloadEmbedded(mounted, widget, image, proxy) {
743
+ mounted.unmount();
744
+ return mountEmbedded(
745
+ widget,
746
+ { target: mounted.target, mode: "embedded", inputs: mounted.inputs },
747
+ image,
748
+ proxy
749
+ );
750
+ }
751
+
752
+ // src/transforms/cdn.ts
753
+ var DEFAULT_CDN_BASE2 = "https://esm.sh";
754
+ var cdnBaseUrl2 = DEFAULT_CDN_BASE2;
755
+ function setCdnBaseUrl2(url) {
756
+ cdnBaseUrl2 = url;
757
+ }
758
+ var EXTERNAL_PACKAGES = /* @__PURE__ */ new Set(["react", "react-dom", "ink"]);
759
+ var NODE_BUILTINS = /* @__PURE__ */ new Set([
760
+ "assert",
761
+ "buffer",
762
+ "child_process",
763
+ "cluster",
764
+ "crypto",
765
+ "dgram",
766
+ "dns",
767
+ "events",
768
+ "fs",
769
+ "http",
770
+ "http2",
771
+ "https",
772
+ "net",
773
+ "os",
774
+ "path",
775
+ "perf_hooks",
776
+ "process",
777
+ "querystring",
778
+ "readline",
779
+ "stream",
780
+ "string_decoder",
781
+ "timers",
782
+ "tls",
783
+ "tty",
784
+ "url",
785
+ "util",
786
+ "v8",
787
+ "vm",
788
+ "worker_threads",
789
+ "zlib"
790
+ ]);
791
+ function toEsmShUrl(packageName, version, subpath, deps) {
792
+ let url = `${cdnBaseUrl2}/${packageName}`;
793
+ if (version) {
794
+ url += `@${version}`;
795
+ }
796
+ if (subpath) {
797
+ url += `/${subpath}`;
798
+ }
799
+ if (deps && Object.keys(deps).length > 0) {
800
+ const depsStr = Object.entries(deps).map(([name, ver]) => `${name}@${ver}`).join(",");
801
+ url += `?deps=${depsStr}`;
802
+ }
803
+ return url;
804
+ }
805
+ function isBareImport(path) {
806
+ if (path.startsWith(".") || path.startsWith("/") || path.startsWith("http://") || path.startsWith("https://")) {
807
+ return false;
808
+ }
809
+ return true;
810
+ }
811
+ function parseImportPath(importPath) {
812
+ if (importPath.startsWith("@")) {
813
+ const parts2 = importPath.split("/");
814
+ if (parts2.length >= 2) {
815
+ const packageName2 = `${parts2[0]}/${parts2[1]}`;
816
+ const subpath2 = parts2.slice(2).join("/");
817
+ return { packageName: packageName2, subpath: subpath2 || void 0 };
818
+ }
819
+ }
820
+ const parts = importPath.split("/");
821
+ const packageName = parts[0];
822
+ const subpath = parts.slice(1).join("/");
823
+ return { packageName, subpath: subpath || void 0 };
824
+ }
825
+ function matchAlias(importPath, aliases) {
826
+ for (const [pattern, target] of Object.entries(aliases)) {
827
+ if (pattern.endsWith("/*")) {
828
+ const prefix = pattern.slice(0, -2);
829
+ if (importPath === prefix || importPath.startsWith(prefix + "/")) {
830
+ return target;
831
+ }
832
+ }
833
+ if (importPath === pattern) {
834
+ return target;
835
+ }
836
+ }
837
+ return null;
838
+ }
839
+ function cdnTransformPlugin(options = {}) {
840
+ const {
841
+ packages = {},
842
+ external = [],
843
+ bundle = false,
844
+ globals = {},
845
+ deps = {},
846
+ aliases = {}
847
+ } = options;
848
+ const externalSet = /* @__PURE__ */ new Set([...EXTERNAL_PACKAGES, ...external]);
849
+ const globalsSet = new Set(Object.keys(globals));
850
+ return {
851
+ name: "cdn-transform",
852
+ setup(build2) {
853
+ build2.onResolve({ filter: /.*/ }, (args) => {
854
+ const aliasTarget = matchAlias(args.path, aliases);
855
+ if (aliasTarget) {
856
+ const { packageName, subpath } = parseImportPath(aliasTarget);
857
+ if (globalsSet.has(packageName)) {
858
+ return {
859
+ path: aliasTarget,
860
+ namespace: "global-inject"
861
+ };
862
+ }
863
+ const version = packages[packageName];
864
+ let url = toEsmShUrl(
865
+ packageName,
866
+ version,
867
+ subpath,
868
+ Object.keys(deps).length > 0 ? deps : void 0
869
+ );
870
+ if (bundle) {
871
+ url += url.includes("?") ? "&bundle" : "?bundle";
872
+ }
873
+ return {
874
+ path: url,
875
+ external: true
876
+ };
877
+ }
878
+ return null;
879
+ });
880
+ build2.onResolve({ filter: /.*/ }, (args) => {
881
+ if (!isBareImport(args.path)) {
882
+ return null;
883
+ }
884
+ const { packageName } = parseImportPath(args.path);
885
+ if (globalsSet.has(packageName)) {
886
+ return {
887
+ path: args.path,
888
+ namespace: "global-inject"
889
+ };
890
+ }
891
+ return null;
892
+ });
893
+ build2.onLoad({ filter: /.*/, namespace: "global-inject" }, (args) => {
894
+ const { packageName, subpath } = parseImportPath(args.path);
895
+ const globalName = globals[packageName];
896
+ if (!globalName) return null;
897
+ if (subpath) {
898
+ return {
899
+ contents: `export * from '${packageName}'; export { default } from '${packageName}';`,
900
+ loader: "js"
901
+ };
902
+ }
903
+ const contents = `
904
+ const mod = window.${globalName};
905
+ export default mod;
906
+ // Re-export all properties as named exports
907
+ const { ${getCommonExports(packageName).join(", ")} } = mod;
908
+ export { ${getCommonExports(packageName).join(", ")} };
909
+ `;
910
+ return {
911
+ contents,
912
+ loader: "js"
913
+ };
914
+ });
915
+ build2.onResolve({ filter: /.*/ }, (args) => {
916
+ if (!isBareImport(args.path)) {
917
+ return null;
918
+ }
919
+ if (NODE_BUILTINS.has(args.path)) {
920
+ return { external: true };
921
+ }
922
+ const { packageName, subpath } = parseImportPath(args.path);
923
+ if (globalsSet.has(packageName)) {
924
+ return null;
925
+ }
926
+ if (externalSet.has(packageName)) {
927
+ return { external: true };
928
+ }
929
+ const version = packages[packageName];
930
+ let url = toEsmShUrl(
931
+ packageName,
932
+ version,
933
+ subpath,
934
+ Object.keys(deps).length > 0 ? deps : void 0
935
+ );
936
+ if (bundle) {
937
+ url += url.includes("?") ? "&bundle" : "?bundle";
1116
938
  }
1117
- }
1118
- }
1119
- } finally {
1120
- URL.revokeObjectURL(scriptUrl);
1121
- }
1122
- const unmount = () => {
1123
- if (moduleCleanup) {
1124
- moduleCleanup();
1125
- }
1126
- removeNamespaceGlobals(window, namespaceNames);
1127
- const style = document.getElementById(`${mountId}-style`);
1128
- if (style) {
1129
- style.remove();
939
+ return {
940
+ path: url,
941
+ external: true
942
+ };
943
+ });
1130
944
  }
1131
- container.remove();
1132
945
  };
1133
- return {
1134
- id: mountId,
1135
- widget,
1136
- mode: "embedded",
1137
- target,
1138
- inputs,
1139
- unmount
946
+ }
947
+ function getCommonExports(packageName) {
948
+ const exports = {
949
+ react: [
950
+ "useState",
951
+ "useEffect",
952
+ "useCallback",
953
+ "useMemo",
954
+ "useRef",
955
+ "useContext",
956
+ "useReducer",
957
+ "useLayoutEffect",
958
+ "useId",
959
+ "createContext",
960
+ "createElement",
961
+ "cloneElement",
962
+ "createRef",
963
+ "forwardRef",
964
+ "lazy",
965
+ "memo",
966
+ "Fragment",
967
+ "Suspense",
968
+ "StrictMode",
969
+ "Component",
970
+ "PureComponent",
971
+ "Children",
972
+ "isValidElement"
973
+ ],
974
+ "react-dom": [
975
+ "createPortal",
976
+ "flushSync",
977
+ "render",
978
+ "hydrate",
979
+ "unmountComponentAtNode"
980
+ ]
1140
981
  };
982
+ return exports[packageName] || [];
1141
983
  }
1142
- async function reloadEmbedded(mounted, widget, image, proxy) {
1143
- mounted.unmount();
1144
- return mountEmbedded(
1145
- widget,
1146
- { target: mounted.target, mode: "embedded", inputs: mounted.inputs },
1147
- image,
1148
- proxy
1149
- );
984
+ function generateImportMap(packages) {
985
+ const imports = {};
986
+ for (const [name, version] of Object.entries(packages)) {
987
+ imports[name] = toEsmShUrl(name, version);
988
+ }
989
+ return imports;
1150
990
  }
1151
991
 
1152
992
  // src/mount/iframe.ts
@@ -1474,16 +1314,178 @@ function disposeIframeBridge() {
1474
1314
  }
1475
1315
  }
1476
1316
 
1317
+ // src/transforms/vfs.ts
1318
+ function dirname(path) {
1319
+ const idx = path.lastIndexOf("/");
1320
+ return idx === -1 ? "." : path.slice(0, idx) || ".";
1321
+ }
1322
+ function normalizePath(path) {
1323
+ const parts = [];
1324
+ for (const segment of path.split("/")) {
1325
+ if (segment === "..") parts.pop();
1326
+ else if (segment && segment !== ".") parts.push(segment);
1327
+ }
1328
+ return parts.join("/");
1329
+ }
1330
+ function inferLoader(path, language) {
1331
+ if (language) {
1332
+ switch (language) {
1333
+ case "typescript":
1334
+ case "ts":
1335
+ return "ts";
1336
+ case "tsx":
1337
+ return "tsx";
1338
+ case "javascript":
1339
+ case "js":
1340
+ return "js";
1341
+ case "jsx":
1342
+ return "jsx";
1343
+ case "json":
1344
+ return "json";
1345
+ case "css":
1346
+ return "css";
1347
+ }
1348
+ }
1349
+ const ext = path.split(".").pop();
1350
+ switch (ext) {
1351
+ case "ts":
1352
+ return "ts";
1353
+ case "tsx":
1354
+ return "tsx";
1355
+ case "js":
1356
+ return "js";
1357
+ case "jsx":
1358
+ return "jsx";
1359
+ case "json":
1360
+ return "json";
1361
+ case "css":
1362
+ return "css";
1363
+ default:
1364
+ return "tsx";
1365
+ }
1366
+ }
1367
+ function normalizeVFSPath(path) {
1368
+ if (path.startsWith("@/")) {
1369
+ return path.slice(2);
1370
+ }
1371
+ return path;
1372
+ }
1373
+ function resolveRelativePath(importer, target) {
1374
+ const importerDir = dirname(normalizeVFSPath(importer));
1375
+ const combined = importerDir === "." ? target : `${importerDir}/${target}`;
1376
+ return normalizePath(combined);
1377
+ }
1378
+ function matchAlias2(importPath, aliases) {
1379
+ if (!aliases) return null;
1380
+ for (const [pattern, target] of Object.entries(aliases)) {
1381
+ if (pattern.endsWith("/*")) {
1382
+ const prefix = pattern.slice(0, -2);
1383
+ if (importPath === prefix || importPath.startsWith(prefix + "/")) {
1384
+ return target;
1385
+ }
1386
+ }
1387
+ if (importPath === pattern) {
1388
+ return target;
1389
+ }
1390
+ }
1391
+ return null;
1392
+ }
1393
+ function findFile(project, path) {
1394
+ if (project.files.has(path)) return path;
1395
+ const extensions = [".tsx", ".ts", ".jsx", ".js", ".json"];
1396
+ for (const ext of extensions) {
1397
+ if (project.files.has(path + ext)) return path + ext;
1398
+ }
1399
+ for (const ext of extensions) {
1400
+ const indexPath = `${path}/index${ext}`;
1401
+ if (project.files.has(indexPath)) return indexPath;
1402
+ }
1403
+ return null;
1404
+ }
1405
+ function vfsPlugin(project, options = {}) {
1406
+ return {
1407
+ name: "patchwork-vfs",
1408
+ setup(build2) {
1409
+ build2.onResolve({ filter: /^@\// }, (args) => {
1410
+ const aliased = matchAlias2(args.path, options.aliases);
1411
+ if (aliased) return null;
1412
+ return { path: args.path, namespace: "vfs" };
1413
+ });
1414
+ build2.onResolve({ filter: /^\./ }, (args) => {
1415
+ if (args.namespace !== "vfs") return null;
1416
+ const resolved = resolveRelativePath(args.importer, args.path);
1417
+ return { path: resolved, namespace: "vfs" };
1418
+ });
1419
+ build2.onLoad({ filter: /.*/, namespace: "vfs" }, (args) => {
1420
+ const normalPath = normalizeVFSPath(args.path);
1421
+ const filePath = findFile(project, normalPath);
1422
+ if (!filePath) {
1423
+ throw new Error(`File not found in VFS: ${args.path}`);
1424
+ }
1425
+ const file = project.files.get(filePath);
1426
+ return {
1427
+ contents: file.content,
1428
+ loader: inferLoader(filePath, file.language)
1429
+ };
1430
+ });
1431
+ }
1432
+ };
1433
+ }
1434
+
1435
+ // src/vfs/project.ts
1436
+ function createProjectFromFiles(files, id = crypto.randomUUID()) {
1437
+ const fileMap = /* @__PURE__ */ new Map();
1438
+ for (const file of files) {
1439
+ fileMap.set(file.path, file);
1440
+ }
1441
+ return { id, entry: resolveEntry(fileMap), files: fileMap };
1442
+ }
1443
+ function resolveEntry(files) {
1444
+ const paths = Array.from(files.keys());
1445
+ const mainFile = paths.find((p) => /\bmain\.(tsx?|jsx?)$/.test(p));
1446
+ if (mainFile) return mainFile;
1447
+ const indexFile = paths.find((p) => /\bindex\.(tsx?|jsx?)$/.test(p));
1448
+ if (indexFile) return indexFile;
1449
+ const firstTsx = paths.find((p) => /\.(tsx|jsx)$/.test(p));
1450
+ if (firstTsx) return firstTsx;
1451
+ return paths[0] || "main.tsx";
1452
+ }
1453
+ function detectMainFile(language) {
1454
+ switch (language) {
1455
+ case "tsx":
1456
+ case "typescript":
1457
+ return "main.tsx";
1458
+ case "jsx":
1459
+ case "javascript":
1460
+ return "main.jsx";
1461
+ case "ts":
1462
+ return "main.ts";
1463
+ case "js":
1464
+ return "main.js";
1465
+ default:
1466
+ return "main.tsx";
1467
+ }
1468
+ }
1469
+ function createSingleFileProject(content, entry = "main.tsx", id = "inline") {
1470
+ return {
1471
+ id,
1472
+ entry,
1473
+ files: /* @__PURE__ */ new Map([[entry, { path: entry, content }]])
1474
+ };
1475
+ }
1476
+
1477
1477
  // src/compiler.ts
1478
1478
  var esbuildInitialized = false;
1479
1479
  var esbuildInitPromise = null;
1480
- async function initEsbuild() {
1480
+ var DEFAULT_ESBUILD_WASM_URL = "https://unpkg.com/esbuild-wasm/esbuild.wasm";
1481
+ async function initEsbuild(urlOverrides) {
1481
1482
  if (esbuildInitialized) return;
1482
1483
  if (esbuildInitPromise) return esbuildInitPromise;
1484
+ const wasmUrl = urlOverrides?.["esbuild-wasm/esbuild.wasm"] || DEFAULT_ESBUILD_WASM_URL;
1483
1485
  esbuildInitPromise = (async () => {
1484
1486
  try {
1485
1487
  await esbuild.initialize({
1486
- wasmURL: "https://unpkg.com/esbuild-wasm/esbuild.wasm"
1488
+ wasmURL: wasmUrl
1487
1489
  });
1488
1490
  esbuildInitialized = true;
1489
1491
  } catch (error) {
@@ -1506,7 +1508,7 @@ function hashContent(content) {
1506
1508
  return Math.abs(hash).toString(16).padStart(8, "0");
1507
1509
  }
1508
1510
  async function createCompiler(options) {
1509
- await initEsbuild();
1511
+ await initEsbuild(options.urlOverrides);
1510
1512
  const { image: imageSpec, proxyUrl, cdnBaseUrl: cdnBaseUrl3, widgetCdnBaseUrl } = options;
1511
1513
  if (cdnBaseUrl3) {
1512
1514
  setCdnBaseUrl(cdnBaseUrl3);
@@ -1518,7 +1520,7 @@ async function createCompiler(options) {
1518
1520
  }
1519
1521
  const registry = getImageRegistry();
1520
1522
  await registry.preload(imageSpec);
1521
- const proxy = createHttpServiceProxy(proxyUrl);
1523
+ const proxy = createHttpProxy(proxyUrl);
1522
1524
  return new PatchworkCompiler(proxy, registry);
1523
1525
  }
1524
1526
  var PatchworkCompiler = class {
@@ -1941,6 +1943,8 @@ var SyncEngineImpl = class {
1941
1943
  this.basePath = config.basePath ?? "";
1942
1944
  this.startRemoteWatch();
1943
1945
  }
1946
+ local;
1947
+ remote;
1944
1948
  status = "idle";
1945
1949
  intervalId;
1946
1950
  listeners = /* @__PURE__ */ new Map();
@@ -2246,7 +2250,7 @@ function openDB() {
2246
2250
  const request = indexedDB.open(DB_NAME, DB_VERSION);
2247
2251
  request.onerror = () => reject(request.error);
2248
2252
  request.onsuccess = () => resolve(request.result);
2249
- request.onupgradeneeded = (event) => {
2253
+ request.onupgradeneeded = (_event) => {
2250
2254
  const db = request.result;
2251
2255
  if (!db.objectStoreNames.contains(FILES_STORE)) {
2252
2256
  db.createObjectStore(FILES_STORE);
@@ -2272,6 +2276,7 @@ var IndexedDBBackend = class {
2272
2276
  constructor(prefix = "vfs") {
2273
2277
  this.prefix = prefix;
2274
2278
  }
2279
+ prefix;
2275
2280
  key(path) {
2276
2281
  return `${this.prefix}:${normalizePath2(path)}`;
2277
2282
  }
@@ -2442,6 +2447,7 @@ var HttpBackend = class {
2442
2447
  constructor(config) {
2443
2448
  this.config = config;
2444
2449
  }
2450
+ config;
2445
2451
  async readFile(path) {
2446
2452
  const res = await fetch(this.url(path));
2447
2453
  if (!res.ok) throw new Error(`ENOENT: ${path}`);
@@ -2545,6 +2551,7 @@ var VFSStore = class {
2545
2551
  }
2546
2552
  }
2547
2553
  }
2554
+ provider;
2548
2555
  local;
2549
2556
  syncEngine;
2550
2557
  root;
@@ -2715,8 +2722,8 @@ export {
2715
2722
  cdnTransformPlugin,
2716
2723
  createCompiler,
2717
2724
  createFieldAccessProxy,
2718
- createHttpServiceProxy,
2719
- createIframeServiceProxy,
2725
+ createHttpProxy,
2726
+ createIframeProxy,
2720
2727
  createImageRegistry,
2721
2728
  createProjectFromFiles,
2722
2729
  createSingleFileProject,