@wular/pnext 0.0.4 → 0.0.7

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 (395) hide show
  1. package/README.md +22 -16
  2. package/bin/pnext +6 -1
  3. package/config/lint/base.js +7 -7
  4. package/config/ts/base.json +2 -4
  5. package/config/ts/react.json +2 -6
  6. package/package.json +23 -2
  7. package/reference/compat.md +87 -22
  8. package/reference/config.md +40 -93
  9. package/reference/css.md +42 -33
  10. package/reference/dev.md +26 -33
  11. package/reference/env.md +18 -20
  12. package/reference/getting-started.md +132 -0
  13. package/reference/metadata.md +31 -46
  14. package/reference/navigation.md +65 -105
  15. package/reference/performance.md +21 -142
  16. package/reference/rendering.md +78 -75
  17. package/reference/routing.md +97 -107
  18. package/reference/typegen.md +27 -29
  19. package/src/api/cache.ts +36 -37
  20. package/src/api/client-cache.ts +2 -2
  21. package/src/api/client-navigation.ts +121 -114
  22. package/src/api/dynamic.tsx +58 -55
  23. package/src/api/link.tsx +52 -53
  24. package/src/api/navigation.ts +59 -58
  25. package/src/api/server.ts +152 -144
  26. package/src/api/suspense.ts +4 -4
  27. package/src/cli/adapters/vercel-warm.ts +126 -121
  28. package/src/cli/adapters/vercel.ts +437 -443
  29. package/src/cli/analyze.ts +333 -144
  30. package/src/cli/{named-bin.ts → boot/named-bin.ts} +37 -37
  31. package/src/cli/{boot-trace.ts → boot/trace.ts} +10 -10
  32. package/src/cli/build.ts +976 -978
  33. package/src/cli/create.ts +72 -64
  34. package/src/cli/dev.ts +116 -116
  35. package/src/cli/index.ts +94 -85
  36. package/src/cli/migrate/package-json.ts +73 -71
  37. package/src/cli/migrate/report.ts +32 -33
  38. package/src/cli/migrate/{index.ts → run.ts} +48 -49
  39. package/src/cli/migrate/scan.ts +46 -46
  40. package/src/cli/migrate/spinner.ts +9 -9
  41. package/src/cli/migrate/tsconfig.ts +35 -35
  42. package/src/cli/{server-entry.ts → serve/entry.ts} +57 -57
  43. package/src/cli/{request-pipeline.ts → serve/pipeline.ts} +386 -394
  44. package/src/cli/{serve-ui.ts → serve/ui.ts} +47 -47
  45. package/src/cli/start.ts +65 -66
  46. package/src/{typegen.ts → cli/typegen.ts} +59 -59
  47. package/src/client/build.ts +802 -768
  48. package/src/client/chunk-fold.ts +245 -240
  49. package/src/client/{paths.ts → chunk-name.ts} +6 -6
  50. package/src/client/entry.ts +162 -147
  51. package/src/client/prebuilt.ts +231 -223
  52. package/src/client/profile.ts +29 -29
  53. package/src/client/react-compiler.ts +20 -15
  54. package/src/client/{compat-surface.ts → react-tier.ts} +64 -64
  55. package/src/client/reference-stub.ts +51 -51
  56. package/src/client/reference.ts +19 -19
  57. package/src/{api → client}/router/events.ts +32 -17
  58. package/src/{api → client}/router/history.ts +16 -16
  59. package/src/{api → client}/router/hub.ts +52 -53
  60. package/src/{api/router.ts → client/router/index.ts} +61 -60
  61. package/src/{api → client}/router/policies.ts +24 -24
  62. package/src/{api → client}/router/runtime.ts +2022 -1995
  63. package/src/{api → client}/router/types.ts +98 -98
  64. package/src/compat/actions/client-plugin.ts +42 -43
  65. package/src/compat/actions/client-stub.ts +14 -14
  66. package/src/compat/actions/{action-client.ts → client.ts} +194 -193
  67. package/src/compat/actions/config.ts +63 -64
  68. package/src/compat/actions/detect.ts +68 -68
  69. package/src/compat/actions/discovery.ts +105 -105
  70. package/src/compat/actions/{action-dispatch.ts → dispatch.ts} +277 -274
  71. package/src/compat/actions/early-submit.ts +1 -1
  72. package/src/compat/actions/endpoint.ts +198 -198
  73. package/src/compat/actions/extensions.ts +811 -0
  74. package/src/compat/actions/flight.ts +23 -23
  75. package/src/compat/actions/form-state.ts +34 -34
  76. package/src/compat/actions/hoist.ts +382 -236
  77. package/src/compat/actions/ids.ts +7 -12
  78. package/src/compat/actions/index.ts +8 -8
  79. package/src/compat/actions/instances.ts +46 -46
  80. package/src/compat/actions/origin.ts +47 -48
  81. package/src/compat/actions/protocol.ts +22 -22
  82. package/src/compat/actions/registry.ts +19 -19
  83. package/src/compat/{misc/action-return.ts → actions/return.ts} +60 -57
  84. package/src/compat/actions/rewrite.ts +125 -125
  85. package/src/compat/actions/{action-router.ts → router.ts} +10 -10
  86. package/src/compat/actions/serve.ts +132 -136
  87. package/src/compat/actions/server-tag.ts +4 -4
  88. package/src/compat/actions/{action-shared.ts → shared.ts} +34 -34
  89. package/src/compat/actions/unrecognized-error.ts +4 -4
  90. package/src/compat/{index.ts → aliases.ts} +112 -109
  91. package/src/compat/bundler/bun-externals.ts +18 -18
  92. package/src/compat/bundler/cjs-exports.ts +271 -223
  93. package/src/compat/bundler/config.ts +116 -111
  94. package/src/compat/bundler/externals.ts +12 -12
  95. package/src/compat/bundler/import-meta-url.ts +19 -19
  96. package/src/compat/bundler/modularize-imports.ts +36 -33
  97. package/src/compat/bundler/new-url-asset.ts +22 -24
  98. package/src/compat/bundler/optimize-package-imports.ts +111 -107
  99. package/src/compat/bundler/polyfill.ts +28 -28
  100. package/src/compat/bundler/react-compiler.ts +35 -29
  101. package/src/compat/bundler/react-profiler.tsx +11 -11
  102. package/src/compat/bundler/relay-transform.ts +48 -47
  103. package/src/compat/bundler/require-context.ts +119 -113
  104. package/src/compat/bundler/resolve-extensions.ts +19 -19
  105. package/src/compat/bundler/source-cache.ts +25 -25
  106. package/src/compat/bundler/static-imports.ts +7 -7
  107. package/src/compat/bundler/symlink-imports.ts +46 -46
  108. package/src/compat/bundler/tsconfig-paths.ts +13 -15
  109. package/src/compat/bundler/wasm.ts +58 -60
  110. package/src/compat/bundler/webpack-loaders.ts +254 -241
  111. package/src/compat/bundler/worker.ts +101 -104
  112. package/src/compat/cache/build-flags.ts +29 -29
  113. package/src/compat/cache/build-prerender-errors.ts +40 -44
  114. package/src/compat/cache/custom-handler.ts +60 -53
  115. package/src/compat/cache/fetch-patch.ts +240 -240
  116. package/src/compat/cache/handler.ts +27 -31
  117. package/src/compat/cache/modern-handler.ts +148 -126
  118. package/src/compat/cache/resume-data-cache.ts +47 -45
  119. package/src/compat/cache/revalidate.ts +233 -232
  120. package/src/compat/cache/runtime-error.ts +35 -35
  121. package/src/compat/cache/use-cache-transform.ts +442 -417
  122. package/src/compat/cache/use-cache.ts +650 -614
  123. package/src/compat/cache-control.ts +140 -142
  124. package/src/compat/client/base-path.ts +21 -20
  125. package/src/compat/client/css-order.ts +18 -18
  126. package/src/compat/client/errors/bare-boundary.ts +11 -11
  127. package/src/compat/client/errors/control-flow.ts +23 -23
  128. package/src/compat/client/errors/error-boundary.ts +61 -61
  129. package/src/compat/client/errors/global-error.ts +101 -91
  130. package/src/compat/client/errors/install.ts +71 -72
  131. package/src/compat/client/errors/lazy.ts +23 -23
  132. package/src/compat/client/errors/primitive-throw.ts +47 -45
  133. package/src/compat/client/errors/soft-refresh.ts +4 -4
  134. package/src/compat/client/link-status.ts +33 -33
  135. package/src/compat/client/{nav-compat-runtime.ts → nav-runtime.ts} +20 -20
  136. package/src/compat/client/{nav-compat.ts → nav.ts} +12 -13
  137. package/src/compat/client/navigation-scroll.ts +63 -63
  138. package/src/compat/client/optimistic-routing.ts +93 -88
  139. package/src/compat/client/prefetch-cache.ts +23 -24
  140. package/src/compat/client/route-announcer.ts +35 -35
  141. package/src/compat/client/segment-cache-policy.ts +20 -20
  142. package/src/compat/client/segment-cache.ts +309 -315
  143. package/src/compat/client/segment-prefetch.ts +127 -132
  144. package/src/compat/client/trailing-slash.ts +5 -4
  145. package/src/compat/css/chunking.ts +113 -116
  146. package/src/compat/css/inline-css.ts +21 -21
  147. package/src/compat/css/lightningcss.ts +37 -38
  148. package/src/compat/css/modules.ts +161 -175
  149. package/src/compat/css/nonce.ts +7 -7
  150. package/src/compat/css/sass-plugin.ts +18 -21
  151. package/src/compat/css/sass.ts +150 -152
  152. package/src/compat/css/styled-jsx-runtime.ts +27 -27
  153. package/src/compat/css/styled-jsx.ts +21 -21
  154. package/src/compat/edge-runtime.ts +27 -27
  155. package/src/compat/{adapter → export}/build-complete.ts +72 -75
  156. package/src/compat/export/client.ts +29 -31
  157. package/src/compat/export/{index.ts → emit.ts} +111 -110
  158. package/src/compat/export/standalone.ts +62 -54
  159. package/src/compat/image-optimizer/cache.ts +51 -49
  160. package/src/compat/image-optimizer/detect.ts +52 -52
  161. package/src/compat/image-optimizer/{index.ts → optimize.ts} +189 -194
  162. package/src/compat/image-optimizer/source.ts +77 -80
  163. package/src/compat/lifecycle/after-scope.ts +26 -26
  164. package/src/compat/lifecycle/after.ts +48 -45
  165. package/src/compat/lifecycle/error-funnel.ts +98 -102
  166. package/src/compat/lifecycle/error-serialize.ts +30 -26
  167. package/src/compat/lifecycle/error-ui.ts +67 -32
  168. package/src/compat/lifecycle/instrumentation-client.ts +36 -38
  169. package/src/compat/lifecycle/instrumentation.ts +85 -85
  170. package/src/compat/lifecycle/node-console.ts +11 -11
  171. package/src/compat/lifecycle/testmode.ts +160 -132
  172. package/src/compat/mdx/compile.ts +60 -57
  173. package/src/compat/mdx/plugin.ts +11 -11
  174. package/src/compat/mdx/{next-mdx-stub.ts → stub.ts} +5 -5
  175. package/src/compat/{metadata-route-artifacts.ts → metadata-artifacts.ts} +195 -191
  176. package/src/compat/metadata.ts +75 -81
  177. package/src/compat/next/cache.ts +68 -69
  178. package/src/compat/next/canonical-url.ts +9 -9
  179. package/src/compat/next/client-cache.ts +19 -19
  180. package/src/compat/next/client-navigation.ts +112 -116
  181. package/src/compat/next/client-only.ts +1 -1
  182. package/src/compat/next/client-script.tsx +99 -93
  183. package/src/compat/next/client-server.ts +10 -10
  184. package/src/compat/next/config-loader.ts +176 -173
  185. package/src/compat/next/config.ts +7 -7
  186. package/src/compat/next/constants.cjs +6 -6
  187. package/src/compat/next/constants.ts +6 -6
  188. package/src/compat/next/custom-server.ts +26 -24
  189. package/src/compat/next/dist/client/components/app-router-headers.ts +21 -21
  190. package/src/compat/next/dist/server/app-render/work-unit-async-storage.external.cjs +3 -4
  191. package/src/compat/next/dist/server/web/spec-extension/revalidate.ts +1 -1
  192. package/src/compat/next/dist/server/web/spec-extension/unstable-cache.ts +1 -1
  193. package/src/compat/next/dist/server/web/spec-extension/unstable-no-store.ts +1 -1
  194. package/src/compat/next/dynamic.tsx +21 -18
  195. package/src/compat/next/error.tsx +52 -52
  196. package/src/compat/next/font/cache.ts +74 -74
  197. package/src/compat/next/font/google.ts +2 -2
  198. package/src/compat/next/font/index.ts +1 -1
  199. package/src/compat/next/font/local.ts +3 -3
  200. package/src/compat/next/font/runtime-client.ts +17 -15
  201. package/src/compat/next/font/runtime.ts +443 -408
  202. package/src/compat/next/font/shared.ts +120 -108
  203. package/src/compat/next/form.tsx +63 -63
  204. package/src/compat/next/head.tsx +2 -2
  205. package/src/compat/next/headers.ts +103 -95
  206. package/src/compat/next/image/client.tsx +220 -0
  207. package/src/compat/next/image/config.ts +56 -58
  208. package/src/compat/next/image/optimizer.ts +40 -36
  209. package/src/compat/next/image/patterns.ts +37 -40
  210. package/src/compat/next/{image-props.ts → image/props.ts} +208 -202
  211. package/src/compat/next/image/shared.ts +65 -57
  212. package/src/compat/next/image/static-metadata.ts +98 -107
  213. package/src/compat/next/image/validate.ts +79 -88
  214. package/src/compat/next/image.tsx +19 -23
  215. package/src/compat/next/index.ts +1 -1
  216. package/src/compat/next/legacy-image.tsx +59 -60
  217. package/src/compat/next/{link-validation-transform.ts → link-transform.ts} +95 -96
  218. package/src/compat/next/link.tsx +158 -158
  219. package/src/compat/next/navigation.cjs +12 -3
  220. package/src/compat/next/navigation.ts +48 -50
  221. package/src/compat/next/offline.ts +27 -27
  222. package/src/compat/next/og.ts +121 -124
  223. package/src/compat/next/preferred-region.ts +13 -14
  224. package/src/compat/next/redirects.ts +58 -56
  225. package/src/compat/next/resource-hints.ts +73 -76
  226. package/src/compat/next/rewrites.ts +130 -133
  227. package/src/compat/next/root-params.ts +45 -45
  228. package/src/compat/next/{optimistic-route-state.ts → route-state.ts} +52 -52
  229. package/src/compat/next/router.cjs +4 -2
  230. package/src/compat/next/router.ts +58 -61
  231. package/src/compat/next/script.tsx +108 -108
  232. package/src/compat/next/server-only.ts +1 -1
  233. package/src/compat/next/server.ts +19 -19
  234. package/src/compat/next/svgr.ts +18 -17
  235. package/src/compat/next/telemetry.ts +24 -24
  236. package/src/compat/next/{image-usage.ts → usage.ts} +70 -39
  237. package/src/compat/next/user-agent.ts +53 -49
  238. package/src/compat/next/web-vitals.ts +22 -24
  239. package/src/compat/otel/api.ts +41 -41
  240. package/src/compat/otel/client-trace-metadata.ts +25 -27
  241. package/src/compat/otel/fetch-span.ts +29 -29
  242. package/src/compat/otel/tracer.ts +331 -331
  243. package/src/compat/pages/api.ts +456 -0
  244. package/src/compat/pages/client-plugin.ts +36 -36
  245. package/src/compat/pages/router-state.ts +34 -34
  246. package/src/compat/pages/{index.ts → router.ts} +130 -135
  247. package/src/compat/ppr/io.ts +12 -12
  248. package/src/compat/ppr/missing-root-params.ts +34 -38
  249. package/src/compat/ppr/root-params-scan.ts +66 -66
  250. package/src/compat/ppr/root-params-transform.ts +24 -26
  251. package/src/compat/ppr/root-params.ts +30 -30
  252. package/src/compat/ppr/segment-config-incompat.ts +6 -7
  253. package/src/compat/protocol.ts +71 -70
  254. package/src/compat/react/action-state.ts +47 -48
  255. package/src/compat/react/client-lite.ts +15 -15
  256. package/src/compat/react/client.ts +4 -4
  257. package/src/compat/react/compiler-runtime.ts +11 -11
  258. package/src/compat/react/dom-client.ts +44 -44
  259. package/src/compat/react/dom-react-server.ts +10 -16
  260. package/src/compat/react/dom-server.ts +10 -10
  261. package/src/compat/react/dom.ts +52 -52
  262. package/src/compat/react/hooks-extra.ts +34 -35
  263. package/src/compat/react/parity.ts +64 -61
  264. package/src/compat/react/preact.ts +81 -82
  265. package/src/compat/react/react-server.ts +28 -28
  266. package/src/compat/react/router-shim.ts +1 -1
  267. package/src/compat/react/server-component-use.ts +8 -8
  268. package/src/compat/react/server-inserted-html.ts +30 -31
  269. package/src/compat/react/server.ts +53 -55
  270. package/src/compat/react/use.ts +32 -32
  271. package/src/compat/react/view-transition.ts +20 -20
  272. package/src/compat/register/actions.ts +35 -824
  273. package/src/compat/register/boot.ts +41 -41
  274. package/src/compat/register/build-tier.ts +5 -5
  275. package/src/compat/register/build.ts +74 -70
  276. package/src/compat/register/bundler.ts +161 -156
  277. package/src/compat/register/cache.ts +20 -20
  278. package/src/compat/register/client-errors.ts +3 -3
  279. package/src/compat/register/config.ts +6 -6
  280. package/src/compat/register/css-extras.ts +30 -34
  281. package/src/compat/register/edge-runtime.ts +3 -3
  282. package/src/compat/register/errors.ts +10 -12
  283. package/src/compat/register/export.ts +16 -16
  284. package/src/compat/register/font.ts +11 -11
  285. package/src/compat/register/hooks.ts +2 -2
  286. package/src/compat/register/image.ts +40 -40
  287. package/src/compat/register/index.ts +59 -62
  288. package/src/compat/register/instrumentation-client.ts +10 -10
  289. package/src/compat/register/lifecycle.ts +25 -28
  290. package/src/compat/register/mdx.ts +10 -10
  291. package/src/compat/register/middleware.ts +226 -16
  292. package/src/compat/register/otel.ts +80 -88
  293. package/src/compat/register/pages-api.ts +10 -463
  294. package/src/compat/register/ppr.ts +16 -16
  295. package/src/compat/register/protocol.ts +17 -18
  296. package/src/compat/register/proxy.ts +49 -51
  297. package/src/compat/register/render.ts +79 -76
  298. package/src/compat/register/routing.ts +162 -159
  299. package/src/compat/register/segment.ts +24 -1897
  300. package/src/compat/register/static-image.ts +3 -3
  301. package/src/compat/register/{misc.ts → taint.ts} +9 -9
  302. package/src/compat/register/typed-routes.ts +14 -14
  303. package/src/compat/register/{usecache.ts → use-cache.ts} +39 -39
  304. package/src/compat/register/validation.ts +18 -18
  305. package/src/compat/segment/loading-boundary.ts +43 -45
  306. package/src/compat/segment/page-slot.ts +69 -69
  307. package/src/compat/segment/serve.ts +1884 -0
  308. package/src/compat/segment/tree.ts +113 -112
  309. package/src/compat/segment/vary-key.ts +38 -38
  310. package/src/compat/segment/vary-params.ts +138 -142
  311. package/src/compat/static-params.ts +14 -12
  312. package/src/compat/tsconfig-defaults.ts +87 -91
  313. package/src/compat/typecheck/{index.ts → check.ts} +234 -212
  314. package/src/compat/typecheck/worker.ts +15 -12
  315. package/src/compat/typed-routes/{index.ts → generate.ts} +36 -36
  316. package/src/compat/typed-routes/manifest.ts +174 -170
  317. package/src/compat/typed-routes/typegen.ts +127 -110
  318. package/src/compat/validation/errors.ts +16 -19
  319. package/src/compat/validation/prerender-diagnostics.ts +521 -504
  320. package/src/compat/validation/{index.ts → validate.ts} +647 -648
  321. package/src/compat-bootstrap.ts +16 -16
  322. package/src/config.ts +86 -69
  323. package/src/css/build.ts +230 -227
  324. package/src/css/postcss.ts +79 -80
  325. package/src/css/worker.ts +14 -15
  326. package/src/dev/client-actions.ts +10 -10
  327. package/src/dev/client-chunk-store.ts +27 -27
  328. package/src/dev/{client-key-cache.ts → restart/client-key.ts} +76 -76
  329. package/src/dev/{restart-cache.ts → restart/enabled.ts} +1 -1
  330. package/src/dev/{global-css-cache.ts → restart/global-css.ts} +91 -83
  331. package/src/dev/{node-module-bundle-cache.ts → restart/node-modules.ts} +24 -24
  332. package/src/dev/{route-bundle-key-cache.ts → restart/route-bundle-key.ts} +53 -53
  333. package/src/dev/{route-facts-cache.ts → restart/route-facts.ts} +82 -82
  334. package/src/dev/server.ts +804 -820
  335. package/src/env.ts +46 -43
  336. package/src/extensions.ts +491 -478
  337. package/src/index.ts +8 -8
  338. package/src/internal.ts +20 -23
  339. package/src/{islands → render}/boundary-error.ts +3 -3
  340. package/src/render/hooks.ts +71 -71
  341. package/src/render/island-context.ts +14 -14
  342. package/src/render/metadata.ts +310 -310
  343. package/src/{ppr-postpone.ts → render/postpone.ts} +5 -5
  344. package/src/{ppr.ts → render/ppr.ts} +244 -245
  345. package/src/render/renderer.ts +2087 -2082
  346. package/src/render/resource-hints.ts +16 -17
  347. package/src/render/slots.tsx +224 -235
  348. package/src/{islands → render}/static-children.ts +9 -12
  349. package/src/{islands → render}/static-slots.ts +37 -37
  350. package/src/{cache/context.ts → request/cache.ts} +20 -20
  351. package/src/request/context.ts +107 -107
  352. package/src/{dynamic/source.ts → resolve/dynamic.ts} +139 -139
  353. package/src/resolve/engine.ts +90 -77
  354. package/src/resolve/imports.ts +475 -463
  355. package/src/resolve/scan-facts.ts +318 -296
  356. package/src/resolve/source-text.ts +37 -37
  357. package/src/{dynamic → resolve}/tree-shake.ts +132 -128
  358. package/src/routing/forwarded.ts +19 -19
  359. package/src/routing/handler.ts +84 -91
  360. package/src/routing/href.ts +87 -70
  361. package/src/routing/{metadata.ts → metadata-files.ts} +403 -401
  362. package/src/{proxy.ts → routing/proxy.ts} +306 -312
  363. package/src/routing/{request-runtime.ts → request-environment.ts} +10 -10
  364. package/src/routing/routes.ts +827 -815
  365. package/src/routing/slots.ts +164 -160
  366. package/src/runtime/loader.ts +954 -0
  367. package/src/{dev → runtime}/module-cache.ts +309 -287
  368. package/src/{dev → runtime}/module-generations.ts +9 -9
  369. package/src/{dev → runtime}/module-transform.ts +81 -72
  370. package/src/{dev/imports.ts → runtime/modules.ts} +934 -847
  371. package/src/runtime/{server.ts → vendor-build.ts} +848 -1696
  372. package/src/runtime/vendor.ts +428 -406
  373. package/src/styles.d.ts +9 -0
  374. package/src/types.ts +324 -335
  375. package/src/utils/ansi.ts +5 -5
  376. package/src/utils/{source.ts → code.ts} +15 -12
  377. package/src/utils/content-type.ts +3 -3
  378. package/src/utils/decode.ts +2 -2
  379. package/src/utils/dev-profile.ts +13 -13
  380. package/src/utils/error-log.ts +6 -6
  381. package/src/utils/esbuild.ts +18 -18
  382. package/src/utils/fs-cache.ts +13 -13
  383. package/src/utils/fs.ts +57 -49
  384. package/src/utils/html.ts +20 -24
  385. package/src/utils/native-require.ts +8 -8
  386. package/src/utils/serialize.ts +139 -146
  387. package/src/utils/verbose.ts +18 -18
  388. package/reference/overview.md +0 -35
  389. package/src/cli/analyze-print.ts +0 -181
  390. package/src/compat/middleware/manifest.ts +0 -210
  391. package/src/compat/next/image-client.tsx +0 -215
  392. package/src/compat/next/link-usage.ts +0 -29
  393. package/src/css/index.ts +0 -2
  394. package/src/render/index.ts +0 -1
  395. package/src/style-modules.d.ts +0 -9
