veryfront 0.1.1095 → 0.1.1098
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/esm/deno.js +1 -1
- package/esm/src/rendering/orchestrator/module-loader/esm-rewriter.d.ts.map +1 -1
- package/esm/src/rendering/orchestrator/module-loader/esm-rewriter.js +49 -6
- package/esm/src/rendering/orchestrator/module-loader/index.js +1 -1
- package/esm/src/transforms/esm/specifier-resolver.d.ts +3 -0
- package/esm/src/transforms/esm/specifier-resolver.d.ts.map +1 -1
- package/esm/src/transforms/esm/specifier-resolver.js +54 -4
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +5 -5
package/esm/deno.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"esm-rewriter.d.ts","sourceRoot":"","sources":["../../../../../src/src/rendering/orchestrator/module-loader/esm-rewriter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"esm-rewriter.d.ts","sourceRoot":"","sources":["../../../../../src/src/rendering/orchestrator/module-loader/esm-rewriter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAkCzE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAmCrE;AAED,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,cAAc,EAC5B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC,CAwEjB"}
|
|
@@ -1,7 +1,28 @@
|
|
|
1
1
|
import { rendererLogger } from "../../../utils/index.js";
|
|
2
2
|
import { MODULE_NOT_FOUND } from "../../../errors/index.js";
|
|
3
3
|
import { generateHash } from "./cache.js";
|
|
4
|
+
import { parseImports } from "../../../transforms/esm/lexer.js";
|
|
4
5
|
const logger = rendererLogger.component("module-loader");
|
|
6
|
+
/**
|
|
7
|
+
* Specifiers `code` imports statically, as opposed to through `import(...)` or
|
|
8
|
+
* merely mentioning in a string.
|
|
9
|
+
*
|
|
10
|
+
* A lex failure returns every discovered specifier as static, so an unparseable
|
|
11
|
+
* bundle keeps the pre-graceful-degradation behaviour of failing loudly rather
|
|
12
|
+
* than quietly shipping a remote dependency.
|
|
13
|
+
*/
|
|
14
|
+
async function staticImportSpecifiers(code) {
|
|
15
|
+
try {
|
|
16
|
+
const imports = await parseImports(code);
|
|
17
|
+
return new Set(imports.filter((imp) => imp.d === -1 && imp.n).map((imp) => imp.n));
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
logger.debug("Could not lex a fetched module; treating its imports as static", {
|
|
21
|
+
error: error instanceof Error ? error.message : String(error),
|
|
22
|
+
});
|
|
23
|
+
return new Set(code.match(/https:\/\/esm\.sh\/[^"']+/g) ?? []);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
5
26
|
function escapeRegExp(value) {
|
|
6
27
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7
28
|
}
|
|
@@ -53,17 +74,39 @@ export async function fetchEsmModule(url, tmpDir, localAdapter, esmCache) {
|
|
|
53
74
|
allEsmUrls.add(match[1]);
|
|
54
75
|
}
|
|
55
76
|
const urlArray = Array.from(allEsmUrls);
|
|
56
|
-
const
|
|
77
|
+
const staticUrls = await staticImportSpecifiers(code);
|
|
78
|
+
// Nested pre-fetches of a URL this module only reaches lazily are
|
|
79
|
+
// best-effort: a broken esm.sh build for one package logs a warning and the
|
|
80
|
+
// URL stays in the emitted code for the runtime to resolve at call time. A
|
|
81
|
+
// URL the module imports statically is part of its own import graph and must
|
|
82
|
+
// still resolve here, so the emitted artifact's static dependencies stay
|
|
83
|
+
// local. See `transforms/esm/specifier-resolver.ts` for the same rule on the
|
|
84
|
+
// SSR transform path.
|
|
85
|
+
const settledPaths = await Promise.allSettled(urlArray.map((esmUrl) => fetchEsmModule(esmUrl, tmpDir, localAdapter, esmCache)));
|
|
57
86
|
if (urlArray.length) {
|
|
58
87
|
const replacementMap = new Map();
|
|
59
88
|
for (let i = 0; i < urlArray.length; i++) {
|
|
60
89
|
const url = urlArray[i];
|
|
61
|
-
const
|
|
62
|
-
if (url
|
|
63
|
-
|
|
90
|
+
const result = settledPaths[i];
|
|
91
|
+
if (!url || !result)
|
|
92
|
+
continue;
|
|
93
|
+
if (result.status === "fulfilled") {
|
|
94
|
+
replacementMap.set(url, `file://${result.value}`);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
// A statically imported dependency must be local before this module is
|
|
98
|
+
// handed to the runtime loader, so its failure stays fatal.
|
|
99
|
+
if (staticUrls.has(url))
|
|
100
|
+
throw result.reason;
|
|
101
|
+
logger.warn("Leaving an unfetchable lazy esm.sh module for runtime resolution", {
|
|
102
|
+
url,
|
|
103
|
+
error: result.reason instanceof Error ? result.reason.message : String(result.reason),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
if (replacementMap.size) {
|
|
107
|
+
const combinedPattern = new RegExp(Array.from(replacementMap.keys()).map(escapeRegExp).join("|"), "g");
|
|
108
|
+
code = code.replace(combinedPattern, (m) => replacementMap.get(m) ?? m);
|
|
64
109
|
}
|
|
65
|
-
const combinedPattern = new RegExp(urlArray.map(escapeRegExp).join("|"), "g");
|
|
66
|
-
code = code.replace(combinedPattern, (m) => replacementMap.get(m) ?? m);
|
|
67
110
|
}
|
|
68
111
|
const hash = await generateHash(url);
|
|
69
112
|
const tempFilePath = `${tmpDir}/esm-${hash}.js`;
|
|
@@ -147,7 +147,7 @@ export async function loadModule(filePath, config) {
|
|
|
147
147
|
const tmpDir = await getModuleCacheDir(config);
|
|
148
148
|
const localAdapter = await getLocalAdapter();
|
|
149
149
|
const tempFilePath = await transformModuleWithDeps(filePath, tmpDir, localAdapter, config);
|
|
150
|
-
const moduleUrl = `file://${tempFilePath}
|
|
150
|
+
const moduleUrl = `file://${tempFilePath}`;
|
|
151
151
|
try {
|
|
152
152
|
return await import(moduleUrl);
|
|
153
153
|
}
|
|
@@ -11,6 +11,9 @@ import { type CacheOptions } from "./http-cache-helpers.js";
|
|
|
11
11
|
export type CacheHttpModuleFn = (url: string, options: CacheOptions) => Promise<string | null>;
|
|
12
12
|
/**
|
|
13
13
|
* Build a map of specifier replacements by resolving all imports in the code.
|
|
14
|
+
*
|
|
15
|
+
* Resolution failure is fatal for a static import and best-effort for a
|
|
16
|
+
* specifier only ever used in `import(...)`. See {@link isDynamicOnly}.
|
|
14
17
|
*/
|
|
15
18
|
export declare function buildReplacements(code: string, baseUrl: string | undefined, options: CacheOptions, cacheHttpModule: CacheHttpModuleFn): Promise<Map<string, string>>;
|
|
16
19
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"specifier-resolver.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/specifier-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"specifier-resolver.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/specifier-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH,OAAO,EACL,KAAK,YAAY,EAQlB,MAAM,yBAAyB,CAAC;AAEjC,kFAAkF;AAClF,MAAM,MAAM,iBAAiB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AA4G/F;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,OAAO,EAAE,YAAY,EACrB,eAAe,EAAE,iBAAiB,GACjC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAoC9B;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,YAAY,EACrB,eAAe,EAAE,iBAAiB,GACjC,OAAO,CAAC,MAAM,CAAC,CAKjB"}
|
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { basename } from "../../platform/compat/path/index.js";
|
|
10
10
|
import { resolveImport } from "../../modules/import-map/resolver.js";
|
|
11
|
+
import { rendererLogger } from "../../utils/index.js";
|
|
11
12
|
import { parseImports, replaceSpecifiers } from "./lexer.js";
|
|
13
|
+
const logger = rendererLogger.component("specifier-resolver");
|
|
12
14
|
import { isCanonicalReactEsmUrl, isExternalScheme, isHttpUrl, isInternalBare, isParentHttpModule, isRelative, resolveBareSpecifier, } from "./http-cache-helpers.js";
|
|
13
15
|
function isLocalMappedSpecifier(specifier) {
|
|
14
16
|
return specifier.startsWith("/_vf_modules/") ||
|
|
@@ -80,20 +82,68 @@ async function resolveSpecifier(specifier, baseUrl, options, cacheHttpModule) {
|
|
|
80
82
|
return mapped;
|
|
81
83
|
return resolveSpecifier(mapped, baseUrl, options, cacheHttpModule);
|
|
82
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Specifiers this module only ever reaches through `import(...)`.
|
|
87
|
+
*
|
|
88
|
+
* The distinction decides what a resolution failure means. A static import is
|
|
89
|
+
* part of the emitted module's own import graph, so the artifact contract holds
|
|
90
|
+
* for it: every static dependency resolves to a local path before the module is
|
|
91
|
+
* handed to the runtime loader, and a failure to do that is fatal, exactly as
|
|
92
|
+
* it was before graceful degradation existed.
|
|
93
|
+
*
|
|
94
|
+
* A dynamic specifier is resolved by the runtime at call time and is routinely
|
|
95
|
+
* guarded by the caller (`platform/adapters/redis/modules.js` only calls
|
|
96
|
+
* `await import("redis")` when the redis adapter is actually used). Pre-fetching
|
|
97
|
+
* it is an optimisation, so failing to pre-fetch it leaves the specifier in
|
|
98
|
+
* place rather than taking down a render that would never have imported it.
|
|
99
|
+
*/
|
|
100
|
+
function isDynamicOnly(imports) {
|
|
101
|
+
const dynamic = new Set();
|
|
102
|
+
const staticSpecifiers = new Set();
|
|
103
|
+
for (const imp of imports) {
|
|
104
|
+
if (!imp.n)
|
|
105
|
+
continue;
|
|
106
|
+
(imp.d > -1 ? dynamic : staticSpecifiers).add(imp.n);
|
|
107
|
+
}
|
|
108
|
+
for (const specifier of staticSpecifiers)
|
|
109
|
+
dynamic.delete(specifier);
|
|
110
|
+
return dynamic;
|
|
111
|
+
}
|
|
83
112
|
/**
|
|
84
113
|
* Build a map of specifier replacements by resolving all imports in the code.
|
|
114
|
+
*
|
|
115
|
+
* Resolution failure is fatal for a static import and best-effort for a
|
|
116
|
+
* specifier only ever used in `import(...)`. See {@link isDynamicOnly}.
|
|
85
117
|
*/
|
|
86
118
|
export async function buildReplacements(code, baseUrl, options, cacheHttpModule) {
|
|
87
119
|
const imports = await parseImports(code);
|
|
88
120
|
const uniqueSpecifiers = [...new Set(imports.map((imp) => imp.n).filter(Boolean))];
|
|
89
|
-
const
|
|
121
|
+
const dynamicOnly = isDynamicOnly(imports);
|
|
122
|
+
const settled = await Promise.allSettled(uniqueSpecifiers.map(async (specifier) => ({
|
|
90
123
|
specifier,
|
|
91
124
|
resolved: await resolveSpecifier(specifier, baseUrl, options, cacheHttpModule),
|
|
92
125
|
})));
|
|
93
126
|
const replacements = new Map();
|
|
94
|
-
for (
|
|
95
|
-
|
|
96
|
-
|
|
127
|
+
for (let i = 0; i < settled.length; i++) {
|
|
128
|
+
const outcome = settled[i];
|
|
129
|
+
const specifier = uniqueSpecifiers[i];
|
|
130
|
+
if (!outcome || specifier === undefined)
|
|
131
|
+
continue;
|
|
132
|
+
if (outcome.status === "fulfilled") {
|
|
133
|
+
const { specifier: resolvedFor, resolved } = outcome.value;
|
|
134
|
+
if (resolved && resolved !== resolvedFor)
|
|
135
|
+
replacements.set(resolvedFor, resolved);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
// A static import must resolve. Leaving one unresolved would emit a module
|
|
139
|
+
// whose own import graph reaches outside the local cache, which is not what
|
|
140
|
+
// the runtime loader is handed anywhere else.
|
|
141
|
+
if (!dynamicOnly.has(specifier))
|
|
142
|
+
throw outcome.reason;
|
|
143
|
+
logger.warn("Leaving an unresolvable dynamic specifier for runtime resolution", {
|
|
144
|
+
specifier,
|
|
145
|
+
error: outcome.reason instanceof Error ? outcome.reason.message : String(outcome.reason),
|
|
146
|
+
});
|
|
97
147
|
}
|
|
98
148
|
return replacements;
|
|
99
149
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "veryfront",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1098",
|
|
4
4
|
"description": "The simplest way to build AI-powered apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -328,10 +328,10 @@
|
|
|
328
328
|
"@types/react": "19.2.14",
|
|
329
329
|
"@types/react-dom": "19.2.3",
|
|
330
330
|
"ws": "8.21.0",
|
|
331
|
-
"@veryfront/ext-bundler-esbuild": "0.1.
|
|
332
|
-
"@veryfront/ext-content-mdx": "0.1.
|
|
333
|
-
"@veryfront/ext-css-tailwind": "0.1.
|
|
334
|
-
"@veryfront/ext-parser-babel": "0.1.
|
|
331
|
+
"@veryfront/ext-bundler-esbuild": "0.1.1098",
|
|
332
|
+
"@veryfront/ext-content-mdx": "0.1.1098",
|
|
333
|
+
"@veryfront/ext-css-tailwind": "0.1.1098",
|
|
334
|
+
"@veryfront/ext-parser-babel": "0.1.1098"
|
|
335
335
|
},
|
|
336
336
|
"devDependencies": {
|
|
337
337
|
"@types/node": "20.9.0"
|