@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,13 +1,13 @@
1
- import { createHash } from 'node:crypto';
2
- import { readFileSync, readdirSync, statSync, type Dirent } from 'node:fs';
3
- import path from 'node:path';
4
- import { build, type BuildOptions, type Metafile, type Plugin } from 'esbuild';
5
- import type { ResolvedConfig } from '../config';
6
- import { getImportAliasExtensions } from '../extensions';
7
- import { scanFacts } from '../resolve/scan-facts';
8
- import { ensureDir, writeText } from '../utils/fs';
9
- import { escapeRegex } from '../utils/source';
10
- import { CLIENT_RUNTIME_MODULE } from './entry';
1
+ import { createHash } from 'node:crypto'
2
+ import { readFileSync, readdirSync, statSync, type Dirent } from 'node:fs'
3
+ import path from 'node:path'
4
+ import { build, type BuildOptions, type Metafile, type Plugin } from 'esbuild'
5
+ import type { ResolvedConfig } from '../config'
6
+ import { getImportAliasExtensions } from '../extensions'
7
+ import { scanFacts } from '../resolve/scan-facts'
8
+ import { ensureDir, writeText } from '../utils/fs'
9
+ import { escapeRegex } from '../utils/code'
10
+ import { CLIENT_RUNTIME_MODULE } from './entry'
11
11
 
12
12
  /**
13
13
  * The route-independent half of every client bundle - pnext's own client runtime, the compat
@@ -22,29 +22,29 @@ import { CLIENT_RUNTIME_MODULE } from './entry';
22
22
  */
23
23
  export interface PrebuiltRuntime {
24
24
  /** Content address of (framework source × alias set × build options). */
25
- key: string;
25
+ key: string
26
26
  /** Directory holding the artifact. */
27
- dir: string;
27
+ dir: string
28
28
  /** URL prefix route entries import the artifact from — the SERVED url. */
29
- publicPath: string;
29
+ publicPath: string
30
30
  /**
31
31
  * The same directory as an `assets/…` path, for the preload bookkeeping that
32
32
  * speaks in app-relative asset names rather than urls.
33
33
  */
34
- assetPath: string;
34
+ assetPath: string
35
35
  /** specifier → every export name that module has (learned by a probe build). */
36
- exports: Map<string, string[]>;
36
+ exports: Map<string, string[]>
37
37
  /** specifier → the export names route entries actually bind. What ships. */
38
- surface: Map<string, Set<string>>;
38
+ surface: Map<string, Set<string>>
39
39
  /** Artifact files statically reachable from the aggregate, relative to it. */
40
- closure: { static: string[]; dynamic: string[] };
40
+ closure: { static: string[]; dynamic: string[] }
41
41
  }
42
42
 
43
43
  /** The aggregate's file name inside the artifact dir. */
44
- export const PREBUILT_MODULE = 'pnext-runtime.js';
44
+ export const PREBUILT_MODULE = 'pnext-runtime.js'
45
45
 
46
46
  /** Framework source root — anything resolving inside it is route-independent. */
47
- const frameworkSrc = path.resolve(import.meta.dirname, '..');
47
+ const frameworkSrc = path.resolve(import.meta.dirname, '..')
48
48
 
49
49
  /**
50
50
  * The vendor half of the surface. Single-instance modules (context identity,
@@ -58,7 +58,7 @@ const vendorSpecifiers = [
58
58
  'preact/compat/client',
59
59
  'preact/jsx-runtime',
60
60
  'preact/jsx-dev-runtime',
61
- ];
61
+ ]
62
62
 
63
63
  /**
64
64
  * The react-compat aliases seed the artifact alongside the vendors: their targets are `export *`
@@ -66,37 +66,37 @@ const vendorSpecifiers = [
66
66
  * preact/compat's WHOLE surface. Everything else is discovered lazily - a leaf compat module
67
67
  * bundled once costs only what its importer named.
68
68
  */
69
- const reactAliasSpecifier = /^react(?:-dom)?(?:\/|$)/;
69
+ const reactAliasSpecifier = /^react(?:-dom)?(?:\/|$)/
70
70
 
71
71
  /**
72
72
  * The React Compiler's runtime is resolved per build (and asserted on in the
73
73
  * route bundle), so it stays out of the artifact.
74
74
  */
75
- const isCompilerRuntime = (specifier: string) => specifier.endsWith('compiler-runtime');
75
+ const isCompilerRuntime = (specifier: string) => specifier.endsWith('compiler-runtime')
76
76
 
77
- const identifier = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
77
+ const identifier = /^[A-Za-z_$][A-Za-z0-9_$]*$/
78
78
 
79
79
  /** (specifier, export name) → one collision-free identifier in the aggregate. */
80
80
  export function mangledName(specifier: string, name: string) {
81
- return `__p_${shortHash(specifier)}_${name}`;
81
+ return `__p_${shortHash(specifier)}_${name}`
82
82
  }