@@ -1,12 +1,13 @@
1
- import { isNotFoundError, isRedirectError } from '../api/navigation';
2
- import { getWorkUnit, runWithRequest } from '../request/context';
3
- import { nextResponseMeta, toNextRequest } from '../api/server';
4
- import { reportRequestError } from '../extensions';
5
- import type { NextRequest, RouteManifestEntry, RouteParamValue } from '../types';
1
+ import { isNotFoundError, isRedirectError } from '../api/navigation'
2
+ import { getWorkUnit, runWithRequest } from '../request/context'
3
+ import { nextResponseMeta, toNextRequest } from '../api/server'
4
+ import { reportRequestError } from '../extensions'
5
+ import type { NextRequest, RouteManifestEntry, RouteParamValue } from '../types'
6
+ import { safeDecode } from '../utils/decode'
6
7
 
7
- const routeMethods = ['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'] as const;
8
+ const routeMethods = ['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'] as const
8
9
 
9
- type RouteMethod = (typeof routeMethods)[number];
10
+ type RouteMethod = (typeof routeMethods)[number]
10
11
 
11
12
  // Methods that are valid HTTP verbs but may be unimplemented on a route (405),
12
13
  // vs. tokens that are not HTTP methods at all (400). Next answers 400 for the
@@ -21,32 +22,32 @@ const httpMethods = new Set([
21
22
  'OPTIONS',
22
23
  'CONNECT',
23
24
  'TRACE',
24
- ]);
25
+ ])
25
26
 
