@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
@@ -15,67 +15,67 @@
15
15
  // Registered first in both client and server esbuild plugin arrays so a configured rule preempts
16
16
  // pnext's default handling for the same extension.
17
17
 
18
- import { createHash } from 'node:crypto';
19
- import { existsSync, readFile, readFileSync, realpathSync } from 'node:fs';
20
- import { mkdir, readFile as readFileP, writeFile } from 'node:fs/promises';
21
- import { createRequire } from 'node:module';
22
- import path from 'node:path';
23
- import { pathToFileURL } from 'node:url';
24
- import type { Plugin } from 'esbuild';
25
- import type { ResolvedConfig } from '../../config';
26
- import { rewriteSpecifierLiterals } from '../../resolve/scan-facts';
27
- import { turbopackLoaderRules, turbopackResolveAlias, type WebpackLoaderRule } from './config';
18
+ import { createHash } from 'node:crypto'
19
+ import { existsSync, readFile, readFileSync, realpathSync } from 'node:fs'
20
+ import { mkdir, readFile as readFileP, writeFile } from 'node:fs/promises'
21
+ import { createRequire } from 'node:module'
22
+ import path from 'node:path'
23
+ import { pathToFileURL } from 'node:url'
24
+ import type { Plugin } from 'esbuild'
25
+ import type { ResolvedConfig } from '../../config'
26
+ import { rewriteSpecifierLiterals } from '../../resolve/scan-facts'
27
+ import { turbopackLoaderRules, turbopackResolveAlias, type WebpackLoaderRule } from './config'
28
28
 
29
29
  interface LoaderFn {
30
- (this: LoaderContext, content: string | Buffer): unknown;
31
- raw?: boolean;
30
+ (this: LoaderContext, content: string | Buffer): unknown
31
+ raw?: boolean
32
32
  }
33
33
 
34
34
  interface LoaderContext {
35
- resourcePath: string;
36
- resourceQuery: string;
37
- mode: string;
35
+ resourcePath: string
36
+ resourceQuery: string
37
+ mode: string
38
38
  fs: {
39
- readFile: typeof readFile;
40
- readFileSync: typeof readFileSync;
41
- };
42
- addDependency: (file: string) => void;
43
- getOptions: () => Record<string, unknown>;
44
- async: () => (err: unknown, result?: unknown) => void;
45
- callback: (err: unknown, result?: unknown, ...rest: unknown[]) => void;
46
- getResolve: (options?: unknown) => (context: string, request: string) => Promise<string>;
47
- emitFile: (name: string, content: unknown) => void;
48
- importModule: (request: string) => Promise<unknown>;
39
+ readFile: typeof readFile
40
+ readFileSync: typeof readFileSync
41
+ }
42
+ addDependency: (file: string) => void
43
+ getOptions: () => Record<string, unknown>
44
+ async: () => (err: unknown, result?: unknown) => void
45
+ callback: (err: unknown, result?: unknown, ...rest: unknown[]) => void
46
+ getResolve: (options?: unknown) => (context: string, request: string) => Promise<string>
47
+ emitFile: (name: string, content: unknown) => void
48
+ importModule: (request: string) => Promise<unknown>
49
49
  }
50
50
 
51
51
  /** Where a loader chain runs — client builds cannot support `this.importModule`. */
52
- type LoaderContextTarget = 'client' | 'server';
52
+ type LoaderContextTarget = 'client' | 'server'
53
53
 
54
- const RESOLVE_EXTENSIONS = ['', '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.json'];
54
+ const RESOLVE_EXTENSIONS = ['', '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.json']
55
55
 
56
56
  function stripLeadingWildcard(glob: string): string {
57
- return glob.startsWith('*') ? glob.slice(1) : glob;
57
+ return glob.startsWith('*') ? glob.slice(1) : glob
58
58
  }
59
59
 
60
60
  function escapeRegExp(value: string): string {
61
- return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
61
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
62
62
  }
63
63
 
64
64
  function ruleMatches(rule: WebpackLoaderRule, filePath: string): boolean {
65
65
  return rule.glob.startsWith('*')
66
66
  ? filePath.endsWith(stripLeadingWildcard(rule.glob))
67
- : path.basename(filePath) === rule.glob;
67
+ : path.basename(filePath) === rule.glob
68
68
  }
69
69
 
70
70
  function conditionMatches(rule: WebpackLoaderRule, resourceQuery: string): boolean {
71
- if (!rule.condition) return true;
72
- const query = rule.condition.query;
73
- return typeof query === 'string' ? resourceQuery === query : query.test(resourceQuery);
71
+ if (!rule.condition) return true
72
+ const query = rule.condition.query
73
+ return typeof query === 'string' ? resourceQuery === query : query.test(resourceQuery)
74
74
  }
75
75
 
76
76
  /** First rule whose glob matches (ignoring any `condition`). */
77
77
  function findRule(rules: WebpackLoaderRule[], filePath: string): WebpackLoaderRule | undefined {
78
- return rules.find(rule => ruleMatches(rule, filePath));
78
+ return rules.find(rule => ruleMatches(rule, filePath))
79
79
  }
80
80
 
81
81
  /** First rule whose glob matches AND whose `condition.query` accepts `resourceQuery`. */
@@ -84,7 +84,7 @@ function findRuleForResource(
84
84
  filePath: string,
85
85
  resourceQuery: string,
86
86
  ): WebpackLoaderRule | undefined {
87
- return rules.find(rule => ruleMatches(rule, filePath) && conditionMatches(rule, resourceQuery));
87
+ return rules.find(rule => ruleMatches(rule, filePath) && conditionMatches(rule, resourceQuery))
88
88
  }
89
89
 
90
90
  /**
@@ -96,8 +96,8 @@ function findRuleForResource(
96
96
  * optional query or hash suffix and strips it here.
97
97
  */