83
83
 
84
84
  function shortHash(value: string) {
85
- return createHash('sha1').update(value).digest('hex').slice(0, 8);
85
+ return createHash('sha1').update(value).digest('hex').slice(0, 8)
86
86
  }
87
87
 
88
88
  function seedSpecifiers(aliases: string[]) {
89
89
  const react = aliases.filter(
90
90
  alias => reactAliasSpecifier.test(alias) && !isCompilerRuntime(alias),
91
- );
92
- return [...new Set([...vendorSpecifiers, ...react])];
91
+ )
92
+ return [...new Set([...vendorSpecifiers, ...react])]
93
93
  }
94
94
 
95
95
  /** Every framework specifier this app could demand: aliases + preact + pnext src. */
96
96
  export function prebuiltSpecifierFilter(config: ResolvedConfig): RegExp {
97
- const aliases = Object.keys(getImportAliasExtensions().aliases(config, 'client'));
98
- const bare = [...new Set([...aliases, ...vendorSpecifiers])];
99
- return new RegExp(`^(?:${bare.map(escapeRegex).join('|')}|${escapeRegex(frameworkSrc)}/)`);
97
+ const aliases = Object.keys(getImportAliasExtensions().aliases(config, 'client'))
98
+ const bare = [...new Set([...aliases, ...vendorSpecifiers])]
99
+ return new RegExp(`^(?:${bare.map(escapeRegex).join('|')}|${escapeRegex(frameworkSrc)}/)`)
100
100
  }
101
101
 
102
102
  /**
@@ -106,10 +106,10 @@ export function prebuiltSpecifierFilter(config: ResolvedConfig): RegExp {
106
106
  * glue whose weight - router, compat, preact - is external through it anyway.
107
107
  */
108
108
  export function isFrameworkSpecifier(specifier: string, filter: RegExp) {
109
- if (specifier === CLIENT_RUNTIME_MODULE) return false;
110
- if (isCompilerRuntime(specifier)) return false;
111
- if (specifier.startsWith(frameworkSrc)) return true;
112
- return filter.test(specifier) && !specifier.startsWith('.');
109
+ if (specifier === CLIENT_RUNTIME_MODULE) return false
110
+ if (isCompilerRuntime(specifier)) return false
111
+ if (specifier.startsWith(frameworkSrc)) return true
112
+ return filter.test(specifier) && !specifier.startsWith('.')
113
113
  }
114
114
 
115
115
  /**
@@ -124,59 +124,64 @@ export function prebuiltRuntimeKey(
124
124
  buildOptions: BuildOptions,
125
125
  signature = '',
126
126
  ) {
127
- const hash = createHash('sha1');
128
- hash.update(frameworkSourceHash());
129
- hash.update('\0');
130
- hash.update(JSON.stringify(Object.keys(getImportAliasExtensions().aliases(config, 'client'))));
131
- hash.update('\0');
127
+ const hash = createHash('sha1')
128
+ hash.update(frameworkSourceHash())
129
+ hash.update('\0')
130
+ hash.update(JSON.stringify(Object.keys(getImportAliasExtensions().aliases(config, 'client'))))
131
+ hash.update('\0')
132
132
  hash.update(
133
- JSON.stringify([buildOptions.define, buildOptions.minify, buildOptions.target, buildOptions.pure]),
134
- );
135
- hash.update('\0');
136
- hash.update(signature);
137
- return hash.digest('hex').slice(0, 16);
133
+ JSON.stringify([
134
+ buildOptions.define,
135
+ buildOptions.minify,
136
+ buildOptions.target,
137
+ buildOptions.pure,
138
+ ]),
139
+ )
140
+ hash.update('\0')
141
+ hash.update(signature)
142
+ return hash.digest('hex').slice(0, 16)
138
143
  }
139
144
 
140
- let cachedSourceHash: string | undefined;
145
+ let cachedSourceHash: string | undefined
141
146
 
142
147
  /**
143
148
  * Hash of pnext's own source. Cheap on the cold path: mtime+size per file, not contents - the tree is
144
149
  * pnext's own install, so a same-mtime file is the same file.
145
150
  */
