@aprovan/patchwork-compiler 0.1.2-dev.6bd527d → 0.1.2-dev.879ed82
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.cjs +567 -542
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +81 -27
- package/dist/index.d.ts +81 -27
- package/dist/index.js +557 -539
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
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"]);
|
|
@@ -130,7 +88,7 @@ var DEFAULT_CLI_IMAGE_CONFIG = {
|
|
|
130
88
|
}
|
|
131
89
|
};
|
|
132
90
|
|
|
133
|
-
// src/
|
|
91
|
+
// src/cdn-config.ts
|
|
134
92
|
var DEFAULT_CDN_BASE = "https://esm.sh";
|
|
135
93
|
var cdnBaseUrl = DEFAULT_CDN_BASE;
|
|
136
94
|
function setCdnBaseUrl(url) {
|
|
@@ -139,7 +97,24 @@ function setCdnBaseUrl(url) {
|
|
|
139
97
|
function getCdnBaseUrl() {
|
|
140
98
|
return cdnBaseUrl;
|
|
141
99
|
}
|
|
142
|
-
function
|
|
100
|
+
function toEsmShUrl(packageName, version2, subpath, deps) {
|
|
101
|
+
let url = `${cdnBaseUrl}/${packageName}`;
|
|
102
|
+
if (version2) {
|
|
103
|
+
url += `@${version2}`;
|
|
104
|
+
}
|
|
105
|
+
if (subpath) {
|
|
106
|
+
url += `/${subpath}`;
|
|
107
|
+
}
|
|
108
|
+
if (deps && Object.keys(deps).length > 0) {
|
|
109
|
+
const depsStr = Object.entries(deps).map(([name, ver]) => `${name}@${ver}`).join(",");
|
|
110
|
+
url += `?deps=${depsStr}`;
|
|
111
|
+
}
|
|
112
|
+
return url;
|
|
113
|
+
}
|
|
114
|
+
function isBareImport(path) {
|
|
115
|
+
return !(path.startsWith(".") || path.startsWith("/") || path.startsWith("http://") || path.startsWith("https://"));
|
|
116
|
+
}
|
|
117
|
+
function parsePackageSpec(spec) {
|
|
143
118
|
if (spec.startsWith("@")) {
|
|
144
119
|
const parts = spec.split("/");
|
|
145
120
|
if (parts.length >= 2) {
|
|
@@ -164,14 +139,77 @@ function parseImageSpec(spec) {
|
|
|
164
139
|
}
|
|
165
140
|
return { name: spec };
|
|
166
141
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
142
|
+
function parseImportPath(importPath) {
|
|
143
|
+
if (importPath.startsWith("@")) {
|
|
144
|
+
const parts2 = importPath.split("/");
|
|
145
|
+
if (parts2.length >= 2) {
|
|
146
|
+
const packageName2 = `${parts2[0]}/${parts2[1]}`;
|
|
147
|
+
const subpath2 = parts2.slice(2).join("/");
|
|
148
|
+
return { packageName: packageName2, subpath: subpath2 || void 0 };
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const parts = importPath.split("/");
|
|
152
|
+
const packageName = parts[0];
|
|
153
|
+
const subpath = parts.slice(1).join("/");
|
|
154
|
+
return { packageName, subpath: subpath || void 0 };
|
|
155
|
+
}
|
|
156
|
+
function matchAlias(importPath, aliases) {
|
|
157
|
+
for (const [pattern, target] of Object.entries(aliases)) {
|
|
158
|
+
if (pattern.endsWith("/*")) {
|
|
159
|
+
const prefix = pattern.slice(0, -2);
|
|
160
|
+
if (importPath === prefix || importPath.startsWith(prefix + "/")) {
|
|
161
|
+
return target;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (importPath === pattern) {
|
|
165
|
+
return target;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
var COMMON_EXPORTS = {
|
|
171
|
+
react: [
|
|
172
|
+
"useState",
|
|
173
|
+
"useEffect",
|
|
174
|
+
"useCallback",
|
|
175
|
+
"useMemo",
|
|
176
|
+
"useRef",
|
|
177
|
+
"useContext",
|
|
178
|
+
"useReducer",
|
|
179
|
+
"useLayoutEffect",
|
|
180
|
+
"useId",
|
|
181
|
+
"createContext",
|
|
182
|
+
"createElement",
|
|
183
|
+
"cloneElement",
|
|
184
|
+
"createRef",
|
|
185
|
+
"forwardRef",
|
|
186
|
+
"lazy",
|
|
187
|
+
"memo",
|
|
188
|
+
"Fragment",
|
|
189
|
+
"Suspense",
|
|
190
|
+
"StrictMode",
|
|
191
|
+
"Component",
|
|
192
|
+
"PureComponent",
|
|
193
|
+
"Children",
|
|
194
|
+
"isValidElement"
|
|
195
|
+
],
|
|
196
|
+
"react-dom": ["createPortal", "flushSync", "render", "hydrate", "unmountComponentAtNode"]
|
|
197
|
+
};
|
|
198
|
+
function getCommonExports(packageName) {
|
|
199
|
+
return COMMON_EXPORTS[packageName] ?? [];
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// src/images/loader.ts
|
|
203
|
+
function parseImageSpec(spec) {
|
|
204
|
+
return parsePackageSpec(spec);
|
|
205
|
+
}
|
|
206
|
+
async function fetchPackageJson(packageName, version2) {
|
|
207
|
+
const cdnBaseUrl2 = getCdnBaseUrl();
|
|
208
|
+
const versionSuffix = version2 ? `@${version2}` : "";
|
|
209
|
+
const url = `${cdnBaseUrl2}/${packageName}${versionSuffix}/package.json`;
|
|
170
210
|
const response = await fetch(url);
|
|
171
211
|
if (!response.ok) {
|
|
172
|
-
throw new Error(
|
|
173
|
-
`Failed to fetch package.json for ${packageName}: ${response.statusText}`
|
|
174
|
-
);
|
|
212
|
+
throw new Error(`Failed to fetch package.json for ${packageName}: ${response.statusText}`);
|
|
175
213
|
}
|
|
176
214
|
return response.json();
|
|
177
215
|
}
|
|
@@ -226,21 +264,22 @@ async function loadLocalImage(name) {
|
|
|
226
264
|
}
|
|
227
265
|
}
|
|
228
266
|
async function loadImage(spec) {
|
|
229
|
-
const { name, version } = parseImageSpec(spec);
|
|
267
|
+
const { name, version: version2 } = parseImageSpec(spec);
|
|
230
268
|
const localImage = await loadLocalImage(name);
|
|
231
269
|
if (localImage) {
|
|
232
270
|
return localImage;
|
|
233
271
|
}
|
|
234
|
-
const packageJson = await fetchPackageJson(name,
|
|
272
|
+
const packageJson = await fetchPackageJson(name, version2);
|
|
235
273
|
const config = safeParseImageConfig(packageJson.patchwork) || DEFAULT_IMAGE_CONFIG;
|
|
236
274
|
let setup;
|
|
237
275
|
let mount;
|
|
238
276
|
let moduleUrl;
|
|
239
277
|
if (packageJson.main && typeof window !== "undefined") {
|
|
240
278
|
try {
|
|
241
|
-
const
|
|
279
|
+
const cdnBaseUrl2 = getCdnBaseUrl();
|
|
280
|
+
const versionSuffix = version2 ? `@${version2}` : "";
|
|
242
281
|
const mainEntry = packageJson.main.startsWith("./") ? packageJson.main.slice(2) : packageJson.main;
|
|
243
|
-
const importUrl = `${
|
|
282
|
+
const importUrl = `${cdnBaseUrl2}/${name}${versionSuffix}/${mainEntry}`;
|
|
244
283
|
moduleUrl = importUrl;
|
|
245
284
|
const imageModule = await import(
|
|
246
285
|
/* @vite-ignore */
|
|
@@ -271,443 +310,85 @@ async function loadImage(spec) {
|
|
|
271
310
|
var ImageRegistry = class {
|
|
272
311
|
images = /* @__PURE__ */ new Map();
|
|
273
312
|
loading = /* @__PURE__ */ new Map();
|
|
274
|
-
/**
|
|
275
|
-
* Get a loaded image by spec
|
|
276
|
-
*/
|
|
277
|
-
get(spec) {
|
|
278
|
-
const { name } = parseImageSpec(spec);
|
|
279
|
-
return this.images.get(name);
|
|
280
|
-
}
|
|
281
|
-
/**
|
|
282
|
-
* Check if an image is loaded
|
|
283
|
-
*/
|
|
284
|
-
has(spec) {
|
|
285
|
-
const { name } = parseImageSpec(spec);
|
|
286
|
-
return this.images.has(name);
|
|
287
|
-
}
|
|
288
|
-
/**
|
|
289
|
-
* Load an image (or return cached)
|
|
290
|
-
*/
|
|
291
|
-
async load(spec) {
|
|
292
|
-
const { name } = parseImageSpec(spec);
|
|
293
|
-
const cached = this.images.get(name);
|
|
294
|
-
if (cached) {
|
|
295
|
-
return cached;
|
|
296
|
-
}
|
|
297
|
-
const inProgress = this.loading.get(name);
|
|
298
|
-
if (inProgress) {
|
|
299
|
-
return inProgress;
|
|
300
|
-
}
|
|
301
|
-
const loadPromise = loadImage(spec).then((image) => {
|
|
302
|
-
this.images.set(name, image);
|
|
303
|
-
this.loading.delete(name);
|
|
304
|
-
return image;
|
|
305
|
-
});
|
|
306
|
-
this.loading.set(name, loadPromise);
|
|
307
|
-
return loadPromise;
|
|
308
|
-
}
|
|
309
|
-
/**
|
|
310
|
-
* Preload an image
|
|
311
|
-
*/
|
|
312
|
-
async preload(spec) {
|
|
313
|
-
await this.load(spec);
|
|
314
|
-
}
|
|
315
|
-
/**
|
|
316
|
-
* Clear a specific image from cache
|
|
317
|
-
*/
|
|
318
|
-
clear(spec) {
|
|
319
|
-
const { name } = parseImageSpec(spec);
|
|
320
|
-
this.images.delete(name);
|
|
321
|
-
this.loading.delete(name);
|
|
322
|
-
}
|
|
323
|
-
/**
|
|
324
|
-
* Clear all cached images
|
|
325
|
-
*/
|
|
326
|
-
clearAll() {
|
|
327
|
-
this.images.clear();
|
|
328
|
-
this.loading.clear();
|
|
329
|
-
}
|
|
330
|
-
/**
|
|
331
|
-
* Get all loaded image names
|
|
332
|
-
*/
|
|
333
|
-
getLoadedNames() {
|
|
334
|
-
return Array.from(this.images.keys());
|
|
335
|
-
}
|
|
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";
|
|
313
|
+
/**
|
|
314
|
+
* Get a loaded image by spec
|
|
315
|
+
*/
|
|
316
|
+
get(spec) {
|
|
317
|
+
const { name } = parseImageSpec(spec);
|
|
318
|
+
return this.images.get(name);
|
|
636
319
|
}
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
320
|
+
/**
|
|
321
|
+
* Check if an image is loaded
|
|
322
|
+
*/
|
|
323
|
+
has(spec) {
|
|
324
|
+
const { name } = parseImageSpec(spec);
|
|
325
|
+
return this.images.has(name);
|
|
641
326
|
}
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
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
|
-
}
|
|
327
|
+
/**
|
|
328
|
+
* Load an image (or return cached)
|
|
329
|
+
*/
|
|
330
|
+
async load(spec) {
|
|
331
|
+
const { name } = parseImageSpec(spec);
|
|
332
|
+
const cached = this.images.get(name);
|
|
333
|
+
if (cached) {
|
|
334
|
+
return cached;
|
|
657
335
|
}
|
|
658
|
-
|
|
659
|
-
|
|
336
|
+
const inProgress = this.loading.get(name);
|
|
337
|
+
if (inProgress) {
|
|
338
|
+
return inProgress;
|
|
660
339
|
}
|
|
340
|
+
const loadPromise = loadImage(spec).then((image) => {
|
|
341
|
+
this.images.set(name, image);
|
|
342
|
+
this.loading.delete(name);
|
|
343
|
+
return image;
|
|
344
|
+
});
|
|
345
|
+
this.loading.set(name, loadPromise);
|
|
346
|
+
return loadPromise;
|
|
661
347
|
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
for (const ext of extensions) {
|
|
668
|
-
if (project.files.has(path + ext)) return path + ext;
|
|
348
|
+
/**
|
|
349
|
+
* Preload an image
|
|
350
|
+
*/
|
|
351
|
+
async preload(spec) {
|
|
352
|
+
await this.load(spec);
|
|
669
353
|
}
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
354
|
+
/**
|
|
355
|
+
* Clear a specific image from cache
|
|
356
|
+
*/
|
|
357
|
+
clear(spec) {
|
|
358
|
+
const { name } = parseImageSpec(spec);
|
|
359
|
+
this.images.delete(name);
|
|
360
|
+
this.loading.delete(name);
|
|
673
361
|
}
|
|
674
|
-
|
|
362
|
+
/**
|
|
363
|
+
* Clear all cached images
|
|
364
|
+
*/
|
|
365
|
+
clearAll() {
|
|
366
|
+
this.images.clear();
|
|
367
|
+
this.loading.clear();
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Get all loaded image names
|
|
371
|
+
*/
|
|
372
|
+
getLoadedNames() {
|
|
373
|
+
return Array.from(this.images.keys());
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
var globalRegistry = null;
|
|
377
|
+
function getImageRegistry() {
|
|
378
|
+
if (!globalRegistry) {
|
|
379
|
+
globalRegistry = new ImageRegistry();
|
|
380
|
+
}
|
|
381
|
+
return globalRegistry;
|
|
675
382
|
}
|
|
676
|
-
function
|
|
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
|
-
};
|
|
383
|
+
function createImageRegistry() {
|
|
384
|
+
return new ImageRegistry();
|
|
704
385
|
}
|
|
705
386
|
|
|
706
387
|
// src/mount/bridge.ts
|
|
707
388
|
function generateMessageId() {
|
|
708
389
|
return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
|
|
709
390
|
}
|
|
710
|
-
function
|
|
391
|
+
function createHttpProxy(proxyUrl) {
|
|
711
392
|
return {
|
|
712
393
|
async call(namespace, procedure, args) {
|
|
713
394
|
const url = `${proxyUrl}/${namespace}/${procedure}`;
|
|
@@ -851,7 +532,7 @@ var ParentBridge = class {
|
|
|
851
532
|
this.pendingCalls.clear();
|
|
852
533
|
}
|
|
853
534
|
};
|
|
854
|
-
function
|
|
535
|
+
function createIframeProxy() {
|
|
855
536
|
const pendingCalls = /* @__PURE__ */ new Map();
|
|
856
537
|
if (typeof window !== "undefined") {
|
|
857
538
|
window.addEventListener("message", (event) => {
|
|
@@ -983,9 +664,9 @@ function injectImportMap(globals, preloadUrls, deps) {
|
|
|
983
664
|
if (preloadUrls[index]) {
|
|
984
665
|
imports[pkgName] = preloadUrls[index];
|
|
985
666
|
} else if (deps?.[pkgName]) {
|
|
986
|
-
imports[pkgName] =
|
|
667
|
+
imports[pkgName] = toEsmShUrl(pkgName, deps[pkgName]);
|
|
987
668
|
} else {
|
|
988
|
-
imports[pkgName] =
|
|
669
|
+
imports[pkgName] = toEsmShUrl(pkgName);
|
|
989
670
|
}
|
|
990
671
|
});
|
|
991
672
|
if (imports["react-dom"]) {
|
|
@@ -1055,13 +736,11 @@ async function mountEmbedded(widget, options, image, proxy) {
|
|
|
1055
736
|
const deps = frameworkConfig.deps || {};
|
|
1056
737
|
injectImportMap(globalMapping, preloadUrls, deps);
|
|
1057
738
|
const preloadedModules = await Promise.all(
|
|
1058
|
-
preloadUrls.map(
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
)
|
|
1064
|
-
)
|
|
739
|
+
preloadUrls.map((url) => import(
|
|
740
|
+
/* webpackIgnore: true */
|
|
741
|
+
/* @vite-ignore */
|
|
742
|
+
url
|
|
743
|
+
))
|
|
1065
744
|
);
|
|
1066
745
|
const win = window;
|
|
1067
746
|
const globalNames = Object.values(globalMapping);
|
|
@@ -1105,48 +784,198 @@ async function mountEmbedded(widget, options, image, proxy) {
|
|
|
1105
784
|
if (typeof root.unmount === "function") {
|
|
1106
785
|
moduleCleanup = () => root.unmount();
|
|
1107
786
|
}
|
|
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;
|
|
787
|
+
} else if (createElement && renderer?.kind === "render") {
|
|
788
|
+
renderer.render(createElement(Component, inputs), container);
|
|
789
|
+
} else {
|
|
790
|
+
const result = Component(inputs);
|
|
791
|
+
if (result instanceof HTMLElement) {
|
|
792
|
+
container.appendChild(result);
|
|
793
|
+
} else if (typeof result === "string") {
|
|
794
|
+
container.innerHTML = result;
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
} finally {
|
|
799
|
+
URL.revokeObjectURL(scriptUrl);
|
|
800
|
+
}
|
|
801
|
+
const unmount = () => {
|
|
802
|
+
if (moduleCleanup) {
|
|
803
|
+
moduleCleanup();
|
|
804
|
+
}
|
|
805
|
+
removeNamespaceGlobals(window, namespaceNames);
|
|
806
|
+
const style = document.getElementById(`${mountId}-style`);
|
|
807
|
+
if (style) {
|
|
808
|
+
style.remove();
|
|
809
|
+
}
|
|
810
|
+
container.remove();
|
|
811
|
+
};
|
|
812
|
+
return {
|
|
813
|
+
id: mountId,
|
|
814
|
+
widget,
|
|
815
|
+
mode: "embedded",
|
|
816
|
+
target,
|
|
817
|
+
inputs,
|
|
818
|
+
unmount
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
async function reloadEmbedded(mounted, widget, image, proxy) {
|
|
822
|
+
mounted.unmount();
|
|
823
|
+
return mountEmbedded(
|
|
824
|
+
widget,
|
|
825
|
+
{ target: mounted.target, mode: "embedded", inputs: mounted.inputs },
|
|
826
|
+
image,
|
|
827
|
+
proxy
|
|
828
|
+
);
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
// src/transforms/cdn.ts
|
|
832
|
+
var EXTERNAL_PACKAGES = /* @__PURE__ */ new Set(["react", "react-dom", "ink"]);
|
|
833
|
+
var NODE_BUILTINS = /* @__PURE__ */ new Set([
|
|
834
|
+
"assert",
|
|
835
|
+
"buffer",
|
|
836
|
+
"child_process",
|
|
837
|
+
"cluster",
|
|
838
|
+
"crypto",
|
|
839
|
+
"dgram",
|
|
840
|
+
"dns",
|
|
841
|
+
"events",
|
|
842
|
+
"fs",
|
|
843
|
+
"http",
|
|
844
|
+
"http2",
|
|
845
|
+
"https",
|
|
846
|
+
"net",
|
|
847
|
+
"os",
|
|
848
|
+
"path",
|
|
849
|
+
"perf_hooks",
|
|
850
|
+
"process",
|
|
851
|
+
"querystring",
|
|
852
|
+
"readline",
|
|
853
|
+
"stream",
|
|
854
|
+
"string_decoder",
|
|
855
|
+
"timers",
|
|
856
|
+
"tls",
|
|
857
|
+
"tty",
|
|
858
|
+
"url",
|
|
859
|
+
"util",
|
|
860
|
+
"v8",
|
|
861
|
+
"vm",
|
|
862
|
+
"worker_threads",
|
|
863
|
+
"zlib"
|
|
864
|
+
]);
|
|
865
|
+
function cdnTransformPlugin(options = {}) {
|
|
866
|
+
const {
|
|
867
|
+
packages = {},
|
|
868
|
+
external = [],
|
|
869
|
+
bundle = false,
|
|
870
|
+
globals = {},
|
|
871
|
+
deps = {},
|
|
872
|
+
aliases = {}
|
|
873
|
+
} = options;
|
|
874
|
+
const externalSet = /* @__PURE__ */ new Set([...EXTERNAL_PACKAGES, ...external]);
|
|
875
|
+
const globalsSet = new Set(Object.keys(globals));
|
|
876
|
+
return {
|
|
877
|
+
name: "cdn-transform",
|
|
878
|
+
setup(build2) {
|
|
879
|
+
build2.onResolve({ filter: /.*/ }, (args) => {
|
|
880
|
+
const aliasTarget = matchAlias(args.path, aliases);
|
|
881
|
+
if (aliasTarget) {
|
|
882
|
+
const { packageName, subpath } = parseImportPath(aliasTarget);
|
|
883
|
+
if (globalsSet.has(packageName)) {
|
|
884
|
+
return {
|
|
885
|
+
path: aliasTarget,
|
|
886
|
+
namespace: "global-inject"
|
|
887
|
+
};
|
|
888
|
+
}
|
|
889
|
+
const version2 = packages[packageName];
|
|
890
|
+
let url = toEsmShUrl(
|
|
891
|
+
packageName,
|
|
892
|
+
version2,
|
|
893
|
+
subpath,
|
|
894
|
+
Object.keys(deps).length > 0 ? deps : void 0
|
|
895
|
+
);
|
|
896
|
+
if (bundle) {
|
|
897
|
+
url += url.includes("?") ? "&bundle" : "?bundle";
|
|
898
|
+
}
|
|
899
|
+
return {
|
|
900
|
+
path: url,
|
|
901
|
+
external: true
|
|
902
|
+
};
|
|
903
|
+
}
|
|
904
|
+
return null;
|
|
905
|
+
});
|
|
906
|
+
build2.onResolve({ filter: /.*/ }, (args) => {
|
|
907
|
+
if (!isBareImport(args.path)) {
|
|
908
|
+
return null;
|
|
909
|
+
}
|
|
910
|
+
const { packageName } = parseImportPath(args.path);
|
|
911
|
+
if (globalsSet.has(packageName)) {
|
|
912
|
+
return {
|
|
913
|
+
path: args.path,
|
|
914
|
+
namespace: "global-inject"
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
return null;
|
|
918
|
+
});
|
|
919
|
+
build2.onLoad({ filter: /.*/, namespace: "global-inject" }, (args) => {
|
|
920
|
+
const { packageName, subpath } = parseImportPath(args.path);
|
|
921
|
+
const globalName = globals[packageName];
|
|
922
|
+
if (!globalName) return null;
|
|
923
|
+
if (subpath) {
|
|
924
|
+
return {
|
|
925
|
+
contents: `export * from '${packageName}'; export { default } from '${packageName}';`,
|
|
926
|
+
loader: "js"
|
|
927
|
+
};
|
|
928
|
+
}
|
|
929
|
+
const contents = `
|
|
930
|
+
const mod = window.${globalName};
|
|
931
|
+
export default mod;
|
|
932
|
+
// Re-export all properties as named exports
|
|
933
|
+
const { ${getCommonExports(packageName).join(", ")} } = mod;
|
|
934
|
+
export { ${getCommonExports(packageName).join(", ")} };
|
|
935
|
+
`;
|
|
936
|
+
return {
|
|
937
|
+
contents,
|
|
938
|
+
loader: "js"
|
|
939
|
+
};
|
|
940
|
+
});
|
|
941
|
+
build2.onResolve({ filter: /.*/ }, (args) => {
|
|
942
|
+
if (!isBareImport(args.path)) {
|
|
943
|
+
return null;
|
|
1116
944
|
}
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
945
|
+
if (NODE_BUILTINS.has(args.path)) {
|
|
946
|
+
return { external: true };
|
|
947
|
+
}
|
|
948
|
+
const { packageName, subpath } = parseImportPath(args.path);
|
|
949
|
+
if (globalsSet.has(packageName)) {
|
|
950
|
+
return null;
|
|
951
|
+
}
|
|
952
|
+
if (externalSet.has(packageName)) {
|
|
953
|
+
return { external: true };
|
|
954
|
+
}
|
|
955
|
+
const version2 = packages[packageName];
|
|
956
|
+
let url = toEsmShUrl(
|
|
957
|
+
packageName,
|
|
958
|
+
version2,
|
|
959
|
+
subpath,
|
|
960
|
+
Object.keys(deps).length > 0 ? deps : void 0
|
|
961
|
+
);
|
|
962
|
+
if (bundle) {
|
|
963
|
+
url += url.includes("?") ? "&bundle" : "?bundle";
|
|
964
|
+
}
|
|
965
|
+
return {
|
|
966
|
+
path: url,
|
|
967
|
+
external: true
|
|
968
|
+
};
|
|
969
|
+
});
|
|
1130
970
|
}
|
|
1131
|
-
container.remove();
|
|
1132
|
-
};
|
|
1133
|
-
return {
|
|
1134
|
-
id: mountId,
|
|
1135
|
-
widget,
|
|
1136
|
-
mode: "embedded",
|
|
1137
|
-
target,
|
|
1138
|
-
inputs,
|
|
1139
|
-
unmount
|
|
1140
971
|
};
|
|
1141
972
|
}
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
proxy
|
|
1149
|
-
);
|
|
973
|
+
function generateImportMap(packages) {
|
|
974
|
+
const imports = {};
|
|
975
|
+
for (const [name, version2] of Object.entries(packages)) {
|
|
976
|
+
imports[name] = toEsmShUrl(name, version2);
|
|
977
|
+
}
|
|
978
|
+
return imports;
|
|
1150
979
|
}
|
|
1151
980
|
|
|
1152
981
|
// src/mount/iframe.ts
|
|
@@ -1474,20 +1303,183 @@ function disposeIframeBridge() {
|
|
|
1474
1303
|
}
|
|
1475
1304
|
}
|
|
1476
1305
|
|
|
1306
|
+
// src/transforms/vfs.ts
|
|
1307
|
+
function dirname(path) {
|
|
1308
|
+
const idx = path.lastIndexOf("/");
|
|
1309
|
+
return idx === -1 ? "." : path.slice(0, idx) || ".";
|
|
1310
|
+
}
|
|
1311
|
+
function normalizePath(path) {
|
|
1312
|
+
const parts = [];
|
|
1313
|
+
for (const segment of path.split("/")) {
|
|
1314
|
+
if (segment === "..") parts.pop();
|
|
1315
|
+
else if (segment && segment !== ".") parts.push(segment);
|
|
1316
|
+
}
|
|
1317
|
+
return parts.join("/");
|
|
1318
|
+
}
|
|
1319
|
+
function inferLoader(path, language) {
|
|
1320
|
+
if (language) {
|
|
1321
|
+
switch (language) {
|
|
1322
|
+
case "typescript":
|
|
1323
|
+
case "ts":
|
|
1324
|
+
return "ts";
|
|
1325
|
+
case "tsx":
|
|
1326
|
+
return "tsx";
|
|
1327
|
+
case "javascript":
|
|
1328
|
+
case "js":
|
|
1329
|
+
return "js";
|
|
1330
|
+
case "jsx":
|
|
1331
|
+
return "jsx";
|
|
1332
|
+
case "json":
|
|
1333
|
+
return "json";
|
|
1334
|
+
case "css":
|
|
1335
|
+
return "css";
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
const ext = path.split(".").pop();
|
|
1339
|
+
switch (ext) {
|
|
1340
|
+
case "ts":
|
|
1341
|
+
return "ts";
|
|
1342
|
+
case "tsx":
|
|
1343
|
+
return "tsx";
|
|
1344
|
+
case "js":
|
|
1345
|
+
return "js";
|
|
1346
|
+
case "jsx":
|
|
1347
|
+
return "jsx";
|
|
1348
|
+
case "json":
|
|
1349
|
+
return "json";
|
|
1350
|
+
case "css":
|
|
1351
|
+
return "css";
|
|
1352
|
+
default:
|
|
1353
|
+
return "tsx";
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
function normalizeVFSPath(path) {
|
|
1357
|
+
if (path.startsWith("@/")) {
|
|
1358
|
+
return path.slice(2);
|
|
1359
|
+
}
|
|
1360
|
+
return path;
|
|
1361
|
+
}
|
|
1362
|
+
function resolveRelativePath(importer, target) {
|
|
1363
|
+
const importerDir = dirname(normalizeVFSPath(importer));
|
|
1364
|
+
const combined = importerDir === "." ? target : `${importerDir}/${target}`;
|
|
1365
|
+
return normalizePath(combined);
|
|
1366
|
+
}
|
|
1367
|
+
function matchAlias2(importPath, aliases) {
|
|
1368
|
+
if (!aliases) return null;
|
|
1369
|
+
for (const [pattern, target] of Object.entries(aliases)) {
|
|
1370
|
+
if (pattern.endsWith("/*")) {
|
|
1371
|
+
const prefix = pattern.slice(0, -2);
|
|
1372
|
+
if (importPath === prefix || importPath.startsWith(prefix + "/")) {
|
|
1373
|
+
return target;
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
if (importPath === pattern) {
|
|
1377
|
+
return target;
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
return null;
|
|
1381
|
+
}
|
|
1382
|
+
function findFile(project, path) {
|
|
1383
|
+
if (project.files.has(path)) return path;
|
|
1384
|
+
const extensions = [".tsx", ".ts", ".jsx", ".js", ".json"];
|
|
1385
|
+
for (const ext of extensions) {
|
|
1386
|
+
if (project.files.has(path + ext)) return path + ext;
|
|
1387
|
+
}
|
|
1388
|
+
for (const ext of extensions) {
|
|
1389
|
+
const indexPath = `${path}/index${ext}`;
|
|
1390
|
+
if (project.files.has(indexPath)) return indexPath;
|
|
1391
|
+
}
|
|
1392
|
+
return null;
|
|
1393
|
+
}
|
|
1394
|
+
function vfsPlugin(project, options = {}) {
|
|
1395
|
+
return {
|
|
1396
|
+
name: "patchwork-vfs",
|
|
1397
|
+
setup(build2) {
|
|
1398
|
+
build2.onResolve({ filter: /^@\// }, (args) => {
|
|
1399
|
+
const aliased = matchAlias2(args.path, options.aliases);
|
|
1400
|
+
if (aliased) return null;
|
|
1401
|
+
return { path: args.path, namespace: "vfs" };
|
|
1402
|
+
});
|
|
1403
|
+
build2.onResolve({ filter: /^\./ }, (args) => {
|
|
1404
|
+
const fromEntry = args.namespace !== "vfs" && args.importer === project.entry;
|
|
1405
|
+
if (args.namespace !== "vfs" && !fromEntry) return null;
|
|
1406
|
+
const resolved = resolveRelativePath(args.importer, args.path);
|
|
1407
|
+
return { path: resolved, namespace: "vfs" };
|
|
1408
|
+
});
|
|
1409
|
+
build2.onLoad({ filter: /.*/, namespace: "vfs" }, (args) => {
|
|
1410
|
+
const normalPath = normalizeVFSPath(args.path);
|
|
1411
|
+
const filePath = findFile(project, normalPath);
|
|
1412
|
+
if (!filePath) {
|
|
1413
|
+
throw new Error(`File not found in VFS: ${args.path}`);
|
|
1414
|
+
}
|
|
1415
|
+
const file = project.files.get(filePath);
|
|
1416
|
+
return {
|
|
1417
|
+
contents: file.content,
|
|
1418
|
+
loader: inferLoader(filePath, file.language)
|
|
1419
|
+
};
|
|
1420
|
+
});
|
|
1421
|
+
}
|
|
1422
|
+
};
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
// src/vfs/project.ts
|
|
1426
|
+
function createProjectFromFiles(files, id = crypto.randomUUID()) {
|
|
1427
|
+
const fileMap = /* @__PURE__ */ new Map();
|
|
1428
|
+
for (const file of files) {
|
|
1429
|
+
fileMap.set(file.path, file);
|
|
1430
|
+
}
|
|
1431
|
+
return { id, entry: resolveEntry(fileMap), files: fileMap };
|
|
1432
|
+
}
|
|
1433
|
+
function resolveEntry(files) {
|
|
1434
|
+
const paths = Array.from(files.keys());
|
|
1435
|
+
const mainFile = paths.find((p) => /\bmain\.(tsx?|jsx?)$/.test(p));
|
|
1436
|
+
if (mainFile) return mainFile;
|
|
1437
|
+
const indexFile = paths.find((p) => /\bindex\.(tsx?|jsx?)$/.test(p));
|
|
1438
|
+
if (indexFile) return indexFile;
|
|
1439
|
+
const firstTsx = paths.find((p) => /\.(tsx|jsx)$/.test(p));
|
|
1440
|
+
if (firstTsx) return firstTsx;
|
|
1441
|
+
return paths[0] || "main.tsx";
|
|
1442
|
+
}
|
|
1443
|
+
function detectMainFile(language) {
|
|
1444
|
+
switch (language) {
|
|
1445
|
+
case "tsx":
|
|
1446
|
+
case "typescript":
|
|
1447
|
+
return "main.tsx";
|
|
1448
|
+
case "jsx":
|
|
1449
|
+
case "javascript":
|
|
1450
|
+
return "main.jsx";
|
|
1451
|
+
case "ts":
|
|
1452
|
+
return "main.ts";
|
|
1453
|
+
case "js":
|
|
1454
|
+
return "main.js";
|
|
1455
|
+
default:
|
|
1456
|
+
return "main.tsx";
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
function createSingleFileProject(content, entry = "main.tsx", id = "inline") {
|
|
1460
|
+
return {
|
|
1461
|
+
id,
|
|
1462
|
+
entry,
|
|
1463
|
+
files: /* @__PURE__ */ new Map([[entry, { path: entry, content }]])
|
|
1464
|
+
};
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1477
1467
|
// src/compiler.ts
|
|
1478
1468
|
var esbuildInitialized = false;
|
|
1479
1469
|
var esbuildInitPromise = null;
|
|
1480
|
-
|
|
1470
|
+
var DEFAULT_ESBUILD_WASM_URL = `https://unpkg.com/esbuild-wasm@${esbuild.version}/esbuild.wasm`;
|
|
1471
|
+
async function initEsbuild(urlOverrides) {
|
|
1481
1472
|
if (esbuildInitialized) return;
|
|
1482
1473
|
if (esbuildInitPromise) return esbuildInitPromise;
|
|
1474
|
+
const wasmUrl = urlOverrides?.["esbuild-wasm/esbuild.wasm"] || DEFAULT_ESBUILD_WASM_URL;
|
|
1483
1475
|
esbuildInitPromise = (async () => {
|
|
1484
1476
|
try {
|
|
1485
1477
|
await esbuild.initialize({
|
|
1486
|
-
wasmURL:
|
|
1478
|
+
wasmURL: wasmUrl
|
|
1487
1479
|
});
|
|
1488
1480
|
esbuildInitialized = true;
|
|
1489
1481
|
} catch (error) {
|
|
1490
|
-
if (error instanceof Error && error.message.includes("
|
|
1482
|
+
if (error instanceof Error && error.message.includes("initialize")) {
|
|
1491
1483
|
esbuildInitialized = true;
|
|
1492
1484
|
} else {
|
|
1493
1485
|
throw error;
|
|
@@ -1506,19 +1498,19 @@ function hashContent(content) {
|
|
|
1506
1498
|
return Math.abs(hash).toString(16).padStart(8, "0");
|
|
1507
1499
|
}
|
|
1508
1500
|
async function createCompiler(options) {
|
|
1509
|
-
await initEsbuild();
|
|
1510
|
-
const { image: imageSpec, proxyUrl, cdnBaseUrl:
|
|
1511
|
-
if (
|
|
1512
|
-
setCdnBaseUrl(
|
|
1501
|
+
await initEsbuild(options.urlOverrides);
|
|
1502
|
+
const { image: imageSpec, proxyUrl, cdnBaseUrl: cdnBaseUrl2, widgetCdnBaseUrl } = options;
|
|
1503
|
+
if (cdnBaseUrl2) {
|
|
1504
|
+
setCdnBaseUrl(cdnBaseUrl2);
|
|
1513
1505
|
}
|
|
1514
1506
|
if (widgetCdnBaseUrl) {
|
|
1515
|
-
|
|
1516
|
-
} else if (
|
|
1517
|
-
|
|
1507
|
+
setCdnBaseUrl(widgetCdnBaseUrl);
|
|
1508
|
+
} else if (cdnBaseUrl2) {
|
|
1509
|
+
setCdnBaseUrl(cdnBaseUrl2);
|
|
1518
1510
|
}
|
|
1519
1511
|
const registry = getImageRegistry();
|
|
1520
1512
|
await registry.preload(imageSpec);
|
|
1521
|
-
const proxy =
|
|
1513
|
+
const proxy = createHttpProxy(proxyUrl);
|
|
1522
1514
|
return new PatchworkCompiler(proxy, registry);
|
|
1523
1515
|
}
|
|
1524
1516
|
var PatchworkCompiler = class {
|
|
@@ -1795,11 +1787,13 @@ var VirtualFS = class {
|
|
|
1795
1787
|
return this.backend.readFile(path, encoding);
|
|
1796
1788
|
}
|
|
1797
1789
|
async writeFile(path, content) {
|
|
1790
|
+
await this.ensureParentDir(path);
|
|
1798
1791
|
const existed = await this.backend.exists(path);
|
|
1799
1792
|
await this.backend.writeFile(path, content);
|
|
1800
1793
|
this.recordChange(path, existed ? "update" : "create");
|
|
1801
1794
|
}
|
|
1802
1795
|
async applyRemoteFile(path, content) {
|
|
1796
|
+
await this.ensureParentDir(path);
|
|
1803
1797
|
await this.backend.writeFile(path, content);
|
|
1804
1798
|
}
|
|
1805
1799
|
async applyRemoteDelete(path) {
|
|
@@ -1871,6 +1865,11 @@ var VirtualFS = class {
|
|
|
1871
1865
|
listener(record);
|
|
1872
1866
|
}
|
|
1873
1867
|
}
|
|
1868
|
+
async ensureParentDir(path) {
|
|
1869
|
+
const dir = dirname2(path);
|
|
1870
|
+
if (!dir) return;
|
|
1871
|
+
await this.backend.mkdir(dir, { recursive: true });
|
|
1872
|
+
}
|
|
1874
1873
|
};
|
|
1875
1874
|
|
|
1876
1875
|
// src/vfs/sync/differ.ts
|
|
@@ -1934,6 +1933,8 @@ var SyncEngineImpl = class {
|
|
|
1934
1933
|
this.basePath = config.basePath ?? "";
|
|
1935
1934
|
this.startRemoteWatch();
|
|
1936
1935
|
}
|
|
1936
|
+
local;
|
|
1937
|
+
remote;
|
|
1937
1938
|
status = "idle";
|
|
1938
1939
|
intervalId;
|
|
1939
1940
|
listeners = /* @__PURE__ */ new Map();
|
|
@@ -2239,7 +2240,7 @@ function openDB() {
|
|
|
2239
2240
|
const request = indexedDB.open(DB_NAME, DB_VERSION);
|
|
2240
2241
|
request.onerror = () => reject(request.error);
|
|
2241
2242
|
request.onsuccess = () => resolve(request.result);
|
|
2242
|
-
request.onupgradeneeded = (
|
|
2243
|
+
request.onupgradeneeded = (_event) => {
|
|
2243
2244
|
const db = request.result;
|
|
2244
2245
|
if (!db.objectStoreNames.contains(FILES_STORE)) {
|
|
2245
2246
|
db.createObjectStore(FILES_STORE);
|
|
@@ -2265,6 +2266,7 @@ var IndexedDBBackend = class {
|
|
|
2265
2266
|
constructor(prefix = "vfs") {
|
|
2266
2267
|
this.prefix = prefix;
|
|
2267
2268
|
}
|
|
2269
|
+
prefix;
|
|
2268
2270
|
key(path) {
|
|
2269
2271
|
return `${this.prefix}:${normalizePath2(path)}`;
|
|
2270
2272
|
}
|
|
@@ -2435,6 +2437,7 @@ var HttpBackend = class {
|
|
|
2435
2437
|
constructor(config) {
|
|
2436
2438
|
this.config = config;
|
|
2437
2439
|
}
|
|
2440
|
+
config;
|
|
2438
2441
|
async readFile(path) {
|
|
2439
2442
|
const res = await fetch(this.url(path));
|
|
2440
2443
|
if (!res.ok) throw new Error(`ENOENT: ${path}`);
|
|
@@ -2538,6 +2541,7 @@ var VFSStore = class {
|
|
|
2538
2541
|
}
|
|
2539
2542
|
}
|
|
2540
2543
|
}
|
|
2544
|
+
provider;
|
|
2541
2545
|
local;
|
|
2542
2546
|
syncEngine;
|
|
2543
2547
|
root;
|
|
@@ -2647,6 +2651,13 @@ var VFSStore = class {
|
|
|
2647
2651
|
)
|
|
2648
2652
|
);
|
|
2649
2653
|
}
|
|
2654
|
+
watch(path, callback) {
|
|
2655
|
+
if (this.provider.watch) {
|
|
2656
|
+
return this.provider.watch(this.remotePath(path), callback);
|
|
2657
|
+
}
|
|
2658
|
+
return () => {
|
|
2659
|
+
};
|
|
2660
|
+
}
|
|
2650
2661
|
async sync() {
|
|
2651
2662
|
if (!this.syncEngine) {
|
|
2652
2663
|
return { pushed: 0, pulled: 0, conflicts: [] };
|
|
@@ -2683,6 +2694,7 @@ var VFSStore = class {
|
|
|
2683
2694
|
};
|
|
2684
2695
|
export {
|
|
2685
2696
|
CompileOptionsSchema,
|
|
2697
|
+
DEFAULT_CDN_BASE,
|
|
2686
2698
|
DEFAULT_CLI_IMAGE_CONFIG,
|
|
2687
2699
|
DEFAULT_IMAGE_CONFIG,
|
|
2688
2700
|
DEV_SANDBOX,
|
|
@@ -2701,8 +2713,8 @@ export {
|
|
|
2701
2713
|
cdnTransformPlugin,
|
|
2702
2714
|
createCompiler,
|
|
2703
2715
|
createFieldAccessProxy,
|
|
2704
|
-
|
|
2705
|
-
|
|
2716
|
+
createHttpProxy,
|
|
2717
|
+
createIframeProxy,
|
|
2706
2718
|
createImageRegistry,
|
|
2707
2719
|
createProjectFromFiles,
|
|
2708
2720
|
createSingleFileProject,
|
|
@@ -2714,14 +2726,19 @@ export {
|
|
|
2714
2726
|
generateImportMap,
|
|
2715
2727
|
generateNamespaceGlobals,
|
|
2716
2728
|
getCdnBaseUrl,
|
|
2729
|
+
getCommonExports,
|
|
2717
2730
|
getImageRegistry,
|
|
2718
2731
|
injectNamespaceGlobals,
|
|
2732
|
+
isBareImport,
|
|
2719
2733
|
loadImage,
|
|
2734
|
+
matchAlias,
|
|
2720
2735
|
mountEmbedded,
|
|
2721
2736
|
mountIframe,
|
|
2722
2737
|
parseImageConfig,
|
|
2723
2738
|
parseImageSpec,
|
|
2739
|
+
parseImportPath,
|
|
2724
2740
|
parseManifest,
|
|
2741
|
+
parsePackageSpec,
|
|
2725
2742
|
reloadEmbedded,
|
|
2726
2743
|
reloadIframe,
|
|
2727
2744
|
removeNamespaceGlobals,
|
|
@@ -2729,6 +2746,7 @@ export {
|
|
|
2729
2746
|
safeParseImageConfig,
|
|
2730
2747
|
safeParseManifest,
|
|
2731
2748
|
setCdnBaseUrl,
|
|
2749
|
+
toEsmShUrl,
|
|
2732
2750
|
vfsPlugin
|
|
2733
2751
|
};
|
|
2734
2752
|
//# sourceMappingURL=index.js.map
|