98
98
  export function hasWebpackLoaderRuleFor(filePath: string): boolean {
99
- const [sourcePath = filePath] = filePath.split(/[?#]/, 1);
100
- return findRule(turbopackLoaderRules(), sourcePath) !== undefined;
99
+ const [sourcePath = filePath] = filePath.split(/[?#]/, 1)
100
+ return findRule(turbopackLoaderRules(), sourcePath) !== undefined
101
101
  }
102
102
 
103
103
  /**
@@ -116,25 +116,25 @@ export function webpackLoaderRuleModule(
116
116
  specifier: string,
117
117
  importer: string,
118
118
  ): string | undefined | Promise<string | undefined> {
119
- const rules = turbopackLoaderRules();
120
- if (rules.length === 0) return undefined;
121
- const [base = specifier] = specifier.split(/[?#]/, 1);
122
- const query = specifier.slice(base.length);
123
- const fromDir = path.dirname(originalResourcePath(importer, config));
124
- const resourcePath = resolveSpecifier(config.root, fromDir, base) ?? base;
125
- if (!findRuleForResource(rules, resourcePath, query)) return undefined;
126
- const key = `${resourcePath}\0${query}`;
127
- const existing = ruleModuleArtifacts.get(key);
128
- if (existing) return existing;
119
+ const rules = turbopackLoaderRules()
120
+ if (rules.length === 0) return undefined
121
+ const [base = specifier] = specifier.split(/[?#]/, 1)
122
+ const query = specifier.slice(base.length)
123
+ const fromDir = path.dirname(originalResourcePath(importer, config))
124
+ const resourcePath = resolveSpecifier(config.root, fromDir, base) ?? base
125
+ if (!findRuleForResource(rules, resourcePath, query)) return undefined
126
+ const key = `${resourcePath}\0${query}`
127
+ const existing = ruleModuleArtifacts.get(key)
128
+ if (existing) return existing
129
129
  const built = buildRuleModuleArtifact(config, rules, resourcePath, query).catch(error => {
130
- ruleModuleArtifacts.delete(key);
131
- throw error;
132
- });
133
- ruleModuleArtifacts.set(key, built);
134
- return built;
130
+ ruleModuleArtifacts.delete(key)
131
+ throw error
132
+ })
133
+ ruleModuleArtifacts.set(key, built)
134
+ return built
135
135
  }
136
136
 
137
- const ruleModuleArtifacts = new Map<string, Promise<string | undefined>>();
137
+ const ruleModuleArtifacts = new Map<string, Promise<string | undefined>>()
138
138
 
139
139
  async function buildRuleModuleArtifact(
140
140
  config: ResolvedConfig,
@@ -142,38 +142,43 @@ async function buildRuleModuleArtifact(
142
142
  resourcePath: string,
143
143
  query: string,
144
144
  ): Promise<string | undefined> {
145
- const loaded = await loadRuleModule(config.root, rules, resourcePath, query, 'server', config);
146
- if (!loaded) return undefined;
145
+ const loaded = await loadRuleModule(config.root, rules, resourcePath, query, 'server', config)
146
+ if (!loaded) return undefined
147
147
  // Named by the source name + a hash of (path, query, output): distinct
148
148
  // `?query` imports of one file stay distinct modules, and a re-run that
149
149
  // produces the same text reuses the same artifact.
150
150
  const hash = createHash('sha256')
151
151
  .update(`${resourcePath}\0${query}\0${loaded.contents}`)
152
152
  .digest('hex')
153
- .slice(0, 16);
154
- const name = path.basename(resourcePath).replace(/[^A-Za-z0-9_.-]+/g, '-');
153
+ .slice(0, 16)
154
+ const name = path.basename(resourcePath).replace(/[^A-Za-z0-9_.-]+/g, '-')
155
155
  // The chain's output loader doubles as the artifact extension, so Bun and
156
156
  // esbuild both parse it the way the rule's `as` declared.
157
- const outFile = path.join(config.outPath, 'cache', 'loader-rules', `${name}.${hash}.${loaded.loader}`);
158
- await mkdir(path.dirname(outFile), { recursive: true });
159
- await writeFile(outFile, loaded.contents);
160
- return outFile;
157
+ const outFile = path.join(
158
+ config.outPath,
159
+ 'cache',
160
+ 'loader-rules',
161
+ `${name}.${hash}.${loaded.loader}`,
162
+ )
163
+ await mkdir(path.dirname(outFile), { recursive: true })
164
+ await writeFile(outFile, loaded.contents)
165
+ return outFile
161
166
  }
162
167
 
163
168
  /** esbuild/Bun `loader` for a rule's declared (or inferred) output extension. */
164
169
  function outputLoader(rule: WebpackLoaderRule, resourcePath: string): 'ts' | 'tsx' | 'jsx' {
165
- const ext = (rule.as ? stripLeadingWildcard(rule.as) : path.extname(resourcePath)).toLowerCase();
166
- if (ext.endsWith('.tsx')) return 'tsx';
167
- if (ext.endsWith('.ts')) return 'ts';
168
- return 'jsx';
170
+ const ext = (rule.as ? stripLeadingWildcard(rule.as) : path.extname(resourcePath)).toLowerCase()
171
+ if (ext.endsWith('.tsx')) return 'tsx'
172
+ if (ext.endsWith('.ts')) return 'ts'
173
+ return 'jsx'
169
174
  }
170
175
 
171
176
  function toBuffer(content: string | Buffer): Buffer {
172
- return Buffer.isBuffer(content) ? content : Buffer.from(content, 'utf8');
177
+ return Buffer.isBuffer(content) ? content : Buffer.from(content, 'utf8')
173
178
  }
174
179
 
175
180
  function toStringContent(content: string | Buffer): string {
176
- return Buffer.isBuffer(content) ? content.toString('utf8') : content;
181
+ return Buffer.isBuffer(content) ? content.toString('utf8') : content
177
182
  }
178
183
 
179
184
  // ---------------------------------------------------------------------------
@@ -183,19 +188,19 @@ function toStringContent(content: string | Buffer): string {
183
188
  // Absolute path of pnext's own `src/` (or `dist/` in a built install) — modules
184
189
  // under it are framework runtime, not app code, and are exempt from user
185
190
  // `resolveAlias`/`resolve.alias` entries.
186
- const PNEXT_RUNTIME_ROOT = path.resolve(import.meta.dirname, '../..');
191
+ const PNEXT_RUNTIME_ROOT = path.resolve(import.meta.dirname, '../..')
187
192
 
188
193
  function isPNextRuntimeImporter(importer: string): boolean {
189
- if (!importer) return false;
190
- const rel = path.relative(PNEXT_RUNTIME_ROOT, importer);
191
- return Boolean(rel) && !rel.startsWith('..') && !path.isAbsolute(rel);
194
+ if (!importer) return false
195
+ const rel = path.relative(PNEXT_RUNTIME_ROOT, importer)
196
+ return Boolean(rel) && !rel.startsWith('..') && !path.isAbsolute(rel)
192
197
  }
193
198
 
194
199
  function firstExisting(base: string): string | undefined {
195
200
  for (const ext of RESOLVE_EXTENSIONS) {
196
- if (existsSync(base + ext)) return base + ext;
201
+ if (existsSync(base + ext)) return base + ext
197
202
  }
198
- return undefined;
203
+ return undefined
199
204
  }
200
205
 
201
206
  /**
@@ -205,23 +210,25 @@ function firstExisting(base: string): string | undefined {
205
210
  function resolveAliasSpecifier(specifier: string, root: string): string | undefined {
206
211
  for (const [key, target] of Object.entries(turbopackResolveAlias())) {
207
212
  if (key.endsWith('/*')) {
208
- const prefix = key.slice(0, -1); // e.g. '@/*' -> '@/'
213
+ const prefix = key.slice(0, -1) // e.g. '@/*' -> '@/'
209
214
  if (specifier.startsWith(prefix)) {
210
- const rest = specifier.slice(prefix.length);
211
- const mapped = target.endsWith('/*') ? target.slice(0, -1) + rest : target.replace('*', rest);
212
- return resolveAliasTarget(mapped, root);
215
+ const rest = specifier.slice(prefix.length)
216
+ const mapped = target.endsWith('/*')
217
+ ? target.slice(0, -1) + rest
218
+ : target.replace('*', rest)
219
+ return resolveAliasTarget(mapped, root)
213
220
  }
214
221
  } else if (specifier === key) {
215
- return resolveAliasTarget(target, root);
222
+ return resolveAliasTarget(target, root)
216
223
  }
217
224
  }
218
- return undefined;
225
+ return undefined
219
226
  }
220
227
 
221
228
  function resolveAliasTarget(target: string, root: string): string {
222
- if (path.isAbsolute(target)) return target;
223
- if (target.startsWith('.')) return path.resolve(root, target);
224
- return target;
229
+ if (path.isAbsolute(target)) return target
230
+ if (target.startsWith('.')) return path.resolve(root, target)
231
+ return target
225
232
  }
226
233
 
227
234
  /**
@@ -230,14 +237,14 @@ function resolveAliasTarget(target: string, root: string): string {
230
237
  * resolver.
231
238
  */
232
239
  function resolveSpecifier(root: string, fromDir: string, specifier: string): string | undefined {
233
- const aliased = resolveAliasSpecifier(specifier, root);
234
- if (aliased) return firstExisting(aliased) ?? aliased;
235
- if (path.isAbsolute(specifier)) return firstExisting(specifier) ?? specifier;
240
+ const aliased = resolveAliasSpecifier(specifier, root)
241
+ if (aliased) return firstExisting(aliased) ?? aliased
242
+ if (path.isAbsolute(specifier)) return firstExisting(specifier) ?? specifier
236
243
  if (specifier.startsWith('.')) {
237
- const base = path.resolve(fromDir, specifier);
238
- return firstExisting(base) ?? base;
244
+ const base = path.resolve(fromDir, specifier)
245
+ return firstExisting(base) ?? base
239
246
  }
240
- return undefined;
247
+ return undefined
241
248
  }
242
249
 
243
250
  /**
@@ -251,28 +258,28 @@ function resolveSpecifier(root: string, fromDir: string, specifier: string): str
251
258
  * are left alone - those resolve natively.
252
259
  */
253
260
  export function rewriteResolveAliasImports(source: string, file: string, root: string): string {
254
- const aliases = turbopackResolveAlias();
255
- if (Object.keys(aliases).length === 0) return source;
261
+ const aliases = turbopackResolveAlias()
262
+ if (Object.keys(aliases).length === 0) return source
256
263
  return rewriteSpecifierLiterals(source, file, (specifier, kind) => {
257
264
  // Same scope as the `from`-anchored regex this replaced: side-effect
258
265
  // imports stay with the host resolver.
259
- if (kind === 'side-effect') return undefined;
260
- if (specifier.startsWith('.') || path.isAbsolute(specifier)) return undefined;
261
- const aliased = resolveAliasSpecifier(specifier, root);
262
- if (!aliased) return undefined;
263
- const target = firstExisting(aliased) ?? aliased;
266
+ if (kind === 'side-effect') return undefined
267
+ if (specifier.startsWith('.') || path.isAbsolute(specifier)) return undefined
268
+ const aliased = resolveAliasSpecifier(specifier, root)
269
+ if (!aliased) return undefined
270
+ const target = firstExisting(aliased) ?? aliased
264
271
  // A bare alias target (e.g. `'preact/compat': 'react'`) is not a file path;
265
272
  // leave the host resolver to handle it.
266
- if (!path.isAbsolute(target)) return undefined;
267
- return JSON.stringify(target);
268
- });
273
+ if (!path.isAbsolute(target)) return undefined
274
+ return JSON.stringify(target)
275
+ })
269
276
  }
270
277
 
271
278
  /** `this.getResolve()(context, request)` — alias-aware, extension-probing. */
272
279
  function resolveLoaderRequest(root: string, context: string, request: string): Promise<string> {
273
- const resolved = resolveSpecifier(root, context, request);
274
- if (resolved && existsSync(resolved)) return Promise.resolve(resolved);
275
- return Promise.reject(new Error(`Cannot resolve '${request}' from '${context}'`));
280
+ const resolved = resolveSpecifier(root, context, request)
281
+ if (resolved && existsSync(resolved)) return Promise.resolve(resolved)
282
+ return Promise.reject(new Error(`Cannot resolve '${request}' from '${context}'`))
276
283
  }
277
284
 
278
285
  /**
@@ -286,19 +293,19 @@ function resolveLoaderRequest(root: string, context: string, request: string): P
286
293
  */
287
294
  function originalResourcePath(resourcePath: string, config: ResolvedConfig | undefined): string {
288
295
  if (config) {
289
- const cacheRoot = path.join(config.outPath, 'cache', 'server');
290
- const rel = path.relative(cacheRoot, resourcePath);
296
+ const cacheRoot = path.join(config.outPath, 'cache', 'server')
297
+ const rel = path.relative(cacheRoot, resourcePath)
291
298
  if (rel && !rel.startsWith('..') && !path.isAbsolute(rel)) {
292
- const segments = rel.split(path.sep);
293
- segments.shift(); // drop <profileDir>
294
- const original = path.join(config.workspaceRoot, ...segments);
295
- if (existsSync(original)) return original;
299
+ const segments = rel.split(path.sep)
300
+ segments.shift() // drop <profileDir>
301
+ const original = path.join(config.workspaceRoot, ...segments)
302
+ if (existsSync(original)) return original
296
303
  }
297
304
  }
298
305
  try {
299
- return realpathSync(resourcePath);
306
+ return realpathSync(resourcePath)
300
307
  } catch {
301
- return resourcePath;
308
+ return resourcePath
302
309
  }
303
310
  }
304
311
 
@@ -318,12 +325,12 @@ async function importModuleFor(
318
325
  request: string,
319
326
  config: ResolvedConfig | undefined,
320
327
  ): Promise<unknown> {
321
- if (config) registerWebpackLoaderRuleRuntime(config);
322
- const resolved = resolveSpecifier(root, path.dirname(resourcePath), request);
328
+ if (config) registerWebpackLoaderRuleRuntime(config)
329
+ const resolved = resolveSpecifier(root, path.dirname(resourcePath), request)
323
330
  if (!resolved) {
324
- throw new Error(`this.importModule: cannot resolve '${request}' from '${resourcePath}'`);
331
+ throw new Error(`this.importModule: cannot resolve '${request}' from '${resourcePath}'`)
325
332
  }
326
- return import(pathToFileURL(resolved).href);
333
+ return import(pathToFileURL(resolved).href)
327
334
  }
328
335
 
329
336
  // ---------------------------------------------------------------------------
@@ -341,13 +348,13 @@ function runLoader(
341
348
  config: ResolvedConfig | undefined,
342
349
  ): Promise<string | Buffer> {
343
350
  return new Promise((resolve, reject) => {
344
- let settled = false;
351
+ let settled = false
345
352
  const finish = (err: unknown, result?: unknown) => {
346
- if (settled) return;
347
- settled = true;
348
- if (err) reject(err instanceof Error ? err : new Error(JSON.stringify(err)));
349
- else resolve(result as string | Buffer);
350
- };
353
+ if (settled) return
354
+ settled = true
355
+ if (err) reject(err instanceof Error ? err : new Error(JSON.stringify(err)))
356
+ else resolve(result as string | Buffer)
357
+ }
351
358
  const ctx: LoaderContext = {
352
359
  resourcePath,
353
360
  resourceQuery,
@@ -358,7 +365,8 @@ function runLoader(
358
365
  getOptions: () => ({}),
359
366
  async: () => finish,
360
367
  callback: finish,
361
- getResolve: () => (context: string, request: string) => resolveLoaderRequest(root, context, request),
368
+ getResolve: () => (context: string, request: string) =>
369
+ resolveLoaderRequest(root, context, request),
362
370
  // eslint-disable-next-line @typescript-eslint/no-empty-function -- emitted files aren't tracked
363
371
  emitFile: () => {},
364
372
  importModule:
@@ -368,26 +376,27 @@ function runLoader(
368
376
  Promise.reject(
369
377
  new Error('this.importModule() is not supported in the client build context'),
370
378
  ),
371
- };
379
+ }
372
380
  try {
373
- const result = fn.call(ctx, input);
374
- if (result === undefined) return; // loader signaled async via this.async()/this.callback()
381
+ const result = fn.call(ctx, input)
382
+ if (result === undefined) return // loader signaled async via this.async()/this.callback()
375
383
  if (result && typeof (result as Promise<unknown>).then === 'function') {
376
- (result as Promise<unknown>).then(value => finish(null, value), finish);
384
+ ;(result as Promise<unknown>).then(value => finish(null, value), finish)
377
385
  } else {
378
- finish(null, result);
386
+ finish(null, result)
379
387
  }
380
388
  } catch (error) {
381
- finish(error);
389
+ finish(error)
382
390
  }
383
- });
391
+ })
384
392
  }
385
393
 
386
394
  function resolveLoaderExport(mod: unknown): LoaderFn {
387
- if (typeof mod === 'function') return mod as LoaderFn;
388
- const withDefault = mod as { default?: unknown } | null | undefined;
389
- if (withDefault && typeof withDefault.default === 'function') return withDefault.default as LoaderFn;
390
- return mod as LoaderFn;
395
+ if (typeof mod === 'function') return mod as LoaderFn
396
+ const withDefault = mod as { default?: unknown } | null | undefined
397
+ if (withDefault && typeof withDefault.default === 'function')
398
+ return withDefault.default as LoaderFn
399
+ return mod as LoaderFn
391
400
  }
392
401
 
393
402
  // A loader commonly returns CJS-style source on the assumption webpack's CJS/ESM interop will bind a
@@ -395,8 +404,8 @@ function resolveLoaderExport(mod: unknown): LoaderFn {
395
404
  // for the runtime's per-file SSR loading - does not synthesize a default export from a bare
396
405
  // `module.exports` assignment, so normalize to a real ESM default export.
397
406
  function normalizeToEsmDefault(contents: string): string {
398
- const match = /^\s*module\.exports\s*=\s*([\s\S]*?);?\s*$/.exec(contents);
399
- return match ? `export default (${match[1]});` : contents;
407
+ const match = /^\s*module\.exports\s*=\s*([\s\S]*?);?\s*$/.exec(contents)
408
+ return match ? `export default (${match[1]});` : contents
400
409
  }
401
410
 
402
411
  export async function runLoaderChain(
@@ -407,21 +416,23 @@ export async function runLoaderChain(
407
416
  target: LoaderContextTarget,
408
417
  config: ResolvedConfig | undefined,
409
418
  ): Promise<string> {
410
- const requireFromRoot = createRequire(path.join(root, 'noop-require.cjs'));
419
+ const requireFromRoot = createRequire(path.join(root, 'noop-require.cjs'))
411
420
  // esbuild loads the materialized copy, but the loader context (`this.resourcePath`
412
421
  // and the base dir for relative `importModule`/`getResolve`) must point at the
413
422
  // original source so sibling modules resolve. Reading the materialized copy
414
423
  // yields identical bytes.
415
- const contextPath = originalResourcePath(resourcePath, config);
416
- let content: string | Buffer = await readFileP(resourcePath);
424
+ const contextPath = originalResourcePath(resourcePath, config)
425
+ let content: string | Buffer = await readFileP(resourcePath)
417
426
  for (const specifier of rule.loaders) {
418
- const resolvedSpecifier = path.isAbsolute(specifier) ? specifier : requireFromRoot.resolve(specifier);
419
- const mod: unknown = requireFromRoot(resolvedSpecifier);
420
- const fn = resolveLoaderExport(mod);
421
- const input = fn.raw ? toBuffer(content) : toStringContent(content);
422
- content = await runLoader(fn, root, contextPath, resourceQuery, input, target, config);
427
+ const resolvedSpecifier = path.isAbsolute(specifier)
428
+ ? specifier
429
+ : requireFromRoot.resolve(specifier)
430
+ const mod: unknown = requireFromRoot(resolvedSpecifier)
431
+ const fn = resolveLoaderExport(mod)
432
+ const input = fn.raw ? toBuffer(content) : toStringContent(content)
433
+ content = await runLoader(fn, root, contextPath, resourceQuery, input, target, config)
423
434
  }
424
- return normalizeToEsmDefault(toStringContent(content));
435
+ return normalizeToEsmDefault(toStringContent(content))
425
436
  }
426
437
 
427
438
  // ---------------------------------------------------------------------------
@@ -434,15 +445,17 @@ async function emitAssetResourceModule(
434
445
  resourcePath: string,
435
446
  bytes: Uint8Array,
436
447
  ): Promise<string> {
437
- const ext = path.extname(resourcePath).toLowerCase() || '.bin';
438
- const hash = createHash('sha256').update(bytes).digest('hex').slice(0, 8);
439
- const base = path.basename(resourcePath, path.extname(resourcePath)).replace(/[^A-Za-z0-9_-]+/g, '-');
440
- const relative = path.posix.join('_next', 'static', 'media', `${base}.${hash}${ext}`);
441
- const target = path.join(config.outPath, 'public', ...relative.split('/'));
442
- await mkdir(path.dirname(target), { recursive: true });
443
- if (!existsSync(target)) await writeFile(target, bytes);
444
- const src = `/${relative}`;
445
- return `const src = ${JSON.stringify(src)};\nexport default src;\nexport { src };\n`;
448
+ const ext = path.extname(resourcePath).toLowerCase() || '.bin'
449
+ const hash = createHash('sha256').update(bytes).digest('hex').slice(0, 8)
450
+ const base = path
451
+ .basename(resourcePath, path.extname(resourcePath))
452
+ .replace(/[^A-Za-z0-9_-]+/g, '-')
453
+ const relative = path.posix.join('_next', 'static', 'media', `${base}.${hash}${ext}`)
454
+ const target = path.join(config.outPath, 'public', ...relative.split('/'))
455
+ await mkdir(path.dirname(target), { recursive: true })
456
+ if (!existsSync(target)) await writeFile(target, bytes)
457
+ const src = `/${relative}`
458
+ return `const src = ${JSON.stringify(src)};\nexport default src;\nexport { src };\n`
446
459
  }
447
460
 
448
461
  async function loadTypeAssetModule(
@@ -450,17 +463,17 @@ async function loadTypeAssetModule(
450
463
  resourcePath: string,
451
464
  config: ResolvedConfig | undefined,
452
465
  ): Promise<string> {
453
- const bytes = new Uint8Array(await readFileP(resourcePath));
466
+ const bytes = new Uint8Array(await readFileP(resourcePath))
454
467
  if (rule.assetType === 'bytes') {
455
- return `export default new Uint8Array(${JSON.stringify(Array.from(bytes))});`;
468
+ return `export default new Uint8Array(${JSON.stringify(Array.from(bytes))});`
456
469
  }
457
470
  if (rule.assetType === 'source') {
458
- return `export default ${JSON.stringify(Buffer.from(bytes).toString('utf8'))};`;
471
+ return `export default ${JSON.stringify(Buffer.from(bytes).toString('utf8'))};`
459
472
  }
460
473
  // asset/resource — needs a config to know the output tree; without one, fall
461
474
  // back to exporting the basename so a build still resolves the import.
462
- if (config) return emitAssetResourceModule(config, resourcePath, bytes);
463
- return `export default ${JSON.stringify(`/${path.basename(resourcePath)}`)};`;
475
+ if (config) return emitAssetResourceModule(config, resourcePath, bytes)
476
+ return `export default ${JSON.stringify(`/${path.basename(resourcePath)}`)};`
464
477
  }
465
478
 
466
479
  // ---------------------------------------------------------------------------
@@ -468,8 +481,8 @@ async function loadTypeAssetModule(
468
481
  // ---------------------------------------------------------------------------
469
482
 
470
483
  interface LoadedRuleModule {
471
- contents: string;
472
- loader: 'ts' | 'tsx' | 'jsx' | 'js';
484
+ contents: string
485
+ loader: 'ts' | 'tsx' | 'jsx' | 'js'
473
486
  }
474
487
 
475
488
  async function loadRuleModule(
@@ -480,13 +493,13 @@ async function loadRuleModule(
480
493
  target: LoaderContextTarget,
481
494
  config: ResolvedConfig | undefined,
482
495
  ): Promise<LoadedRuleModule | undefined> {
483
- const rule = findRuleForResource(rules, resourcePath, resourceQuery);
484
- if (!rule) return undefined;
496
+ const rule = findRuleForResource(rules, resourcePath, resourceQuery)
497
+ if (!rule) return undefined
485
498
  if (rule.assetType) {
486
- return { contents: await loadTypeAssetModule(rule, resourcePath, config), loader: 'js' };
499
+ return { contents: await loadTypeAssetModule(rule, resourcePath, config), loader: 'js' }
487
500
  }
488
- const contents = await runLoaderChain(root, rule, resourcePath, resourceQuery, target, config);
489
- return { contents, loader: outputLoader(rule, resourcePath) };
501
+ const contents = await runLoaderChain(root, rule, resourcePath, resourceQuery, target, config)
502
+ return { contents, loader: outputLoader(rule, resourcePath) }
490
503
  }
491
504
 
492
505
  function ruleSuffixFilter(rules: WebpackLoaderRule[]): RegExp | undefined {
@@ -494,26 +507,26 @@ function ruleSuffixFilter(rules: WebpackLoaderRule[]): RegExp | undefined {
494
507
  ...new Set(
495
508
  rules.filter(rule => rule.glob.startsWith('*')).map(rule => stripLeadingWildcard(rule.glob)),
496
509
  ),
497
- ];
498
- if (suffixes.length === 0) return undefined;
499
- return new RegExp(`(?:${suffixes.map(escapeRegExp).join('|')})$`);
510
+ ]
511
+ if (suffixes.length === 0) return undefined
512
+ return new RegExp(`(?:${suffixes.map(escapeRegExp).join('|')})$`)
500
513
  }
501
514
 
502
515
  /** Build the alias-key onResolve filter (exact keys + trailing-`/*` prefixes). */
503
516
  function aliasSpecifierFilter(): RegExp | undefined {
504
- const keys = Object.keys(turbopackResolveAlias());
505
- if (keys.length === 0) return undefined;
517
+ const keys = Object.keys(turbopackResolveAlias())
518
+ if (keys.length === 0) return undefined
506
519
  const alternatives = keys.map(key =>
507
520
  key.endsWith('/*') ? escapeRegExp(key.slice(0, -1)) : `${escapeRegExp(key)}$`,
508
- );
509
- return new RegExp(`^(?:${alternatives.join('|')})`);
521
+ )
522
+ return new RegExp(`^(?:${alternatives.join('|')})`)
510
523
  }
511
524
 
512
525
  // A null byte separates a virtual query module's real path from its threaded
513
526
  // resourceQuery (real paths never contain a null byte); used for the Bun
514
527
  // runtime namespace so two `?query` imports of one file stay distinct modules.
515
- const QUERY_SEPARATOR = '\0';
516
- const QUERY_NAMESPACE = 'pnext-webpack-loader-query';
528
+ const QUERY_SEPARATOR = '\0'
529
+ const QUERY_NAMESPACE = 'pnext-webpack-loader-query'
517
530
 
518
531
  /**
519
532
  * esbuild plugin applying configured `turbopack.rules` loader chains (plus
@@ -524,10 +537,10 @@ export function webpackLoaderRulesPlugin(
524
537
  config: ResolvedConfig,
525
538
  target: LoaderContextTarget,
526
539
  ): Plugin | undefined {
527
- const rules = turbopackLoaderRules();
528
- const filter = ruleSuffixFilter(rules);
529
- const aliasFilter = aliasSpecifierFilter();
530
- if (!filter && !aliasFilter) return undefined;
540
+ const rules = turbopackLoaderRules()
541
+ const filter = ruleSuffixFilter(rules)
542
+ const aliasFilter = aliasSpecifierFilter()
543
+ if (!filter && !aliasFilter) return undefined
531
544
  return {
532
545
  name: 'pnext-compat-webpack-loader-rules',
533
546
  setup(build) {
@@ -536,44 +549,44 @@ export function webpackLoaderRulesPlugin(
536
549
  // `suffix` so the two `?query` imports of one file stay distinct modules.
537
550
  if (filter) {
538
551
  build.onResolve({ filter: /\?/ }, args => {
539
- const queryIndex = args.path.indexOf('?');
540
- if (queryIndex === -1) return undefined;
541
- const base = args.path.slice(0, queryIndex);
542
- const query = args.path.slice(queryIndex);
543
- const resolved = resolveSpecifier(config.root, args.resolveDir, base);
544
- if (!resolved || !findRule(rules, resolved)) return undefined;
545
- return { path: resolved, suffix: query };
546
- });
552
+ const queryIndex = args.path.indexOf('?')
553
+ if (queryIndex === -1) return undefined
554
+ const base = args.path.slice(0, queryIndex)
555
+ const query = args.path.slice(queryIndex)
556
+ const resolved = resolveSpecifier(config.root, args.resolveDir, base)
557
+ if (!resolved || !findRule(rules, resolved)) return undefined
558
+ return { path: resolved, suffix: query }
559
+ })
547
560
  }
548
561
  // `resolveAlias` specifier rewrites (without a query — query handled above).
549
562
  if (aliasFilter) {
550
563
  build.onResolve({ filter: aliasFilter }, async args => {
551
- if (args.path.includes('?')) return undefined;
564
+ if (args.path.includes('?')) return undefined
552
565
  // A user alias describes the APP's module graph. pnext's own runtime imports preact/compat to
553
566
  // build the react shim, so a config alias redirecting preact/compat to react points the shim
554
567
  // at the module pnext maps back to the shim - a self-import that throws on client bundle
555
568
  // init, killing all client JS. Framework modules resolve unaliased.
556
- if (isPNextRuntimeImporter(args.importer)) return undefined;
557
- const resolved = resolveAliasSpecifier(args.path, config.root);
558
- if (!resolved) return undefined;
559
- const target = firstExisting(resolved) ?? resolved;
569
+ if (isPNextRuntimeImporter(args.importer)) return undefined
570
+ const resolved = resolveAliasSpecifier(args.path, config.root)
571
+ if (!resolved) return undefined
572
+ const target = firstExisting(resolved) ?? resolved
560
573
  // A bare alias target (e.g. `'preact/compat': 'react'`) is not a
561
574
  // file path — hand it back to esbuild's own resolver.
562
575
  if (!path.isAbsolute(target)) {
563
- if (target === args.path) return undefined;
576
+ if (target === args.path) return undefined
564
577
  return build.resolve(target, {
565
578
  resolveDir: args.resolveDir,
566
579
  kind: args.kind,
567
580
  importer: args.importer,
568
- });
581
+ })
569
582
  }
570
- return { path: target };
571
- });
583
+ return { path: target }
584
+ })
572
585
  }
573
586
  if (filter) {
574
587
  build.onLoad({ filter, namespace: 'file' }, async args => {
575
- const resourcePath = path.resolve(args.path);
576
- const resourceQuery = args.suffix ?? '';
588
+ const resourcePath = path.resolve(args.path)
589
+ const resourceQuery = args.suffix ?? ''
577
590
  try {
578
591
  const loaded = await loadRuleModule(
579
592
  config.root,
@@ -582,18 +595,18 @@ export function webpackLoaderRulesPlugin(
582
595
  resourceQuery,
583
596
  target,
584
597
  config,
585
- );
586
- return loaded ?? undefined;
598
+ )
599
+ return loaded ?? undefined
587
600
  } catch (error) {
588
- return { errors: [{ text: error instanceof Error ? error.message : String(error) }] };
601
+ return { errors: [{ text: error instanceof Error ? error.message : String(error) }] }
589
602
  }
590
- });
603
+ })
591
604
  }
592
605
  },
593
- };
606
+ }
594
607
  }
595
608
 
596
- const runtimeRegisteredRoots = new Set<string>();
609
+ const runtimeRegisteredRoots = new Set<string>()
597
610
 
598
611
  /**
599
612
  * Registers a Bun.plugin hook applying `turbopack.rules` loader chains (plus resolveAlias and query
@@ -601,16 +614,16 @@ const runtimeRegisteredRoots = new Set<string>();
601
614
  * esbuild build() pass. Idempotent per project root; a no-op when nothing is configured.
602
615
  */
603
616
  export function registerWebpackLoaderRuleRuntime(config: ResolvedConfig): void {
604
- const rules = turbopackLoaderRules();
605
- const suffixFilter = ruleSuffixFilter(rules);
606
- const aliasFilter = aliasSpecifierFilter();
607
- if (!suffixFilter && !aliasFilter) return;
608
- const root = path.resolve(config.root);
609
- if (runtimeRegisteredRoots.has(root)) return;
610
- runtimeRegisteredRoots.add(root);
617
+ const rules = turbopackLoaderRules()
618
+ const suffixFilter = ruleSuffixFilter(rules)
619
+ const aliasFilter = aliasSpecifierFilter()
620
+ if (!suffixFilter && !aliasFilter) return
621
+ const root = path.resolve(config.root)
622
+ if (runtimeRegisteredRoots.has(root)) return
623
+ runtimeRegisteredRoots.add(root)
611
624
  const ruleFileFilter = suffixFilter
612
625
  ? new RegExp(`^${escapeRegExp(root)}(?:/.*)?${suffixFilter.source}`)
613
- : undefined;
626
+ : undefined
614
627
  Bun.plugin({
615
628
  name: `pnext-compat-webpack-loader-runtime-${root}`,
616
629
  setup(plugin) {
@@ -620,47 +633,47 @@ export function registerWebpackLoaderRuleRuntime(config: ResolvedConfig): void {
620
633
  // path). The onLoad below reads the query back off the path.
621
634
  if (suffixFilter) {
622
635
  plugin.onResolve({ filter: /\?/ }, args => {
623
- const queryIndex = args.path.indexOf('?');
624
- if (queryIndex === -1) return undefined;
625
- const base = args.path.slice(0, queryIndex);
626
- const query = args.path.slice(queryIndex);
627
- const fromDir = args.importer ? path.dirname(args.importer) : root;
628
- const resolved = resolveSpecifier(root, fromDir, base);
629
- if (!resolved || !findRule(rules, resolved)) return undefined;
630
- return { path: `${resolved}${QUERY_SEPARATOR}${query}`, namespace: QUERY_NAMESPACE };
631
- });
636
+ const queryIndex = args.path.indexOf('?')
637
+ if (queryIndex === -1) return undefined
638
+ const base = args.path.slice(0, queryIndex)
639
+ const query = args.path.slice(queryIndex)
640
+ const fromDir = args.importer ? path.dirname(args.importer) : root
641
+ const resolved = resolveSpecifier(root, fromDir, base)
642
+ if (!resolved || !findRule(rules, resolved)) return undefined
643
+ return { path: `${resolved}${QUERY_SEPARATOR}${query}`, namespace: QUERY_NAMESPACE }
644
+ })
632
645
  }
633
646
  // `resolveAlias` specifier rewrites (without a query — query handled above).
634
647
  if (aliasFilter) {
635
648
  plugin.onResolve({ filter: aliasFilter }, args => {
636
- if (args.path.includes('?')) return undefined;
649
+ if (args.path.includes('?')) return undefined
637
650
  // See the build-time alias hook: pnext's own runtime graph is exempt
638
651
  // from user aliases, or the react shim self-imports.
639
- if (isPNextRuntimeImporter(args.importer)) return undefined;
640
- const resolved = resolveAliasSpecifier(args.path, root);
641
- if (!resolved) return undefined;
642
- const target = firstExisting(resolved) ?? resolved;
652
+ if (isPNextRuntimeImporter(args.importer)) return undefined
653
+ const resolved = resolveAliasSpecifier(args.path, root)
654
+ if (!resolved) return undefined
655
+ const target = firstExisting(resolved) ?? resolved
643
656
  // Bare alias target: resolve through Bun's resolver relative to the
644
657
  // importer so a specifier like 'react' becomes a real file path.
645
658
  if (!path.isAbsolute(target)) {
646
- if (target === args.path) return undefined;
647
- const fromDir = args.importer ? path.dirname(args.importer) : root;
659
+ if (target === args.path) return undefined
660
+ const fromDir = args.importer ? path.dirname(args.importer) : root
648
661
  try {
649
- return { path: Bun.resolveSync(target, fromDir) };
662
+ return { path: Bun.resolveSync(target, fromDir) }
650
663
  } catch {
651
- return undefined;
664
+ return undefined
652
665
  }
653
666
  }
654
- return { path: target };
655
- });
667
+ return { path: target }
668
+ })
656
669
  }
657
670
  plugin.onLoad({ filter: /.*/, namespace: QUERY_NAMESPACE }, async ({ path: virtualPath }) => {
658
- const sep = virtualPath.indexOf(QUERY_SEPARATOR);
659
- const realPath = sep === -1 ? virtualPath : virtualPath.slice(0, sep);
660
- const resourceQuery = sep === -1 ? '' : virtualPath.slice(sep + 1);
661
- const loaded = await loadRuleModule(root, rules, realPath, resourceQuery, 'server', config);
662
- return loaded ?? { contents: await readFileP(realPath, 'utf8'), loader: 'text' };
663
- });
671
+ const sep = virtualPath.indexOf(QUERY_SEPARATOR)
672
+ const realPath = sep === -1 ? virtualPath : virtualPath.slice(0, sep)
673
+ const resourceQuery = sep === -1 ? '' : virtualPath.slice(sep + 1)
674
+ const loaded = await loadRuleModule(root, rules, realPath, resourceQuery, 'server', config)
675
+ return loaded ?? { contents: await readFileP(realPath, 'utf8'), loader: 'text' }
676
+ })
664
677
  // `.mjs` sources are NOT claimed by core's runtime load hook (its filter is `[jt]sx?`), so they
665
678
  // never see the registered server source transforms - including the resolveAlias rewrite. Bun then
666
679
  // resolves their bare imports natively and an aliased specifier throws, since its onResolve hook is
@@ -668,18 +681,18 @@ export function registerWebpackLoaderRuleRuntime(config: ResolvedConfig): void {
668
681
  // the hook always hands the source back. Kept synchronous, and `.cjs` deliberately left out: an
669
682
  // onLoad hook turns the module async, which breaks require() of the materialized next.config.
670
683
  if (aliasFilter) {
671
- const esmFilter = new RegExp(`^${escapeRegExp(root)}(?!.*/node_modules/)(?:/.*)?\\.mjs$`);
684
+ const esmFilter = new RegExp(`^${escapeRegExp(root)}(?!.*/node_modules/)(?:/.*)?\\.mjs$`)
672
685
  plugin.onLoad({ filter: esmFilter }, ({ path: file }) => ({
673
686
  contents: rewriteResolveAliasImports(readFileSync(file, 'utf8'), file, root),
674
687
  loader: 'js',
675
- }));
688
+ }))
676
689
  }
677
690
  if (ruleFileFilter) {
678
691
  plugin.onLoad({ filter: ruleFileFilter }, async ({ path: file }) => {
679
- const loaded = await loadRuleModule(root, rules, path.resolve(file), '', 'server', config);
680
- return loaded ?? { contents: await readFileP(file, 'utf8'), loader: 'text' };
681
- });
692
+ const loaded = await loadRuleModule(root, rules, path.resolve(file), '', 'server', config)
693
+ return loaded ?? { contents: await readFileP(file, 'utf8'), loader: 'text' }
694
+ })
682
695
  }
683
696
  },
684
- });
697
+ })
685
698
  }