vinext 0.1.3 → 0.1.5

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 (185) hide show
  1. package/dist/build/client-build-config.d.ts +11 -2
  2. package/dist/build/client-build-config.js +17 -6
  3. package/dist/build/css-url-assets.d.ts +1 -1
  4. package/dist/build/css-url-assets.js +9 -7
  5. package/dist/build/prerender.js +3 -1
  6. package/dist/cache/cache-adapters-virtual.js +1 -1
  7. package/dist/client/pages-router-link-navigation.d.ts +33 -7
  8. package/dist/client/pages-router-link-navigation.js +32 -2
  9. package/dist/client/vinext-next-data.js +2 -0
  10. package/dist/cloudflare/src/cache/kv-data-adapter.runtime.d.ts +1 -1
  11. package/dist/config/config-matchers.d.ts +11 -1
  12. package/dist/config/config-matchers.js +14 -2
  13. package/dist/config/tsconfig-paths.js +14 -1
  14. package/dist/deploy.js +20 -13
  15. package/dist/entries/app-rsc-entry.js +27 -22
  16. package/dist/entries/pages-client-entry.js +14 -13
  17. package/dist/entries/pages-server-entry.js +8 -27
  18. package/dist/index.js +365 -147
  19. package/dist/plugins/css-data-url.js +30 -26
  20. package/dist/plugins/dynamic-preload-metadata.js +2 -4
  21. package/dist/plugins/extensionless-dynamic-import.js +27 -24
  22. package/dist/plugins/fonts.js +5 -4
  23. package/dist/plugins/import-meta-url.js +21 -15
  24. package/dist/plugins/instrumentation-client.js +1 -1
  25. package/dist/plugins/middleware-server-only.js +7 -6
  26. package/dist/plugins/og-assets.js +48 -46
  27. package/dist/plugins/optimize-imports.js +9 -3
  28. package/dist/plugins/remove-console.d.ts +7 -1
  29. package/dist/plugins/remove-console.js +4 -1
  30. package/dist/plugins/require-context.js +21 -20
  31. package/dist/plugins/strip-server-exports.d.ts +16 -8
  32. package/dist/plugins/strip-server-exports.js +496 -46
  33. package/dist/routing/app-route-graph.js +2 -2
  34. package/dist/server/app-bfcache-identity.d.ts +26 -0
  35. package/dist/server/app-bfcache-identity.js +127 -0
  36. package/dist/server/app-browser-action-result.js +1 -1
  37. package/dist/server/app-browser-entry.js +22 -12
  38. package/dist/server/app-browser-navigation-controller.d.ts +1 -1
  39. package/dist/server/app-browser-navigation-controller.js +1 -1
  40. package/dist/server/app-browser-state.d.ts +3 -22
  41. package/dist/server/app-browser-state.js +23 -139
  42. package/dist/server/app-browser-stream.js +1 -1
  43. package/dist/server/app-browser-visible-commit.d.ts +1 -1
  44. package/dist/server/app-browser-visible-commit.js +3 -2
  45. package/dist/server/app-fallback-renderer.d.ts +1 -1
  46. package/dist/server/app-layout-param-observation.d.ts +1 -1
  47. package/dist/server/app-layout-param-observation.js +1 -1
  48. package/dist/server/app-middleware.js +2 -1
  49. package/dist/server/app-page-boundary-render.d.ts +1 -1
  50. package/dist/server/app-page-boundary.js +1 -1
  51. package/dist/server/app-page-cache-finalizer.d.ts +62 -0
  52. package/dist/server/app-page-cache-finalizer.js +122 -0
  53. package/dist/server/app-page-cache-render.d.ts +2 -2
  54. package/dist/server/app-page-cache-render.js +1 -1
  55. package/dist/server/app-page-cache.d.ts +2 -53
  56. package/dist/server/app-page-cache.js +5 -131
  57. package/dist/server/app-page-dispatch.d.ts +2 -2
  58. package/dist/server/app-page-dispatch.js +10 -8
  59. package/dist/server/app-page-probe.js +3 -2
  60. package/dist/server/app-page-render-observation.js +2 -2
  61. package/dist/server/app-page-render.d.ts +3 -3
  62. package/dist/server/app-page-render.js +3 -2
  63. package/dist/server/app-page-stream.d.ts +2 -9
  64. package/dist/server/app-page-stream.js +1 -35
  65. package/dist/server/app-pages-bridge.d.ts +5 -1
  66. package/dist/server/app-pages-bridge.js +5 -13
  67. package/dist/server/app-request-context.d.ts +1 -2
  68. package/dist/server/app-request-context.js +2 -1
  69. package/dist/server/app-route-handler-dispatch.js +3 -2
  70. package/dist/server/app-route-handler-execution.d.ts +1 -1
  71. package/dist/server/app-route-handler-execution.js +1 -1
  72. package/dist/server/app-route-handler-response.d.ts +1 -1
  73. package/dist/server/app-router-entry.js +2 -1
  74. package/dist/server/app-rsc-handler.d.ts +3 -0
  75. package/dist/server/app-rsc-handler.js +73 -31
  76. package/dist/server/app-rsc-response-finalizer.js +1 -1
  77. package/dist/server/app-rsc-route-matching.js +6 -2
  78. package/dist/server/app-server-action-execution.d.ts +1 -1
  79. package/dist/server/app-server-action-execution.js +10 -6
  80. package/dist/server/app-ssr-entry.d.ts +1 -1
  81. package/dist/server/app-ssr-entry.js +12 -38
  82. package/dist/server/app-ssr-router-instance.d.ts +6 -0
  83. package/dist/server/app-ssr-router-instance.js +24 -0
  84. package/dist/server/app-ssr-stream.js +1 -1
  85. package/dist/server/artifact-compatibility.js +1 -1
  86. package/dist/server/before-interactive-head.d.ts +17 -0
  87. package/dist/server/before-interactive-head.js +35 -0
  88. package/dist/server/client-reuse-manifest.js +1 -1
  89. package/dist/server/csp.js +1 -4
  90. package/dist/server/defer-until-stream-consumed.d.ts +7 -0
  91. package/dist/server/defer-until-stream-consumed.js +34 -0
  92. package/dist/server/dev-server.js +82 -37
  93. package/dist/server/instrumentation.js +1 -1
  94. package/dist/server/isr-cache.d.ts +1 -1
  95. package/dist/server/isr-cache.js +1 -1
  96. package/dist/server/isr-decision.d.ts +1 -1
  97. package/dist/server/middleware-matcher.js +20 -9
  98. package/dist/server/middleware-runtime.d.ts +3 -4
  99. package/dist/server/middleware-runtime.js +4 -2
  100. package/dist/server/navigation-planner.d.ts +3 -12
  101. package/dist/server/navigation-planner.js +24 -0
  102. package/dist/server/navigation-trace.d.ts +2 -1
  103. package/dist/server/navigation-trace.js +1 -0
  104. package/dist/server/open-redirect.d.ts +12 -0
  105. package/dist/server/open-redirect.js +21 -0
  106. package/dist/server/operation-token.d.ts +40 -0
  107. package/dist/server/operation-token.js +85 -0
  108. package/dist/server/pages-data-route.d.ts +1 -1
  109. package/dist/server/pages-data-route.js +7 -4
  110. package/dist/server/pages-dev-module-url.d.ts +4 -0
  111. package/dist/server/pages-dev-module-url.js +15 -0
  112. package/dist/server/pages-document-initial-props.d.ts +4 -15
  113. package/dist/server/pages-document-initial-props.js +27 -56
  114. package/dist/server/pages-i18n.js +2 -2
  115. package/dist/server/pages-page-data.d.ts +1 -1
  116. package/dist/server/pages-page-data.js +3 -1
  117. package/dist/server/pages-page-handler.js +3 -1
  118. package/dist/server/pages-page-response.d.ts +3 -1
  119. package/dist/server/pages-page-response.js +6 -6
  120. package/dist/server/pages-readiness.js +1 -1
  121. package/dist/server/pages-request-pipeline.d.ts +7 -7
  122. package/dist/server/pages-request-pipeline.js +63 -21
  123. package/dist/server/prod-server.d.ts +3 -1
  124. package/dist/server/prod-server.js +43 -11
  125. package/dist/server/request-pipeline.d.ts +1 -24
  126. package/dist/server/request-pipeline.js +1 -33
  127. package/dist/server/seed-cache.d.ts +1 -1
  128. package/dist/server/static-file-cache.js +16 -4
  129. package/dist/shims/before-interactive-context.d.ts +14 -3
  130. package/dist/shims/cache-handler.d.ts +106 -0
  131. package/dist/shims/cache-handler.js +176 -0
  132. package/dist/shims/cache-request-state.d.ts +47 -0
  133. package/dist/shims/cache-request-state.js +126 -0
  134. package/dist/shims/cache-runtime.d.ts +2 -2
  135. package/dist/shims/cache-runtime.js +3 -14
  136. package/dist/shims/cache.d.ts +3 -231
  137. package/dist/shims/cache.js +17 -383
  138. package/dist/shims/cdn-cache.d.ts +1 -1
  139. package/dist/shims/cdn-cache.js +1 -1
  140. package/dist/shims/document.d.ts +15 -20
  141. package/dist/shims/document.js +5 -8
  142. package/dist/shims/error-boundary-navigation.d.ts +7 -0
  143. package/dist/shims/error-boundary-navigation.js +44 -0
  144. package/dist/shims/error-boundary.js +10 -8
  145. package/dist/shims/error.js +2 -1
  146. package/dist/shims/fetch-cache.js +1 -1
  147. package/dist/shims/form.js +1 -1
  148. package/dist/shims/image.js +74 -9
  149. package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -0
  150. package/dist/shims/internal/app-page-props-cache-key.js +16 -0
  151. package/dist/shims/internal/navigation-untracked.js +2 -1
  152. package/dist/shims/internal/pages-data-fetch-dedup.d.ts +6 -7
  153. package/dist/shims/internal/pages-data-fetch-dedup.js +67 -14
  154. package/dist/shims/internal/pages-data-target.js +1 -1
  155. package/dist/shims/layout-segment-context.d.ts +1 -1
  156. package/dist/shims/layout-segment-context.js +2 -1
  157. package/dist/shims/link.js +38 -17
  158. package/dist/shims/metadata.js +4 -4
  159. package/dist/shims/navigation-context-state.d.ts +40 -0
  160. package/dist/shims/navigation-context-state.js +116 -0
  161. package/dist/shims/navigation-errors.d.ts +55 -0
  162. package/dist/shims/navigation-errors.js +110 -0
  163. package/dist/shims/navigation-server.d.ts +3 -0
  164. package/dist/shims/navigation-server.js +3 -0
  165. package/dist/shims/navigation-state.d.ts +1 -2
  166. package/dist/shims/navigation-state.js +2 -1
  167. package/dist/shims/navigation.d.ts +3 -291
  168. package/dist/shims/navigation.js +16 -445
  169. package/dist/shims/navigation.react-server.d.ts +2 -2
  170. package/dist/shims/navigation.react-server.js +3 -1
  171. package/dist/shims/request-state-types.d.ts +3 -3
  172. package/dist/shims/router.d.ts +6 -2
  173. package/dist/shims/router.js +99 -20
  174. package/dist/shims/script.js +9 -5
  175. package/dist/shims/slot.js +3 -1
  176. package/dist/shims/unified-request-context.d.ts +2 -2
  177. package/dist/utils/has-trailing-comma.d.ts +24 -0
  178. package/dist/utils/has-trailing-comma.js +62 -0
  179. package/dist/utils/text-stream.d.ts +1 -1
  180. package/dist/utils/text-stream.js +2 -2
  181. package/dist/utils/virtual-module.d.ts +5 -0
  182. package/dist/utils/virtual-module.js +0 -0
  183. package/dist/utils/vite-version.d.ts +12 -1
  184. package/dist/utils/vite-version.js +9 -1
  185. package/package.json +5 -1
