vinext 0.1.0 → 0.1.2

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 (205) hide show
  1. package/README.md +2 -5
  2. package/dist/build/assets-ignore.d.ts +32 -0
  3. package/dist/build/assets-ignore.js +48 -0
  4. package/dist/build/client-build-config.d.ts +33 -1
  5. package/dist/build/client-build-config.js +66 -1
  6. package/dist/check.js +4 -3
  7. package/dist/cli.js +2 -0
  8. package/dist/client/navigation-runtime.d.ts +11 -2
  9. package/dist/client/navigation-runtime.js +1 -1
  10. package/dist/client/vinext-next-data.d.ts +2 -1
  11. package/dist/client/window-next.d.ts +6 -4
  12. package/dist/config/config-matchers.d.ts +31 -5
  13. package/dist/config/config-matchers.js +50 -3
  14. package/dist/config/next-config.d.ts +29 -3
  15. package/dist/config/next-config.js +32 -2
  16. package/dist/deploy.js +47 -304
  17. package/dist/entries/app-rsc-entry.d.ts +8 -2
  18. package/dist/entries/app-rsc-entry.js +61 -5
  19. package/dist/entries/app-rsc-manifest.js +20 -2
  20. package/dist/entries/pages-client-entry.js +1 -1
  21. package/dist/entries/pages-server-entry.js +16 -7
  22. package/dist/index.d.ts +0 -2
  23. package/dist/index.js +233 -280
  24. package/dist/plugins/dynamic-preload-metadata.d.ts +13 -0
  25. package/dist/plugins/dynamic-preload-metadata.js +415 -0
  26. package/dist/plugins/og-assets.js +2 -2
  27. package/dist/plugins/optimize-imports.d.ts +8 -4
  28. package/dist/plugins/optimize-imports.js +16 -12
  29. package/dist/plugins/postcss.js +18 -14
  30. package/dist/plugins/require-context.d.ts +6 -0
  31. package/dist/plugins/require-context.js +184 -0
  32. package/dist/plugins/sass.d.ts +53 -24
  33. package/dist/plugins/sass.js +249 -1
  34. package/dist/plugins/wasm-module-import.d.ts +15 -0
  35. package/dist/plugins/wasm-module-import.js +50 -0
  36. package/dist/routing/app-route-graph.d.ts +35 -2
  37. package/dist/routing/app-route-graph.js +179 -8
  38. package/dist/routing/file-matcher.js +1 -1
  39. package/dist/routing/route-pattern.d.ts +2 -1
  40. package/dist/routing/route-pattern.js +16 -1
  41. package/dist/server/api-handler.js +4 -0
  42. package/dist/server/app-browser-entry.js +155 -215
  43. package/dist/server/app-browser-error.d.ts +4 -1
  44. package/dist/server/app-browser-error.js +7 -1
  45. package/dist/server/app-browser-history-controller.d.ts +104 -0
  46. package/dist/server/app-browser-history-controller.js +210 -0
  47. package/dist/server/app-browser-interception-context.d.ts +2 -1
  48. package/dist/server/app-browser-interception-context.js +15 -2
  49. package/dist/server/app-browser-navigation-controller.d.ts +13 -2
  50. package/dist/server/app-browser-navigation-controller.js +83 -4
  51. package/dist/server/app-browser-popstate.d.ts +12 -3
  52. package/dist/server/app-browser-popstate.js +19 -4
  53. package/dist/server/app-browser-rsc-redirect.d.ts +11 -2
  54. package/dist/server/app-browser-rsc-redirect.js +30 -8
  55. package/dist/server/app-browser-state.d.ts +3 -0
  56. package/dist/server/app-browser-state.js +10 -10
  57. package/dist/server/app-browser-visible-commit.js +10 -8
  58. package/dist/server/app-fallback-renderer.d.ts +2 -1
  59. package/dist/server/app-fallback-renderer.js +3 -1
  60. package/dist/server/app-history-state.d.ts +45 -1
  61. package/dist/server/app-history-state.js +109 -1
  62. package/dist/server/app-middleware.js +1 -0
  63. package/dist/server/app-optimistic-routing.js +22 -1
  64. package/dist/server/app-page-boundary-render.d.ts +2 -1
  65. package/dist/server/app-page-boundary-render.js +45 -21
  66. package/dist/server/app-page-cache.js +9 -7
  67. package/dist/server/app-page-dispatch.d.ts +14 -0
  68. package/dist/server/app-page-dispatch.js +21 -6
  69. package/dist/server/app-page-element-builder.d.ts +23 -2
  70. package/dist/server/app-page-element-builder.js +58 -17
  71. package/dist/server/app-page-execution.d.ts +1 -1
  72. package/dist/server/app-page-execution.js +32 -17
  73. package/dist/server/app-page-render.d.ts +7 -1
  74. package/dist/server/app-page-render.js +11 -16
  75. package/dist/server/app-page-request.d.ts +9 -6
  76. package/dist/server/app-page-request.js +14 -10
  77. package/dist/server/app-page-response.d.ts +2 -2
  78. package/dist/server/app-page-response.js +2 -2
  79. package/dist/server/app-page-route-wiring.d.ts +3 -1
  80. package/dist/server/app-page-route-wiring.js +10 -8
  81. package/dist/server/app-page-stream.d.ts +37 -7
  82. package/dist/server/app-page-stream.js +36 -6
  83. package/dist/server/app-pages-bridge.d.ts +16 -0
  84. package/dist/server/app-pages-bridge.js +23 -3
  85. package/dist/server/app-route-handler-cache.d.ts +1 -0
  86. package/dist/server/app-route-handler-cache.js +1 -0
  87. package/dist/server/app-route-handler-dispatch.d.ts +1 -0
  88. package/dist/server/app-route-handler-dispatch.js +2 -0
  89. package/dist/server/app-route-handler-execution.d.ts +1 -0
  90. package/dist/server/app-route-handler-execution.js +1 -0
  91. package/dist/server/app-route-handler-response.js +11 -10
  92. package/dist/server/app-route-handler-runtime.d.ts +1 -0
  93. package/dist/server/app-route-handler-runtime.js +15 -3
  94. package/dist/server/app-rsc-handler.d.ts +1 -0
  95. package/dist/server/app-rsc-handler.js +5 -4
  96. package/dist/server/app-rsc-response-finalizer.js +1 -1
  97. package/dist/server/app-rsc-route-matching.d.ts +20 -1
  98. package/dist/server/app-rsc-route-matching.js +29 -4
  99. package/dist/server/app-server-action-execution.d.ts +22 -1
  100. package/dist/server/app-server-action-execution.js +73 -12
  101. package/dist/server/app-ssr-entry.d.ts +6 -0
  102. package/dist/server/app-ssr-entry.js +19 -3
  103. package/dist/server/app-ssr-stream.js +9 -1
  104. package/dist/server/dev-lockfile.js +2 -1
  105. package/dist/server/dev-server.d.ts +1 -1
  106. package/dist/server/dev-server.js +97 -43
  107. package/dist/server/headers.d.ts +8 -1
  108. package/dist/server/headers.js +8 -1
  109. package/dist/server/instrumentation-runtime.d.ts +6 -0
  110. package/dist/server/instrumentation-runtime.js +8 -0
  111. package/dist/server/isr-cache.d.ts +37 -1
  112. package/dist/server/isr-cache.js +85 -1
  113. package/dist/server/isr-decision.d.ts +79 -0
  114. package/dist/server/isr-decision.js +70 -0
  115. package/dist/server/metadata-route-response.js +5 -3
  116. package/dist/server/middleware-runtime.d.ts +13 -0
  117. package/dist/server/middleware-runtime.js +11 -7
  118. package/dist/server/middleware.js +1 -0
  119. package/dist/server/navigation-planner.d.ts +62 -1
  120. package/dist/server/navigation-planner.js +193 -3
  121. package/dist/server/navigation-trace.d.ts +12 -2
  122. package/dist/server/navigation-trace.js +11 -1
  123. package/dist/server/normalize-path.d.ts +0 -8
  124. package/dist/server/normalize-path.js +3 -1
  125. package/dist/server/otel-tracer-extension.d.ts +45 -0
  126. package/dist/server/otel-tracer-extension.js +89 -0
  127. package/dist/server/pages-api-route.d.ts +14 -3
  128. package/dist/server/pages-api-route.js +6 -1
  129. package/dist/server/pages-asset-tags.d.ts +15 -4
  130. package/dist/server/pages-asset-tags.js +18 -12
  131. package/dist/server/pages-data-route.js +5 -1
  132. package/dist/server/pages-node-compat.d.ts +5 -11
  133. package/dist/server/pages-node-compat.js +175 -118
  134. package/dist/server/pages-page-data.d.ts +38 -7
  135. package/dist/server/pages-page-data.js +64 -18
  136. package/dist/server/pages-page-handler.d.ts +10 -2
  137. package/dist/server/pages-page-handler.js +49 -20
  138. package/dist/server/pages-page-response.d.ts +55 -2
  139. package/dist/server/pages-page-response.js +74 -6
  140. package/dist/server/pages-readiness.d.ts +36 -0
  141. package/dist/server/pages-readiness.js +21 -0
  142. package/dist/server/pages-request-pipeline.d.ts +113 -0
  143. package/dist/server/pages-request-pipeline.js +230 -0
  144. package/dist/server/pages-revalidate.d.ts +15 -0
  145. package/dist/server/pages-revalidate.js +19 -0
  146. package/dist/server/prod-server.d.ts +45 -3
  147. package/dist/server/prod-server.js +182 -234
  148. package/dist/server/socket-error-backstop.d.ts +19 -1
  149. package/dist/server/socket-error-backstop.js +77 -4
  150. package/dist/shims/app-router-scroll.js +22 -4
  151. package/dist/shims/cache-runtime.js +39 -2
  152. package/dist/shims/dynamic-preload-chunks.d.ts +8 -0
  153. package/dist/shims/dynamic-preload-chunks.js +77 -0
  154. package/dist/shims/dynamic.d.ts +4 -0
  155. package/dist/shims/dynamic.js +4 -2
  156. package/dist/shims/error-boundary.d.ts +17 -7
  157. package/dist/shims/error-boundary.js +8 -1
  158. package/dist/shims/error.js +37 -11
  159. package/dist/shims/fetch-cache.d.ts +22 -1
  160. package/dist/shims/fetch-cache.js +28 -1
  161. package/dist/shims/hash-scroll.d.ts +1 -0
  162. package/dist/shims/hash-scroll.js +3 -1
  163. package/dist/shims/head.js +6 -1
  164. package/dist/shims/headers.d.ts +16 -2
  165. package/dist/shims/headers.js +37 -1
  166. package/dist/shims/image-config.js +7 -1
  167. package/dist/shims/internal/app-route-detection.d.ts +6 -3
  168. package/dist/shims/internal/app-route-detection.js +10 -6
  169. package/dist/shims/internal/app-router-context.d.ts +5 -0
  170. package/dist/shims/internal/link-status-registry.d.ts +43 -0
  171. package/dist/shims/internal/link-status-registry.js +42 -0
  172. package/dist/shims/internal/route-pattern-for-warning.d.ts +27 -0
  173. package/dist/shims/internal/route-pattern-for-warning.js +40 -0
  174. package/dist/shims/internal/utils.d.ts +1 -0
  175. package/dist/shims/link.js +20 -6
  176. package/dist/shims/metadata.d.ts +6 -2
  177. package/dist/shims/metadata.js +32 -14
  178. package/dist/shims/navigation.d.ts +9 -18
  179. package/dist/shims/navigation.js +96 -23
  180. package/dist/shims/router-state.d.ts +1 -0
  181. package/dist/shims/router-state.js +2 -0
  182. package/dist/shims/router.d.ts +6 -3
  183. package/dist/shims/router.js +156 -22
  184. package/dist/shims/script-nonce-context.d.ts +1 -1
  185. package/dist/shims/script-nonce-context.js +11 -3
  186. package/dist/shims/server.d.ts +17 -1
  187. package/dist/shims/server.js +31 -6
  188. package/dist/shims/slot.js +1 -1
  189. package/dist/shims/unified-request-context.js +1 -0
  190. package/dist/typegen.js +1 -0
  191. package/dist/utils/client-build-manifest.d.ts +8 -1
  192. package/dist/utils/client-build-manifest.js +41 -6
  193. package/dist/utils/client-entry-manifest.d.ts +11 -0
  194. package/dist/utils/client-entry-manifest.js +29 -0
  195. package/dist/utils/client-runtime-metadata.d.ts +45 -0
  196. package/dist/utils/client-runtime-metadata.js +63 -0
  197. package/dist/utils/hash.d.ts +17 -1
  198. package/dist/utils/hash.js +36 -1
  199. package/dist/utils/lazy-chunks.d.ts +27 -1
  200. package/dist/utils/lazy-chunks.js +65 -1
  201. package/dist/utils/manifest-paths.d.ts +20 -2
  202. package/dist/utils/manifest-paths.js +38 -3
  203. package/dist/utils/path.d.ts +2 -1
  204. package/dist/utils/path.js +5 -1
  205. package/package.json +6 -2