146
151
  function frameworkSourceHash() {
147
- if (cachedSourceHash) return cachedSourceHash;
148
- const hash = createHash('sha1');
152
+ if (cachedSourceHash) return cachedSourceHash
153
+ const hash = createHash('sha1')
149
154
  const walk = (dir: string) => {
150
- let entries: Dirent[];
155
+ let entries: Dirent[]
151
156
  try {
152
- entries = readdirSync(dir, { withFileTypes: true });
157
+ entries = readdirSync(dir, { withFileTypes: true })
153
158
  } catch {
154
- return;
159
+ return
155
160
  }
156
161
  for (const entry of entries.sort((a, b) => (a.name < b.name ? -1 : 1))) {
157
- const file = path.join(dir, entry.name);
158
- if (entry.isDirectory()) walk(file);
162
+ const file = path.join(dir, entry.name)
163
+ if (entry.isDirectory()) walk(file)
159
164
  else if (/\.(?:tsx?|jsx?|mjs|cjs)$/.test(entry.name)) {
160
- const stats = statSync(file, { throwIfNoEntry: false });
161
- if (stats) hash.update(`${file}:${stats.size}:${stats.mtimeMs}\n`);
165
+ const stats = statSync(file, { throwIfNoEntry: false })
166
+ if (stats) hash.update(`${file}:${stats.size}:${stats.mtimeMs}\n`)
162
167
  }
163
168
  }
164
- };
165
- walk(frameworkSrc);
166
- cachedSourceHash = hash.digest('hex').slice(0, 16);
167
- return cachedSourceHash;
169
+ }
170
+ walk(frameworkSrc)
171
+ cachedSourceHash = hash.digest('hex').slice(0, 16)
172
+ return cachedSourceHash
168
173
  }
169
174
 
170
175
  export interface ArtifactOptions {
171
176
  /** The client import aliases in force, part of the key and of the seed. */
172
- aliases: string[];
173
- dir: string;
174
- publicPath: string;
175
- assetPath: string;
176
- key: string;
177
- buildOptions: BuildOptions;
177
+ aliases: string[]
178
+ dir: string
179
+ publicPath: string
180
+ assetPath: string
181
+ key: string
182
+ buildOptions: BuildOptions
178
183
  /** Fresh plugin chain per build — esbuild plugins carry per-build state. */
179
- plugins: () => Plugin[];
184
+ plugins: () => Plugin[]
180
185
  }
181
186
 
182
187
  /**
@@ -187,15 +192,15 @@ export interface ArtifactOptions {
187
192
  * re-export through several levels of their own stars.
188
193
  */
189
194
  async function probeExports(specifiers: string[], options: ArtifactOptions) {
190
- const found = new Map<string, string[]>();
191
- if (specifiers.length === 0) return found;
192
- const probeDir = path.join(options.dir, '.probe');
193
- await ensureDir(probeDir);
194
- const entryPoints: { in: string; out: string }[] = [];
195
+ const found = new Map<string, string[]>()
196
+ if (specifiers.length === 0) return found
197
+ const probeDir = path.join(options.dir, '.probe')
198
+ await ensureDir(probeDir)
199
+ const entryPoints: { in: string; out: string }[] = []
195
200
  for (const specifier of specifiers) {
196
- const file = path.join(probeDir, `${shortHash(specifier)}.ts`);
197
- await writeText(file, `export * from ${JSON.stringify(specifier)};\n`);
198
- entryPoints.push({ in: file, out: shortHash(specifier) });
201
+ const file = path.join(probeDir, `${shortHash(specifier)}.ts`)
202
+ await writeText(file, `export * from ${JSON.stringify(specifier)};\n`)
203
+ entryPoints.push({ in: file, out: shortHash(specifier) })
199
204
  }
200
205
  const result = await build({
201
206
  ...options.buildOptions,
@@ -206,15 +211,18 @@ async function probeExports(specifiers: string[], options: ArtifactOptions) {
206
211
  write: false,
207
212
  metafile: true,
208
213
  plugins: options.plugins(),
209
- });
214
+ })
210
215
  for (const specifier of specifiers) {
211
216
  const output = Object.entries(result.metafile.outputs).find(
212
217
  ([name]) => path.basename(name) === `${shortHash(specifier)}.js`,
213
- );
218
+ )
214
219
  // `export *` never carries `default`; probeSurface asks for it separately.
215
- found.set(specifier, (output?.[1].exports ?? []).filter(name => identifier.test(name)));
220
+ found.set(
221
+ specifier,
222
+ (output?.[1].exports ?? []).filter(name => identifier.test(name)),
223
+ )
216
224
  }
217
- return found;
225
+ return found
218
226
  }
219
227
 
220
228
  /**
@@ -226,18 +234,18 @@ async function probeExports(specifiers: string[], options: ArtifactOptions) {
226
234
  * once, unwritten, and every name that did not materialize is dropped.
227
235
  */
228
236
  async function probeSurface(specifiers: string[], options: ArtifactOptions) {
229
- const probed = await probeExports(specifiers, options);
230
- if (probed.size === 0) return probed;
237
+ const probed = await probeExports(specifiers, options)
238
+ if (probed.size === 0) return probed
231
239
  const candidate = new Map(
232
240
  [...probed].map(([specifier, names]) => [specifier, new Set([...names, 'default'])]),
233
- );
234
- const { text } = await buildAggregate(options, candidate, false);
241
+ )
242
+ const { text } = await buildAggregate(options, candidate, false)
235
243
  return new Map(
236
244
  [...candidate].map(([specifier, names]) => [
237
245
  specifier,
238
246
  [...names].filter(name => text.includes(mangledName(specifier, name))),
239
247
  ]),
240
- );
248
+ )
241
249
  }