26
27
  interface RouteHandlerContext {
27
- params?: Promise<Record<string, RouteParamValue>>;
28
+ params?: Promise<Record<string, RouteParamValue>>
28
29
  }
29
30
 
30
31
  interface HandleRouteOptions {
31
32
  /** Absolute route file path, used in the "no response returned" CLI error. */
32
- routeFile?: string;
33
+ routeFile?: string
33
34
  }
34
35
 
35
36
  export interface RouteHandlerModule {
36
- params?: () => Record<string, RouteParamValue>[] | Promise<Record<string, RouteParamValue>[]>;
37
- GET?: RouteHandler;
38
- HEAD?: RouteHandler;
39
- POST?: RouteHandler;
40
- PUT?: RouteHandler;
41
- PATCH?: RouteHandler;
42
- DELETE?: RouteHandler;
43
- OPTIONS?: RouteHandler;
37
+ params?: () => Record<string, RouteParamValue>[] | Promise<Record<string, RouteParamValue>[]>
38
+ GET?: RouteHandler
39
+ HEAD?: RouteHandler
40
+ POST?: RouteHandler
41
+ PUT?: RouteHandler
42
+ PATCH?: RouteHandler
43
+ DELETE?: RouteHandler
44
+ OPTIONS?: RouteHandler
44
45
  }