@@ -2,22 +2,20 @@ import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
2
2
  import { hasBasePath, stripBasePath } from "../utils/base-path.js";
3
3
  import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_STATIC_FILE_HEADER } from "./headers.js";
4
4
  import { normalizePath } from "./normalize-path.js";
5
- import { applyMiddlewareRequestHeaders, isExternalUrl, matchRedirect, matchRewrite, proxyExternalRequest, requestContextFromRequest, sanitizeDestination } from "../config/config-matchers.js";
6
5
  import { notFoundResponse } from "./http-error-responses.js";
7
- import { applyConfigHeadersToHeaderRecord, filterInternalHeaders, isOpenRedirectShaped, normalizeTrailingSlash } from "./request-pipeline.js";
8
- import { mergeRewriteQuery } from "../utils/query.js";
9
- import { normalizeDefaultLocalePathname, stripI18nLocaleForApiRoute } from "./pages-i18n.js";
6
+ import { filterInternalHeaders, isOpenRedirectShaped } from "./request-pipeline.js";
7
+ import { isUnknownRecord } from "../utils/record.js";
10
8
  import { resolveRequestHost, resolveRequestProtocol, trustProxy, trustedHosts } from "./proxy-trust.js";
11
9
  import { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, isImageOptimizationPath, isSafeImageContentType, parseImageParams } from "./image-optimization.js";
