@aprovan/patchwork-compiler 0.1.2-dev.c00a8ae → 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,6 +1314,166 @@ 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;
@@ -1520,7 +1520,7 @@ async function createCompiler(options) {
1520
1520
  }
1521
1521
  const registry = getImageRegistry();
1522
1522
  await registry.preload(imageSpec);
1523
- const proxy = createHttpServiceProxy(proxyUrl);
1523
+ const proxy = createHttpProxy(proxyUrl);
1524
1524
  return new PatchworkCompiler(proxy, registry);
1525
1525
  }
1526
1526
  var PatchworkCompiler = class {
@@ -1943,6 +1943,8 @@ var SyncEngineImpl = class {
1943
1943
  this.basePath = config.basePath ?? "";
1944
1944
  this.startRemoteWatch();
1945
1945
  }
1946
+ local;
1947
+ remote;
1946
1948
  status = "idle";
1947
1949
  intervalId;
1948
1950
  listeners = /* @__PURE__ */ new Map();
@@ -2248,7 +2250,7 @@ function openDB() {
2248
2250
  const request = indexedDB.open(DB_NAME, DB_VERSION);
2249
2251
  request.onerror = () => reject(request.error);
2250
2252
  request.onsuccess = () => resolve(request.result);
2251
- request.onupgradeneeded = (event) => {
2253
+ request.onupgradeneeded = (_event) => {
2252
2254
  const db = request.result;
2253
2255
  if (!db.objectStoreNames.contains(FILES_STORE)) {
2254
2256
  db.createObjectStore(FILES_STORE);
@@ -2274,6 +2276,7 @@ var IndexedDBBackend = class {
2274
2276
  constructor(prefix = "vfs") {
2275
2277
  this.prefix = prefix;
2276
2278
  }
2279
+ prefix;
2277
2280
  key(path) {
2278
2281
  return `${this.prefix}:${normalizePath2(path)}`;
2279
2282
  }
@@ -2444,6 +2447,7 @@ var HttpBackend = class {
2444
2447
  constructor(config) {
2445
2448
  this.config = config;
2446
2449
  }
2450
+ config;
2447
2451
  async readFile(path) {
2448
2452
  const res = await fetch(this.url(path));
2449
2453
  if (!res.ok) throw new Error(`ENOENT: ${path}`);
@@ -2547,6 +2551,7 @@ var VFSStore = class {
2547
2551
  }
2548
2552
  }
2549
2553
  }
2554
+ provider;
2550
2555
  local;
2551
2556
  syncEngine;
2552
2557
  root;
@@ -2717,8 +2722,8 @@ export {
2717
2722
  cdnTransformPlugin,
2718
2723
  createCompiler,
2719
2724
  createFieldAccessProxy,
2720
- createHttpServiceProxy,
2721
- createIframeServiceProxy,
2725
+ createHttpProxy,
2726
+ createIframeProxy,
2722
2727
  createImageRegistry,
2723
2728
  createProjectFromFiles,
2724
2729
  createSingleFileProject,