45
46
 
46
47
  type RouteHandler = (
47
48
  request: NextRequest,
48
49
  context: RouteHandlerContext,
49
- ) => Response | undefined | void | Promise<Response | undefined | void>;
50
+ ) => Response | undefined | void | Promise<Response | undefined | void>
50
51
 
51
52
  export async function handleRouteModule(
52
53
  module: RouteHandlerModule,
@@ -58,16 +59,16 @@ export async function handleRouteModule(
58
59
  // draftMode().enable() append set-cookie here while the handler runs, and
59
60
  // the headers are merged onto whatever response goes out — including the
60
61
  // synthesized redirect response when the handler throws redirect().
61
- const responseHeaders = new Headers();
62
- const method = request.method.toUpperCase();
62
+ const responseHeaders = new Headers()
63
+ const method = request.method.toUpperCase()
63
64
  try {
64
65
  // A request method that is not a valid HTTP verb is a bad request, not an
65
66
  // unimplemented one (Next returns 400 with an empty body).
66
- if (!httpMethods.has(method)) return new Response(null, { status: 400 });
67
+ if (!httpMethods.has(method)) return new Response(null, { status: 400 })
67
68
 
68
69
  const handler = routeMethods.includes(method as RouteMethod)
69
70
  ? module[method as RouteMethod]
70
- : undefined;
71
+ : undefined
71
72
 
72
73
  if (!handler) {
73
74
  if (method === 'HEAD' && module.GET) {
@@ -77,10 +78,10 @@ export async function handleRouteModule(
77
78
  request,
78
79
  responseHeaders,
79
80
  options,
80
- );
81
- return new Response(null, { status: response.status, headers: response.headers });
81
+ )
82
+ return new Response(null, { status: response.status, headers: response.headers })
82
83
  }
83
- return missingMethodResponse(module, method);
84
+ return missingMethodResponse(module, method)
84
85
  }
85
86
 
86
87
  return finalizeResponse(
@@ -88,21 +89,21 @@ export async function handleRouteModule(
88
89
  request,
89
90
  responseHeaders,
90
91
  options,
91
- );
92
+ )
92
93
  } catch (error) {
93
94
  if (isRedirectError(error)) {
94
95
  // POST submissions get a 303 (Next's behavior for redirect() and
95
96
  // permanentRedirect() thrown in route handlers): the browser follows
96
97
  // with a GET instead of replaying the POST against the target.
97
- const status = method === 'POST' ? 303 : error.status;
98
+ const status = method === 'POST' ? 303 : error.status
98
99
  return withResponseHeaders(
99
100
  new Response(null, { status, headers: { location: error.location } }),
100
101
  responseHeaders,
101
- );
102
+ )
102
103
  }
103
104
  // notFound() thrown inside a handler is a 404 with an empty body.
104
105
  if (isNotFoundError(error)) {
105
- return withResponseHeaders(new Response(null, { status: 404 }), responseHeaders);
106
+ return withResponseHeaders(new Response(null, { status: 404 }), responseHeaders)
106
107
  }
107
108
  // Any other throw is a 500 with an empty body. Report it through the error
108
109
  // funnel (onRequestError) here since core no longer sees it as uncaught.
@@ -110,9 +111,9 @@ export async function handleRouteModule(
110
111
  error,
111
112
  { method, url: request.url, headers: request.headers },
112
113
  { phase: 'handler', routeKind: 'route-handler', ...(getWorkUnit()?.responseHints ?? {}) },
113
- );
114
- console.error(error);
115
- return new Response(null, { status: 500 });
114
+ )
115
+ console.error(error)
116
+ return new Response(null, { status: 500 })
116
117
  }