242
250
 
243
251
  /**
@@ -249,20 +257,20 @@ async function buildAggregate(
249
257
  surface: Map<string, Set<string>>,
250
258
  write: boolean,
251
259
  ) {
252
- const lines: string[] = [];
260
+ const lines: string[] = []
253
261
  for (const specifier of [...surface.keys()].sort()) {
254
- const names = [...surface.get(specifier)!].filter(name => identifier.test(name)).sort();
255
- const spec = JSON.stringify(specifier);
256
- if (names.length === 0) lines.push(`import ${spec};`);
262
+ const names = [...surface.get(specifier)!].filter(name => identifier.test(name)).sort()
263
+ const spec = JSON.stringify(specifier)
264
+ if (names.length === 0) lines.push(`import ${spec};`)
257
265
  else {
258
- const clause = names.map(name => `${name} as ${mangledName(specifier, name)}`).join(', ');
259
- lines.push(`export { ${clause} } from ${spec};`);
266
+ const clause = names.map(name => `${name} as ${mangledName(specifier, name)}`).join(', ')
267
+ lines.push(`export { ${clause} } from ${spec};`)
260
268
  }
261
269
  }
262
- const aggregateDir = path.join(options.dir, '.aggregate');
263
- await ensureDir(aggregateDir);
264
- const entry = path.join(aggregateDir, 'runtime.ts');
265
- await writeText(entry, `${lines.join('\n')}\n`);
270
+ const aggregateDir = path.join(options.dir, '.aggregate')
271
+ await ensureDir(aggregateDir)
272
+ const entry = path.join(aggregateDir, 'runtime.ts')
273
+ await writeText(entry, `${lines.join('\n')}\n`)
266
274
 
267
275
  const result = await build({
268
276
  ...options.buildOptions,
@@ -273,17 +281,17 @@ async function buildAggregate(
273
281
  write,
274
282
  metafile: true,
275
283
  plugins: options.plugins(),
276
- });
277
- const emitted = result.outputFiles?.find(file => path.basename(file.path) === PREBUILT_MODULE);
278
- const text = emitted?.text ?? readFileSafe(path.join(options.dir, PREBUILT_MODULE));
279
- return { text, metafile: result.metafile };
284
+ })
285
+ const emitted = result.outputFiles?.find(file => path.basename(file.path) === PREBUILT_MODULE)
286
+ const text = emitted?.text ?? readFileSafe(path.join(options.dir, PREBUILT_MODULE))
287
+ return { text, metafile: result.metafile }
280
288
  }
281
289
 
282
290
  function readFileSafe(file: string) {
283
291
  try {
284
- return readFileSync(file, 'utf8');
292
+ return readFileSync(file, 'utf8')
285
293
  } catch {
286
- return '';
294
+ return ''
287
295
  }
288
296
  }
289
297
 
@@ -297,7 +305,7 @@ export async function buildPrebuiltRuntime(
297
305
  exportsBySpecifier: Map<string, string[]>,
298
306
  surface: Map<string, Set<string>>,
299
307
  ): Promise<PrebuiltRuntime> {
300
- const { metafile } = await buildAggregate(options, surface, true);
308
+ const { metafile } = await buildAggregate(options, surface, true)
301
309
  return {
302
310
  key: options.key,
303
311
  dir: options.dir,
@@ -306,33 +314,32 @@ export async function buildPrebuiltRuntime(
306
314
  exports: exportsBySpecifier,
307
315
  surface,
308
316
  closure: aggregateClosure(metafile),
309
- };
317
+ }
310
318
  }
311
319
 
312
-
313
320
  function aggregateClosure(metafile: Metafile) {
314
- const entry = Object.keys(metafile.outputs).find(name => path.basename(name) === PREBUILT_MODULE);
315
- const statics = new Set<string>();
316
- const dynamics = new Set<string>();
317
- if (!entry) return { static: [], dynamic: [] };
318
- const seen = new Set([`${entry}:static`]);
319
- const queue = [{ output: entry, dynamic: false }];
321
+ const entry = Object.keys(metafile.outputs).find(name => path.basename(name) === PREBUILT_MODULE)
322
+ const statics = new Set<string>()
323
+ const dynamics = new Set<string>()
324
+ if (!entry) return { static: [], dynamic: [] }
325
+ const seen = new Set([`${entry}:static`])
326
+ const queue = [{ output: entry, dynamic: false }]
320
327
  // eslint-disable-next-line @typescript-eslint/prefer-for-of
321
328
  for (let head = 0; head < queue.length; head += 1) {
322
- const current = queue[head]!;
329
+ const current = queue[head]!
323
330
  for (const imported of metafile.outputs[current.output]?.imports ?? []) {
324
- if (imported.kind !== 'import-statement' && imported.kind !== 'dynamic-import') continue;
325
- const dynamic = current.dynamic || imported.kind === 'dynamic-import';
326
- const visitKey = `${imported.path}:${dynamic ? 'dynamic' : 'static'}`;
327
- if (seen.has(visitKey)) continue;
328
- seen.add(visitKey);
329
- queue.push({ output: imported.path, dynamic });
330
- const relative = path.relative(path.dirname(entry), imported.path).split(path.sep).join('/');
331
- (dynamic ? dynamics : statics).add(relative);
331
+ if (imported.kind !== 'import-statement' && imported.kind !== 'dynamic-import') continue
332
+ const dynamic = current.dynamic || imported.kind === 'dynamic-import'
333
+ const visitKey = `${imported.path}:${dynamic ? 'dynamic' : 'static'}`
334
+ if (seen.has(visitKey)) continue
335
+ seen.add(visitKey)
336
+ queue.push({ output: imported.path, dynamic })
337
+ const relative = path.relative(path.dirname(entry), imported.path).split(path.sep).join('/')
338
+ ;(dynamic ? dynamics : statics).add(relative)
332
339
  }
333
340
  }
334
- for (const name of statics) dynamics.delete(name);
335
- return { static: [...statics], dynamic: [...dynamics] };
341
+ for (const name of statics) dynamics.delete(name)
342
+ return { static: [...statics], dynamic: [...dynamics] }
336
343
  }
337
344
  /**
338
345
  * Route-build seam. A framework specifier resolves to a virtual module that re-exports the target's
@@ -347,50 +354,48 @@ export function prebuiltExternalPlugin(
347
354
  unprobed: Set<string>,
348
355
  sourceOf: (importer: string) => string | undefined,
349
356
  ): Plugin {
350
- const namespace = 'pnext-prebuilt';
351
- const moduleUrl = prebuiltModuleUrl(runtime);
357
+ const namespace = 'pnext-prebuilt'
358
+ const moduleUrl = prebuiltModuleUrl(runtime)
352
359
  return {
353
360
  name: 'pnext-prebuilt-runtime',
354
361
  setup(build) {
355
362
  build.onResolve({ filter: new RegExp(`^${escapeRegex(moduleUrl)}$`) }, () => ({
356
363
  path: moduleUrl,
357
364
  external: true,
358
- }));
365
+ }))
359
366
  build.onResolve({ filter }, args => {
360
- if (args.namespace === namespace) return undefined;
361
- if (!isFrameworkSpecifier(args.path, filter)) return undefined;
367
+ if (args.namespace === namespace) return undefined
368
+ if (!isFrameworkSpecifier(args.path, filter)) return undefined
362
369
  if (!runtime.exports.has(args.path)) {
363
- unprobed.add(args.path);
364
- return undefined;
370
+ unprobed.add(args.path)
371
+ return undefined
365
372
  }
366
373
  // A dynamic import takes the module as a NAMESPACE - every export is live - so routing one
367
374
  // through the artifact would drag the whole surface into the initial tier that the dynamic
368
375
  // import exists to stay out of. Leave it deferred, unless the artifact already ships that
369
376
  // module, in which case serving it from there keeps the single instance.
370
- if (args.kind === 'dynamic-import' && !runtime.surface.has(args.path)) return undefined;
377
+ if (args.kind === 'dynamic-import' && !runtime.surface.has(args.path)) return undefined
371
378
  // The importer travels in the path because onLoad is not told it, and
372
379
  // the demanded names are a property of the IMPORTER, not the specifier:
373
380
  // esbuild cannot shake named imports out of an external module, so
374
381
  // whatever the virtual module offers is what ships.
375
- return { path: `${args.path}\0${args.importer}`, namespace };
376
- });
382
+ return { path: `${args.path}\0${args.importer}`, namespace }
383
+ })
377
384
  build.onLoad({ filter: /.*/, namespace }, args => {
378
- const separator = args.path.lastIndexOf('\0');
379
- const specifier = args.path.slice(0, separator);
380
- const importer = args.path.slice(separator + 1);
381
- const available = runtime.exports.get(specifier) ?? [];
382
- const demanded = demandedNames(importer, specifier, sourceOf(importer), available);
383
- const clause = demanded
384
- .map(name => `${mangledName(specifier, name)} as ${name}`)
385
- .join(', ');
385
+ const separator = args.path.lastIndexOf('\0')
386
+ const specifier = args.path.slice(0, separator)
387
+ const importer = args.path.slice(separator + 1)
388
+ const available = runtime.exports.get(specifier) ?? []
389
+ const demanded = demandedNames(importer, specifier, sourceOf(importer), available)
390
+ const clause = demanded.map(name => `${mangledName(specifier, name)} as ${name}`).join(', ')
386
391
  const contents =
387
392
  clause.length > 0
388
393
  ? `export { ${clause} } from ${JSON.stringify(moduleUrl)};\n`
389
- : `import ${JSON.stringify(moduleUrl)};\n`;
390
- return { contents, loader: 'js', resolveDir: path.dirname(specifier) };
391
- });
394
+ : `import ${JSON.stringify(moduleUrl)};\n`
395
+ return { contents, loader: 'js', resolveDir: path.dirname(specifier) }
396
+ })
392
397
  },