12
10
  import { installSocketErrorBackstop } from "./socket-error-backstop.js";
13
- import { ASSET_PREFIX_URL_DIR, assetPrefixPathname, isAbsoluteAssetPrefix, resolveAssetsDir } from "../utils/asset-prefix.js";
11
+ import { ASSET_PREFIX_URL_DIR, assetPrefixPathname, isAbsoluteAssetPrefix } from "../utils/asset-prefix.js";
14
12
  import { CONTENT_TYPES, StaticFileCache, etagFromFilenameHash } from "./static-file-cache.js";
15
13
  import { buildNextDataNotFoundResponse, isNextDataPathname, parseNextDataPathname } from "./pages-data-route.js";
16
14
  import { collectInlineCssManifest } from "../build/inline-css.js";
17
- import { manifestFileWithBase } from "../utils/manifest-paths.js";
15
+ import { mergeHeaders } from "./worker-utils.js";
16
+ import { runPagesRequest, wrapMiddlewareWithBasePath } from "./pages-request-pipeline.js";
18
17
  import { readTrustedPrerenderRouteParamsFromHeaders, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
19
- import { computeLazyChunks } from "../utils/lazy-chunks.js";
20
- import { findClientEntryFile, readClientBuildManifest } from "../utils/client-build-manifest.js";
18
+ import { computeClientRuntimeMetadata } from "../utils/client-runtime-metadata.js";
21
19
  import { readPrerenderSecret } from "../build/server-manifest.js";
22
20
  import { seedMemoryCacheFromPrerender } from "./seed-cache.js";
23
21
  import fs from "node:fs";
@@ -47,6 +45,68 @@ import { Readable, pipeline } from "node:stream";
47
45
  * - dist/server/index.js — RSC entry (default export: handler(Request) → Response)
48
46
  * - dist/server/ssr/index.js — SSR entry (imported by RSC entry at runtime)
49
47
  */
48
+ /**
49
+ * mtime of the build each bare (query-less) server-entry URL was first
50
+ * imported from in this process. Node's ESM cache pins a bare URL to that
51
+ * build forever, so rebuilds to the same path must be detected and loaded
52
+ * through a cache-busted URL instead.
53
+ */
54
+ const bareServerEntryMtimes = /* @__PURE__ */ new Map();
55
+ /**
56
+ * Import a built server entry module (App Router RSC entry or Pages Router
57
+ * server entry) by absolute file path.
58
+ *
59
+ * The first import of a given path uses the plain file:// URL with NO query
60
+ * string. This is load-bearing: code-split builds emit lazy chunks that
61
+ * import the entry back by bare specifier (default Vite builds on both
62
+ * supported majors — Rollup on Vite 7 and Rolldown on Vite 8 — hoist modules
63
+ * shared between the entry's static graph and lazy route chunks into the
64
+ * entry chunk, which the chunks then import as e.g. "../../index.js").
65
+ * Node keys its ESM cache on the full URL including the query string, so if
66
+ * the server imported the entry as `index.js?t=<mtime>`, a chunk's bare
67
+ * back-import would evaluate the entire server bundle a second time and
68
+ * module-level singletons (db pools, service registries) would silently
69
+ * diverge between the two copies. See
70
+ * https://github.com/cloudflare/vinext/issues/1923.
71
+ *
72
+ * A `?t=<mtime>` query string is appended only when the same path is
73
+ * imported again after a rebuild (different mtime) — e.g. test suites that
74
+ * rebuild a fixture to the same output path within one process — where the
75
+ * bare URL's cache entry would return the stale previous build. Note this
76
+ * rebuild branch trades the single-instance guarantee back: chunks that
77
+ * import the entry by bare path still resolve to the FIRST build's cache
78
+ * entry, so freshness and single-instance only hold together on the first
79
+ * import of a path. Production processes import each entry path exactly
80
+ * once and always get both.
81
+ *
82
+ * The entry is imported via its canonical real path: the bundler
83
+ * canonicalizes module ids with fs.realpathSync.native, so chunks evaluate
84
+ * under realpath-based URLs and their relative imports resolve to realpath
85
+ * URLs too. Importing the entry through a symlinked path (macOS /var/...
86
+ * tmpdirs, symlinked deploy directories) would otherwise create a second
87
+ * instance keyed on the symlinked URL.
88
+ *
89
+ * Exported for direct unit testing of the URL choice.
90
+ */
91
+ function resolveServerEntryImportUrl(entryPath) {
92
+ let canonicalEntryPath;
93
+ try {
94
+ canonicalEntryPath = fs.realpathSync.native(entryPath);
95
+ } catch {
96
+ canonicalEntryPath = entryPath;
97
+ }
98
+ const href = pathToFileURL(canonicalEntryPath).href;
99
+ const mtime = fs.statSync(canonicalEntryPath).mtimeMs;
100
+ const bareMtime = bareServerEntryMtimes.get(href);
101
+ if (bareMtime === void 0 || bareMtime === mtime) {
102
+ bareServerEntryMtimes.set(href, mtime);
103
+ return href;
104
+ }
105
+ return `${href}?t=${mtime}`;
106
+ }
107
+ async function importServerEntryModule(entryPath) {
108
+ return import(resolveServerEntryImportUrl(entryPath));
109
+ }
50
110
  /** Convert a Node.js IncomingMessage into a ReadableStream for Web Request body. */
51
111
  function readNodeStream(req) {
52
112
  return new ReadableStream({ start(controller) {
@@ -157,12 +217,14 @@ const NO_BODY_RESPONSE_STATUSES = new Set([
157
217
  205,
158
218
  304
159
219
  ]);
160
- function hasHeader(headersRecord, name) {
161
- const target = name.toLowerCase();
162
- return Object.keys(headersRecord).some((key) => key.toLowerCase() === target);
163
- }
164
- function omitHeadersCaseInsensitive(headersRecord, names) {
165
- const targets = new Set(names.map((name) => name.toLowerCase()));
220
+ const OMIT_BODY_HEADERS = new Set(["content-length", "content-type"]);
221
+ const OMIT_STATIC_RESPONSE_HEADERS = new Set([
222
+ VINEXT_STATIC_FILE_HEADER,
223
+ "content-encoding",
224
+ "content-length",
225
+ "content-type"
226
+ ]);
227
+ function omitHeadersCaseInsensitive(headersRecord, targets) {
166
228
  const filtered = {};
167
229
  for (const [key, value] of Object.entries(headersRecord)) {
168
230
  if (targets.has(key.toLowerCase())) continue;
@@ -175,9 +237,14 @@ function matchesIfNoneMatchHeader(ifNoneMatch, etag) {
175
237
  if (ifNoneMatch === "*") return true;
176
238
  return ifNoneMatch.split(",").map((value) => value.trim()).some((value) => value === etag);
177
239
  }
178
- function stripHeaders(headersRecord, names) {
179
- const targets = new Set(names.map((name) => name.toLowerCase()));
180
- for (const key of Object.keys(headersRecord)) if (targets.has(key.toLowerCase())) delete headersRecord[key];
240
+ function installClientBuildManifestGlobals(clientDir, assetBase, assetPrefix) {
241
+ const metadata = computeClientRuntimeMetadata({
242
+ clientDir,
243
+ assetBase,
244
+ assetPrefix
245
+ });
246
+ globalThis.__VINEXT_LAZY_CHUNKS__ = metadata.lazyChunks;
247
+ globalThis.__VINEXT_DYNAMIC_PRELOADS__ = metadata.dynamicPreloads;
181
248
  }
182
249
  function isNoBodyResponseStatus(status) {
183
250
  return NO_BODY_RESPONSE_STATUSES.has(status);
@@ -201,36 +268,15 @@ function logProdServerStarted(host, port, purpose) {
201
268
  /**
202
269
  * Merge middleware/config headers and an optional status override into a new
203
270
  * Web Response while preserving the original body stream when allowed.
204
- * Keep this in sync with server/worker-utils.ts and the generated copy in
205
- * deploy.ts.
271
+ *
272
+ * This is the canonical {@link mergeHeaders} (server/worker-utils.ts) with the
273
+ * arguments in (headers, response) order. The request path now calls
274
+ * `runPagesRequest`, which uses `mergeHeaders` directly; this wrapper is retained
275
+ * only for its existing tests and any external callers, so there is a single
276
+ * implementation to keep in sync. (deploy.ts still emits its own generated copy.)
206
277
  */
207
278
  function mergeWebResponse(middlewareHeaders, response, statusOverride) {
208
- const filteredMiddlewareHeaders = omitHeadersCaseInsensitive(middlewareHeaders, ["content-length"]);
209
- const status = statusOverride ?? response.status;
210
- const mergedHeaders = mergeResponseHeaders(filteredMiddlewareHeaders, response);
211
- const shouldDropBody = isNoBodyResponseStatus(status);
212
- const shouldStripStreamLength = isVinextStreamedHtmlResponse(response) && hasHeader(mergedHeaders, "content-length");
213
- if (!Object.keys(filteredMiddlewareHeaders).length && statusOverride === void 0 && !shouldDropBody && !shouldStripStreamLength) return response;
214
- if (shouldDropBody) {
215
- cancelResponseBody(response);
216
- stripHeaders(mergedHeaders, [
217
- "content-encoding",
218
- "content-length",
219
- "content-type",
220
- "transfer-encoding"
221
- ]);
222
- return new Response(null, {
223
- status,
224
- statusText: status === response.status ? response.statusText : void 0,
225
- headers: toWebHeaders(mergedHeaders)
226
- });
227
- }
228
- if (shouldStripStreamLength) stripHeaders(mergedHeaders, ["content-length"]);
229
- return new Response(response.body, {
230
- status,
231
- statusText: status === response.status ? response.statusText : void 0,
232
- headers: toWebHeaders(mergedHeaders)
233
- });
279
+ return mergeHeaders(response, middlewareHeaders, statusOverride);
234
280
  }
235
281
  /**
236
282
  * Send a compressed response if the content type is compressible and the
@@ -240,7 +286,7 @@ function sendCompressed(req, res, body, contentType, statusCode, extraHeaders =
240
286
  const buf = typeof body === "string" ? Buffer.from(body) : body;
241
287
  const baseType = contentType.split(";")[0].trim();
242
288
  const encoding = compress ? negotiateEncoding(req) : null;
243
- const headersWithoutBodyHeaders = omitHeadersCaseInsensitive(extraHeaders, ["content-length", "content-type"]);
289
+ const headersWithoutBodyHeaders = omitHeadersCaseInsensitive(extraHeaders, OMIT_BODY_HEADERS);
244
290
  const writeHead = (headers) => {
245
291
  if (statusText) res.writeHead(statusCode, statusText, headers);
246
292
  else res.writeHead(statusCode, headers);
@@ -624,6 +670,40 @@ function resolveAppRouterAssetPath(pathname, assetPathPrefix, assetPrefix) {
624
670
  if (pathname.startsWith(nextStaticDir)) return pathname;
625
671
  return null;
626
672
  }
673
+ function isSsrManifest(value) {
674
+ if (!isUnknownRecord(value)) return false;
675
+ return Object.values(value).every((files) => Array.isArray(files) && files.every((file) => typeof file === "string"));
676
+ }
677
+ function readSsrManifest(clientDir) {
678
+ const manifestPath = path.join(clientDir, ".vite", "ssr-manifest.json");
679
+ if (!fs.existsSync(manifestPath)) return {};
680
+ let parsed;
681
+ try {
682
+ parsed = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
683
+ } catch (error) {
684
+ console.warn(`[vinext] Ignoring unparseable SSR manifest at ${manifestPath}:`, error);
685
+ return {};
686
+ }
687
+ if (!isSsrManifest(parsed)) {
688
+ console.warn(`[vinext] Ignoring SSR manifest with unexpected shape at ${manifestPath}`);
689
+ return {};
690
+ }
691
+ return parsed;
692
+ }
693
+ function installPagesClientAssetGlobals(options) {
694
+ const ssrManifest = readSsrManifest(options.clientDir);
695
+ globalThis.__VINEXT_SSR_MANIFEST__ = Object.keys(ssrManifest).length > 0 ? ssrManifest : void 0;
696
+ const metadata = computeClientRuntimeMetadata({
697
+ clientDir: options.clientDir,
698
+ assetBase: options.assetBase,
699
+ assetPrefix: options.assetPrefix,
700
+ includeClientEntry: options.clientEntryLookup === "pages-client-entry" ? "pages-client-entry" : true
701
+ });
702
+ globalThis.__VINEXT_CLIENT_ENTRY__ = metadata.clientEntryFile;
703
+ globalThis.__VINEXT_LAZY_CHUNKS__ = metadata.lazyChunks;
704
+ globalThis.__VINEXT_DYNAMIC_PRELOADS__ = metadata.dynamicPreloads;
705
+ return ssrManifest;
706
+ }
627
707
  /**
628
708
  * Start the App Router production server.
629
709
  *
@@ -649,13 +729,22 @@ async function startAppRouterServer(options) {
649
729
  imageConfig = JSON.parse(fs.readFileSync(imageConfigPath, "utf-8"));
650
730
  } catch {}
651
731
  const prerenderSecret = readPrerenderSecret(path.dirname(rscEntryPath));
652
- const rscMtime = fs.statSync(rscEntryPath).mtimeMs;
653
- const rscModule = await import(`${pathToFileURL(rscEntryPath).href}?t=${rscMtime}`);
732
+ const rscModule = await importServerEntryModule(rscEntryPath);
654
733
  const rscHandler = resolveAppRouterHandler(rscModule.default);
655
734
  const appRouterAssetPrefix = typeof rscModule.__assetPrefix === "string" ? rscModule.__assetPrefix : "";
735
+ const appRouterBasePath = typeof rscModule.__basePath === "string" ? rscModule.__basePath : "";
656
736
  const appRouterInlineCss = rscModule.__inlineCss === true;
737
+ const appRouterHasPagesDir = rscModule.__hasPagesDir === true;
657
738
  globalThis.__VINEXT_INLINE_CSS__ = appRouterInlineCss ? collectInlineCssManifest(clientDir, appRouterAssetPrefix) : void 0;
658
739
  const appAssetPathPrefix = assetPrefixPathname(appRouterAssetPrefix);
740
+ const appAssetBase = appRouterBasePath ? `${appRouterBasePath}/` : "/";
741
+ if (appRouterHasPagesDir) installPagesClientAssetGlobals({
742
+ clientDir,
743
+ assetPrefix: appRouterAssetPrefix,
744
+ assetBase: appAssetBase,
745
+ clientEntryLookup: "pages-client-entry"
746
+ });
747
+ else installClientBuildManifestGlobals(clientDir, appAssetBase, appRouterAssetPrefix);
659
748
  const seededRoutes = await resolveAppRouterPrerenderSeeder(rscModule)(path.dirname(rscEntryPath));
660
749
  if (seededRoutes > 0) console.log(`[vinext] Seeded ${seededRoutes} pre-rendered route${seededRoutes !== 1 ? "s" : ""} into memory cache`);
661
750
  const staticCache = await StaticFileCache.create(clientDir);
@@ -726,12 +815,7 @@ async function startAppRouterServer(options) {
726
815
  } catch {
727
816
  staticFilePath = staticFileSignal;
728
817
  }
729
- const staticResponseHeaders = omitHeadersCaseInsensitive(mergeResponseHeaders({}, response), [
730
- VINEXT_STATIC_FILE_HEADER,
731
- "content-encoding",
732
- "content-length",
733
- "content-type"
734
- ]);
818
+ const staticResponseHeaders = omitHeadersCaseInsensitive(mergeResponseHeaders({}, response), OMIT_STATIC_RESPONSE_HEADERS);
735
819
  const served = await tryServeStatic(req, res, clientDir, staticFilePath, compress, staticCache, staticResponseHeaders, response.status);
736
820
  cancelResponseBody(response);
737
821
  if (served) return;
@@ -785,8 +869,7 @@ function readPagesServerEntryPageRoutes(value) {
785
869
  */
786
870
  async function startPagesRouterServer(options) {
787
871
  const { port, host, clientDir, serverEntryPath, compress, purpose } = options;
788
- const serverMtime = fs.statSync(serverEntryPath).mtimeMs;
789
- const serverEntry = await import(`${pathToFileURL(serverEntryPath).href}?t=${serverMtime}`);
872
+ const serverEntry = await importServerEntryModule(serverEntryPath);
790
873
  const { renderPage, handleApiRoute: handleApi, runMiddleware, vinextConfig, buildId: pagesBuildId } = serverEntry;
791
874
  const matchPageRoute = typeof serverEntry.matchPageRoute === "function" ? serverEntry.matchPageRoute : void 0;
792
875
  const pageRoutes = readPagesServerEntryPageRoutes(serverEntry.pageRoutes);
@@ -811,20 +894,12 @@ async function startPagesRouterServer(options) {
811
894
  contentDispositionType: vinextConfig.images.contentDispositionType,
812
895
  contentSecurityPolicy: vinextConfig.images.contentSecurityPolicy
813
896
  } : void 0;
814
- let ssrManifest = {};
815
- const manifestPath = path.join(clientDir, ".vite", "ssr-manifest.json");
816
- if (fs.existsSync(manifestPath)) ssrManifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
817
- const buildManifest = readClientBuildManifest(path.join(clientDir, ".vite", "manifest.json"));
818
- globalThis.__VINEXT_CLIENT_ENTRY__ = findClientEntryFile({
819
- buildManifest,
897
+ const ssrManifest = installPagesClientAssetGlobals({
820
898
  clientDir,
821
- assetsSubdir: resolveAssetsDir(assetPrefix),
822
- assetBase
899
+ assetPrefix,
900
+ assetBase,
901
+ clientEntryLookup: "any-client-entry"
823
902
  });
824
- if (buildManifest) {
825
- const lazyChunks = computeLazyChunks(buildManifest).map((file) => manifestFileWithBase(file, assetBase));
826
- globalThis.__VINEXT_LAZY_CHUNKS__ = lazyChunks.length > 0 ? lazyChunks : void 0;
827
- } else globalThis.__VINEXT_LAZY_CHUNKS__ = void 0;
828
903
  const staticCache = await StaticFileCache.create(clientDir);
829
904
  const handleRequest = async (req, res) => {
830
905
  const rawUrl = req.url ?? "/";
@@ -915,20 +990,6 @@ async function startPagesRouterServer(options) {
915
990
  pathname = stripped;
916
991
  }
917
992
  }
918
- const basePathState = {
919
- basePath,
920
- hadBasePath
921
- };
922
- {
923
- const qs = url.includes("?") ? url.slice(url.indexOf("?")) : "";
924
- const trailingSlashRedirect = normalizeTrailingSlash(pathname, basePath, trailingSlash, qs);
925
- if (trailingSlashRedirect) {
926
- const location = trailingSlashRedirect.headers.get("Location");
927
- res.writeHead(trailingSlashRedirect.status, location ? { Location: location } : void 0);
928
- res.end();
929
- return;
930
- }
931
- }
932
993
  let isDataReq = false;
933
994
  if (isNextDataPathname(pathname)) {
934
995
  const dataMatch = pagesBuildId ? parseNextDataPathname(pathname, pagesBuildId) : null;
@@ -948,167 +1009,54 @@ async function startPagesRouterServer(options) {
948
1009
  const reqHeaders = filterInternalHeaders(rawReqHeaders);
949
1010
  const method = req.method ?? "GET";
950
1011
  const hasBody = method !== "GET" && method !== "HEAD";
951
- let webRequest = new Request(`${protocol}://${hostHeader}${url}`, {
1012
+ const result = await runPagesRequest(new Request(`${protocol}://${hostHeader}${url}`, {
952
1013
  method,
953
1014
  headers: reqHeaders,
954
1015
  body: hasBody ? readNodeStream(req) : void 0,
955
1016
  duplex: hasBody ? "half" : void 0
956
- });
957
- const reqCtx = requestContextFromRequest(webRequest);
958
- const requestHostname = i18nConfig ? new URL(webRequest.url).hostname : "";
959
- const matchPathname = i18nConfig ? normalizeDefaultLocalePathname(pathname, i18nConfig, { hostname: requestHostname }) : pathname;
960
- if (configRedirects.length) {
961
- const redirect = matchRedirect(matchPathname, configRedirects, reqCtx, basePathState);
962
- if (redirect) {
963
- const dest = sanitizeDestination(basePath && hadBasePath && !isExternalUrl(redirect.destination) && !hasBasePath(redirect.destination, basePath) ? basePath + redirect.destination : redirect.destination);
964
- res.writeHead(redirect.permanent ? 308 : 307, { Location: dest });
965
- res.end();
966
- return;
967
- }
968
- }
969
- let resolvedUrl = url;
970
- const middlewareHeaders = {};
971
- let middlewareStatus;
972
- if (typeof runMiddleware === "function") {
973
- const result = await runMiddleware(webRequest, void 0, { isDataRequest });
974
- if (result.waitUntilPromises && result.waitUntilPromises.length > 0) Promise.allSettled(result.waitUntilPromises);
975
- if (!result.continue) {
976
- if (result.redirectUrl) {
977
- const redirectHeaders = { Location: result.redirectUrl };
978
- if (result.responseHeaders) for (const [key, value] of result.responseHeaders) {
979
- const existing = redirectHeaders[key];
980
- if (existing === void 0) redirectHeaders[key] = value;
981
- else if (Array.isArray(existing)) existing.push(value);
982
- else redirectHeaders[key] = [existing, value];
983
- }
984
- res.writeHead(result.redirectStatus ?? 307, redirectHeaders);
985
- res.end();
986
- return;
987
- }
988
- if (result.response) {
989
- const body = Buffer.from(await result.response.arrayBuffer());
990
- const respHeaders = {};
991
- result.response.headers.forEach((value, key) => {
992
- if (key === "set-cookie") return;
993
- respHeaders[key] = value;
994
- });
995
- const setCookies = result.response.headers.getSetCookie?.() ?? [];
996
- if (setCookies.length > 0) respHeaders["set-cookie"] = setCookies;
997
- if (result.response.statusText) res.writeHead(result.response.status, result.response.statusText, respHeaders);
998
- else res.writeHead(result.response.status, respHeaders);
999
- res.end(body);
1000
- return;
1001
- }
1002
- }
1003
- if (result.responseHeaders) for (const [key, value] of result.responseHeaders) if (key === "set-cookie") {
1004
- const existing = middlewareHeaders[key];
1005
- if (Array.isArray(existing)) existing.push(value);
1006
- else if (existing) middlewareHeaders[key] = [existing, value];
1007
- else middlewareHeaders[key] = [value];
1008
- } else middlewareHeaders[key] = value;
1009
- if (result.rewriteUrl) resolvedUrl = result.rewriteUrl;
1010
- middlewareStatus = result.status ?? result.rewriteStatus;
1011
- }
1012
- const { postMwReqCtx, request: postMwReq } = applyMiddlewareRequestHeaders(middlewareHeaders, webRequest, { preserveCredentialHeaders: isExternalUrl(resolvedUrl) });
1013
- webRequest = postMwReq;
1014
- let resolvedPathname = resolvedUrl.split("?")[0];
1015
- const matchResolvedPathname = (p) => i18nConfig ? normalizeDefaultLocalePathname(p, i18nConfig, { hostname: requestHostname }) : p;
1016
- if (configHeaders.length) applyConfigHeadersToHeaderRecord(middlewareHeaders, {
1017
+ }), {
1018
+ basePath,
1019
+ trailingSlash,
1020
+ i18nConfig,
1021
+ configRedirects,
1022
+ configRewrites,
1017
1023
  configHeaders,
1018
- pathname: matchPathname,
1019
- requestContext: reqCtx,
1020
- basePathState
1021
- });
1022
- if (isExternalUrl(resolvedUrl)) {
1023
- await sendWebResponse(mergeWebResponse(middlewareHeaders, await proxyExternalRequest(webRequest, resolvedUrl), void 0), req, res, compress);
1024
- return;
1025
- }
1026
- if (staticLookupPath !== "/" && !staticLookupPath.startsWith("/api/") && !staticLookupPath.startsWith(`/_next/static/`) && await tryServeStatic(req, res, clientDir, staticLookupPath, compress, staticCache, middlewareHeaders)) return;
1027
- let configRewriteFired = false;
1028
- if (configRewrites.beforeFiles?.length) {
1029
- const rewritten = matchRewrite(matchResolvedPathname(resolvedPathname), configRewrites.beforeFiles, postMwReqCtx, basePathState);
1030
- if (rewritten) {
1031
- if (isExternalUrl(rewritten)) {
1032
- await sendWebResponse(await proxyExternalRequest(webRequest, rewritten), req, res, compress);
1033
- return;
1034
- }
1035
- resolvedUrl = mergeRewriteQuery(resolvedUrl, rewritten);
1036
- resolvedPathname = resolvedUrl.split("?")[0];
1037
- configRewriteFired = true;
1024
+ hadBasePath,
1025
+ isDataReq,
1026
+ isDataRequest,
1027
+ ctx: void 0,
1028
+ rawSearch: rawQs,
1029
+ matchPageRoute: matchPageRoute ?? null,
1030
+ runMiddleware: typeof runMiddleware === "function" ? wrapMiddlewareWithBasePath(runMiddleware, basePath, hadBasePath) : null,
1031
+ renderPage: typeof renderPage === "function" ? (request, resolvedUrl, options, stagedHeaders) => renderPage(request, resolvedUrl, ssrManifest, void 0, stagedHeaders, options) : null,
1032
+ handleApi: typeof handleApi === "function" ? (request, apiUrl) => handleApi(request, apiUrl, createNodeExecutionContext()) : null,
1033
+ serveStaticFile: async (requestPathname, stagedHeaders) => {
1034
+ if (requestPathname === "/" || requestPathname.startsWith("/api/") || requestPathname.startsWith(`/_next/static/`)) return false;
1035
+ return tryServeStatic(req, res, clientDir, requestPathname, compress, staticCache, stagedHeaders);
1038
1036
  }
1039
- }
1040
- if (basePath && !hadBasePath && !configRewriteFired) {
1041
- res.writeHead(404, { "Content-Type": "text/html; charset=utf-8" });
1042
- res.end("This page could not be found");
1043
- return;
1044
- }
1045
- const apiLookupUrl = stripI18nLocaleForApiRoute(resolvedUrl, vinextConfig?.i18n ?? null);
1046
- const apiLookupPathname = apiLookupUrl.split("?")[0];
1047
- if (apiLookupPathname.startsWith("/api/") || apiLookupPathname === "/api") {
1048
- let response;
1049
- if (typeof handleApi === "function") response = await handleApi(webRequest, apiLookupUrl, createNodeExecutionContext());
1050
- else response = new Response("404 - API route not found", { status: 404 });
1051
- const mergedResponse = mergeWebResponse(middlewareHeaders, response, middlewareStatus);
1052
- if (!mergedResponse.body) {
1053
- await sendWebResponse(mergedResponse, req, res, compress);
1037
+ });
1038
+ if (result.type === "handled") return;
1039
+ if (result.type === "response") {
1040
+ const { response } = result;
1041
+ if (isVinextStreamedHtmlResponse(response) || !response.body || result.defaultContentType === void 0) {
1042
+ await sendWebResponse(response, req, res, compress);
1054
1043
  return;
1055
1044
  }
1056
- const responseBody = Buffer.from(await mergedResponse.arrayBuffer());
1057
- const ct = mergedResponse.headers.get("content-type") ?? "application/octet-stream";
1058
- const responseHeaders = mergeResponseHeaders({}, mergedResponse);
1059
- const finalStatusText = mergedResponse.statusText || void 0;
1060
- sendCompressed(req, res, responseBody, ct, mergedResponse.status, responseHeaders, compress, finalStatusText);
1061
- return;
1062
- }
1063
- const pageMatch = matchPageRoute ? matchPageRoute(resolvedPathname, webRequest) : null;
1064
- if ((!pageMatch || pageMatch.route.isDynamic) && configRewrites.afterFiles?.length) {
1065
- const rewritten = matchRewrite(matchResolvedPathname(resolvedPathname), configRewrites.afterFiles, postMwReqCtx, basePathState);
1066
- if (rewritten) {
1067
- if (isExternalUrl(rewritten)) {
1068
- await sendWebResponse(await proxyExternalRequest(webRequest, rewritten), req, res, compress);
1069
- return;
1070
- }
1071
- resolvedUrl = mergeRewriteQuery(resolvedUrl, rewritten);
1072
- resolvedPathname = resolvedUrl.split("?")[0];
1073
- }
1074
- }
1075
- let response;
1076
- if (typeof renderPage === "function") {
1077
- const middlewareResponseHeaders = toWebHeaders(middlewareHeaders);
1078
- const renderPageMatch = matchPageRoute ? matchPageRoute(resolvedPathname, webRequest) : null;
1079
- const shouldDeferErrorPageOnMiss = !isDataReq && !!matchPageRoute && !renderPageMatch;
1080
- const dataRenderOptions = isDataReq ? { isDataReq: true } : void 0;
1081
- response = await renderPage(webRequest, resolvedUrl, ssrManifest, void 0, middlewareResponseHeaders, shouldDeferErrorPageOnMiss ? { renderErrorPageOnMiss: false } : dataRenderOptions);
1082
- let matchedFallbackRewrite = false;
1083
- if (response && response.status === 404 && shouldDeferErrorPageOnMiss && configRewrites.fallback?.length) {
1084
- const fallbackRewrite = matchRewrite(matchResolvedPathname(resolvedPathname), configRewrites.fallback, postMwReqCtx, basePathState);
1085
- if (fallbackRewrite) {
1086
- if (isExternalUrl(fallbackRewrite)) {
1087
- await sendWebResponse(await proxyExternalRequest(webRequest, fallbackRewrite), req, res, compress);
1088
- return;
1089
- }
1090
- matchedFallbackRewrite = true;
1091
- response = await renderPage(webRequest, mergeRewriteQuery(resolvedUrl, fallbackRewrite), ssrManifest, void 0, middlewareResponseHeaders, dataRenderOptions);
1092
- }
1093
- }
1094
- if (response && response.status === 404 && shouldDeferErrorPageOnMiss && !matchedFallbackRewrite) response = await renderPage(webRequest, resolvedUrl, ssrManifest, void 0, middlewareResponseHeaders);
1095
- }
1096
- if (!response) {
1097
- res.writeHead(404);
1098
- res.end("This page could not be found");
1099
- return;
1100
- }
1101
- const shouldStreamPagesResponse = isVinextStreamedHtmlResponse(response);
1102
- const mergedResponse = mergeWebResponse(middlewareHeaders, response, middlewareStatus);
1103
- if (shouldStreamPagesResponse || !mergedResponse.body) {
1104
- await sendWebResponse(mergedResponse, req, res, compress);
1045
+ const responseBody = Buffer.from(await response.arrayBuffer());
1046
+ const ct = response.headers.get("content-type") ?? result.defaultContentType;
1047
+ const responseHeaders = {};
1048
+ response.headers.forEach((v, k) => {
1049
+ if (k === "set-cookie") return;
1050
+ responseHeaders[k] = v;
1051
+ });
1052
+ const setCookies = response.headers.getSetCookie?.() ?? [];
1053
+ if (setCookies.length > 0) responseHeaders["set-cookie"] = setCookies;
1054
+ const finalStatusText = response.statusText || void 0;
1055
+ sendCompressed(req, res, responseBody, ct, response.status, responseHeaders, compress, finalStatusText);
1105
1056
  return;
1106
1057
  }
1107
- const responseBody = Buffer.from(await mergedResponse.arrayBuffer());
1108
- const ct = mergedResponse.headers.get("content-type") ?? "text/html";
1109
- const responseHeaders = mergeResponseHeaders({}, mergedResponse);
1110
- const finalStatusText = mergedResponse.statusText || void 0;
1111
- sendCompressed(req, res, responseBody, ct, mergedResponse.status, responseHeaders, compress, finalStatusText);
1058
+ res.writeHead(404);
1059
+ res.end("This page could not be found");
1112
1060
  } catch (e) {
1113
1061
  console.error("[vinext] Server error:", e);
1114
1062
  if (!res.headersSent) {
@@ -1134,4 +1082,4 @@ async function startPagesRouterServer(options) {
1134
1082
  };
1135
1083
  }
1136
1084
  //#endregion
1137
- export { COMPRESSIBLE_TYPES, COMPRESS_THRESHOLD, mergeResponseHeaders, mergeWebResponse, negotiateEncoding, nodeToWebRequest, resolveAppRouterAssetPath, resolveAppRouterPrerenderSeeder, resolveRequestHost as resolveHost, sendCompressed, sendWebResponse, startProdServer, trustProxy, trustedHosts, tryServeStatic };
1085
+ export { COMPRESSIBLE_TYPES, COMPRESS_THRESHOLD, importServerEntryModule, mergeResponseHeaders, mergeWebResponse, negotiateEncoding, nodeToWebRequest, resolveAppRouterAssetPath, resolveAppRouterPrerenderSeeder, resolveRequestHost as resolveHost, resolveServerEntryImportUrl, sendCompressed, sendWebResponse, startProdServer, trustProxy, trustedHosts, tryServeStatic };
@@ -5,6 +5,24 @@
5
5
  * Exported for unit testing in isolation (no process-state mutation).
6
6
  */
7
7
  declare function peerDisconnectCode(err: unknown): string | undefined;
8
+ /**
9
+ * Pure predicate: returns `true` when `err` is a benign failure from a
10
+ * dynamic `import()` of a static asset URL — the "URL dependency" pattern
11
+ * that Next.js tolerates at build time. Two shapes are recognised:
12
+ *
13
+ * - `ERR_UNKNOWN_FILE_EXTENSION`: the asset resolved on disk but is not an
14
+ * ES module (e.g. a co-located `./style.css`). The error message ends in
15
+ * the offending extension in quotes: `... extension ".css" for /path`.
16
+ * - `ERR_MODULE_NOT_FOUND`: the asset URL did not resolve (the chunk lives
17
+ * in `dist/server/` but the source asset does not). Node attaches the
18
+ * unresolved specifier on `err.url`; we match only when it points at a
19
+ * static-asset extension.
20
+ *
21
+ * Anything outside this allow-list (including missing `.js`/`.mjs`/`.ts`
22
+ * modules with no extension) returns `false` so real bugs still crash.
23
+ * Exported for unit testing in isolation.
24
+ */
25
+ declare function isBenignAssetImportError(err: unknown): boolean;
8
26
  /**
9
27
  * Test-only: returns whether the backstop has been installed in this
10
28
  * process. Used by the unit test to assert idempotent install via the
@@ -13,4 +31,4 @@ declare function peerDisconnectCode(err: unknown): string | undefined;
13
31
  declare function isSocketErrorBackstopInstalled(): boolean;
14
32
  declare function installSocketErrorBackstop(): void;
15
33
  //#endregion
16
- export { installSocketErrorBackstop, isSocketErrorBackstopInstalled, peerDisconnectCode };
34
+ export { installSocketErrorBackstop, isBenignAssetImportError, isSocketErrorBackstopInstalled, peerDisconnectCode };