117
118
  }
118
119
 
@@ -128,21 +129,21 @@ function finalizeResponse(
128
129
  responseHeaders: Headers,
129
130
  options: HandleRouteOptions,
130
131
  ) {
131
- const method = request.method.toUpperCase();
132
+ const method = request.method.toUpperCase()
132
133
  if (!response) {
133
- const file = options.routeFile ?? '<route>';
134
+ const file = options.routeFile ?? '<route>'
134
135
  console.error(
135
136
  `No response is returned from route handler '${file}'. Expected a Response object but ` +
136
137
  `received '${typeof response}' (method: ${method}, url: ${request.url}). Ensure you ` +
137
138
  'return a `Response` or a `NextResponse` in all branches of your handler.',
138
- );
139
- return new Response(null, { status: 500 });
139
+ )
140
+ return new Response(null, { status: 500 })
140
141
  }
141
142
  if (nextResponseMeta(response)?.kind === 'next') {
142
- console.error('https://nextjs.org/docs/messages/next-response-next-in-app-route-handler');
143
- return new Response(null, { status: 500 });
143
+ console.error('https://nextjs.org/docs/messages/next-response-next-in-app-route-handler')
144
+ return new Response(null, { status: 500 })
144
145
  }
145
- return withResponseHeaders(response, responseHeaders);
146
+ return withResponseHeaders(response, responseHeaders)
146
147
  }
147
148
 
148
149
  function callHandler(
@@ -151,121 +152,113 @@ function callHandler(
151
152
  params: Record<string, RouteParamValue>,
152
153
  responseHeaders: Headers,
153
154
  ) {
154
- const nextRequest = toNextRequest(request);
155
+ const nextRequest = toNextRequest(request)
155
156
  // Static routes (no dynamic segments) get no `params` in context — Next
156
157
  // omits it, so `context.params` is `undefined` rather than a promise of `{}`.
157
158
  const context: RouteHandlerContext =
158
- Object.keys(params).length > 0 ? { params: Promise.resolve(params) } : {};
159
+ Object.keys(params).length > 0 ? { params: Promise.resolve(params) } : {}
159
160
  return runWithRequest(nextRequest, () => handler(nextRequest, context), params, {
160
161
  responseHeaders,
161
- });
162
+ })
162
163
  }
163
164
 
164
165
  /** Merge scope-collected headers (set-cookie appends, everything else sets) onto the response. */
