veryfront 0.1.826 → 0.1.828

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.
Files changed (52) hide show
  1. package/esm/deno.js +1 -1
  2. package/esm/src/build/production-build/build/output-generator.d.ts.map +1 -1
  3. package/esm/src/build/production-build/build/output-generator.js +4 -2
  4. package/esm/src/html/html-shell-generator.js +2 -2
  5. package/esm/src/html/hydration-script-builder/index.d.ts +1 -1
  6. package/esm/src/html/hydration-script-builder/index.d.ts.map +1 -1
  7. package/esm/src/html/hydration-script-builder/index.js +1 -1
  8. package/esm/src/html/hydration-script-builder/prod-scripts.d.ts +3 -0
  9. package/esm/src/html/hydration-script-builder/prod-scripts.d.ts.map +1 -1
  10. package/esm/src/html/hydration-script-builder/prod-scripts.js +14 -1
  11. package/esm/src/modules/react-loader/ssr-module-loader/import-rewriter.d.ts +2 -2
  12. package/esm/src/modules/react-loader/ssr-module-loader/import-rewriter.d.ts.map +1 -1
  13. package/esm/src/modules/react-loader/ssr-module-loader/import-rewriter.js +14 -22
  14. package/esm/src/modules/react-loader/ssr-module-loader/loader.js +2 -2
  15. package/esm/src/modules/react-loader/ssr-module-loader/ssr-cache-manager.d.ts.map +1 -1
  16. package/esm/src/modules/react-loader/ssr-module-loader/ssr-cache-manager.js +11 -4
  17. package/esm/src/modules/react-loader/ssr-module-loader/vf-module-resolver.d.ts +2 -2
  18. package/esm/src/modules/react-loader/ssr-module-loader/vf-module-resolver.d.ts.map +1 -1
  19. package/esm/src/modules/react-loader/ssr-module-loader/vf-module-resolver.js +22 -15
  20. package/esm/src/release-assets/build-executor.d.ts.map +1 -1
  21. package/esm/src/release-assets/build-executor.js +43 -62
  22. package/esm/src/release-assets/html-consumption.d.ts +2 -1
  23. package/esm/src/release-assets/html-consumption.d.ts.map +1 -1
  24. package/esm/src/release-assets/html-consumption.js +4 -2
  25. package/esm/src/rendering/rsc/component-analyzer.d.ts.map +1 -1
  26. package/esm/src/rendering/rsc/component-analyzer.js +2 -1
  27. package/esm/src/rendering/rsc/export-extractor.d.ts +5 -3
  28. package/esm/src/rendering/rsc/export-extractor.d.ts.map +1 -1
  29. package/esm/src/rendering/rsc/export-extractor.js +59 -36
  30. package/esm/src/server/handlers/request/prod-hydration-module.handler.d.ts.map +1 -1
  31. package/esm/src/server/handlers/request/prod-hydration-module.handler.js +10 -3
  32. package/esm/src/server/handlers/request/static.handler.d.ts.map +1 -1
  33. package/esm/src/server/handlers/request/static.handler.js +2 -0
  34. package/esm/src/server/runtime-handler/request-utils.js +1 -1
  35. package/esm/src/transforms/mdx/esm-module-loader/cache/index.d.ts.map +1 -1
  36. package/esm/src/transforms/mdx/esm-module-loader/cache/index.js +8 -14
  37. package/esm/src/transforms/mdx/esm-module-loader/import-transformer.d.ts +1 -1
  38. package/esm/src/transforms/mdx/esm-module-loader/import-transformer.d.ts.map +1 -1
  39. package/esm/src/transforms/mdx/esm-module-loader/import-transformer.js +32 -26
  40. package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/nested-imports.d.ts.map +1 -1
  41. package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/nested-imports.js +7 -5
  42. package/esm/src/transforms/mdx/esm-module-loader/module-writer.d.ts.map +1 -1
  43. package/esm/src/transforms/mdx/esm-module-loader/module-writer.js +8 -8
  44. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/import-finder.d.ts +2 -2
  45. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/import-finder.d.ts.map +1 -1
  46. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/import-finder.js +16 -26
  47. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/index.js +1 -1
  48. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/transform.d.ts.map +1 -1
  49. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/transform.js +8 -5
  50. package/esm/src/utils/version-constant.d.ts +1 -1
  51. package/esm/src/utils/version-constant.js +1 -1
  52. package/package.json +1 -1