393
- };
398
+ }
394
399
  }
395
400
  /**
396
401
  * The names one importer binds off one specifier. A namespace import, an `export * from`, or an import
@@ -403,110 +408,113 @@ function demandedNames(
403
408
  source: string | undefined,
404
409
  available: string[],
405
410
  ) {
406
- if (source === undefined) return available;
411
+ if (source === undefined) return available
407
412
  // The generated entries are virtual and their importer id carries no extension; scanFacts picks
408
413
  // the parser off the name, so an id like `index` would parse as plain JS, leaving the entry's
409
414
  // TypeScript unreadable - which reads as "demands everything".
410
- const sourceFile = /\.[cm]?[jt]sx?$/i.test(importer) ? importer : `${importer}.tsx`;
411
- let edges;
415
+ const sourceFile = /\.[cm]?[jt]sx?$/i.test(importer) ? importer : `${importer}.tsx`
416
+ let edges
412
417
  try {
413
- edges = scanFacts(sourceFile, source).imports;
418
+ edges = scanFacts(sourceFile, source).imports
414
419
  } catch {
415
- return available;
420
+ return available
416
421
  }
417
- const names = new Set<string>();
418
- let named = false;
422
+ const names = new Set<string>()
423
+ let named = false
419
424
  for (const edge of edges) {
420
- if (edge.specifier !== specifier) continue;
421
- named = true;
422
- if (edge.star || edge.exports.includes('*')) return available;
423
- for (const name of edge.exports) names.add(name);
425
+ if (edge.specifier !== specifier) continue
426
+ named = true
427
+ if (edge.star || edge.exports.includes('*')) return available
428
+ for (const name of edge.exports) names.add(name)
424
429
  }
425
- if (!named) return available;
426
- const offered = available.filter(name => names.has(name));
430
+ if (!named) return available
431
+ const offered = available.filter(name => names.has(name))
427
432
  // A name the target does not export is the build's error to report, not
428
433
  // something to silently drop — offer it and let esbuild say so.
429
- for (const name of names) if (!available.includes(name)) offered.push(name);
430
- return offered;
434
+ for (const name of names) if (!available.includes(name)) offered.push(name)
435
+ return offered
431
436
  }
432
437
 
433
438
  export function prebuiltModuleUrl(runtime: Pick<PrebuiltRuntime, 'publicPath'>) {
434
- return `${runtime.publicPath}/${PREBUILT_MODULE}`;
439
+ return `${runtime.publicPath}/${PREBUILT_MODULE}`
435
440
  }
436
441
  /**
437
442
  * Read the surface the build actually demanded back off its own output: every mangled name imported
438
443
  * from the artifact url. Exact by construction - it is the same list the browser will ask for.
439
444
  */