165
166
  function withResponseHeaders(response: Response, extra: Headers) {
166
- const withSetCookie = extra as Headers & { getSetCookie?: () => string[] };
167
- const scopeCookies = withSetCookie.getSetCookie?.() ?? [];
168
- let hasOthers = false;
167
+ const withSetCookie = extra as Headers & { getSetCookie?: () => string[] }
168
+ const scopeCookies = withSetCookie.getSetCookie?.() ?? []
169
+ let hasOthers = false
169
170
  extra.forEach((_, key) => {
170
- if (key !== 'set-cookie') hasOthers = true;
171
- });
172
- if (scopeCookies.length === 0 && !hasOthers) return response;
171
+ if (key !== 'set-cookie') hasOthers = true
172
+ })
173
+ if (scopeCookies.length === 0 && !hasOthers) return response
173
174
 
174
175
  const apply = (headers: Headers) => {
175
176
  extra.forEach((value, key) => {
176
- if (key !== 'set-cookie') headers.set(key, value);
177
- });
177
+ if (key !== 'set-cookie') headers.set(key, value)
178
+ })
178
179
  // Cookie-jar merge (Next's ResponseCookies semantics): scope cookies
179
180
  // (cookies().set during the handler) first, the response's own Set-Cookie
180
181
  // headers override same-name entries, and every cookie is normalized with
181
182
  // a default Path=/.
182
183
  const responseCookies =
183
- (headers as Headers & { getSetCookie?: () => string[] }).getSetCookie?.() ?? [];
184
- const jar = new Map<string, string>();
184
+ (headers as Headers & { getSetCookie?: () => string[] }).getSetCookie?.() ?? []
185
+ const jar = new Map<string, string>()
185
186
  for (const cookie of [...scopeCookies, ...responseCookies]) {
186
- jar.set(cookieName(cookie), normalizeSetCookie(cookie));
187
+ jar.set(cookieName(cookie), normalizeSetCookie(cookie))
187
188
  }
188
- headers.delete('set-cookie');
189
- for (const cookie of jar.values()) headers.append('set-cookie', cookie);
190
- };
189
+ headers.delete('set-cookie')
190
+ for (const cookie of jar.values()) headers.append('set-cookie', cookie)
191
+ }
191
192
  try {
192
- apply(response.headers);
193
- return response;
193
+ apply(response.headers)
194
+ return response
194
195
  } catch {
195
196
  // Immutable headers (e.g. a Response forwarded from fetch): re-wrap.
196
- const headers = new Headers(response.headers);
197
- apply(headers);
197
+ const headers = new Headers(response.headers)
198
+ apply(headers)
198
199
  return new Response(response.body, {
199
200
  status: response.status,
200
201
  statusText: response.statusText,
201
202
  headers,
202
- });
203
+ })
203
204
  }
204
205
  }
205
206
 
206
207
  function cookieName(setCookie: string) {
207
- return (setCookie.split('=')[0] ?? '').trim();
208
+ return (setCookie.split('=')[0] ?? '').trim()
208
209
  }
209
210
 
210
211
  function normalizeSetCookie(setCookie: string) {
211
- return /;\s*path=/i.test(setCookie) ? setCookie : `${setCookie}; Path=/`;
212
+ return /;\s*path=/i.test(setCookie) ? setCookie : `${setCookie}; Path=/`
212
213
  }
213
214
 
214
215
  export async function staticRouteParams(route: RouteManifestEntry, module: RouteHandlerModule) {
215
- if (typeof module.GET !== 'function') return [];
216
+ if (typeof module.GET !== 'function') return []
216
217
  // `dynamic = 'force-static'` and `dynamic = 'error'` both evaluate a static
217
218
  // request; the latter lets request APIs fail at their call sites. A
218
219
  // `revalidate` export opts a request-independent GET into static/ISR output.
219
- const config = route.segmentConfig;
220
+ const config = route.segmentConfig
220
221
  const optedStatic =
221
222
  config?.dynamic === 'force-static' ||
222
223
  config?.dynamic === 'error' ||
223
224
  config?.revalidate === false ||
224
- (typeof config?.revalidate === 'number' && config.revalidate > 0);
225
- if (route.hasStaticParams) return module.params?.() ?? [];
226
- if (route.usesRequest && !optedStatic) return [];
227
- return route.mode === 'static' || optedStatic ? [{}] : [];
225
+ (typeof config?.revalidate === 'number' && config.revalidate > 0)
226
+ if (route.hasStaticParams) return module.params?.() ?? []
227
+ if (route.usesRequest && !optedStatic) return []
228
+ return route.mode === 'static' || optedStatic ? [{}] : []
228
229
  }
229
230
 
230
231
  export function routeParamsFromPath(
231
232
  route: Pick<RouteManifestEntry, 'catchAll' | 'params' | 'pattern'>,
232
233
  pathname: string,
233
234
  ) {
234
- const match = new RegExp(`^${route.pattern}$`).exec(pathname);
235
- const params: Record<string, RouteParamValue> = {};
236
- if (!match) return params;
235
+ const match = new RegExp(`^${route.pattern}$`).exec(pathname)
236
+ const params: Record<string, RouteParamValue> = {}
237
+ if (!match) return params
237
238
 
238
239
  for (let index = 0; index < route.params.length; index += 1) {
239
- params[route.params[index]!] = safeDecode(match[index + 1] ?? '');
240
+ params[route.params[index]!] = safeDecode(match[index + 1] ?? '')
240
241
  }
241
242
  if (route.catchAll) {
242
243
  params[route.catchAll] = (match[route.params.length + 1] ?? '')
243
244
  .split('/')
244
245
  .filter(Boolean)
245
- .map(safeDecode);
246
+ .map(safeDecode)
246
247
  }
247
- return params;
248
+ return params
248
249
  }
249
250
 
250
251
  function missingMethodResponse(module: RouteHandlerModule, method: string) {
251
- const headers = { Allow: allowedMethods(module).join(', ') };
252
- if (method === 'OPTIONS') return new Response(null, { status: 204, headers });
253
- return new Response(null, { status: 405, headers });
252
+ const headers = { Allow: allowedMethods(module).join(', ') }
253
+ if (method === 'OPTIONS') return new Response(null, { status: 204, headers })
254
+ return new Response(null, { status: 405, headers })
254
255
  }
255
256
 
256
257
  function allowedMethods(module: RouteHandlerModule) {
257
- const allowed = new Set(routeMethods.filter(method => typeof module[method] === 'function'));
258
+ const allowed = new Set(routeMethods.filter(method => typeof module[method] === 'function'))
258
259
  // GET implies auto-HEAD; every route gets auto-OPTIONS. The Allow header is
259
260
  // sorted (Next emits e.g. `OPTIONS, POST`).
260
- if (allowed.has('GET')) allowed.add('HEAD');
261
- allowed.add('OPTIONS');
262
- return [...allowed].sort();
263
- }
264
-
265
- function safeDecode(value: string) {
266
- try {
267
- return decodeURIComponent(value);
268
- } catch {
269
- return value;
270
- }
261
+ if (allowed.has('GET')) allowed.add('HEAD')
262
+ allowed.add('OPTIONS')
263
+ return [...allowed].sort()
271
264
  }