@@ -12,10 +12,11 @@ export async function analyzeComponent(filePath, fs) {
12
12
  const hasUseServer = detectDirective(content, "use server");
13
13
  // Determine component type: directive takes precedence over file naming convention
14
14
  const type = hasUseClient || filePath.includes(".client.") ? "client" : "server";
15
+ const exports = await extractExportNames(content, filePath);
15
16
  return {
16
17
  type,
17
18
  filePath,
18
- exports: extractExportNames(content),
19
+ exports,
19
20
  id: generateComponentId(filePath),
20
21
  hasUseClient,
21
22
  hasUseServer,
@@ -1,6 +1,8 @@
1
1
  /**
2
- * Extract all export names from source code.
3
- * Handles export function/class/const, named exports, and default exports.
2
+ * Extract runtime export names from source code.
3
+ *
4
+ * Uses the CodeParser AST contract so export-looking strings, comments, and
5
+ * type-only exports do not enter RSC manifests.
4
6
  */
5
- export declare function extractExportNames(source: string): string[];
7
+ export declare function extractExportNames(source: string, filePath?: string): Promise<string[]>;
6
8
  //# sourceMappingURL=export-extractor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"export-extractor.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/rsc/export-extractor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAuC3D"}
1
+ {"version":3,"file":"export-extractor.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/rsc/export-extractor.ts"],"names":[],"mappings":"AAiEA;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,QAAQ,SAAkB,GACzB,OAAO,CAAC,MAAM,EAAE,CAAC,CAwBnB"}
@@ -1,42 +1,65 @@
1
+ import { resolve } from "../../extensions/contracts.js";
2
+ function readName(node) {
3
+ if (typeof node?.name === "string")
4
+ return node.name;
5
+ if (typeof node?.value === "string")
6
+ return node.value;
7
+ return null;
8
+ }
9
+ function isTypeOnlyDeclaration(declaration) {
10
+ if (!declaration)
11
+ return false;
12
+ if (declaration.declare === true)
13
+ return true;
14
+ return declaration.type === "TSInterfaceDeclaration" ||
15
+ declaration.type === "TSTypeAliasDeclaration";
16
+ }
17
+ function addDeclarationNames(names, declaration) {
18
+ if (!declaration || isTypeOnlyDeclaration(declaration))
19
+ return;
20
+ if (declaration.type === "FunctionDeclaration" ||
21
+ declaration.type === "ClassDeclaration" ||
22
+ declaration.type === "TSEnumDeclaration") {
23
+ const name = readName(declaration.id);
24
+ if (name)
25
+ names.add(name);
26
+ return;
27
+ }
28
+ if (declaration.type !== "VariableDeclaration")
29
+ return;
30
+ for (const declarator of declaration.declarations ?? []) {
31
+ const name = readName(declarator.id);
32
+ if (name)
33
+ names.add(name);
34
+ }
35
+ }
1
36
  /**
2
- * Extract all export names from source code.
3
- * Handles export function/class/const, named exports, and default exports.
37
+ * Extract runtime export names from source code.
38
+ *
39
+ * Uses the CodeParser AST contract so export-looking strings, comments, and
40
+ * type-only exports do not enter RSC manifests.
4
41
  */
5
- export function extractExportNames(source) {
42
+ export async function extractExportNames(source, filePath = "component.tsx") {
43
+ const parser = resolve("CodeParser");
44
+ const ast = await parser.parse({ code: source, filePath });
6
45
  const names = new Set();
7
- if (/export\s+default\s+/m.test(source)) {
8
- names.add("default");
9
- }
10
- for (const match of source.matchAll(/export\s+function\s+([A-Za-z0-9_]+)/g)) {
11
- if (match[1])
12
- names.add(match[1]);
13
- }
14
- for (const match of source.matchAll(/export\s+class\s+([A-Za-z0-9_]+)/g)) {
15
- if (match[1])
16
- names.add(match[1]);
17
- }
18
- for (const match of source.matchAll(/export\s+(?:const|let|var)\s+([A-Za-z0-9_]+)/g)) {
19
- if (match[1])
20
- names.add(match[1]);
21
- }
22
- for (const match of source.matchAll(/export\s*\{([^}]+)\}/g)) {
23
- const innerRaw = match[1];
24
- if (!innerRaw)
25
- continue;
26
- const inner = innerRaw.split(",");
27
- for (const seg of inner) {
28
- const part = seg.trim();
29
- if (!part)
30
- continue;
31
- const asMatch = part.match(/([A-Za-z0-9_]+)\s+as\s+([A-Za-z0-9_]+)/i);
32
- if (asMatch?.[2]) {
33
- names.add(asMatch[2]);
34
- continue;
46
+ parser.traverse(ast, {
47
+ ExportDefaultDeclaration() {
48
+ names.add("default");
49
+ },
50
+ ExportNamedDeclaration(path) {
51
+ const node = path.node;
52
+ if (node.exportKind === "type")
53
+ return;
54
+ addDeclarationNames(names, node.declaration);
55
+ for (const specifier of node.specifiers ?? []) {
56
+ if (specifier.exportKind === "type")
57
+ continue;
58
+ const name = readName(specifier.exported) ?? readName(specifier.local);
59
+ if (name)
60
+ names.add(name);
35
61
  }
36
- const plain = part.match(/^([A-Za-z0-9_]+)/);
37
- if (plain?.[1])
38
- names.add(plain[1]);
39
- }
40
- }
62
+ },
63
+ });
41
64
  return [...names];
42
65
  }
@@ -1 +1 @@
1
- {"version":3,"file":"prod-hydration-module.handler.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/request/prod-hydration-module.handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AAqBnG,qBAAa,0BAA2B,SAAQ,WAAW;IACzD,QAAQ,EAAE,eAAe,CAOvB;IAEI,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;CA2BxE"}
1
+ {"version":3,"file":"prod-hydration-module.handler.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/request/prod-hydration-module.handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AAuBnG,qBAAa,0BAA2B,SAAQ,WAAW;IACzD,QAAQ,EAAE,eAAe,CASvB;IAEI,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;CAgCxE"}
@@ -1,5 +1,5 @@
1
1
  import { BaseHandler } from "../response/base.js";
2
- import { generateProdHydrationModule, PROD_HYDRATION_MODULE_PATH, } from "../../../html/hydration-script-builder/prod-scripts.js";
2
+ import { generateProdHydrationModule, isVersionedProdHydrationModulePath, PROD_HYDRATION_MODULE_PATH, PROD_HYDRATION_MODULE_VERSIONED_PATH_PATTERN, } from "../../../html/hydration-script-builder/prod-scripts.js";
3
3
  import { computeStrongEtag, hasMatchingEtag } from "../utils/etag.js";
4
4
  import { HTTP_OK, PRIORITY_HIGH_DEV } from "../../../utils/constants/index.js";
5
5
  let cachedModule = null;
@@ -20,6 +20,8 @@ export class ProdHydrationModuleHandler extends BaseHandler {
20
20
  patterns: [
21
21
  { pattern: PROD_HYDRATION_MODULE_PATH, exact: true, method: "GET" },
22
22
  { pattern: PROD_HYDRATION_MODULE_PATH, exact: true, method: "HEAD" },
23
+ { pattern: PROD_HYDRATION_MODULE_VERSIONED_PATH_PATTERN, method: "GET" },
24
+ { pattern: PROD_HYDRATION_MODULE_VERSIONED_PATH_PATTERN, method: "HEAD" },
23
25
  ],
24
26
  };
25
27
  async handle(req, ctx) {
@@ -27,14 +29,19 @@ export class ProdHydrationModuleHandler extends BaseHandler {
27
29
  return this.continue();
28
30
  }
29
31
  const method = req.method.toUpperCase();
32
+ const pathname = new URL(req.url).pathname;
33
+ const cacheStrategy = isVersionedProdHydrationModulePath(pathname) ? "immutable" : "no-cache";
30
34
  const { js, etag } = getProdHydrationModuleBundle();
31
35
  const builder = this.createResponseBuilder(ctx).withCORS(req, ctx.securityConfig?.cors);
32
36
  if (hasMatchingEtag(req, etag)) {
33
- return this.respond(builder.withSecurity(ctx.securityConfig ?? undefined, req).notModified(etag));
37
+ return this.respond(builder
38
+ .withSecurity(ctx.securityConfig ?? undefined, req)
39
+ .withCache(cacheStrategy)
40
+ .notModified(etag));
34
41
  }
35
42
  return this.respond(builder
36
43
  .withSecurity(ctx.securityConfig ?? undefined, req)
37
- .withCache("no-cache")
44
+ .withCache(cacheStrategy)
38
45
  .withETag(etag)
39
46
  .withContentType("application/javascript; charset=utf-8", method === "HEAD" ? null : js, HTTP_OK));
40
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"static.handler.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/request/static.handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AAkCnG,qBAAa,aAAc,SAAQ,WAAW;IAC5C,QAAQ,EAAE,eAAe,CAOvB;IAEF,OAAO,CAAC,aAAa,CAA2B;IAEhD,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAejE,OAAO,CAAC,cAAc;CAwEvB"}
1
+ {"version":3,"file":"static.handler.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/request/static.handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AAoCnG,qBAAa,aAAc,SAAQ,WAAW;IAC5C,QAAQ,EAAE,eAAe,CAOvB;IAEF,OAAO,CAAC,aAAa,CAA2B;IAEhD,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAejE,OAAO,CAAC,cAAc;CAwEvB"}
@@ -15,6 +15,7 @@ import { withSpan } from "../../../observability/tracing/otlp-setup.js";
15
15
  import { StaticFileService } from "../../services/static/index.js";
16
16
  import { addNonceToHtmlTags } from "../../../html/nonce-injection.js";
17
17
  import { computeEtag } from "../utils/etag.js";
18
+ import { isVersionedProdHydrationModulePath } from "../../../html/hydration-script-builder/prod-scripts.js";
18
19
  function isHtmlResponse(contentType) {
19
20
  return /\btext\/html\b/i.test(contentType);
20
21
  }
@@ -24,6 +25,7 @@ function isProductionBuildAssetPath(pathname) {
24
25
  pathname === "/_veryfront/router.js" ||
25
26
  pathname === "/_veryfront/prefetch.js" ||
26
27
  pathname === "/_veryfront/hydration-runtime.js" ||
28
+ isVersionedProdHydrationModulePath(pathname) ||
27
29
  pathname === "/_veryfront/manifest.json" ||
28
30
  pathname.startsWith("/_veryfront/chunks/") ||
29
31
  pathname.startsWith("/_veryfront/pages/") ||
@@ -50,7 +50,7 @@ export const LIGHTWEIGHT_PATH_PREFIXES = [
50
50
  "/_vf_modules/",
51
51
  "/_vf_styles/",
52
52
  "/_veryfront/modules/",
53
- "/_veryfront/hydration-runtime.js",
53
+ "/_veryfront/hydration-runtime",
54
54
  "/_veryfront/preview-hmr.js",
55
55
  "/_veryfront/studio-bridge.js",
56
56
  "/_vf/css/",
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/cache/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAYH,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAI5D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C,MAAM,MAAM,iBAAiB,GACzB;IAAE,MAAM,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAClB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAK9D,eAAO,MAAM,kBAAkB,wBAE7B,CAAC;AA6IH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAsBvF;AAED,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAezE;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAK3C;AAQD,2DAA2D;AAC3D,wBAAgB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAElD;AAuBD,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI,CA0ElE;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,YAAY,SAAwB,GACnC,IAAI,CAgBN;AAOD,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAevD;AAED,wBAAsB,yBAAyB,CAC7C,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,CAwCf;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAc1D;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAIzD;AAmBD,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,YAAY,CAAC,EAAE,MAAM,EAAE,oDAAoD;AAC3E,eAAe,CAAC,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,EAChE,YAAY,SAAwB,GACnC,OAAO,CAAC,iBAAiB,CAAC,CA+J5B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/cache/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAYH,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAK5D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C,MAAM,MAAM,iBAAiB,GACzB;IAAE,MAAM,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAClB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAK9D,eAAO,MAAM,kBAAkB,wBAE7B,CAAC;AAsIH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAsBvF;AAED,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAezE;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAK3C;AAQD,2DAA2D;AAC3D,wBAAgB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAElD;AAuBD,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI,CA0ElE;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,YAAY,SAAwB,GACnC,IAAI,CAgBN;AAOD,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAevD;AAED,wBAAsB,yBAAyB,CAC7C,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,CAwCf;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAc1D;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAIzD;AAmBD,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,YAAY,CAAC,EAAE,MAAM,EAAE,oDAAoD;AAC3E,eAAe,CAAC,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,EAChE,YAAY,SAAwB,GACnC,OAAO,CAAC,iBAAiB,CAAC,CA+J5B"}
@@ -15,6 +15,7 @@ import { LRUCache } from "../../../../utils/lru-wrapper.js";
15
15
  import { registerCache } from "../../../../utils/memory/index.js";
16
16
  import { buildMdxEsmPathCacheKey, MDX_ESM_ALL_FILE_URL_PATTERN_SOURCE } from "../cache-format.js";
17
17
  import { ensureMdxModuleDependencies } from "../module-fetcher/dependency-recovery.js";
18
+ import { findStaticImportFromSpans } from "../utils/source-spans.js";
18
19
  export { getLocalFs } from "./local-fs.js";
19
20
  import { getLocalFs } from "./local-fs.js";
20
21
  const MAX_VERIFIED_MODULE_DEPS = 2_000;
@@ -105,27 +106,20 @@ async function findMissingFileDependencies(code) {
105
106
  }
106
107
  return missing;
107
108
  }
108
- /**
109
- * Pattern to match unresolved /_vf_modules/ imports that weren't converted to proper file:// paths.
110
- * Matches both:
111
- * - `from "/_vf_modules/..."` or `from "_vf_modules/..."` (unresolved)
112
- * - `from "file:///_vf_modules/..."` (malformed - points to non-existent root /_vf_modules/)
113
- * Note: Uses \s* instead of \s+ because minified code may have no space after `from`.
114
- * These imports will fail at runtime because they can't be resolved by Deno's dynamic import.
115
- */
116
- const UNRESOLVED_VF_MODULES_PATTERN = /from\s*["']((?:file:\/\/)?\/?\/?_vf_modules\/[^"']+)["']/g;
109
+ function matchUnresolvedVfModuleSpecifier(specifier) {
110
+ return specifier.match(/^((?:file:\/\/)?\/?\/?_vf_modules\/[^?]+)(?:\?.*)?$/)?.[1] ?? null;
111
+ }
117
112
  /**
118
113
  * Check if cached code has unresolved or malformed /_vf_modules/ imports.
119
114
  * These should have been resolved to proper file:// paths (e.g., file:///Users/.cache/...).
120
115
  * Returns true if any unresolved or malformed imports are found.
121
116
  */
122
117
  function hasUnresolvedVfModules(code) {
123
- const pattern = new RegExp(UNRESOLVED_VF_MODULES_PATTERN.source, "g");
124
- let match;
125
- while ((match = pattern.exec(code)) !== null) {
126
- const importPath = match[1];
118
+ const matches = findStaticImportFromSpans(code, matchUnresolvedVfModuleSpecifier);
119
+ const first = matches[0];
120
+ if (first) {
127
121
  logger.debug(`${LOG_PREFIX_MDX_LOADER} Cached module has unresolved _vf_modules import`, {
128
- importPath,
122
+ importPath: first.path,
129
123
  });
130
124
  return true;
131
125
  }
@@ -11,7 +11,7 @@ import type { ESMLoaderContext } from "./types.js";
11
11
  /**
12
12
  * Rewrite @/ aliased imports to /_vf_modules/ paths.
13
13
  */
14
- export declare function rewriteProjectAliasImports(code: string): string;
14
+ export declare function rewriteProjectAliasImports(code: string): Promise<string>;
15
15
  /**
16
16
  * Transform bare React specifiers to local file:// paths for Bun/Node.
17
17
  * This ensures the same React instance as react-dom-server.
@@ -1 +1 @@
1
- {"version":3,"file":"import-transformer.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/mdx/esm-module-loader/import-transformer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAe5E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK/D;AAED;;;;GAIG;AACH,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAK9E;AAyBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,GAAG,MAAM,CAIjF;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,gBAAgB,CAAC,SAAS,CAAC,EACpC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CA6HjB"}
1
+ {"version":3,"file":"import-transformer.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/mdx/esm-module-loader/import-transformer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAa5E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;;GAEG;AACH,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAO9E;AAED;;;;GAIG;AACH,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAK9E;AAyBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,GAAG,MAAM,CAIjF;AAOD;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,gBAAgB,CAAC,SAAS,CAAC,EACpC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CAwHjB"}
@@ -9,9 +9,9 @@
9
9
  import { join } from "../../../platform/compat/path/index.js";
10
10
  import { rendererLogger as logger } from "../../../utils/index.js";
11
11
  import { transformImportsWithMap } from "../../../modules/import-map/index.js";
12
- import { replaceSpecifiers } from "../../esm/lexer.js";
12
+ import { parseImports, replaceSpecifiers } from "../../esm/lexer.js";
13
13
  import { getLocalReactPaths, isReactSpecifier } from "../../../platform/compat/react-paths.js";
14
- import { ESBUILD_JSX_FACTORY, ESBUILD_JSX_FRAGMENT, FRAMEWORK_ROOT, JSX_IMPORT_PATTERN, LOG_PREFIX_MDX_LOADER, REACT_IMPORT_PATTERN, } from "./constants.js";
14
+ import { ESBUILD_JSX_FACTORY, ESBUILD_JSX_FRAGMENT, FRAMEWORK_ROOT, LOG_PREFIX_MDX_LOADER, } from "./constants.js";
15
15
  import { getLocalFs } from "./cache/index.js";
16
16
  import { buildMdxJsxCacheFileName } from "./cache-format.js";
17
17
  import { rewriteDntImports } from "./module-fetcher/index.js";
@@ -19,10 +19,13 @@ import { ensureCachedJsxModulePatched } from "./jsx-cache.js";
19
19
  /**
20
20
  * Rewrite @/ aliased imports to /_vf_modules/ paths.
21
21
  */
22
- export function rewriteProjectAliasImports(code) {
23
- return code.replace(/from\s*["']@\/([^"']+)["']/g, (_match, path) => {
22
+ export async function rewriteProjectAliasImports(code) {
23
+ return await replaceSpecifiers(code, (specifier) => {
24
+ if (!specifier.startsWith("@/"))
25
+ return null;
26
+ const path = specifier.slice(2);
24
27
  const jsPath = path.endsWith(".js") ? path : `${path}.js`;
25
- return `from "/_vf_modules/${jsPath}"`;
28
+ return `/_vf_modules/${jsPath}`;
26
29
  });
27
30
  }
28
31
  /**
@@ -65,6 +68,10 @@ export function transformImports(code, importMap) {
65
68
  resolveBare: true,
66
69
  });
67
70
  }
71
+ async function hasReactImport(code) {
72
+ const imports = await parseImports(code);
73
+ return imports.some((importSpecifier) => importSpecifier.n === "react");
74
+ }
68
75
  /**
69
76
  * Transform JSX/TSX imports using esbuild.
70
77
  * Optimized to process all imports in parallel batches for better performance.
@@ -72,25 +79,22 @@ export function transformImports(code, importMap) {
72
79
  export async function transformJsxImports(code, adapter, esmCacheDir) {
73
80
  const { transform } = await import("../../../extensions/bundler/index.js");
74
81
  const importsToProcess = [];
75
- let jsxMatch;
76
- while ((jsxMatch = JSX_IMPORT_PATTERN.exec(code)) !== null) {
77
- const [fullMatch, importClause, filePath, ext] = jsxMatch;
78
- if (!filePath || !importClause || !ext) {
79
- logger.warn(`${LOG_PREFIX_MDX_LOADER} Skipping JSX import with undefined fields`, {
80
- fullMatch,
81
- hasFilePath: !!filePath,
82
- hasImportClause: !!importClause,
83
- hasExt: !!ext,
84
- });
82
+ const imports = await parseImports(code);
83
+ for (const importSpecifier of imports) {
84
+ const specifier = importSpecifier.n;
85
+ if (!specifier?.startsWith("file://"))
85
86
  continue;
86
- }
87
- importsToProcess.push({ fullMatch, importClause, filePath, ext });
87
+ const filePath = specifier.slice("file://".length);
88
+ const ext = filePath.match(/\.(tsx?|jsx?)$/)?.[1];
89
+ if (!ext)
90
+ continue;
91
+ importsToProcess.push({ specifier, filePath, ext });
88
92
  }
89
93
  if (importsToProcess.length === 0)
90
94
  return code;
91
95
  const transformStart = performance.now();
92
96
  logger.debug(`${LOG_PREFIX_MDX_LOADER} Transforming ${importsToProcess.length} JSX imports in parallel`);
93
- const transformResults = await Promise.all(importsToProcess.map(async ({ fullMatch, importClause, filePath, ext }) => {
97
+ const transformResults = await Promise.all(importsToProcess.map(async ({ specifier, filePath, ext }) => {
94
98
  try {
95
99
  const isFrameworkFile = filePath.startsWith(FRAMEWORK_ROOT);
96
100
  let jsxCode;
@@ -115,8 +119,8 @@ export async function transformJsxImports(code, adapter, esmCacheDir) {
115
119
  const useCached = await ensureCachedJsxModulePatched(transformedPath, filePath);
116
120
  if (useCached) {
117
121
  return {
118
- original: fullMatch,
119
- transformed: `import ${importClause} from "file://${transformedPath}";`,
122
+ specifier,
123
+ replacement: `file://${transformedPath}`,
120
124
  cached: true,
121
125
  };
122
126
  }
@@ -140,7 +144,7 @@ export async function transformJsxImports(code, adapter, esmCacheDir) {
140
144
  format: "esm",
141
145
  });
142
146
  let transformed = result.code;
143
- if (!REACT_IMPORT_PATTERN.test(transformed)) {
147
+ if (!(await hasReactImport(transformed))) {
144
148
  transformed = `import React from 'react';\n${transformed}`;
145
149
  }
146
150
  // Rewrite _dnt.polyfills.js / _dnt.shims.js relative imports to absolute file:// paths.
@@ -149,8 +153,8 @@ export async function transformJsxImports(code, adapter, esmCacheDir) {
149
153
  transformed = await rewriteDntImports(transformed, filePath);
150
154
  await getLocalFs().writeTextFile(transformedPath, transformed);
151
155
  return {
152
- original: fullMatch,
153
- transformed: `import ${importClause} from "file://${transformedPath}";`,
156
+ specifier,
157
+ replacement: `file://${transformedPath}`,
154
158
  cached: false,
155
159
  };
156
160
  }
@@ -165,10 +169,12 @@ export async function transformJsxImports(code, adapter, esmCacheDir) {
165
169
  cached: transformResults.filter((r) => r?.cached).length,
166
170
  durationMs: (performance.now() - transformStart).toFixed(1),
167
171
  });
168
- let result = code;
172
+ const replacements = new Map();
169
173
  for (const t of transformResults) {
170
174
  if (t)
171
- result = result.replace(t.original, t.transformed);
175
+ replacements.set(t.specifier, t.replacement);
172
176
  }
173
- return result;
177
+ if (replacements.size === 0)
178
+ return code;
179
+ return await replaceSpecifiers(code, (specifier) => replacements.get(specifier) ?? null);
174
180
  }
@@ -1 +1 @@
1
- {"version":3,"file":"nested-imports.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/module-fetcher/nested-imports.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAQtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AAEjE;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,GACjB;IACD,SAAS,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjF,QAAQ,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjF,CAkCA;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAO3F;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,kBAAkB,EAAE,EAC7B,WAAW,EAAE,MAAM,EACnB,oBAAoB,EAAE,OAAO,EAC7B,gBAAgB,CAAC,EAAE,MAAM,EACzB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,CAqCjB;AAED,MAAM,WAAW,+BAA+B;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/E,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,+BAA+B,GACrC,OAAO,CAAC,MAAM,CAAC,CAuDjB"}
1
+ {"version":3,"file":"nested-imports.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/module-fetcher/nested-imports.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAQtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AAMjE;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,GACjB;IACD,SAAS,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjF,QAAQ,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjF,CAkCA;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAM3F;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,kBAAkB,EAAE,EAC7B,WAAW,EAAE,MAAM,EACnB,oBAAoB,EAAE,OAAO,EAC7B,gBAAgB,CAAC,EAAE,MAAM,EACzB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,CAqCjB;AAED,MAAM,WAAW,+BAA+B;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/E,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,+BAA+B,GACrC,OAAO,CAAC,MAAM,CAAC,CAuDjB"}
@@ -3,10 +3,13 @@
3
3
  *
4
4
  * @module transforms/mdx/esm-module-loader/module-fetcher/nested-imports
5
5
  */
6
- import { LOG_PREFIX_MDX_LOADER, UNRESOLVED_VF_MODULES_PATTERN } from "../constants.js";
6
+ import { LOG_PREFIX_MDX_LOADER } from "../constants.js";
7
7
  import { createStubModule } from "../utils/stub-module.js";
8
8
  import { findStaticImportFromSpans, replaceSourceSpans, } from "../utils/source-spans.js";
9
9
  import { buildMissingModuleError } from "../missing-module.js";
10
+ function matchUnresolvedVfModuleSpecifier(specifier) {
11
+ return specifier.match(/^((?:file:\/\/)?\/?\/?_vf_modules\/[^?]+)(?:\?.*)?$/)?.[1] ?? null;
12
+ }
10
13
  /**
11
14
  * Find nested module imports in code.
12
15
  * Matches both /_vf_modules/... and file:///_vf_modules/... patterns.
@@ -14,7 +17,7 @@ import { buildMissingModuleError } from "../missing-module.js";
14
17
  export function findNestedImports(moduleCode) {
15
18
  const vfModules = [];
16
19
  const relative = [];
17
- for (const { original, path: rawPath, start, end } of findStaticImportFromSpans(moduleCode, (specifier) => specifier.match(/^((?:file:\/\/)?\/?\/?_vf_modules\/[^?]+)(?:\?.*)?$/)?.[1])) {
20
+ for (const { original, path: rawPath, start, end } of findStaticImportFromSpans(moduleCode, matchUnresolvedVfModuleSpecifier)) {
18
21
  // Strip file:// prefix and leading slashes to get clean _vf_modules/... path
19
22
  vfModules.push({
20
23
  original,
@@ -37,11 +40,10 @@ export function findNestedImports(moduleCode) {
37
40
  * Check for unresolved /_vf_modules/ imports.
38
41
  */
39
42
  export function hasUnresolvedImports(moduleCode) {
40
- const pattern = new RegExp(UNRESOLVED_VF_MODULES_PATTERN.source, "g");
41
- const matches = [...moduleCode.matchAll(pattern)];
43
+ const matches = findStaticImportFromSpans(moduleCode, matchUnresolvedVfModuleSpecifier);
42
44
  return {
43
45
  count: matches.length,
44
- paths: matches.map((m) => m[1]).filter((p) => p !== undefined).slice(0, 5),
46
+ paths: matches.map((match) => match.path).slice(0, 5),
45
47
  };
46
48
  }
47
49
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"module-writer.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/mdx/esm-module-loader/module-writer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAyBH,OAAO,KAAK,EAAkB,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAiDnD,wBAAsB,eAAe,CACnC,mBAAmB,EAAE,MAAM,EAC3B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,SAAS,CAAC,CA4VpB"}
1
+ {"version":3,"file":"module-writer.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/mdx/esm-module-loader/module-writer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAyBH,OAAO,KAAK,EAAkB,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA8CnD,wBAAsB,eAAe,CACnC,mBAAmB,EAAE,MAAM,EAC3B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,SAAS,CAAC,CA2VpB"}
@@ -20,7 +20,7 @@ import { loadImportMap } from "../../../modules/import-map/index.js";
20
20
  import { cacheHttpImportsToLocal, ensureHttpBundlesExist } from "../../esm/http-cache.js";
21
21
  import { extractAllHttpBundlePathsRecursive, extractHttpBundlePaths, } from "../../../modules/react-loader/ssr-module-loader/http-bundle-helpers.js";
22
22
  import { setupSSRGlobals } from "../../../rendering/ssr-globals.js";
23
- import { LOG_PREFIX_MDX_LOADER, LOG_PREFIX_MDX_RENDERER, UNRESOLVED_VF_MODULES_PATTERN, } from "./constants.js";
23
+ import { LOG_PREFIX_MDX_LOADER, LOG_PREFIX_MDX_RENDERER } from "./constants.js";
24
24
  import { getLocalFs } from "./cache/index.js";
25
25
  import { hashString } from "./utils/hash.js";
26
26
  import { ssrVfModulesPlugin } from "../../pipeline/stages/ssr-vf-modules.js";
@@ -28,6 +28,7 @@ import { REACT_DEFAULT_VERSION } from "../../../utils/constants/cdn.js";
28
28
  import { extractFrameworkBundlePaths } from "../../shared/framework-bundle-paths.js";
29
29
  import { rewriteProjectAliasImports, transformImports, transformJsxImports, transformReactToLocalPaths, } from "./import-transformer.js";
30
30
  import { findMissingFrameworkBundles, findVfModuleImports, initializeCacheDir, processVfModuleImports, resolveProjectDir, } from "./loader-helpers.js";
31
+ import { hasUnresolvedImports } from "./module-fetcher/nested-imports.js";
31
32
  /** Singleflight for MDX module file writes to prevent race conditions */
32
33
  const mdxWriteFlight = new Singleflight();
33
34
  /**
@@ -64,7 +65,7 @@ export async function doLoadModuleESM(compiledProgramCode, context) {
64
65
  logger.debug(`${LOG_PREFIX_MDX_LOADER} Step: initializeCacheDir START`, { projectSlug });
65
66
  const esmCacheDir = await initializeCacheDir(context);
66
67
  logger.debug(`${LOG_PREFIX_MDX_LOADER} Step: initializeCacheDir DONE`, { projectSlug });
67
- let rewritten = rewriteProjectAliasImports(compiledProgramCode);
68
+ let rewritten = await rewriteProjectAliasImports(compiledProgramCode);
68
69
  const projectDir = resolveProjectDir(context);
69
70
  logger.debug(`${LOG_PREFIX_MDX_LOADER} Step: loadImportMap START`, { projectSlug });
70
71
  const importMap = await loadImportMap(projectDir, adapter);
@@ -103,12 +104,11 @@ export async function doLoadModuleESM(compiledProgramCode, context) {
103
104
  return cached;
104
105
  }
105
106
  logger.debug(`${LOG_PREFIX_MDX_LOADER} Module cache miss`, { projectSlug, compositeKey });
106
- const unresolvedMatches = [
107
- ...rewritten.matchAll(new RegExp(UNRESOLVED_VF_MODULES_PATTERN.source, "g")),
108
- ];
109
- if (unresolvedMatches.length > 0) {
110
- const unresolvedPaths = unresolvedMatches.map((m) => m[1]).slice(0, 5);
111
- const errorMsg = `MDX has ${unresolvedMatches.length} unresolved module imports: ${unresolvedPaths.join(", ")}`;
107
+ const unresolved = hasUnresolvedImports(rewritten);
108
+ if (unresolved.count > 0) {
109
+ const errorMsg = `MDX has ${unresolved.count} unresolved module imports: ${unresolved.paths
110
+ .slice(0, 5)
111
+ .join(", ")}`;
112
112
  logger.error(`${LOG_PREFIX_MDX_RENDERER} ${errorMsg}`);
113
113
  throw IMPORT_RESOLUTION_ERROR.create({ detail: errorMsg });
114
114
  }
@@ -5,10 +5,10 @@
5
5
  * Find all /_vf_modules/_veryfront/ imports in the code.
6
6
  * Only matches framework modules, not user project files.
7
7
  */
8
- export declare function findVfModuleImports(code: string): string[];
8
+ export declare function findVfModuleImports(code: string): Promise<string[]>;
9
9
  /**
10
10
  * Find all relative imports (./foo, ../bar) in the code.
11
11
  * Returns array of specifiers.
12
12
  */
13
- export declare function findRelativeImports(code: string): string[];
13
+ export declare function findRelativeImports(code: string): Promise<string[]>;
14
14
  //# sourceMappingURL=import-finder.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"import-finder.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/pipeline/stages/ssr-vf-modules/import-finder.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAc1D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAiB1D"}
1
+ {"version":3,"file":"import-finder.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/pipeline/stages/ssr-vf-modules/import-finder.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAUzE;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAUzE"}
@@ -1,39 +1,29 @@
1
1
  /**
2
2
  * Import discovery functions for the SSR VF Modules stage.
3
3
  */
4
+ import { parseImports } from "../../../esm/lexer.js";
5
+ function unique(values) {
6
+ return [...new Set(values)];
7
+ }
4
8
  /**
5
9
  * Find all /_vf_modules/_veryfront/ imports in the code.
6
10
  * Only matches framework modules, not user project files.
7
11
  */
8
- export function findVfModuleImports(code) {
9
- const imports = [];
10
- // Note: \s* allows zero whitespace (minified code: from"..." has no space)
11
- // Only match _veryfront/ framework modules, not user project files.
12
- // Handle both raw "/_vf_modules/..." specifiers and malformed
13
- // "file:///_vf_modules/..." variants that can leak out of stale caches.
14
- const pattern = /from\s*["']((?:file:\/\/)?\/_vf_modules\/_veryfront\/[^"']+)["']/g;
15
- let match;
16
- while ((match = pattern.exec(code)) !== null) {
17
- imports.push(match[1]);
18
- }
19
- return [...new Set(imports)];
12
+ export async function findVfModuleImports(code) {
13
+ const imports = await parseImports(code);
14
+ return unique(imports
15
+ .map((imp) => imp.n)
16
+ .filter((specifier) => specifier?.startsWith("/_vf_modules/_veryfront/") === true ||
17
+ specifier?.startsWith("file:///_vf_modules/_veryfront/") === true));
20
18
  }
21
19
  /**
22
20
  * Find all relative imports (./foo, ../bar) in the code.
23
21
  * Returns array of specifiers.
24
22
  */
25
- export function findRelativeImports(code) {
26
- const imports = [];
27
- // Match: from "./foo" or from "../bar"
28
- const fromPattern = /from\s*["'](\.\.?\/[^"']+)["']/g;
29
- // Match side-effect imports: import "./foo" or import "../bar" (no `from`)
30
- const sideEffectPattern = /import\s*["'](\.\.?\/[^"']+)["']/g;
31
- let match;
32
- while ((match = fromPattern.exec(code)) !== null) {
33
- imports.push(match[1]);
34
- }
35
- while ((match = sideEffectPattern.exec(code)) !== null) {
36
- imports.push(match[1]);
37
- }
38
- return [...new Set(imports)];
23
+ export async function findRelativeImports(code) {
24
+ const imports = await parseImports(code);
25
+ return unique(imports
26
+ .map((imp) => imp.n)
27
+ .filter((specifier) => specifier?.startsWith("./") === true ||
28
+ specifier?.startsWith("../") === true));
39
29
  }
@@ -52,7 +52,7 @@ export const ssrVfModulesPlugin = {
52
52
  condition: (ctx) => ctx.target === "ssr",
53
53
  async transform(ctx) {
54
54
  logInitOnce();
55
- const vfModuleImports = findVfModuleImports(ctx.code);
55
+ const vfModuleImports = await findVfModuleImports(ctx.code);
56
56
  logger.debug(`${LOG_PREFIX} Transform called`, {
57
57
  file: ctx.filePath?.slice(-60) ?? "<unknown>",
58
58
  count: vfModuleImports.length,
@@ -1 +1 @@
1
- {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/pipeline/stages/ssr-vf-modules/transform.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAmBrE,OAAO,EAOL,KAAK,gBAAgB,EAGtB,MAAM,gBAAgB,CAAC;AAKxB;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,EAAE,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,CA2BjB;AAgBD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAwMhE;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,gBAAgB,EACrB,oBAAoB,UAAQ,EAC5B,KAAK,SAAI,GACR,OAAO,CAAC,MAAM,CAAC,CA8OjB;AAED;;;GAGG;AACH,wBAAsB,kCAAkC,CACtD,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA4CxB;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,CAEjB"}
1
+ {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/pipeline/stages/ssr-vf-modules/transform.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAmBrE,OAAO,EAOL,KAAK,gBAAgB,EAGtB,MAAM,gBAAgB,CAAC;AAKxB;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,EAAE,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,CA2BjB;AAgBD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAwMhE;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,gBAAgB,EACrB,oBAAoB,UAAQ,EAC5B,KAAK,SAAI,GACR,OAAO,CAAC,MAAM,CAAC,CAgPjB;AAED;;;GAGG;AACH,wBAAsB,kCAAkC,CACtD,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA4CxB;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,CAEjB"}