440
445
  export function demandedFromOutputs(runtime: PrebuiltRuntime, outDir: string) {
441
- const moduleUrl = prebuiltModuleUrl(runtime);
442
- const byMangled = new Map<string, { specifier: string; name: string }>();
446
+ const moduleUrl = prebuiltModuleUrl(runtime)
447
+ const byMangled = new Map<string, { specifier: string; name: string }>()
443
448
  for (const [specifier, names] of runtime.exports) {
444
- for (const name of names) byMangled.set(mangledName(specifier, name), { specifier, name });
449
+ for (const name of names) byMangled.set(mangledName(specifier, name), { specifier, name })
445
450
  }
446
- const demanded = new Map<string, Set<string>>();
451
+ const demanded = new Map<string, Set<string>>()
447
452
  const walk = (dir: string) => {
448
- let entries: Dirent[];
453
+ let entries: Dirent[]
449
454
  try {
450
- entries = readdirSync(dir, { withFileTypes: true });
455
+ entries = readdirSync(dir, { withFileTypes: true })
451
456
  } catch {
452
- return;
457
+ return
453
458
  }
454
459
  for (const entry of entries) {
455
- const file = path.join(dir, entry.name);
460
+ const file = path.join(dir, entry.name)
456
461
  // The artifact itself lives under the out dir in prod; it is where these
457
462
  // names come from, not a consumer of them.
458
463
  if (entry.isDirectory()) {
459
- if (file !== runtime.dir) walk(file);
460
- continue;
464
+ if (file !== runtime.dir) walk(file)
465
+ continue
461
466
  }
462
- if (!entry.name.endsWith('.js')) continue;
463
- let source: string;
467
+ if (!entry.name.endsWith('.js')) continue
468
+ let source: string
464
469
  try {
465
- source = readFileSync(file, 'utf8');
470
+ source = readFileSync(file, 'utf8')
466
471
  } catch {
467
- continue;
472
+ continue
468
473
  }
469
- if (!source.includes(moduleUrl)) continue;
474
+ if (!source.includes(moduleUrl)) continue
470
475
  for (const edge of scanFacts(file, source).imports) {
471
- if (edge.specifier !== moduleUrl) continue;
476
+ if (edge.specifier !== moduleUrl) continue
472
477
  for (const bound of edge.exports) {
473
- const origin = byMangled.get(bound);
474
- if (!origin) continue;
475
- const names = demanded.get(origin.specifier) ?? new Set<string>();
476
- demanded.set(origin.specifier, names);
477
- names.add(origin.name);
478
+ const origin = byMangled.get(bound)
479
+ if (!origin) continue
480
+ const names = demanded.get(origin.specifier) ?? new Set<string>()
481
+ demanded.set(origin.specifier, names)
482
+ names.add(origin.name)
478
483
  }
479
484
  }
480
485
  }
481
- };
482
- walk(outDir);
483
- return demanded;
486
+ }
487
+ walk(outDir)
488
+ return demanded
484
489
  }