@@ -1,26 +1,28 @@
1
- import type { RouteParamValue } from '../types';
1
+ import type { PrefetchMode, RouteParamValue } from '../types'
2
2
 
3
- export type SearchValue = string | number | boolean | null | undefined;
4
- export type SearchInput = URLSearchParams | Record<string, SearchValue | SearchValue[]>;
3
+ export type SearchValue = string | number | boolean | null | undefined
4
+ export type SearchInput = URLSearchParams | Record<string, SearchValue | SearchValue[]>
5
5
 
6
6
  export interface HrefParts {
7
- params?: Record<string, RouteParamValue>;
8
- search?: SearchInput;
9
- hash?: string;
7
+ params?: Record<string, RouteParamValue>
8
+ search?: SearchInput
9
+ hash?: string
10
10
  }
11
11
 
12
12
  export function routeHref(route: string, options: HrefParts = {}) {
13
- const path = applyTrailingSlash(fillParams(route, options.params ?? {}));
14
- const search = searchString(options.search);
15
- const hash = hashString(options.hash);
16
- return `${path}${search}${hash}`;
13
+ const path = applyTrailingSlash(fillParams(route, options.params ?? {}))
14
+ const search = searchString(options.search)
15
+ const hash = hashString(options.hash)
16
+ return `${path}${search}${hash}`
17
17
  }
18
18
 
19
19
  declare global {
20
20
  interface Window {
21
- __PNEXT_TRAILING_SLASH__?: boolean;
21
+ __PNEXT_TRAILING_SLASH__?: boolean
22
+ __PNEXT_PREFETCH__?: PrefetchMode
22
23
  }
23
- var __PNEXT_TRAILING_SLASH__: boolean | undefined;
24
+ var __PNEXT_TRAILING_SLASH__: boolean | undefined
25
+ var __PNEXT_PREFETCH__: PrefetchMode | undefined
24
26
  }
25
27
 
26
28
  // With `trailingSlash: true` the server 308s bare page URLs to their slashed