@@ -36,33 +36,37 @@ function dataUrlCssPlugin() {
36
36
  return {
37
37
  name: "vinext:css-data-url",
38
38
  enforce: "pre",
39
- transform(code, id) {
40
- if (!code.includes(DATA_URL_HINT)) return null;
41
- if (id.startsWith(VIRTUAL_PREFIX)) return null;
42
- let mutated = false;
43
- const rewritten = code.replace(DATA_URL_IMPORT_RE, (_match, quote, moduleFlag, base64Flag, payload) => {
44
- const isModule = moduleFlag === "+module";
45
- const isBase64 = base64Flag === ";base64";
46
- let css;
47
- try {
48
- css = decode(payload, isBase64);
49
- } catch (err) {
50
- throw new Error(`[vinext] Failed to decode CSS data URL import in ${id}: ${err.message}`);
51
- }
52
- const ext = isModule ? ".module.css" : ".css";
53
- const syntheticId = `${VIRTUAL_PREFIX}${hash(css + ext)}${ext}`;
54
- entries.set(syntheticId, {
55
- css,
56
- isModule
39
+ transform: {
40
+ filter: {
41
+ id: { exclude: new RegExp(`^${VIRTUAL_PREFIX}`) },
42
+ code: DATA_URL_HINT
43
+ },
44
+ handler(code, id) {
45
+ let mutated = false;
46
+ const rewritten = code.replace(DATA_URL_IMPORT_RE, (_match, quote, moduleFlag, base64Flag, payload) => {
47
+ const isModule = moduleFlag === "+module";
48
+ const isBase64 = base64Flag === ";base64";
49
+ let css;
50
+ try {
51
+ css = decode(payload, isBase64);
52
+ } catch (err) {
53
+ throw new Error(`[vinext] Failed to decode CSS data URL import in ${id}: ${err.message}`);
54
+ }
55
+ const ext = isModule ? ".module.css" : ".css";
56
+ const syntheticId = `${VIRTUAL_PREFIX}${hash(css + ext)}${ext}`;
57
+ entries.set(syntheticId, {
58
+ css,
59
+ isModule
60
+ });
61
+ mutated = true;
62
+ return `${quote}${syntheticId}${quote}`;
57
63
  });
58
- mutated = true;
59
- return `${quote}${syntheticId}${quote}`;
60
- });
61
- if (!mutated) return null;
62
- return {
63
- code: rewritten,
64
- map: null
65
- };
64
+ if (!mutated) return null;
65
+ return {
66
+ code: rewritten,
67
+ map: null
68
+ };
69
+ }
66
70
  },
67
71
  resolveId(id) {
68
72
  if (id.startsWith(VIRTUAL_PREFIX)) return id;
@@ -1,4 +1,5 @@
1
1
  import { isUnknownRecord } from "../utils/record.js";
2
+ import { hasTrailingComma } from "../utils/has-trailing-comma.js";
2
3
  import { relativeWithinRoot, tryRealpathSync } from "../build/ssr-manifest.js";
3
4
  import path from "node:path";
4
5
  import { parseAst } from "vite";
@@ -281,15 +282,12 @@ function appendObjectProperty(output, objectNode, property) {
281
282
  output.appendLeft(propertyEnd, `, ${property}`);
282
283
  return true;
283
284
  }
284
- function stripComments(source) {
285
- return source.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/[^\n]*/g, "");
286
- }
287
285
  function insertSecondOptionsArgument(output, code, callNode, firstArg, optionsLiteral) {
288
286
  const callEnd = getNumber(callNode, "end");
289
287
  const firstArgEnd = getNumber(firstArg, "end");
290
288
  if (callEnd === null || firstArgEnd === null) return false;
291
289
  const closeParen = callEnd - 1;
292
- const separator = stripComments(code.slice(firstArgEnd, closeParen)).trimEnd().endsWith(",") ? " " : ", ";
290
+ const separator = hasTrailingComma(code.slice(firstArgEnd, closeParen)) ? " " : ", ";
293
291
  output.appendLeft(closeParen, `${separator}${optionsLiteral}`);
294
292
  return true;
295
293
  }
@@ -29,28 +29,34 @@ function createExtensionlessDynamicImportPlugin() {
29
29
  configResolved(config) {
30
30
  moduleExtensions = getModuleExtensions(config);
31
31
  },
32
- transform(code, id) {
33
- if (!/\bimport\s*\(/.test(code)) return null;
34
- if (isDependencyId(id)) return null;
35
- const lang = langForId(id);
36
- if (!lang) return null;
37
- let ast;
38
- try {
39
- ast = parseAst(code, { lang });
40
- } catch {
41
- return null;
32
+ transform: {
33
+ filter: {
34
+ id: {
35
+ include: /\.(?:[cm]?[jt]s|[jt]sx)(?:\?.*)?$/i,
36
+ exclude: /[\\/]node_modules[\\/]/
37
+ },
38
+ code: /\bimport\s*\(/
39
+ },
40
+ handler(code, id) {
41
+ const lang = langForId(id);
42
+ let ast;
43
+ try {
44
+ ast = parseAst(code, { lang });
45
+ } catch {
46
+ return null;
47
+ }
48
+ const imports = collectExtensionlessImports(ast, code, moduleExtensions);
49
+ if (imports.length === 0) return null;
50
+ const output = new MagicString(code);
51
+ for (const dynamicImport of imports) {
52
+ const source = code.slice(dynamicImport.sourceStart, dynamicImport.sourceEnd);
53
+ output.overwrite(dynamicImport.start, dynamicImport.end, buildReplacement(source, dynamicImport.globPattern, dynamicImport.moduleExtensions));
54
+ }
55
+ return {
56
+ code: output.toString(),
57
+ map: output.generateMap({ hires: "boundary" })
58
+ };
42
59
  }
43
- const imports = collectExtensionlessImports(ast, code, moduleExtensions);
44
- if (imports.length === 0) return null;
45
- const output = new MagicString(code);
46
- for (const dynamicImport of imports) {
47
- const source = code.slice(dynamicImport.sourceStart, dynamicImport.sourceEnd);
48
- output.overwrite(dynamicImport.start, dynamicImport.end, buildReplacement(source, dynamicImport.globPattern, dynamicImport.moduleExtensions));
49
- }
50
- return {
51
- code: output.toString(),
52
- map: output.generateMap({ hires: "boundary" })
53
- };
54
60
  }
55
61
  };
56
62
  }
@@ -64,9 +70,6 @@ function langForId(id) {
64
70
  if (ext === ".tsx") return "tsx";
65
71
  return "jsx";
66
72
  }
67
- function isDependencyId(id) {
68
- return id.split("?", 1)[0].replaceAll("\\", "/").includes("/node_modules/");
69
- }
70
73
  function collectExtensionlessImports(ast, code, moduleExtensions) {
71
74
  const imports = [];
72
75
  function visit(value) {
@@ -1,4 +1,5 @@
1
1
  import { escapeRegExp } from "../utils/regex.js";
2
+ import { lastSignificantChar } from "../utils/has-trailing-comma.js";
2
3
  import { buildFallbackFontFace, getFallbackFontOverrideMetrics } from "../build/google-fonts/fallback-metrics.js";
3
4
  import { validateGoogleFontOptions } from "../build/google-fonts/validate.js";
4
5
  import { getFontAxes } from "../build/google-fonts/get-axes.js";
@@ -552,8 +553,8 @@ function createGoogleFontsPlugin(fontGoogleShimPath, shimsDir) {
552
553
  if (validatedFontStyle) internalFontProperties.push(`fontStyle: ${JSON.stringify(validatedFontStyle)}`);
553
554
  const injectedProperties = [`_vinext: { font: { ${internalFontProperties.join(", ")} } }`];
554
555
  const closingBrace = optionsStr.lastIndexOf("}");
555
- const beforeBrace = optionsStr.slice(0, closingBrace).trim();
556
- const separator = beforeBrace.endsWith("{") || beforeBrace.endsWith(",") ? "" : ", ";
556
+ const lastChar = lastSignificantChar(optionsStr.slice(0, closingBrace));
557
+ const separator = lastChar === "{" || lastChar === "," ? "" : ", ";
557
558
  const replacement = `${calleeSource}(${optionsStr.slice(0, closingBrace) + separator + injectedProperties.join(", ") + optionsStr.slice(closingBrace)})`;
558
559
  s.overwrite(callStart, callEnd, replacement);
559
560
  overwrittenRanges.push([callStart, callEnd]);
@@ -688,8 +689,8 @@ function createLocalFontsPlugin(shimsDir) {
688
689
  if (familyPayloadInsertions.has(insertAt)) continue;
689
690
  const optionsStr = code.slice(objRange[0], objRange[1]);
690
691
  if (/(?:^|[,{])\s*_vinext\s*:/.test(optionsStr)) continue;
691
- const beforeClosingBrace = optionsStr.slice(0, -1).trim();
692
- const separator = beforeClosingBrace.endsWith("{") || beforeClosingBrace.endsWith(",") ? "" : ", ";
692
+ const lastChar = lastSignificantChar(optionsStr.slice(0, -1));
693
+ const separator = lastChar === "{" || lastChar === "," ? "" : ", ";
693
694
  s.appendLeft(insertAt, `${separator}_vinext: { font: { family: ${JSON.stringify(bindingName)} } }`);
694
695
  familyPayloadInsertions.add(insertAt);
695
696
  hasChanges = true;
@@ -1,3 +1,4 @@
1
+ import { VIRTUAL_MODULE_ID_RE } from "../utils/virtual-module.js";
1
2
  import { collectBindingNames, forEachAstChild, hasRange, isAstRecord, isIdentifierNamed, nodeArray } from "./ast-utils.js";
2
3
  import { tryRealpathSync } from "../build/ssr-manifest.js";
3
4
  import path from "node:path";
@@ -32,18 +33,26 @@ function createImportMetaUrlPlugin(options) {
32
33
  outputDirs = [config.build.outDir];
33
34
  rootPaths = createRootPaths(root, { outputDirs });
34
35
  },
35
- transform(code, id) {
36
- if (!mayContainSourceIdentityToken(code)) return null;
37
- const paths = getRootPaths();
38
- if (!paths) return null;
39
- const canonicalId = transformableModuleCanonicalId(cleanModuleId(id), paths);
40
- if (!canonicalId) return null;
41
- const rewritten = rewriteCanonicalSourceIdentity(code, canonicalId, paths, this.environment?.name === "client" ? "client" : "server");
42
- if (!rewritten) return null;
43
- return {
44
- code: rewritten.code,
45
- map: rewritten.map
46
- };
36
+ transform: {
37
+ filter: {
38
+ id: {
39
+ include: /\.(?:[cm]?[jt]s|[jt]sx)(?:\?.*)?$/,
40
+ exclude: [/[\\/]node_modules[\\/]/, VIRTUAL_MODULE_ID_RE]
41
+ },
42
+ code: /import\.meta(?:\.|\?\.)url|__filename|__dirname/
43
+ },
44
+ handler(code, id) {
45
+ const paths = getRootPaths();
46
+ if (!paths) return null;
47
+ const canonicalId = transformableModuleCanonicalId(cleanModuleId(id), paths);
48
+ if (!canonicalId) return null;
49
+ const rewritten = rewriteCanonicalSourceIdentity(code, canonicalId, paths, this.environment?.name === "client" ? "client" : "server");
50
+ if (!rewritten) return null;
51
+ return {
52
+ code: rewritten.code,
53
+ map: rewritten.map
54
+ };
55
+ }
47
56
  }
48
57
  };
49
58
  }
@@ -120,9 +129,6 @@ function mayContainImportMetaUrl(code) {
120
129
  function mayContainServerCjsGlobal(code) {
121
130
  return code.includes("__filename") || code.includes("__dirname");
122
131
  }
123
- function mayContainSourceIdentityToken(code) {
124
- return mayContainImportMetaUrl(code) || mayContainServerCjsGlobal(code);
125
- }
126
132
  function excludedRelativePrefixes(canonicalRoot, normalizedRoot, options) {
127
133
  const prefixes = new Set([
128
134
  ".next",
@@ -8,7 +8,7 @@ function createInstrumentationClientTransformPlugin(getInstrumentationClientPath
8
8
  transform(code, id) {
9
9
  const instrumentationClientPath = getInstrumentationClientPath();
10
10
  if (!instrumentationClientPath) return null;
11
- if (normalizePath(id.split("?", 1)[0]) !== normalizePath(instrumentationClientPath)) return null;
11
+ if (normalizePath(id.split("?", 1)[0]) !== instrumentationClientPath) return null;
12
12
  if (code.includes("__vinextInstrumentationClientStart")) return null;
13
13
  const ast = parseAst(code);
14
14
  let insertPos = 0;
@@ -1,3 +1,4 @@
1
+ import { normalizePathSeparators } from "../utils/path.js";
1
2
  //#region src/plugins/middleware-server-only.ts
2
3
  /**
3
4
  * Allow `import 'server-only'` from middleware (and any module reachable
@@ -44,16 +45,16 @@
44
45
  */
45
46
  function createMiddlewareServerOnlyPlugin(options) {
46
47
  const tainted = /* @__PURE__ */ new Set();
48
+ function canonicalizeId(id) {
49
+ const queryIndex = id.indexOf("?");
50
+ return normalizePathSeparators(queryIndex === -1 ? id : id.slice(0, queryIndex));
51
+ }
47
52
  function isTainted(id) {
48
53
  if (!id) return false;
49
- if (tainted.has(id)) return true;
50
- const queryIndex = id.indexOf("?");
51
- if (queryIndex !== -1) return tainted.has(id.slice(0, queryIndex));
52
- return false;
54
+ return tainted.has(canonicalizeId(id));
53
55
  }
54
56
  function addTainted(id) {
55
- const queryIndex = id.indexOf("?");
56
- tainted.add(queryIndex === -1 ? id : id.slice(0, queryIndex));
57
+ tainted.add(canonicalizeId(id));
57
58
  }
58
59
  return {
59
60
  name: "vinext:middleware-server-only",
@@ -25,54 +25,56 @@ function createOgInlineFetchAssetsPlugin() {
25
25
  buildStart() {
26
26
  if (isBuild) cache.clear();
27
27
  },
28
- async transform(code, id) {
29
- if (!code.includes("import.meta.url")) return null;
30
- const useCache = isBuild;
31
- const moduleDir = path.dirname(id);
32
- let newCode = code;
33
- let didReplace = false;
34
- const readAsBase64 = async (absPath) => {
35
- const cached = useCache ? cache.get(absPath) : void 0;
36
- if (cached !== void 0) return cached;
37
- try {
38
- const b64 = (await fs.promises.readFile(absPath)).toString("base64");
39
- if (useCache) cache.set(absPath, b64);
40
- return b64;
41
- } catch {
42
- return null;
28
+ transform: {
29
+ filter: { code: "import.meta.url" },
30
+ async handler(code, id) {
31
+ const useCache = isBuild;
32
+ const moduleDir = path.dirname(id);
33
+ let newCode = code;
34
+ let didReplace = false;
35
+ const readAsBase64 = async (absPath) => {
36
+ const cached = useCache ? cache.get(absPath) : void 0;
37
+ if (cached !== void 0) return cached;
38
+ try {
39
+ const b64 = (await fs.promises.readFile(absPath)).toString("base64");
40
+ if (useCache) cache.set(absPath, b64);
41
+ return b64;
42
+ } catch {
43
+ return null;
44
+ }
45
+ };
46
+ if (code.includes("fetch(")) for (const match of code.matchAll(/fetch\(\s*new URL\(\s*(["'])(\.[^"']+)\1\s*,\s*import\.meta\.url\s*\)\s*\)(?:\.then\(\s*(?:function\s*\([^)]*\)|\([^)]*\)\s*=>)\s*\{?\s*return\s+[^.]+\.arrayBuffer\(\)\s*;?\s*\}?\s*,?\s*\)|\.then\(\s*\([^)]*\)\s*=>\s*[^.]+\.arrayBuffer\(\)\s*,?\s*\))/g)) {
47
+ const fullMatch = match[0];
48
+ const relPath = match[2];
49
+ const fileBase64 = await readAsBase64(path.resolve(moduleDir, relPath));
50
+ if (fileBase64 === null) continue;
51
+ const inlined = [
52
+ `(function(){`,
53
+ `var b=${JSON.stringify(fileBase64)};`,
54
+ `var r=atob(b);`,
55
+ `var a=new Uint8Array(r.length);`,
56
+ `for(var i=0;i<r.length;i++)a[i]=r.charCodeAt(i);`,
57
+ `return Promise.resolve(a.buffer);`,
58
+ `})()`
59
+ ].join("");
60
+ newCode = newCode.replaceAll(fullMatch, inlined);
61
+ didReplace = true;
43
62
  }
44
- };
45
- if (code.includes("fetch(")) for (const match of code.matchAll(/fetch\(\s*new URL\(\s*(["'])(\.[^"']+)\1\s*,\s*import\.meta\.url\s*\)\s*\)(?:\.then\(\s*(?:function\s*\([^)]*\)|\([^)]*\)\s*=>)\s*\{?\s*return\s+[^.]+\.arrayBuffer\(\)\s*;?\s*\}?\s*,?\s*\)|\.then\(\s*\([^)]*\)\s*=>\s*[^.]+\.arrayBuffer\(\)\s*,?\s*\))/g)) {
46
- const fullMatch = match[0];
47
- const relPath = match[2];
48
- const fileBase64 = await readAsBase64(path.resolve(moduleDir, relPath));
49
- if (fileBase64 === null) continue;
50
- const inlined = [
51
- `(function(){`,
52
- `var b=${JSON.stringify(fileBase64)};`,
53
- `var r=atob(b);`,
54
- `var a=new Uint8Array(r.length);`,
55
- `for(var i=0;i<r.length;i++)a[i]=r.charCodeAt(i);`,
56
- `return Promise.resolve(a.buffer);`,
57
- `})()`
58
- ].join("");
59
- newCode = newCode.replaceAll(fullMatch, inlined);
60
- didReplace = true;
61
- }
62
- if (code.includes("readFileSync(")) for (const match of newCode.matchAll(/[a-zA-Z_$][a-zA-Z0-9_$]*\.readFileSync\(\s*(?:[a-zA-Z_$][a-zA-Z0-9_$]*\.)?fileURLToPath\(\s*new URL\(\s*(["'])(\.[^"']+)\1\s*,\s*import\.meta\.url\s*\)\s*\)\s*\)/g)) {
63
- const fullMatch = match[0];
64
- const relPath = match[2];
65
- const fileBase64 = await readAsBase64(path.resolve(moduleDir, relPath));
66
- if (fileBase64 === null) continue;
67
- const inlined = `Buffer.from(${JSON.stringify(fileBase64)},"base64")`;
68
- newCode = newCode.replaceAll(fullMatch, inlined);
69
- didReplace = true;
63
+ if (code.includes("readFileSync(")) for (const match of newCode.matchAll(/[a-zA-Z_$][a-zA-Z0-9_$]*\.readFileSync\(\s*(?:[a-zA-Z_$][a-zA-Z0-9_$]*\.)?fileURLToPath\(\s*new URL\(\s*(["'])(\.[^"']+)\1\s*,\s*import\.meta\.url\s*\)\s*\)\s*\)/g)) {
64
+ const fullMatch = match[0];
65
+ const relPath = match[2];
66
+ const fileBase64 = await readAsBase64(path.resolve(moduleDir, relPath));
67
+ if (fileBase64 === null) continue;
68
+ const inlined = `Buffer.from(${JSON.stringify(fileBase64)},"base64")`;
69
+ newCode = newCode.replaceAll(fullMatch, inlined);
70
+ didReplace = true;
71
+ }
72
+ if (!didReplace) return null;
73
+ return {
74
+ code: newCode,
75
+ map: null
76
+ };
70
77
  }
71
- if (!didReplace) return null;
72
- return {
73
- code: newCode,
74
- map: null
75
- };
76
78
  }
77
79
  };
78
80
  }
@@ -1,5 +1,6 @@
1
1
  import { normalizePathSeparators } from "../utils/path.js";
2
2
  import { escapeRegExp } from "../utils/regex.js";
3
+ import { VIRTUAL_MODULE_ID_RE } from "../utils/virtual-module.js";
3
4
  import { getAstName } from "./ast-utils.js";
4
5
  import { createRequire } from "node:module";
5
6
  import path from "node:path";
@@ -445,12 +446,17 @@ function createOptimizeImportsPlugin(getNextConfig, getRoot) {
445
446
  return await this.resolve(source, barrelEntry, { skipSelf: true }) ?? void 0;
446
447
  },
447
448
  transform: {
448
- filter: { id: { include: /\.(tsx?|jsx?|mjs)$/ } },
449
- async handler(code, id) {
449
+ filter: {
450
+ id: {
451
+ include: /\.(tsx?|jsx?|mjs)$/,
452
+ exclude: VIRTUAL_MODULE_ID_RE
453
+ },
454
+ code: /\bimport\b[\s\S]*\bfrom\b/
455
+ },
456
+ async handler(code) {
450
457
  const env = this.environment;
451
458
  if (env?.name === "client") return null;
452
459
  const preferReactServer = env?.name === "rsc";
453
- if (id.startsWith("\0")) return null;
454
460
  const packages = optimizedPackages;
455
461
  if (!hasOptimizedImportSource(code)) return null;
456
462
  let ast;
@@ -1,7 +1,13 @@
1
+ import MagicString from "magic-string";
2
+
1
3
  //#region src/plugins/remove-console.d.ts
2
4
  type RemoveConsoleConfig = boolean | {
3
5
  exclude: string[];
4
6
  };
7
+ type RemoveConsoleResult = {
8
+ code: string;
9
+ map: ReturnType<MagicString["generateMap"]>;
10
+ };
5
11
  /**
6
12
  * Walk the AST body looking for expression statements whose expression is a
7
13
  * CallExpression with a callee of `console.<identifier>`. When found, check
@@ -10,6 +16,6 @@ type RemoveConsoleConfig = boolean | {
10
16
  *
11
17
  * Returns `null` if no console calls are removed.
12
18
  */
13
- declare function removeConsoleCalls(code: string, config: RemoveConsoleConfig): string | null;
19
+ declare function removeConsoleCalls(code: string, config: RemoveConsoleConfig): RemoveConsoleResult | null;
14
20
  //#endregion
15
21
  export { removeConsoleCalls };
@@ -168,7 +168,10 @@ function removeConsoleCalls(code, config) {
168
168
  }
169
169
  for (const node of ast.body) walk(node);
170
170
  if (!changed) return null;
171
- return s.toString();
171
+ return {
172
+ code: s.toString(),
173
+ map: s.generateMap({ hires: "boundary" })
174
+ };
172
175
  }
173
176
  //#endregion
174
177
  export { removeConsoleCalls };
@@ -16,30 +16,31 @@ function createRequireContextPlugin() {
16
16
  return {
17
17
  name: "vinext:require-context",
18
18
  enforce: "pre",
19
- transform(code, id) {
20
- if (!mayContainRequireContext(code)) return null;
21
- const lang = langForId(id);
22
- if (!lang) return null;
23
- let ast;
24
- try {
25
- ast = parseAst(code, { lang });
26
- } catch {
27
- return null;
19
+ transform: {
20
+ filter: {
21
+ id: /\.(?:[cm]?[jt]s|[jt]sx)(?:\?.*)?$/i,
22
+ code: /\brequire\b[\s\S]*\.context/
23
+ },
24
+ handler(code, id) {
25
+ const lang = langForId(id);
26
+ let ast;
27
+ try {
28
+ ast = parseAst(code, { lang });
29
+ } catch {
30
+ return null;
31
+ }
32
+ const calls = collectRequireContextCalls(ast);
33
+ if (calls.length === 0) return null;
34
+ const output = new MagicString(code);
35
+ for (const call of calls) output.overwrite(call.range.start, call.range.end, buildReplacement(call));
36
+ return {
37
+ code: output.toString(),
38
+ map: output.generateMap({ hires: "boundary" })
39
+ };
28
40
  }
29
- const calls = collectRequireContextCalls(ast);
30
- if (calls.length === 0) return null;
31
- const output = new MagicString(code);
32
- for (const call of calls) output.overwrite(call.range.start, call.range.end, buildReplacement(call));
33
- return {
34
- code: output.toString(),
35
- map: output.generateMap({ hires: "boundary" })
36
- };
37
41
  }
38
42
  };
39
43
  }
40
- function mayContainRequireContext(code) {
41
- return code.includes("require") && code.includes(".context");
42
- }
43
44
  function langForId(id) {
44
45
  const clean = id.split("?", 1)[0];
45
46
  const dot = clean.lastIndexOf(".");
@@ -1,13 +1,21 @@
1
+ import MagicString from "magic-string";
2
+
1
3
  //#region src/plugins/strip-server-exports.d.ts
4
+ declare function hasServerExportCandidate(code: string): boolean;
5
+ declare function hasExportAllCandidate(code: string): boolean;
6
+ declare function validatePageExports(code: string): void;
7
+ type StripServerExportsResult = {
8
+ code: string;
9
+ map: ReturnType<MagicString["generateMap"]>;
10
+ };
2
11
  /**
3
- * Strip server-only data-fetching exports (getServerSideProps,
4
- * getStaticProps, getStaticPaths) from page modules for the client
5
- * bundle. Uses Vite's parseAst (Rollup/acorn) for correct handling
6
- * of all export patterns including function expressions, arrow
7
- * functions with TS return types, and re-exports.
12
+ * Strip server-only Pages Router data-fetching exports and their unique
13
+ * dependency graph from browser bundles.
8
14
  *
9
- * Modeled after Next.js's SWC `next-ssg-transform`.
15
+ * Ported from Next.js:
16
+ * - test/unit/babel-plugin-next-ssg-transform.test.ts
17
+ * - crates/next-custom-transforms/src/transforms/strip_page_exports.rs
10
18
  */
11
- declare function stripServerExports(code: string): string | null;
19
+ declare function stripServerExports(code: string): StripServerExportsResult | null;
12
20
  //#endregion
13
- export { stripServerExports };
21
+ export { hasExportAllCandidate, hasServerExportCandidate, stripServerExports, validatePageExports };