485
490
 
486
491
  /** Is every demanded name already in the artifact on disk? */
487
492
  export function surfaceCovered(runtime: PrebuiltRuntime, demanded: Map<string, Set<string>>) {
488
493
  for (const [specifier, names] of demanded) {
489
- const have = runtime.surface.get(specifier);
490
- if (!have) return false;
491
- for (const name of names) if (!have.has(name)) return false;
494
+ const have = runtime.surface.get(specifier)
495
+ if (!have) return false
496
+ for (const name of names) if (!have.has(name)) return false
492
497
  }
493
- return true;
498
+ return true
494
499
  }
495
500
 
496
- const manifestName = 'pnext-runtime.json';
501
+ const manifestName = 'pnext-runtime.json'
497
502
 
498
503
  /**
499
504
  * One artifact address is shared by every route build in the process, and in
500
505
  * dev several routes compile at once. Serialize per address so two esbuild runs
501
506
  * never write the same directory concurrently.
502
507
  */
503
- const artifactLocks = new Map<string, Promise<unknown>>();
508
+ const artifactLocks = new Map<string, Promise<unknown>>()
504
509
 
505
510
  function underLock<T>(dir: string, run: () => Promise<T>): Promise<T> {
506
- const previous = artifactLocks.get(dir) ?? Promise.resolve();
507
- const next = previous.then(run, run);
508
- artifactLocks.set(dir, next.catch(() => undefined));
509
- return next;
511
+ const previous = artifactLocks.get(dir) ?? Promise.resolve()
512
+ const next = previous.then(run, run)
513
+ artifactLocks.set(
514
+ dir,
515
+ next.catch(() => undefined),
516
+ )
517
+ return next
510
518
  }
511
519
 
512
520
  /**
@@ -516,11 +524,11 @@ function underLock<T>(dir: string, run: () => Promise<T>): Promise<T> {
516
524
  * probed and folded in by the build that first demands it.
517
525
  */
518
526
  export function ensurePrebuiltRuntime(options: ArtifactOptions) {
519
- return underLock(options.dir, () => openPrebuiltRuntime(options));
527
+ return underLock(options.dir, () => openPrebuiltRuntime(options))
520
528
  }
521
529
 
522
530
  async function openPrebuiltRuntime(options: ArtifactOptions) {
523
- const manifest = readManifest(options.dir);
531
+ const manifest = readManifest(options.dir)
524
532
  if (manifest) {
525
533
  return {
526
534
  key: options.key,
@@ -528,14 +536,14 @@ async function openPrebuiltRuntime(options: ArtifactOptions) {
528
536
  publicPath: options.publicPath,
529
537
  assetPath: options.assetPath,
530
538
  ...manifest,
531
- } satisfies PrebuiltRuntime;
539
+ } satisfies PrebuiltRuntime
532
540
  }
533
- const exportsBySpecifier = await probeSurface(seedSpecifiers(options.aliases), options);
541
+ const exportsBySpecifier = await probeSurface(seedSpecifiers(options.aliases), options)
534
542
  // Seed surface: nothing is demanded yet, so the aggregate starts empty and
535
543
  // the first route build's own output says what belongs in it.
536
- const runtime = await buildPrebuiltRuntime(options, exportsBySpecifier, new Map());
537
- await writeManifest(runtime);
538
- return runtime;
544
+ const runtime = await buildPrebuiltRuntime(options, exportsBySpecifier, new Map())
545
+ await writeManifest(runtime)
546
+ return runtime
539
547
  }