@@ -31,16 +33,33 @@ declare global {
31
33
  // Anchored on globalThis, not a module local: this module is dual-copied into
32
34
  // the client/prebundled bundles, where setTrailingSlashUrls never runs.
33
35
  export function setTrailingSlashUrls(enabled: boolean) {
34
- globalThis.__PNEXT_TRAILING_SLASH__ = enabled;
36
+ globalThis.__PNEXT_TRAILING_SLASH__ = enabled
35
37
  }
36
38
 
37
39
  function isTrailingSlashEnabled(): boolean {
38
- if (process.browser || typeof window !== 'undefined') return window.__PNEXT_TRAILING_SLASH__ === true;
39
- return globalThis.__PNEXT_TRAILING_SLASH__ === true;
40
+ if (process.browser || typeof window !== 'undefined')
41
+ return window.__PNEXT_TRAILING_SLASH__ === true
42
+ return globalThis.__PNEXT_TRAILING_SLASH__ === true
40
43
  }
41
44
 
42
45
  export function getTrailingSlashUrls() {
43
- return isTrailingSlashEnabled();
46
+ return isTrailingSlashEnabled()
47
+ }
48
+
49
+ // The app-wide default prefetch mode (config `prefetch`), for links that set
50
+ // none of their own. Isomorphic like the trailing-slash seam: the server sets it
51
+ // from the resolved config, the client reads the injected window global
52
+ // (renderer's prefetchModeScript).
53
+ export function setDefaultPrefetchMode(mode: PrefetchMode | undefined) {
54
+ globalThis.__PNEXT_PREFETCH__ = mode
55
+ }
56
+
57
+ export function getDefaultPrefetchMode(): PrefetchMode {
58
+ const mode =
59
+ process.browser || typeof window !== 'undefined'
60
+ ? window.__PNEXT_PREFETCH__
61
+ : globalThis.__PNEXT_PREFETCH__
62
+ return mode === undefined ? 'visible' : mode
44
63
  }
45
64
 
46
65
  // The configured basePath ('' when unset). Set once per process by the server
@@ -48,14 +67,14 @@ export function getTrailingSlashUrls() {
48
67
  // trailing-slash seam. Core render code (metadata) reads it through
49
68
  // withBasePath so file-convention asset hrefs (og-image, manifest) carry the
50
69
  // prefix without a compat/next.config import in core.
51
- let basePathPrefix = '';
70
+ let basePathPrefix = ''
52
71
 
53
72
  export function setBasePathPrefix(value: string) {
54
- basePathPrefix = value;
73
+ basePathPrefix = value
55
74
  }
56
75
 
57
76
  export function getBasePathPrefix() {
58
- return basePathPrefix;
77
+ return basePathPrefix
59
78
  }
60
79
 
61
80
  /**
@@ -65,26 +84,26 @@ export function getBasePathPrefix() {
65
84
  * always a no-op. Any query/hash on the path rides along untouched.
66
85
  */
67
86
  export function withBasePath(path: string) {
68
- const base = basePathPrefix;
69
- if (!base) return path;
70
- if (!path.startsWith('/') || path.startsWith('//')) return path;
71
- if (path === base || path.startsWith(`${base}/`)) return path;
72
- return `${base}${path}`;
87
+ const base = basePathPrefix
88
+ if (!base) return path
89
+ if (!path.startsWith('/') || path.startsWith('//')) return path
90
+ if (path === base || path.startsWith(`${base}/`)) return path
91
+ return `${base}${path}`
73
92
  }
74
93
 
75
94
  export function applyTrailingSlash(pathname: string) {
76
- const [, path = '', rest = ''] = /^([^?#]*)([\s\S]*)$/.exec(pathname) ?? [];
77
- if (!path.startsWith('/')) return pathname;
95
+ const [, path = '', rest = ''] = /^([^?#]*)([\s\S]*)$/.exec(pathname) ?? []
96
+ if (!path.startsWith('/')) return pathname
78
97
  if (isTrailingSlashEnabled()) {
79
98
  // Add the canonical trailing slash (skip root, already-slashed, and files).
80
- if (path === '/' || path.endsWith('/') || /\.[^/]+$/.test(path)) return pathname;
81
- return `${path}/${rest}`;
99
+ if (path === '/' || path.endsWith('/') || /\.[^/]+$/.test(path)) return pathname
100
+ return `${path}/${rest}`
82
101
  }
83
102
  // trailingSlash:false — Next strips a trailing slash from hrefs so the anchor
84
103
  // matches the canonical (unslashed) form and avoids a 308 on click. Root and
85
104
  // file paths (`/a.txt/` is not a thing) are left alone.
86
- if (path === '/' || !path.endsWith('/') || /\.[^/]+\/$/.test(path)) return pathname;
87
- return `${path.replace(/\/+$/, '')}${rest}`;
105
+ if (path === '/' || !path.endsWith('/') || /\.[^/]+\/$/.test(path)) return pathname
106
+ return `${path.replace(/\/+$/, '')}${rest}`
88
107
  }
89
108
 
90
109
  function fillParams(route: string, params: Record<string, RouteParamValue>) {
@@ -93,47 +112,47 @@ function fillParams(route: string, params: Record<string, RouteParamValue>) {
93
112
  // catch-all form so its doubled brackets aren't mis-parsed.
94
113
  .replace(/\[\[\.\.\.([^\]]+)\]\]/g, (_match, key: string) => encodeParam(params[key], true))
95
114
  .replace(/\[\.\.\.([^\]]+)\]/g, (_match, key: string) => encodeParam(params[key], true))
96
- .replace(/\[([^\]]+)\]/g, (_match, key: string) => encodeParam(params[key], false));
115
+ .replace(/\[([^\]]+)\]/g, (_match, key: string) => encodeParam(params[key], false))
97
116
  // An absent optional catch-all (`[[...slug]]`) leaves a dangling `/`; drop it
98
117
  // so /docs/:slug* with no params yields /docs, not /docs/.
99
- return collapseTrailingSlash(filled);
118
+ return collapseTrailingSlash(filled)
100
119
  }
101
120
 
102
121
  function collapseTrailingSlash(pathname: string) {
103
- if (pathname.length <= 1) return pathname;
104
- return pathname.replace(/\/+$/, '') || '/';
122
+ if (pathname.length <= 1) return pathname
123
+ return pathname.replace(/\/+$/, '') || '/'
105
124
  }
106
125
 
107
126
  function encodeParam(value: RouteParamValue | undefined, catchAll: boolean) {
108
127
  if (Array.isArray(value)) {
109
- const encoded = value.map(segment => encodeURIComponent(segment));
110
- return catchAll ? encoded.join('/') : encoded[0] ?? '';
128
+ const encoded = value.map(segment => encodeURIComponent(segment))
129
+ return catchAll ? encoded.join('/') : (encoded[0] ?? '')
111
130
  }
112
- return encodeURIComponent(value ?? '');
131
+ return encodeURIComponent(value ?? '')
113
132
  }
114
133
 
115
134
  function searchString(search: SearchInput | undefined) {
116
- if (!search) return '';
117
- const params = search instanceof URLSearchParams ? search : objectSearchParams(search);
118
- const value = params.toString();
119
- return value ? `?${value}` : '';
135
+ if (!search) return ''
136
+ const params = search instanceof URLSearchParams ? search : objectSearchParams(search)
137
+ const value = params.toString()
138
+ return value ? `?${value}` : ''
120
139
  }
121
140
 
122
141
  function objectSearchParams(search: Record<string, SearchValue | SearchValue[]>) {
123
- const params = new URLSearchParams();
142
+ const params = new URLSearchParams()
124
143
  for (const [key, value] of Object.entries(search)) {
125
- const values = Array.isArray(value) ? value : [value];
144
+ const values = Array.isArray(value) ? value : [value]
126
145
  for (const item of values) {
127
- if (item == null) continue;
128
- params.append(key, String(item));
146
+ if (item == null) continue
147
+ params.append(key, String(item))
129
148
  }
130
149
  }
131
- return params;
150
+ return params
132
151
  }
133
152
 
134
153
  function hashString(hash: string | undefined) {
135
- if (!hash) return '';
136
- return hash.startsWith('#') ? hash : `#${hash}`;
154
+ if (!hash) return ''
155
+ return hash.startsWith('#') ? hash : `#${hash}`
137
156
  }
138
157
 
139
158
  /**
@@ -142,18 +161,18 @@ function hashString(hash: string | undefined) {
142
161
  * Next. Returns the response when the path cannot be decoded, else null.
143
162
  */
144
163
  export function malformedUrlResponse(request: Request): Response | null {
145
- let pathname: string;
164
+ let pathname: string
146
165
  try {
147
- pathname = new URL(request.url).pathname;
166
+ pathname = new URL(request.url).pathname
148
167
  } catch {
149
- return new Response('Bad Request', { status: 400 });
168
+ return new Response('Bad Request', { status: 400 })
150
169
  }
151
- if (!pathname.includes('%')) return null;
170
+ if (!pathname.includes('%')) return null
152
171
  try {
153
- decodeURIComponent(pathname);
154
- return null;
172
+ decodeURIComponent(pathname)
173
+ return null
155
174
  } catch {
156
- return new Response('Bad Request', { status: 400 });
175
+ return new Response('Bad Request', { status: 400 })
157
176
  }
158
177
  }
159
178
 
@@ -165,13 +184,11 @@ export function malformedUrlResponse(request: Request): Response | null {
165
184
  * already canonical.
166
185
  */
167
186
  export function canonicalTrailingSlashPath(pathname: string, trailingSlash: boolean): string {
168
- if (pathname === '/' || pathname === '') return pathname;
169
- if (/\.[^/]+$/.test(pathname)) return pathname;
170
- const slashed = pathname.endsWith('/');
171
- if (trailingSlash ? slashed : !slashed) return pathname;
172
- return trailingSlash
173
- ? `${pathname.replace(/\/+$/, '')}/`
174
- : pathname.replace(/\/+$/, '') || '/';
187
+ if (pathname === '/' || pathname === '') return pathname
188
+ if (/\.[^/]+$/.test(pathname)) return pathname
189
+ const slashed = pathname.endsWith('/')
190
+ if (trailingSlash ? slashed : !slashed) return pathname
191
+ return trailingSlash ? `${pathname.replace(/\/+$/, '')}/` : pathname.replace(/\/+$/, '') || '/'
175
192
  }
176
193
 
177
194
  /**
@@ -188,15 +205,15 @@ export function trailingSlashRedirect(
188
205
  // skipTrailingSlashRedirect: the app serves both slashed and unslashed URLs
189
206
  // as-is, so no canonical redirect is ever emitted (route matching already
190
207
  // tolerates a trailing slash via normalizePathname).
191
- if (config.skipTrailingSlashRedirect) return null;
192
- if (method !== 'GET' && method !== 'HEAD') return null;
193
- const pathname = url.pathname;
194
- if (pathname === '/' || pathname === '') return null;
195
- if (pathname.startsWith('/__pnext') || pathname.startsWith('/assets/')) return null;
196
- const target = canonicalTrailingSlashPath(pathname, Boolean(config.trailingSlash));
197
- if (target === pathname) return null;
208
+ if (config.skipTrailingSlashRedirect) return null
209
+ if (method !== 'GET' && method !== 'HEAD') return null
210
+ const pathname = url.pathname
211
+ if (pathname === '/' || pathname === '') return null
212
+ if (pathname.startsWith('/__pnext') || pathname.startsWith('/assets/')) return null
213
+ const target = canonicalTrailingSlashPath(pathname, Boolean(config.trailingSlash))
214
+ if (target === pathname) return null
198
215
  return new Response(null, {
199
216
  status: 308,
200
217
  headers: { location: `${target}${url.search}` },
201
- });
218
+ })
202
219
  }