veryfront 0.1.1102 → 0.1.1104
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/agent/ag-ui/tool-shared.d.ts.map +1 -1
- package/esm/src/agent/ag-ui/tool-shared.js +0 -4
- package/esm/src/agent/factory.d.ts.map +1 -1
- package/esm/src/agent/factory.js +29 -31
- package/esm/src/agent/hosted/chat-preparation.d.ts +1 -0
- package/esm/src/agent/hosted/chat-preparation.d.ts.map +1 -1
- package/esm/src/agent/hosted/chat-preparation.js +20 -12
- package/esm/src/agent/hosted/default-project-steering-refresh.d.ts +1 -1
- package/esm/src/agent/hosted/default-project-steering-refresh.d.ts.map +1 -1
- package/esm/src/agent/hosted/default-project-steering-refresh.js +5 -9
- package/esm/src/agent/hosted/runtime-essential-tools.d.ts +1 -1
- package/esm/src/agent/hosted/runtime-essential-tools.d.ts.map +1 -1
- package/esm/src/agent/hosted/runtime-essential-tools.js +14 -5
- package/esm/src/agent/hosted/veryfront-cloud-agent-service.d.ts.map +1 -1
- package/esm/src/agent/hosted/veryfront-cloud-agent-service.js +4 -0
- package/esm/src/agent/index.d.ts +1 -1
- package/esm/src/agent/index.js +1 -1
- package/esm/src/agent/runtime/agent-definition.d.ts.map +1 -1
- package/esm/src/agent/runtime/agent-definition.js +3 -0
- package/esm/src/agent/runtime/agent-runtime-step.js +1 -1
- package/esm/src/agent/runtime/index.d.ts.map +1 -1
- package/esm/src/agent/runtime/index.js +0 -2
- package/esm/src/agent/runtime/skill-metadata.d.ts +11 -0
- package/esm/src/agent/runtime/skill-metadata.d.ts.map +1 -1
- package/esm/src/agent/runtime/skill-metadata.js +24 -0
- package/esm/src/agent/runtime/skill-prompt.d.ts.map +1 -1
- package/esm/src/agent/runtime/skill-prompt.js +5 -2
- package/esm/src/agent/types.d.ts +8 -6
- package/esm/src/agent/types.d.ts.map +1 -1
- package/esm/src/channels/control-plane.d.ts.map +1 -1
- package/esm/src/channels/control-plane.js +1 -4
- package/esm/src/data/helpers.d.ts +20 -3
- package/esm/src/data/helpers.d.ts.map +1 -1
- package/esm/src/data/helpers.js +46 -12
- package/esm/src/data/static-data-fetcher.d.ts.map +1 -1
- package/esm/src/data/static-data-fetcher.js +15 -0
- package/esm/src/extensions/builtin-extensions.d.ts +1 -1
- package/esm/src/extensions/builtin-extensions.d.ts.map +1 -1
- package/esm/src/extensions/builtin-extensions.js +1 -6
- package/esm/src/extensions/builtin-schema-validator.d.ts +3 -0
- package/esm/src/extensions/builtin-schema-validator.d.ts.map +1 -0
- package/esm/src/extensions/builtin-schema-validator.js +8 -0
- package/esm/src/html/hydration-script-builder/templates/renderer.d.ts.map +1 -1
- package/esm/src/html/hydration-script-builder/templates/renderer.js +52 -28
- package/esm/src/internal-agents/run-stream.d.ts.map +1 -1
- package/esm/src/internal-agents/run-stream.js +6 -11
- package/esm/src/internal-agents/run-system-prompt.d.ts +1 -1
- package/esm/src/internal-agents/run-system-prompt.js +1 -1
- package/esm/src/modules/server/module-server.d.ts.map +1 -1
- package/esm/src/modules/server/module-server.js +15 -9
- package/esm/src/rendering/orchestrator/module-loader/build-failure.d.ts +20 -0
- package/esm/src/rendering/orchestrator/module-loader/build-failure.d.ts.map +1 -0
- package/esm/src/rendering/orchestrator/module-loader/build-failure.js +26 -0
- package/esm/src/rendering/orchestrator/module-loader/index.d.ts +2 -1
- package/esm/src/rendering/orchestrator/module-loader/index.d.ts.map +1 -1
- package/esm/src/rendering/orchestrator/module-loader/index.js +69 -7
- package/esm/src/rendering/orchestrator/module-loader/module-persistence.d.ts +6 -0
- package/esm/src/rendering/orchestrator/module-loader/module-persistence.d.ts.map +1 -1
- package/esm/src/rendering/orchestrator/module-loader/module-persistence.js +49 -0
- package/esm/src/rendering/orchestrator/pipeline.d.ts.map +1 -1
- package/esm/src/rendering/orchestrator/pipeline.js +10 -1
- package/esm/src/routing/api/context-builder.d.ts +26 -15
- package/esm/src/routing/api/context-builder.d.ts.map +1 -1
- package/esm/src/routing/api/context-builder.js +34 -15
- package/esm/src/routing/api/module-loader/loader.js +57 -1
- package/esm/src/server/dev-server/middleware.d.ts.map +1 -1
- package/esm/src/server/dev-server/middleware.js +29 -6
- package/esm/src/server/handlers/request/ssr/ssr.handler.d.ts.map +1 -1
- package/esm/src/server/handlers/request/ssr/ssr.handler.js +6 -4
- package/esm/src/skill/prompt-augmentation.d.ts +4 -2
- package/esm/src/skill/prompt-augmentation.d.ts.map +1 -1
- package/esm/src/skill/prompt-augmentation.js +13 -2
- package/esm/src/transforms/esm/import-attributes.d.ts +32 -0
- package/esm/src/transforms/esm/import-attributes.d.ts.map +1 -0
- package/esm/src/transforms/esm/import-attributes.js +116 -0
- package/esm/src/transforms/esm/import-parser.d.ts.map +1 -1
- package/esm/src/transforms/esm/import-parser.js +68 -18
- package/esm/src/transforms/esm/lexer.d.ts +18 -0
- package/esm/src/transforms/esm/lexer.d.ts.map +1 -1
- package/esm/src/transforms/esm/lexer.js +21 -0
- package/esm/src/transforms/esm/specifier-resolver.d.ts.map +1 -1
- package/esm/src/transforms/esm/specifier-resolver.js +13 -0
- package/esm/src/transforms/esm/transform-utils.d.ts +8 -0
- package/esm/src/transforms/esm/transform-utils.d.ts.map +1 -1
- package/esm/src/transforms/esm/transform-utils.js +11 -1
- package/esm/src/transforms/import-rewriter/project-paths.d.ts +26 -0
- package/esm/src/transforms/import-rewriter/project-paths.d.ts.map +1 -0
- package/esm/src/transforms/import-rewriter/project-paths.js +49 -0
- package/esm/src/transforms/import-rewriter/strategies/alias-strategy.d.ts +0 -1
- package/esm/src/transforms/import-rewriter/strategies/alias-strategy.d.ts.map +1 -1
- package/esm/src/transforms/import-rewriter/strategies/alias-strategy.js +5 -20
- package/esm/src/transforms/import-rewriter/strategies/asset-strategy.d.ts +1 -1
- package/esm/src/transforms/import-rewriter/strategies/asset-strategy.d.ts.map +1 -1
- package/esm/src/transforms/import-rewriter/strategies/asset-strategy.js +62 -12
- package/esm/src/transforms/import-rewriter/strategies/bare-strategy.d.ts.map +1 -1
- package/esm/src/transforms/import-rewriter/strategies/bare-strategy.js +19 -3
- package/esm/src/transforms/import-rewriter/strategies/node-builtin-strategy.d.ts +11 -0
- package/esm/src/transforms/import-rewriter/strategies/node-builtin-strategy.d.ts.map +1 -1
- package/esm/src/transforms/import-rewriter/strategies/node-builtin-strategy.js +13 -0
- package/esm/src/transforms/import-rewriter/strategies/relative-strategy.d.ts +0 -1
- package/esm/src/transforms/import-rewriter/strategies/relative-strategy.d.ts.map +1 -1
- package/esm/src/transforms/import-rewriter/strategies/relative-strategy.js +2 -16
- package/esm/src/transforms/import-rewriter/strategies/veryfront-strategy.d.ts.map +1 -1
- package/esm/src/transforms/import-rewriter/strategies/veryfront-strategy.js +4 -3
- package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/nested-imports.d.ts +4 -2
- package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/nested-imports.d.ts.map +1 -1
- package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/nested-imports.js +23 -7
- package/esm/src/transforms/pipeline/stages/browser-node-builtin-imports.d.ts.map +1 -1
- package/esm/src/transforms/pipeline/stages/browser-node-builtin-imports.js +5 -0
- package/esm/src/transforms/pipeline/stages/browser-server-exports-strip.d.ts +25 -3
- package/esm/src/transforms/pipeline/stages/browser-server-exports-strip.d.ts.map +1 -1
- package/esm/src/transforms/pipeline/stages/browser-server-exports-strip.js +285 -44
- package/esm/src/transforms/pipeline/stages/compile.d.ts.map +1 -1
- package/esm/src/transforms/pipeline/stages/compile.js +6 -1
- package/esm/src/transforms/pipeline/stages/ssr-vf-modules/transform.d.ts +9 -5
- package/esm/src/transforms/pipeline/stages/ssr-vf-modules/transform.d.ts.map +1 -1
- package/esm/src/transforms/pipeline/stages/ssr-vf-modules/transform.js +23 -9
- package/esm/src/transforms/shared/server-only-packages.d.ts +30 -0
- package/esm/src/transforms/shared/server-only-packages.d.ts.map +1 -0
- package/esm/src/transforms/shared/server-only-packages.js +47 -0
- package/esm/src/types/entities/getEntityInfo.d.ts.map +1 -1
- package/esm/src/types/entities/getEntityInfo.js +10 -2
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Import attribute rewrites anchored to lexer-reported positions.
|
|
3
|
+
*
|
|
4
|
+
* Every edit here is bounded by a range es-module-lexer reported for a real
|
|
5
|
+
* import statement, so module source embedded in a string literal (the
|
|
6
|
+
* `#deno-config` stub, the generated RSC bundles) is never touched. A plain
|
|
7
|
+
* regex over the module text cannot make that distinction.
|
|
8
|
+
*
|
|
9
|
+
* @module transforms/esm/import-attributes
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Rewrite the withdrawn `assert` spelling of an import attribute clause to
|
|
13
|
+
* `with`, for both the static and the dynamic form.
|
|
14
|
+
*
|
|
15
|
+
* esbuild treats `import-assertions` as a feature separate from
|
|
16
|
+
* `import-attributes` and drops the clause when the configured target does not
|
|
17
|
+
* claim it, which turns a working JSON import into "Attempted to load JSON
|
|
18
|
+
* module without specifying \"type\": \"json\"" at load time. Preserving the
|
|
19
|
+
* clause verbatim is no better: Node 22 and Deno 2 removed the keyword, so the
|
|
20
|
+
* only output that runs anywhere is `with`.
|
|
21
|
+
*/
|
|
22
|
+
export declare function upgradeImportAssertions(code: string): Promise<string>;
|
|
23
|
+
/**
|
|
24
|
+
* Drop `with { type: "json" }` from every import whose specifier the caller
|
|
25
|
+
* accepts, leaving all other attributes in place.
|
|
26
|
+
*
|
|
27
|
+
* Only a lone JSON type attribute is removed. An import that declares anything
|
|
28
|
+
* else is describing something this rewrite knows nothing about, so it is left
|
|
29
|
+
* exactly as written.
|
|
30
|
+
*/
|
|
31
|
+
export declare function stripJsonImportAttributes(code: string, shouldStrip: (specifier: string) => boolean): Promise<string>;
|
|
32
|
+
//# sourceMappingURL=import-attributes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-attributes.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/import-attributes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAgEH;;;;;;;;;;GAUG;AACH,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAiB3E;AAED;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,GAC1C,OAAO,CAAC,MAAM,CAAC,CAmBjB"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Import attribute rewrites anchored to lexer-reported positions.
|
|
3
|
+
*
|
|
4
|
+
* Every edit here is bounded by a range es-module-lexer reported for a real
|
|
5
|
+
* import statement, so module source embedded in a string literal (the
|
|
6
|
+
* `#deno-config` stub, the generated RSC bundles) is never touched. A plain
|
|
7
|
+
* regex over the module text cannot make that distinction.
|
|
8
|
+
*
|
|
9
|
+
* @module transforms/esm/import-attributes
|
|
10
|
+
*/
|
|
11
|
+
import { parseMaskedImports } from "./lexer.js";
|
|
12
|
+
const ASSERT_KEYWORD = "assert";
|
|
13
|
+
/**
|
|
14
|
+
* The legacy `assert` keyword following a static import specifier.
|
|
15
|
+
*
|
|
16
|
+
* es-module-lexer 2 no longer models assertions, so it ends the statement at
|
|
17
|
+
* the specifier and the clause sits immediately after it. Matching is confined
|
|
18
|
+
* to the specifier's own line, which is what the withdrawn grammar required.
|
|
19
|
+
*/
|
|
20
|
+
const STATIC_ASSERT_KEYWORD = /[^\S\r\n]*assert(?=[\s{])/y;
|
|
21
|
+
/** The legacy `assert` key opening the options argument of a dynamic import. */
|
|
22
|
+
const DYNAMIC_ASSERT_KEY = /^\s*,\s*\{\s*assert(?=\s*:)/;
|
|
23
|
+
/** A `with` clause on a static import, capturing the attribute object. */
|
|
24
|
+
const STATIC_WITH_CLAUSE = /^\s*with\s*(\{[^{}]*\})\s*$/;
|
|
25
|
+
/** The options argument of a dynamic import, capturing the attribute object. */
|
|
26
|
+
const DYNAMIC_WITH_ARGUMENT = /^\s*,\s*\{\s*with\s*:\s*(\{[^{}]*\})\s*,?\s*\}\s*$/;
|
|
27
|
+
/** An attribute object declaring a JSON module type and nothing else. */
|
|
28
|
+
const JSON_TYPE_ATTRIBUTE = /^\{\s*(["']?)type\1\s*:\s*(["'])json\2\s*,?\s*\}$/;
|
|
29
|
+
/**
|
|
30
|
+
* The range holding everything a specifier declares after its own text: the
|
|
31
|
+
* `with` clause of a static import, or the options argument of a dynamic one.
|
|
32
|
+
*
|
|
33
|
+
* The range is empty when the import declares no attributes.
|
|
34
|
+
*/
|
|
35
|
+
function attributeRange(imp) {
|
|
36
|
+
// Static: `e` indexes the closing quote and `se` ends the statement before
|
|
37
|
+
// any semicolon, so the clause and its keyword lie between them.
|
|
38
|
+
if (imp.d === -1)
|
|
39
|
+
return { start: imp.e + 1, end: imp.se };
|
|
40
|
+
// Dynamic: `e` is already past the closing quote and `se` is past the
|
|
41
|
+
// closing paren, so the comma and the options argument lie between them.
|
|
42
|
+
return { start: imp.e, end: imp.se - 1 };
|
|
43
|
+
}
|
|
44
|
+
/** Whether the declared attributes are exactly a JSON module type. */
|
|
45
|
+
function declaresJsonTypeOnly(clause, isDynamic) {
|
|
46
|
+
const attributes = (isDynamic ? DYNAMIC_WITH_ARGUMENT : STATIC_WITH_CLAUSE).exec(clause)?.[1];
|
|
47
|
+
return attributes !== undefined && JSON_TYPE_ATTRIBUTE.test(attributes);
|
|
48
|
+
}
|
|
49
|
+
/** Position of the legacy `assert` keyword this import uses, or `null`. */
|
|
50
|
+
function findAssertKeyword(masked, imp) {
|
|
51
|
+
if (imp.d === -1) {
|
|
52
|
+
STATIC_ASSERT_KEYWORD.lastIndex = imp.se;
|
|
53
|
+
const match = STATIC_ASSERT_KEYWORD.exec(masked);
|
|
54
|
+
return match === null ? null : STATIC_ASSERT_KEYWORD.lastIndex - ASSERT_KEYWORD.length;
|
|
55
|
+
}
|
|
56
|
+
const { start, end } = attributeRange(imp);
|
|
57
|
+
if (start >= end)
|
|
58
|
+
return null;
|
|
59
|
+
const match = DYNAMIC_ASSERT_KEY.exec(masked.slice(start, end));
|
|
60
|
+
return match === null ? null : start + match[0].length - ASSERT_KEYWORD.length;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Rewrite the withdrawn `assert` spelling of an import attribute clause to
|
|
64
|
+
* `with`, for both the static and the dynamic form.
|
|
65
|
+
*
|
|
66
|
+
* esbuild treats `import-assertions` as a feature separate from
|
|
67
|
+
* `import-attributes` and drops the clause when the configured target does not
|
|
68
|
+
* claim it, which turns a working JSON import into "Attempted to load JSON
|
|
69
|
+
* module without specifying \"type\": \"json\"" at load time. Preserving the
|
|
70
|
+
* clause verbatim is no better: Node 22 and Deno 2 removed the keyword, so the
|
|
71
|
+
* only output that runs anywhere is `with`.
|
|
72
|
+
*/
|
|
73
|
+
export async function upgradeImportAssertions(code) {
|
|
74
|
+
if (!code.includes(ASSERT_KEYWORD))
|
|
75
|
+
return code;
|
|
76
|
+
const { masked, imports, unmask } = await parseMaskedImports(code);
|
|
77
|
+
let result = masked;
|
|
78
|
+
for (let i = imports.length - 1; i >= 0; i--) {
|
|
79
|
+
const imp = imports[i];
|
|
80
|
+
if (!imp?.n)
|
|
81
|
+
continue;
|
|
82
|
+
const keyword = findAssertKeyword(masked, imp);
|
|
83
|
+
if (keyword === null)
|
|
84
|
+
continue;
|
|
85
|
+
result = result.slice(0, keyword) + "with" + result.slice(keyword + ASSERT_KEYWORD.length);
|
|
86
|
+
}
|
|
87
|
+
return unmask(result);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Drop `with { type: "json" }` from every import whose specifier the caller
|
|
91
|
+
* accepts, leaving all other attributes in place.
|
|
92
|
+
*
|
|
93
|
+
* Only a lone JSON type attribute is removed. An import that declares anything
|
|
94
|
+
* else is describing something this rewrite knows nothing about, so it is left
|
|
95
|
+
* exactly as written.
|
|
96
|
+
*/
|
|
97
|
+
export async function stripJsonImportAttributes(code, shouldStrip) {
|
|
98
|
+
if (!code.includes("with"))
|
|
99
|
+
return code;
|
|
100
|
+
const { masked, imports, unmask } = await parseMaskedImports(code);
|
|
101
|
+
let result = masked;
|
|
102
|
+
for (let i = imports.length - 1; i >= 0; i--) {
|
|
103
|
+
const imp = imports[i];
|
|
104
|
+
if (!imp?.n)
|
|
105
|
+
continue;
|
|
106
|
+
if (!shouldStrip(unmask(imp.n)))
|
|
107
|
+
continue;
|
|
108
|
+
const { start, end } = attributeRange(imp);
|
|
109
|
+
if (start >= end)
|
|
110
|
+
continue;
|
|
111
|
+
if (!declaresJsonTypeOnly(masked.slice(start, end), imp.d > -1))
|
|
112
|
+
continue;
|
|
113
|
+
result = result.slice(0, start) + result.slice(end);
|
|
114
|
+
}
|
|
115
|
+
return unmask(result);
|
|
116
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import-parser.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/import-parser.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"import-parser.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/import-parser.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAKtE,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,uBAAuB;IAC/B,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,UAAU,EAAE,WAAW,EAAE,CAAC;IAC1B,mBAAmB,EAAE,kBAAkB,EAAE,CAAC;IAC1C,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAwCD,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,uBAAuB,CAAC,CA2HlC"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { compileContent } from "../mdx/compiler/index.js";
|
|
2
2
|
import { getEsbuild } from "../../platform/compat/esbuild.js";
|
|
3
|
-
import { join } from "../../platform/compat/path/index.js";
|
|
3
|
+
import { dirname, join, relative } from "../../platform/compat/path/index.js";
|
|
4
|
+
import { computeHash } from "../../utils/hash-utils.js";
|
|
5
|
+
import { LRUCache } from "../../utils/lru-wrapper.js";
|
|
4
6
|
import { createFileSystem } from "../../platform/compat/fs.js";
|
|
5
7
|
import { isFrameworkSourcePath, resolveRelativeFrameworkSourceImport, } from "../../platform/compat/framework-source-resolver.js";
|
|
6
8
|
import { isCrossProjectImport, parseCrossProjectImport } from "./path-resolver.js";
|
|
@@ -8,19 +10,43 @@ import { parseImports } from "./lexer.js";
|
|
|
8
10
|
import { getLoaderFromPath } from "./transform-utils.js";
|
|
9
11
|
const EXTENSIONS = [".tsx", ".ts", ".jsx", ".js", ".mdx"];
|
|
10
12
|
const HAS_EXTENSION_RE = /\.(tsx?|jsx?|mjs|cjs|mdx|css)$/;
|
|
13
|
+
/**
|
|
14
|
+
* Compiled MDX, keyed by project, file and content hash.
|
|
15
|
+
*
|
|
16
|
+
* Dependency parsing runs on every render, including every memory, Redis and
|
|
17
|
+
* MDX-ESM cache hit, and recurses through the dependency tree. Without this the
|
|
18
|
+
* full remark/rehype compile of every MDX file is paid again on each of them,
|
|
19
|
+
* for a result that cannot change while the content does not.
|
|
20
|
+
*/
|
|
21
|
+
const COMPILED_MDX_CACHE_MAX_ENTRIES = 200;
|
|
22
|
+
const compiledMdxCache = new LRUCache({
|
|
23
|
+
maxEntries: COMPILED_MDX_CACHE_MAX_ENTRIES,
|
|
24
|
+
});
|
|
25
|
+
async function compileMdxForParsing(code, filePath, projectDir) {
|
|
26
|
+
const cacheKey = `${projectDir}::${filePath}::${await computeHash(code)}`;
|
|
27
|
+
const cached = compiledMdxCache.get(cacheKey);
|
|
28
|
+
if (cached !== undefined)
|
|
29
|
+
return cached;
|
|
30
|
+
const compiled = await compileContent("development", projectDir, code, undefined, filePath, "server");
|
|
31
|
+
compiledMdxCache.set(cacheKey, compiled.compiledCode);
|
|
32
|
+
return compiled.compiledCode;
|
|
33
|
+
}
|
|
11
34
|
export async function parseLocalImports(code, filePath, projectDir, adapter) {
|
|
12
|
-
|
|
35
|
+
// Markdown compiles to a fixed template whose only import is the bare JSX
|
|
36
|
+
// runtime, which this parser discards, so the answer for a `.md` file is
|
|
37
|
+
// always "no dependencies". Compiling one to learn that is pure cost on a
|
|
38
|
+
// path that runs per render.
|
|
39
|
+
if (filePath.endsWith(".css") || filePath.endsWith(".json") || /\.md$/i.test(filePath)) {
|
|
13
40
|
return { imports: [], cssImports: [], crossProjectImports: [], missing: [] };
|
|
14
41
|
}
|
|
15
|
-
// MDX
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
42
|
+
// MDX is not JSX, so handing the raw source to esbuild under the `jsx` loader
|
|
43
|
+
// fails with "<stdin>:1:1: ERROR: Syntax error", which surfaced to users as
|
|
44
|
+
// "Component has missing dependencies" for a file that exists. Compile
|
|
45
|
+
// content to JSX first, exactly as the transform pipeline's parse stage does,
|
|
46
|
+
// then read the imports out of that.
|
|
20
47
|
let parseSource = code;
|
|
21
|
-
if (/\.mdx
|
|
22
|
-
|
|
23
|
-
parseSource = compiled.compiledCode;
|
|
48
|
+
if (/\.mdx$/i.test(filePath)) {
|
|
49
|
+
parseSource = await compileMdxForParsing(code, filePath, projectDir);
|
|
24
50
|
}
|
|
25
51
|
const esbuild = await getEsbuild();
|
|
26
52
|
const result = await esbuild.transform(parseSource, {
|
|
@@ -49,19 +75,24 @@ export async function parseLocalImports(code, filePath, projectDir, adapter) {
|
|
|
49
75
|
// below and are dropped without even being reported as missing, so an MDX
|
|
50
76
|
// file's sibling components are never recursively transformed.
|
|
51
77
|
if (specifier.startsWith("file://")) {
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
78
|
+
const targetPath = fileUrlToPath(specifier);
|
|
79
|
+
// A rewritten specifier carries a server path the author never wrote, and
|
|
80
|
+
// this record is read back verbatim in the "Component has missing
|
|
81
|
+
// dependencies" build error. Report what the author wrote instead.
|
|
82
|
+
const authoredSpecifier = toAuthoredSpecifier(targetPath, specifier, filePath);
|
|
83
|
+
const resolved = targetPath ? await resolveExistingFilePath(targetPath, adapter) : null;
|
|
84
|
+
if (resolved) {
|
|
85
|
+
const entry = { specifier: authoredSpecifier, absolutePath: resolved };
|
|
86
|
+
if (resolved.endsWith(".css"))
|
|
56
87
|
cssImports.push(entry);
|
|
57
88
|
else
|
|
58
89
|
localImports.push(entry);
|
|
59
90
|
continue;
|
|
60
91
|
}
|
|
61
92
|
missingImports.push({
|
|
62
|
-
specifier,
|
|
93
|
+
specifier: authoredSpecifier,
|
|
63
94
|
fromFile: filePath,
|
|
64
|
-
reason: `File not found: ${
|
|
95
|
+
reason: `File not found: tried extensions ${EXTENSIONS.join(", ")}`,
|
|
65
96
|
});
|
|
66
97
|
continue;
|
|
67
98
|
}
|
|
@@ -116,6 +147,17 @@ export async function parseLocalImports(code, filePath, projectDir, adapter) {
|
|
|
116
147
|
}
|
|
117
148
|
return { imports: localImports, cssImports, crossProjectImports, missing: missingImports };
|
|
118
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* The specifier as the author most likely wrote it, reconstructed from the
|
|
152
|
+
* absolute path a compile step rewrote it to. Falls back to the file name when
|
|
153
|
+
* the URL cannot be read, so no server path escapes into a user-facing report.
|
|
154
|
+
*/
|
|
155
|
+
function toAuthoredSpecifier(targetPath, specifier, fromFile) {
|
|
156
|
+
if (!targetPath)
|
|
157
|
+
return `./${specifier.slice(specifier.lastIndexOf("/") + 1)}`;
|
|
158
|
+
const relativePath = relative(dirname(fromFile), targetPath);
|
|
159
|
+
return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
160
|
+
}
|
|
119
161
|
/** Filesystem path behind a `file://` specifier, or null when it is not one. */
|
|
120
162
|
function fileUrlToPath(specifier) {
|
|
121
163
|
try {
|
|
@@ -147,7 +189,15 @@ async function resolveLocalImportPath(fromFile, importSpecifier, adapter) {
|
|
|
147
189
|
return resolvedFrameworkImport;
|
|
148
190
|
}
|
|
149
191
|
const fromDir = fromFile.substring(0, fromFile.lastIndexOf("/"));
|
|
150
|
-
|
|
192
|
+
return await resolveExistingFilePath(resolveRelative(fromDir, importSpecifier), adapter);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Path of the file a local import points at: the adapter's own resolution
|
|
196
|
+
* first, then the extension and directory-index probes. Every local import
|
|
197
|
+
* shape resolves through here, so an extensionless or directory specifier
|
|
198
|
+
* behaves the same however it reached this module.
|
|
199
|
+
*/
|
|
200
|
+
async function resolveExistingFilePath(basePath, adapter) {
|
|
151
201
|
if (adapter?.fs.resolveFile) {
|
|
152
202
|
try {
|
|
153
203
|
const normalizedPath = basePath.replace(/^\/+/, "");
|
|
@@ -160,7 +210,7 @@ async function resolveLocalImportPath(fromFile, importSpecifier, adapter) {
|
|
|
160
210
|
// Fall through to traditional resolution
|
|
161
211
|
}
|
|
162
212
|
}
|
|
163
|
-
if (HAS_EXTENSION_RE.test(
|
|
213
|
+
if (HAS_EXTENSION_RE.test(basePath)) {
|
|
164
214
|
return (await checkFileExists(basePath, adapter)) ? basePath : null;
|
|
165
215
|
}
|
|
166
216
|
for (const ext of EXTENSIONS) {
|
|
@@ -2,6 +2,24 @@ import type { ImportSpecifier } from "../../extensions/bundler/module-lexer.js";
|
|
|
2
2
|
export type { ImportSpecifier };
|
|
3
3
|
export declare function initLexer(): Promise<void>;
|
|
4
4
|
export declare function parseImports(code: string): Promise<readonly ImportSpecifier[]>;
|
|
5
|
+
/** A parse whose positions index into a masked copy of the source. */
|
|
6
|
+
export interface MaskedParse {
|
|
7
|
+
/** The source with HTTP URLs replaced by fixed-width placeholders. */
|
|
8
|
+
masked: string;
|
|
9
|
+
/** Specifiers whose every positional field indexes into {@link masked}. */
|
|
10
|
+
imports: readonly ImportSpecifier[];
|
|
11
|
+
/** Restore the masked HTTP URLs in a string derived from {@link masked}. */
|
|
12
|
+
unmask: (text: string) => string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Parse imports and hand back the masked source the positions belong to.
|
|
16
|
+
*
|
|
17
|
+
* Masking changes offsets, so `imp.s`, `imp.a` and friends are meaningless
|
|
18
|
+
* against the original text. Callers that splice by position must edit
|
|
19
|
+
* `masked` and run the result through `unmask`; callers that only need
|
|
20
|
+
* specifier names should use {@link parseImports} instead.
|
|
21
|
+
*/
|
|
22
|
+
export declare function parseMaskedImports(code: string): Promise<MaskedParse>;
|
|
5
23
|
/**
|
|
6
24
|
* Replace import specifiers (the path string) in the code.
|
|
7
25
|
* Safe for simple re-mappings like aliases or rewriting URLs.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lexer.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/lexer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAe,MAAM,0CAA0C,CAAC;AAE7F,YAAY,EAAE,eAAe,EAAE,CAAC;AAuDhC,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAS/C;AAyBD,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,eAAe,EAAE,CAAC,CAqBpF;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,KAAK,MAAM,GAAG,IAAI,GAAG,SAAS,GAC7E,OAAO,CAAC,MAAM,CAAC,CAoCjB;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GACnE,OAAO,CAAC,MAAM,CAAC,CAsBjB"}
|
|
1
|
+
{"version":3,"file":"lexer.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/lexer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAe,MAAM,0CAA0C,CAAC;AAE7F,YAAY,EAAE,eAAe,EAAE,CAAC;AAuDhC,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAS/C;AAyBD,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,eAAe,EAAE,CAAC,CAqBpF;AAED,sEAAsE;AACtE,MAAM,WAAW,WAAW;IAC1B,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;IACpC,4EAA4E;IAC5E,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAClC;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAc3E;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,KAAK,MAAM,GAAG,IAAI,GAAG,SAAS,GAC7E,OAAO,CAAC,MAAM,CAAC,CAoCjB;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GACnE,OAAO,CAAC,MAAM,CAAC,CAsBjB"}
|
|
@@ -86,6 +86,27 @@ export async function parseImports(code) {
|
|
|
86
86
|
return restoredN === imp.n ? imp : { ...imp, n: restoredN };
|
|
87
87
|
});
|
|
88
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Parse imports and hand back the masked source the positions belong to.
|
|
91
|
+
*
|
|
92
|
+
* Masking changes offsets, so `imp.s`, `imp.a` and friends are meaningless
|
|
93
|
+
* against the original text. Callers that splice by position must edit
|
|
94
|
+
* `masked` and run the result through `unmask`; callers that only need
|
|
95
|
+
* specifier names should use {@link parseImports} instead.
|
|
96
|
+
*/
|
|
97
|
+
export async function parseMaskedImports(code) {
|
|
98
|
+
await initLexer();
|
|
99
|
+
const { masked, urlMap } = maskHttpUrls(code);
|
|
100
|
+
let imports;
|
|
101
|
+
try {
|
|
102
|
+
imports = getLexer().parse(masked);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
logParseError(error, masked);
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
return { masked, imports, unmask: (text) => unmaskHttpUrls(text, urlMap) };
|
|
109
|
+
}
|
|
89
110
|
/**
|
|
90
111
|
* Replace import specifiers (the path string) in the code.
|
|
91
112
|
* Safe for simple re-mappings like aliases or rewriting URLs.
|
|
@@ -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;AAUH,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;AA+H/F,4EAA4E;AAC5E,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnD,gEAAgE;IAChE,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED,2EAA2E;AAC3E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gEAAgE;IAChE,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,OAAO,EAAE,YAAY,EACrB,eAAe,EAAE,iBAAiB,GACjC,OAAO,CAAC,qBAAqB,CAAC,CAuChC;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,YAAY,EACrB,eAAe,EAAE,iBAAiB,GACjC,OAAO,CAAC,eAAe,CAAC,CAa1B"}
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
import { basename } from "../../platform/compat/path/index.js";
|
|
10
10
|
import { resolveImport } from "../../modules/import-map/resolver.js";
|
|
11
11
|
import { rendererLogger } from "../../utils/index.js";
|
|
12
|
+
import { parseBarePackageSpecifier } from "../shared/package-specifier.js";
|
|
13
|
+
import { isServerOnlyPackage } from "../shared/server-only-packages.js";
|
|
12
14
|
import { parseImports, replaceSpecifiers } from "./lexer.js";
|
|
13
15
|
const logger = rendererLogger.component("specifier-resolver");
|
|
14
16
|
import { isCanonicalReactEsmUrl, isExternalScheme, isHttpUrl, isInternalBare, isParentHttpModule, isRelative, resolveBareSpecifier, } from "./http-cache-helpers.js";
|
|
@@ -26,6 +28,17 @@ function isLocalMappedSpecifier(specifier) {
|
|
|
26
28
|
async function resolveSpecifier(specifier, baseUrl, options, cacheHttpModule) {
|
|
27
29
|
if (isExternalScheme(specifier))
|
|
28
30
|
return null;
|
|
31
|
+
// Server-only packages (`redis`, `pg`, …), including their explicit `npm:`
|
|
32
|
+
// form, must never be routed through esm.sh. esm.sh either 500s building them
|
|
33
|
+
// or emits a browser bundle with Node built-ins stubbed that can never
|
|
34
|
+
// connect. The framework's adapters only `import()` them behind a lazy,
|
|
35
|
+
// configured code path, so leaving the specifier external lets the runtime
|
|
36
|
+
// resolve the real package (node_modules on Node, npm: on Deno) if and when
|
|
37
|
+
// the backend is actually used — and costs nothing when it is not.
|
|
38
|
+
const serverOnlyCandidate = specifier.startsWith("npm:") ? specifier.slice(4) : specifier;
|
|
39
|
+
const serverOnlyParsed = parseBarePackageSpecifier(serverOnlyCandidate);
|
|
40
|
+
if (serverOnlyParsed && isServerOnlyPackage(serverOnlyParsed.packageName))
|
|
41
|
+
return null;
|
|
29
42
|
if (isInternalBare(specifier)) {
|
|
30
43
|
const mapped = resolveImport(specifier, options.importMap);
|
|
31
44
|
if (mapped === specifier)
|
|
@@ -12,9 +12,17 @@ export declare function computeShortContentHash(content: string): Promise<string
|
|
|
12
12
|
* that consumes this output requires the attribute to load a JSON module, so
|
|
13
13
|
* dropping it turns a working import into a load-time error:
|
|
14
14
|
* `Attempted to load JSON module without specifying "type": "json"`.
|
|
15
|
+
*
|
|
16
|
+
* `import-assertions` is the separate feature key esbuild uses for the
|
|
17
|
+
* withdrawn `assert { type: "json" }` spelling of the same clause. It is
|
|
18
|
+
* enabled for the same reason, so the clause reaches the output instead of
|
|
19
|
+
* vanishing. The output must not keep that spelling though, because Node 22
|
|
20
|
+
* and Deno 2 removed the keyword, so every consumer of these options runs the
|
|
21
|
+
* result through `upgradeImportAssertions` to rewrite it to `with`.
|
|
15
22
|
*/
|
|
16
23
|
export declare const ESBUILD_SUPPORTED_FEATURES: {
|
|
17
24
|
readonly "import-attributes": true;
|
|
25
|
+
readonly "import-assertions": true;
|
|
18
26
|
};
|
|
19
27
|
export declare function getLoaderFromPath(filePath: string): Loader;
|
|
20
28
|
export declare function needsTransform(filePath: string): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform-utils.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/transform-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AAGhE;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAExE;AAED
|
|
1
|
+
{"version":3,"file":"transform-utils.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/transform-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AAGhE;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAExE;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,0BAA0B;;;CAG7B,CAAC;AAaX,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG1D;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAExD"}
|
|
@@ -14,8 +14,18 @@ export function computeShortContentHash(content) {
|
|
|
14
14
|
* that consumes this output requires the attribute to load a JSON module, so
|
|
15
15
|
* dropping it turns a working import into a load-time error:
|
|
16
16
|
* `Attempted to load JSON module without specifying "type": "json"`.
|
|
17
|
+
*
|
|
18
|
+
* `import-assertions` is the separate feature key esbuild uses for the
|
|
19
|
+
* withdrawn `assert { type: "json" }` spelling of the same clause. It is
|
|
20
|
+
* enabled for the same reason, so the clause reaches the output instead of
|
|
21
|
+
* vanishing. The output must not keep that spelling though, because Node 22
|
|
22
|
+
* and Deno 2 removed the keyword, so every consumer of these options runs the
|
|
23
|
+
* result through `upgradeImportAssertions` to rewrite it to `with`.
|
|
17
24
|
*/
|
|
18
|
-
export const ESBUILD_SUPPORTED_FEATURES = {
|
|
25
|
+
export const ESBUILD_SUPPORTED_FEATURES = {
|
|
26
|
+
"import-attributes": true,
|
|
27
|
+
"import-assertions": true,
|
|
28
|
+
};
|
|
19
29
|
const EXTENSION_LOADERS = {
|
|
20
30
|
".tsx": "tsx",
|
|
21
31
|
".ts": "ts",
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project-relative path helpers shared by the rewrite strategies.
|
|
3
|
+
*
|
|
4
|
+
* Several strategies need the path of the file being transformed expressed
|
|
5
|
+
* relative to the project root: the alias and relative strategies to build
|
|
6
|
+
* module URLs, the asset strategy to name the importer in its message.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Path of `filePath` relative to `projectDir`, or null when the file is not
|
|
10
|
+
* inside the project.
|
|
11
|
+
*
|
|
12
|
+
* The check is on a path boundary, so `/projectile/src/Header.tsx` is not
|
|
13
|
+
* treated as living inside `/project`.
|
|
14
|
+
*/
|
|
15
|
+
export declare function relativeToProjectDir(filePath: string, projectDir: string): string | null;
|
|
16
|
+
/**
|
|
17
|
+
* Best-effort project-relative path, for callers that need a path to build a
|
|
18
|
+
* module URL from and have no useful fallback.
|
|
19
|
+
*
|
|
20
|
+
* A file outside the project can still be a copy of a project file staged
|
|
21
|
+
* somewhere else (a temp bundle directory, for example), so the project
|
|
22
|
+
* directory name is looked up in the path before giving up and returning the
|
|
23
|
+
* input unchanged.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getProjectRelativePath(filePath: string, projectDir: string): string;
|
|
26
|
+
//# sourceMappingURL=project-paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-paths.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/import-rewriter/project-paths.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQxF;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAanF"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project-relative path helpers shared by the rewrite strategies.
|
|
3
|
+
*
|
|
4
|
+
* Several strategies need the path of the file being transformed expressed
|
|
5
|
+
* relative to the project root: the alias and relative strategies to build
|
|
6
|
+
* module URLs, the asset strategy to name the importer in its message.
|
|
7
|
+
*/
|
|
8
|
+
/** Normalize separators and drop any trailing slash. */
|
|
9
|
+
function normalizeDir(dir) {
|
|
10
|
+
return dir.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Path of `filePath` relative to `projectDir`, or null when the file is not
|
|
14
|
+
* inside the project.
|
|
15
|
+
*
|
|
16
|
+
* The check is on a path boundary, so `/projectile/src/Header.tsx` is not
|
|
17
|
+
* treated as living inside `/project`.
|
|
18
|
+
*/
|
|
19
|
+
export function relativeToProjectDir(filePath, projectDir) {
|
|
20
|
+
const normalizedFilePath = filePath.replace(/\\/g, "/");
|
|
21
|
+
const normalizedProjectDir = normalizeDir(projectDir);
|
|
22
|
+
if (normalizedFilePath === normalizedProjectDir)
|
|
23
|
+
return "";
|
|
24
|
+
if (!normalizedFilePath.startsWith(`${normalizedProjectDir}/`))
|
|
25
|
+
return null;
|
|
26
|
+
return normalizedFilePath.slice(normalizedProjectDir.length + 1);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Best-effort project-relative path, for callers that need a path to build a
|
|
30
|
+
* module URL from and have no useful fallback.
|
|
31
|
+
*
|
|
32
|
+
* A file outside the project can still be a copy of a project file staged
|
|
33
|
+
* somewhere else (a temp bundle directory, for example), so the project
|
|
34
|
+
* directory name is looked up in the path before giving up and returning the
|
|
35
|
+
* input unchanged.
|
|
36
|
+
*/
|
|
37
|
+
export function getProjectRelativePath(filePath, projectDir) {
|
|
38
|
+
const direct = relativeToProjectDir(filePath, projectDir);
|
|
39
|
+
if (direct !== null)
|
|
40
|
+
return direct;
|
|
41
|
+
if (!filePath.startsWith("/"))
|
|
42
|
+
return filePath;
|
|
43
|
+
const pathParts = filePath.split("/");
|
|
44
|
+
const lastProjectPart = normalizeDir(projectDir).split("/").at(-1);
|
|
45
|
+
const projectIndex = lastProjectPart ? pathParts.indexOf(lastProjectPart) : -1;
|
|
46
|
+
if (projectIndex >= 0)
|
|
47
|
+
return pathParts.slice(projectIndex + 1).join("/");
|
|
48
|
+
return filePath;
|
|
49
|
+
}
|
|
@@ -4,7 +4,6 @@ export declare class AliasStrategy implements ImportRewriteStrategy {
|
|
|
4
4
|
readonly priority = 1;
|
|
5
5
|
matches(specifier: string, _ctx: RewriteContext): boolean;
|
|
6
6
|
rewrite(info: ImportSpecifierInfo, ctx: RewriteContext): RewriteResult;
|
|
7
|
-
private getRelativeFilePath;
|
|
8
7
|
}
|
|
9
8
|
export declare const aliasStrategy: AliasStrategy;
|
|
10
9
|
//# sourceMappingURL=alias-strategy.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alias-strategy.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/import-rewriter/strategies/alias-strategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,aAAa,EACd,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"alias-strategy.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/import-rewriter/strategies/alias-strategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,aAAa,EACd,MAAM,aAAa,CAAC;AAIrB,qBAAa,aAAc,YAAW,qBAAqB;IACzD,QAAQ,CAAC,IAAI,WAAW;IACxB,QAAQ,CAAC,QAAQ,KAAK;IAEtB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO;IAIzD,OAAO,CAAC,IAAI,EAAE,mBAAmB,EAAE,GAAG,EAAE,cAAc,GAAG,aAAa;CAwCvE;AAED,eAAO,MAAM,aAAa,eAAsB,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { normalizeExtension } from "../url-builder.js";
|
|
2
|
+
import { getProjectRelativePath } from "../project-paths.js";
|
|
2
3
|
export class AliasStrategy {
|
|
3
4
|
name = "alias";
|
|
4
5
|
priority = 1;
|
|
@@ -11,7 +12,7 @@ export class AliasStrategy {
|
|
|
11
12
|
if (ctx.target === "ssr") {
|
|
12
13
|
let normalizedPath = normalizeExtension(path);
|
|
13
14
|
// Add .js if no extension present
|
|
14
|
-
if (!/\.(tsx?|jsx?|mjs|cjs|mdx|css
|
|
15
|
+
if (!/\.(tsx?|jsx?|mjs|cjs|mdx|css)$/.test(normalizedPath)) {
|
|
15
16
|
normalizedPath = `${normalizedPath}.js`;
|
|
16
17
|
}
|
|
17
18
|
return { specifier: `/_vf_modules/${normalizedPath}` };
|
|
@@ -22,38 +23,22 @@ export class AliasStrategy {
|
|
|
22
23
|
// but module path is "_vf_modules/components/elements/Textarea.js").
|
|
23
24
|
if (ctx.moduleServerUrl) {
|
|
24
25
|
let normalizedPath = normalizeExtension(path);
|
|
25
|
-
if (!/\.(tsx?|jsx?|mjs|cjs|mdx|css
|
|
26
|
+
if (!/\.(tsx?|jsx?|mjs|cjs|mdx|css)$/.test(normalizedPath)) {
|
|
26
27
|
normalizedPath = `${normalizedPath}.js`;
|
|
27
28
|
}
|
|
28
29
|
return { specifier: `${ctx.moduleServerUrl}/${normalizedPath}` };
|
|
29
30
|
}
|
|
30
31
|
// Fallback: Use relative paths when no module server is configured.
|
|
31
32
|
// This is used for local development without a module server.
|
|
32
|
-
const relativeFilePath =
|
|
33
|
+
const relativeFilePath = getProjectRelativePath(ctx.filePath, ctx.projectDir);
|
|
33
34
|
const fileDir = relativeFilePath.substring(0, relativeFilePath.lastIndexOf("/"));
|
|
34
35
|
const depth = fileDir.split("/").filter(Boolean).length;
|
|
35
36
|
const prefix = depth === 0 ? "./" : "../".repeat(depth);
|
|
36
37
|
let relativePath = normalizeExtension(`${prefix}${path}`);
|
|
37
|
-
if (!/\.(tsx?|jsx?|mjs|cjs|mdx|css
|
|
38
|
+
if (!/\.(tsx?|jsx?|mjs|cjs|mdx|css)$/.test(relativePath)) {
|
|
38
39
|
relativePath = `${relativePath}.js`;
|
|
39
40
|
}
|
|
40
41
|
return { specifier: relativePath };
|
|
41
42
|
}
|
|
42
|
-
getRelativeFilePath(filePath, projectDir) {
|
|
43
|
-
const normalizedProjectDir = projectDir.replace(/\\/g, "/").replace(/\/$/, "");
|
|
44
|
-
if (filePath.startsWith(normalizedProjectDir)) {
|
|
45
|
-
return filePath.substring(normalizedProjectDir.length + 1);
|
|
46
|
-
}
|
|
47
|
-
if (!filePath.startsWith("/"))
|
|
48
|
-
return filePath;
|
|
49
|
-
const pathParts = filePath.split("/");
|
|
50
|
-
const projectParts = normalizedProjectDir.split("/");
|
|
51
|
-
const lastProjectPart = projectParts.at(-1);
|
|
52
|
-
const projectIndex = lastProjectPart ? pathParts.indexOf(lastProjectPart) : -1;
|
|
53
|
-
if (projectIndex >= 0) {
|
|
54
|
-
return pathParts.slice(projectIndex + 1).join("/");
|
|
55
|
-
}
|
|
56
|
-
return filePath;
|
|
57
|
-
}
|
|
58
43
|
}
|
|
59
44
|
export const aliasStrategy = new AliasStrategy();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ImportRewriteStrategy, type ImportSpecifierInfo, type RewriteContext, type RewriteResult } from "../types.js";
|
|
2
2
|
/**
|
|
3
3
|
* Reject `import logo from "@/assets/logo.svg"`.
|
|
4
4
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asset-strategy.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/import-rewriter/strategies/asset-strategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"asset-strategy.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/import-rewriter/strategies/asset-strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAkErB;;;;;;;;;;;;;GAaG;AACH,qBAAa,aAAc,YAAW,qBAAqB;IACzD,QAAQ,CAAC,IAAI,WAAW;IAGxB,QAAQ,CAAC,QAAQ,OAAO;IAExB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO;IAWzD,OAAO,CAAC,IAAI,EAAE,mBAAmB,EAAE,GAAG,EAAE,cAAc,GAAG,aAAa;CAevE;AAED,eAAO,MAAM,aAAa,eAAsB,CAAC"}
|