540
548
  /**
541
549
  * Fold what the build demanded - and any specifier it met for the first time - into the artifact. A
@@ -547,7 +555,7 @@ export function settlePrebuiltRuntime(
547
555
  outDir: string,
548
556
  unprobed: Set<string>,
549
557
  ) {
550
- return underLock(options.dir, () => growPrebuiltRuntime(runtime, options, outDir, unprobed));
558
+ return underLock(options.dir, () => growPrebuiltRuntime(runtime, options, outDir, unprobed))
551
559
  }
552
560
 
553
561
  async function growPrebuiltRuntime(
@@ -558,43 +566,43 @@ async function growPrebuiltRuntime(
558
566
  ) {
559
567
  // Another build may have grown the artifact while this one ran; merge onto
560
568
  // what is on disk now, not onto the snapshot this build opened.
561
- const current = readManifest(options.dir);
562
- if (current) runtime = { ...runtime, ...current };
563
- const demanded = demandedFromOutputs(runtime, outDir);
564
- if (unprobed.size === 0 && surfaceCovered(runtime, demanded)) return runtime;
565
- const exportsBySpecifier = new Map(runtime.exports);
569
+ const current = readManifest(options.dir)
570
+ if (current) runtime = { ...runtime, ...current }
571
+ const demanded = demandedFromOutputs(runtime, outDir)
572
+ if (unprobed.size === 0 && surfaceCovered(runtime, demanded)) return runtime
573
+ const exportsBySpecifier = new Map(runtime.exports)
566
574
  for (const [specifier, names] of await probeSurface([...unprobed], options)) {
567
- exportsBySpecifier.set(specifier, names);
575
+ exportsBySpecifier.set(specifier, names)
568
576
  }
569
- const surface = new Map(runtime.surface);
577
+ const surface = new Map(runtime.surface)
570
578
  for (const [specifier, names] of demanded) {
571
- const target = surface.get(specifier) ?? new Set<string>();
572
- surface.set(specifier, target);
573
- for (const name of names) target.add(name);
579
+ const target = surface.get(specifier) ?? new Set<string>()
580
+ surface.set(specifier, target)
581
+ for (const name of names) target.add(name)
574
582
  }
575
- const grown = await buildPrebuiltRuntime(options, exportsBySpecifier, surface);
576
- await writeManifest(grown);
577
- return grown;
583
+ const grown = await buildPrebuiltRuntime(options, exportsBySpecifier, surface)
584
+ await writeManifest(grown)
585
+ return grown
578
586
  }
579
587
 
580
588
  interface Manifest {
581
- key: string;
582
- exports: Record<string, string[]>;
583
- surface: Record<string, string[]>;
584
- closure: { static: string[]; dynamic: string[] };
589
+ key: string
590
+ exports: Record<string, string[]>
591
+ surface: Record<string, string[]>
592
+ closure: { static: string[]; dynamic: string[] }
585
593
  }
586
594
 
587
595
  function readManifest(dir: string) {
588
596
  try {
589
- const parsed = JSON.parse(readFileSync(path.join(dir, manifestName), 'utf8')) as Manifest;
590
- if (!parsed.exports) return undefined;
597
+ const parsed = JSON.parse(readFileSync(path.join(dir, manifestName), 'utf8')) as Manifest
598
+ if (!parsed.exports) return undefined
591
599
  return {
592
600
  exports: new Map(Object.entries(parsed.exports)),
593
601
  surface: new Map(Object.entries(parsed.surface).map(([spec, n]) => [spec, new Set(n)])),
594
602
  closure: parsed.closure,
595
- };
603
+ }
596
604
  } catch {
597
- return undefined;
605
+ return undefined
598
606
  }
599
607
  }
600
608
 
@@ -604,8 +612,8 @@ async function writeManifest(runtime: PrebuiltRuntime) {
604
612
  exports: Object.fromEntries(runtime.exports),
605
613
  surface: Object.fromEntries([...runtime.surface].map(([s, n]) => [s, [...n].sort()])),
606
614
  closure: runtime.closure,
607
- };
608
- await writeText(path.join(runtime.dir, manifestName), JSON.stringify(manifest));
615
+ }
616
+ await writeText(path.join(runtime.dir, manifestName), JSON.stringify(manifest))
609
617
  }
610
618
 
611
619
  /**
@@ -613,9 +621,9 @@ async function writeManifest(runtime: PrebuiltRuntime) {
613
621
  * `assets/…` names — what the rendered page's modulepreload list is written in.
614
622
  */
615
623
  export function prebuiltAssets(runtime: PrebuiltRuntime) {
616
- const join = (name: string) => `${runtime.assetPath}/${name}`;
624
+ const join = (name: string) => `${runtime.assetPath}/${name}`
617
625
  return {
618
626
  static: [join(PREBUILT_MODULE), ...runtime.closure.static.map(join)],
619
627
  dynamic: runtime.closure.dynamic.map(join),
620
- };
628
+ }
621
629
  }