@wular/pnext 0.1.5 → 0.1.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 (302) hide show
  1. package/bin/pnext +9 -2
  2. package/dist/server/_chunks/aliases-j47a10ce.js +44 -0
  3. package/dist/server/_chunks/analyze-arswqe6s.js +445 -0
  4. package/dist/server/_chunks/boot-af0mv3dy.js +36 -0
  5. package/dist/server/_chunks/build-spy3dxp4.js +84 -0
  6. package/dist/server/_chunks/build-t9h0hec3.js +3550 -0
  7. package/dist/server/_chunks/build-tier-m7yvqz61.js +2472 -0
  8. package/dist/server/_chunks/compile-53j02j27.js +22 -0
  9. package/dist/server/_chunks/config-1yzwexq6.js +27 -0
  10. package/dist/server/_chunks/config-n2z7yxps.js +22 -0
  11. package/dist/server/_chunks/create-meec9hs6.js +134 -0
  12. package/dist/server/_chunks/dev-fjmqg6en.js +220 -0
  13. package/dist/server/_chunks/esbuild-yyktfrtt.js +15 -0
  14. package/dist/server/_chunks/generate-n9sh6hzt.js +21 -0
  15. package/dist/server/_chunks/index-0374j2b9.js +66 -0
  16. package/dist/server/_chunks/index-06nyqntx.js +213 -0
  17. package/dist/server/_chunks/index-1011cscr.js +5263 -0
  18. package/dist/server/_chunks/index-11sfk4hb.js +170 -0
  19. package/dist/server/_chunks/index-20ppawv7.js +297 -0
  20. package/dist/server/_chunks/index-2dv4y4wd.js +1065 -0
  21. package/dist/server/_chunks/index-2vz0wzdn.js +59 -0
  22. package/dist/server/_chunks/index-2wfv4kvx.js +182 -0
  23. package/dist/server/_chunks/index-357na4a8.js +109 -0
  24. package/dist/server/_chunks/index-3b3at80h.js +109 -0
  25. package/dist/server/_chunks/index-3tf1xjsp.js +6166 -0
  26. package/dist/server/_chunks/index-3xbr4eyv.js +105 -0
  27. package/dist/server/_chunks/index-4399bvd2.js +18 -0
  28. package/dist/server/_chunks/index-4hgjrqh7.js +851 -0
  29. package/dist/server/_chunks/index-4q2gbfwk.js +2530 -0
  30. package/dist/server/_chunks/index-4t92hdxd.js +172 -0
  31. package/dist/server/_chunks/index-4zzebszd.js +10 -0
  32. package/dist/server/_chunks/index-5gyr4emz.js +107 -0
  33. package/dist/server/_chunks/index-5hr4062s.js +70 -0
  34. package/dist/server/_chunks/index-68m3mwbd.js +84 -0
  35. package/dist/server/_chunks/index-6b009mt0.js +56 -0
  36. package/dist/server/_chunks/index-6e4fqv30.js +588 -0
  37. package/dist/server/_chunks/index-6gex3pfa.js +15 -0
  38. package/dist/server/_chunks/index-6kp9r0d9.js +11 -0
  39. package/dist/server/_chunks/index-6q7zvrap.js +134 -0
  40. package/dist/server/_chunks/index-73z4esab.js +38 -0
  41. package/dist/server/_chunks/index-79ngvam8.js +60 -0
  42. package/dist/server/_chunks/index-7wc9n8be.js +25 -0
  43. package/dist/server/_chunks/index-8k7pfejn.js +1599 -0
  44. package/dist/server/_chunks/index-8kcxdfya.js +206 -0
  45. package/dist/server/_chunks/index-91x12ykq.js +274 -0
  46. package/dist/server/_chunks/index-9ch50vtq.js +18 -0
  47. package/dist/server/_chunks/index-9hx2641q.js +28 -0
  48. package/dist/server/_chunks/index-9n2914ww.js +535 -0
  49. package/dist/server/_chunks/index-9ych9ma8.js +207 -0
  50. package/dist/server/_chunks/index-b6wtkdp4.js +24 -0
  51. package/dist/server/_chunks/index-bcws5eh2.js +35 -0
  52. package/dist/server/_chunks/index-c0g2wf3z.js +92 -0
  53. package/dist/server/_chunks/index-cf4rvxv6.js +95 -0
  54. package/dist/server/_chunks/index-cjgqs13g.js +65 -0
  55. package/dist/server/_chunks/index-ckkdpht5.js +41 -0
  56. package/dist/server/_chunks/index-cyfednwb.js +87 -0
  57. package/dist/server/_chunks/index-danncfhy.js +311 -0
  58. package/dist/server/_chunks/index-dg0f05zs.js +199 -0
  59. package/dist/server/_chunks/index-e3a6yx84.js +18 -0
  60. package/dist/server/_chunks/index-e88tyv35.js +45 -0
  61. package/dist/server/_chunks/index-eajaspjk.js +1253 -0
  62. package/dist/server/_chunks/index-eeaanp2e.js +483 -0
  63. package/dist/server/_chunks/index-egykcqg3.js +101 -0
  64. package/dist/server/_chunks/index-en7n9f7m.js +22 -0
  65. package/dist/server/_chunks/index-ezgj0tr1.js +88 -0
  66. package/dist/server/_chunks/index-fkp000p1.js +590 -0
  67. package/dist/server/_chunks/index-fn1chkkd.js +214 -0
  68. package/dist/server/_chunks/index-fp8r0sqs.js +64 -0
  69. package/dist/server/_chunks/index-ggk2j965.js +9432 -0
  70. package/dist/server/_chunks/index-grta8ap3.js +238 -0
  71. package/dist/server/_chunks/index-h2a70tg4.js +7 -0
  72. package/dist/server/_chunks/index-h4xy648y.js +51 -0
  73. package/dist/server/_chunks/index-hkdfj58q.js +92 -0
  74. package/dist/server/_chunks/index-j2zrcp1k.js +66 -0
  75. package/dist/server/_chunks/index-jcsjq3d1.js +20 -0
  76. package/dist/server/_chunks/index-jepjvcrf.js +198 -0
  77. package/dist/server/_chunks/index-jks0x0a1.js +14 -0
  78. package/dist/server/_chunks/index-jx7bqvw1.js +57 -0
  79. package/dist/server/_chunks/index-k1g3epw0.js +1299 -0
  80. package/dist/server/_chunks/index-knp0s912.js +7 -0
  81. package/dist/server/_chunks/index-kq8kpzye.js +472 -0
  82. package/dist/server/_chunks/index-kqyy1d4f.js +50 -0
  83. package/dist/server/_chunks/index-kresp2n8.js +445 -0
  84. package/dist/server/_chunks/index-ms9v9tnx.js +31 -0
  85. package/dist/server/_chunks/index-n4hxpng2.js +11 -0
  86. package/dist/server/_chunks/index-ncnes8c6.js +17 -0
  87. package/dist/server/_chunks/index-nqh3xhdc.js +57 -0
  88. package/dist/server/_chunks/index-nyrba2kr.js +4130 -0
  89. package/dist/server/_chunks/index-p77b4kcx.js +296 -0
  90. package/dist/server/_chunks/index-pym1cezq.js +39 -0
  91. package/dist/server/_chunks/index-q738kkhj.js +100 -0
  92. package/dist/server/_chunks/index-qjj6gddn.js +54 -0
  93. package/dist/server/_chunks/index-qm6kmhqs.js +110 -0
  94. package/dist/server/_chunks/index-qn4z5s3c.js +819 -0
  95. package/dist/server/_chunks/index-qpwsgt3a.js +158 -0
  96. package/dist/server/_chunks/index-r97ptz1q.js +97 -0
  97. package/dist/server/_chunks/index-ras0sdab.js +26 -0
  98. package/dist/server/_chunks/index-rcs322t1.js +19 -0
  99. package/dist/server/_chunks/index-rn8dyr1f.js +126 -0
  100. package/dist/server/_chunks/index-rt9qq1va.js +4 -0
  101. package/dist/server/_chunks/index-rthrsed5.js +356 -0
  102. package/dist/server/_chunks/index-sctcgyvv.js +185 -0
  103. package/dist/server/_chunks/index-sjpckxqn.js +213 -0
  104. package/dist/server/_chunks/index-sq3kvz3g.js +200 -0
  105. package/dist/server/_chunks/index-stbk3jhn.js +31 -0
  106. package/dist/server/_chunks/index-sv8m6789.js +266 -0
  107. package/dist/server/_chunks/index-tgcakdxc.js +125 -0
  108. package/dist/server/_chunks/index-tgsfjmep.js +74 -0
  109. package/dist/server/_chunks/index-tq0pc7eg.js +154 -0
  110. package/dist/server/_chunks/index-tq1f96v7.js +51 -0
  111. package/dist/server/_chunks/index-tqn2qnnn.js +241 -0
  112. package/dist/server/_chunks/index-tvqkq6e6.js +128 -0
  113. package/dist/server/_chunks/index-v1ags1na.js +132 -0
  114. package/dist/server/_chunks/index-vvmmknm1.js +1431 -0
  115. package/dist/server/_chunks/index-vvq7rqtn.js +329 -0
  116. package/dist/server/_chunks/index-vz0km5qk.js +33 -0
  117. package/dist/server/_chunks/index-w6h8m6vp.js +138 -0
  118. package/dist/server/_chunks/index-web361b8.js +138 -0
  119. package/dist/server/_chunks/index-wpfhfbs4.js +194 -0
  120. package/dist/server/_chunks/index-x0y005nh.js +283 -0
  121. package/dist/server/_chunks/index-x3yn4ywm.js +22 -0
  122. package/dist/server/_chunks/index-x93hv0sc.js +271 -0
  123. package/dist/server/_chunks/index-xvj80c3a.js +30 -0
  124. package/dist/server/_chunks/index-xywjg2vc.js +100 -0
  125. package/dist/server/_chunks/index-y2jr2n72.js +152 -0
  126. package/dist/server/_chunks/index-y36a0ybw.js +57 -0
  127. package/dist/server/_chunks/index-ye9hmsvf.js +47 -0
  128. package/dist/server/_chunks/index-yhxkxghe.js +56 -0
  129. package/dist/server/_chunks/index-ym67zqxp.js +130 -0
  130. package/dist/server/_chunks/index-ytjvpbm2.js +736 -0
  131. package/dist/server/_chunks/index-yz54pxrh.js +960 -0
  132. package/dist/server/_chunks/index-z4z9zv3b.js +733 -0
  133. package/dist/server/_chunks/index-z84ab1w0.js +1270 -0
  134. package/dist/server/_chunks/index-z88qv16t.js +11 -0
  135. package/dist/server/_chunks/index-zqpqyg8p.js +666 -0
  136. package/dist/server/_chunks/loader-7yw0j98z.js +78 -0
  137. package/dist/server/_chunks/modules-jn8bmbn8.js +74 -0
  138. package/dist/server/_chunks/pipeline-yy9jhydf.js +832 -0
  139. package/dist/server/_chunks/production-jar9ztm3.js +44 -0
  140. package/dist/server/_chunks/proxy-config-j84dgksn.js +21 -0
  141. package/dist/server/_chunks/proxy-w1d0wmsn.js +33 -0
  142. package/dist/server/_chunks/router-k1reahfn.js +498 -0
  143. package/dist/server/_chunks/routes-2s277fc6.js +64 -0
  144. package/dist/server/_chunks/run-pvd8bs1t.js +696 -0
  145. package/dist/server/_chunks/server-mt4a994c.js +1835 -0
  146. package/dist/server/_chunks/tsconfig-defaults-1nb3308g.js +20 -0
  147. package/dist/server/_chunks/typegen-0qr0459b.js +35 -0
  148. package/dist/server/api/client-cache.js +14 -0
  149. package/dist/server/cli/index.js +378 -0
  150. package/dist/server/cli/start.js +137 -0
  151. package/dist/server/client/reference.js +16 -0
  152. package/dist/server/compat/next/cache.js +56 -0
  153. package/dist/server/compat/next/canonical-url.js +13 -0
  154. package/dist/server/compat/next/client-cache.js +57 -0
  155. package/dist/server/compat/next/client-navigation.js +232 -0
  156. package/dist/server/compat/next/client-only.js +1 -0
  157. package/dist/server/compat/next/client-script.js +178 -0
  158. package/dist/server/compat/next/client-server.js +34 -0
  159. package/dist/server/compat/next/config-headers.js +32 -0
  160. package/dist/server/compat/next/config-loader.js +25 -0
  161. package/dist/server/compat/next/config.js +10 -0
  162. package/dist/server/compat/next/constants.js +18 -0
  163. package/dist/server/compat/next/custom-server.js +10 -0
  164. package/dist/server/compat/next/dist/client/components/app-router-headers.js +48 -0
  165. package/dist/server/compat/next/dist/server/web/spec-extension/revalidate.js +27 -0
  166. package/dist/server/compat/next/dist/server/web/spec-extension/unstable-cache.js +25 -0
  167. package/dist/server/compat/next/dist/server/web/spec-extension/unstable-no-store.js +25 -0
  168. package/dist/server/compat/next/dynamic.js +32 -0
  169. package/dist/server/compat/next/error.js +112 -0
  170. package/dist/server/compat/next/font/cache.js +14 -0
  171. package/dist/server/compat/next/font/google.js +3 -0
  172. package/dist/server/compat/next/font/index.js +1 -0
  173. package/dist/server/compat/next/font/local.js +22 -0
  174. package/dist/server/compat/next/font/runtime-client.js +33 -0
  175. package/dist/server/compat/next/font/runtime.js +41 -0
  176. package/dist/server/compat/next/font/shared.js +22 -0
  177. package/dist/server/compat/next/form.js +129 -0
  178. package/dist/server/compat/next/head.js +10 -0
  179. package/dist/server/compat/next/headers.js +30 -0
  180. package/dist/server/compat/next/image/client.js +11 -0
  181. package/dist/server/compat/next/image/config.js +18 -0
  182. package/dist/server/compat/next/image/optimizer.js +25 -0
  183. package/dist/server/compat/next/image/patterns.js +12 -0
  184. package/dist/server/compat/next/image/props.js +16 -0
  185. package/dist/server/compat/next/image/shared.js +86 -0
  186. package/dist/server/compat/next/image/static-metadata.js +32 -0
  187. package/dist/server/compat/next/image/validate.js +8 -0
  188. package/dist/server/compat/next/image.js +59 -0
  189. package/dist/server/compat/next/index.js +1 -0
  190. package/dist/server/compat/next/legacy-image.js +78 -0
  191. package/dist/server/compat/next/legacy-request-apis.js +24 -0
  192. package/dist/server/compat/next/link-transform.js +14 -0
  193. package/dist/server/compat/next/link.js +14 -0
  194. package/dist/server/compat/next/navigation.js +190 -0
  195. package/dist/server/compat/next/offline.js +45 -0
  196. package/dist/server/compat/next/og.js +8 -0
  197. package/dist/server/compat/next/preferred-region.js +8 -0
  198. package/dist/server/compat/next/redirects.js +30 -0
  199. package/dist/server/compat/next/resource-hints.js +30 -0
  200. package/dist/server/compat/next/rewrites.js +41 -0
  201. package/dist/server/compat/next/root-params.js +121 -0
  202. package/dist/server/compat/next/route-state.js +23 -0
  203. package/dist/server/compat/next/router.js +103 -0
  204. package/dist/server/compat/next/script.js +37 -0
  205. package/dist/server/compat/next/server-only.js +1 -0
  206. package/dist/server/compat/next/server.js +131 -0
  207. package/dist/server/compat/next/svgr.js +14 -0
  208. package/dist/server/compat/next/telemetry.js +10 -0
  209. package/dist/server/compat/next/usage.js +13 -0
  210. package/dist/server/compat/next/user-agent.js +12 -0
  211. package/dist/server/compat/next/web-vitals.js +35 -0
  212. package/dist/server/compat/react/action-state.js +11 -0
  213. package/dist/server/compat/react/client-lite.js +83 -0
  214. package/dist/server/compat/react/client.js +131 -0
  215. package/dist/server/compat/react/compiler-runtime.js +42 -0
  216. package/dist/server/compat/react/dom-client.js +106 -0
  217. package/dist/server/compat/react/dom-react-server.js +37 -0
  218. package/dist/server/compat/react/dom-server.js +40 -0
  219. package/dist/server/compat/react/dom.js +52 -0
  220. package/dist/server/compat/react/hooks-extra.js +12 -0
  221. package/dist/server/compat/react/internals.js +14 -0
  222. package/dist/server/compat/react/parity.js +11 -0
  223. package/dist/server/compat/react/preact.js +113 -0
  224. package/dist/server/compat/react/react-server.js +133 -0
  225. package/dist/server/compat/react/router-shim.js +8 -0
  226. package/dist/server/compat/react/server-component-use.js +14 -0
  227. package/dist/server/compat/react/server-inserted-html.js +14 -0
  228. package/dist/server/compat/react/server.js +194 -0
  229. package/dist/server/compat/react/style-values.js +10 -0
  230. package/dist/server/compat/react/use.js +10 -0
  231. package/dist/server/compat/react/view-transition.js +12 -0
  232. package/dist/server/generation.json +1 -0
  233. package/package.json +4 -1
  234. package/src/api/dynamic.tsx +2 -0
  235. package/src/api/server.ts +24 -6
  236. package/src/cli/adapters/vercel-warm.ts +315 -61
  237. package/src/cli/adapters/vercel.ts +348 -71
  238. package/src/cli/build.ts +58 -33
  239. package/src/cli/index.ts +23 -10
  240. package/src/cli/serve/entry.ts +21 -159
  241. package/src/cli/serve/immutable.ts +31 -0
  242. package/src/cli/serve/pipeline.ts +82 -84
  243. package/src/cli/start.ts +3 -1
  244. package/src/client/chunk-fold.ts +19 -6
  245. package/src/client/react-tier.ts +3 -2
  246. package/src/client/reference-stub.ts +21 -2
  247. package/src/compat/actions/client-plugin.ts +4 -2
  248. package/src/compat/actions/config.ts +6 -5
  249. package/src/compat/actions/extensions.ts +2 -3
  250. package/src/compat/aliases.ts +8 -1
  251. package/src/compat/bundler/config.ts +88 -0
  252. package/src/compat/bundler/optimize-package-imports.ts +86 -26
  253. package/src/compat/bundler/relay-transform.ts +15 -3
  254. package/src/compat/cache-control.ts +16 -8
  255. package/src/compat/css/modules.ts +18 -5
  256. package/src/compat/lifecycle/error-funnel.ts +1 -1
  257. package/src/compat/lifecycle/instrumentation.ts +117 -24
  258. package/src/compat/lifecycle/testmode.ts +3 -2
  259. package/src/compat/next/config-loader.ts +137 -13
  260. package/src/compat/next/font/runtime.ts +22 -2
  261. package/src/compat/next/og.ts +3 -3
  262. package/src/compat/next/usage.ts +3 -2
  263. package/src/compat/pages/api.ts +83 -14
  264. package/src/compat/pages/router.ts +30 -14
  265. package/src/compat/register/bundler.ts +3 -1
  266. package/src/compat/register/middleware.ts +1 -1
  267. package/src/compat/register/otel.ts +5 -9
  268. package/src/compat/register/render.ts +3 -1
  269. package/src/compat/register/use-cache.ts +3 -1
  270. package/src/compat/release.ts +46 -0
  271. package/src/compat/segment/serve.ts +1 -1
  272. package/src/compat/validation/validate.ts +10 -7
  273. package/src/config.ts +51 -7
  274. package/src/css/assets.ts +213 -0
  275. package/src/css/build.ts +174 -238
  276. package/src/dev/server.ts +27 -8
  277. package/src/extensions.ts +4 -0
  278. package/src/render/hooks.ts +13 -0
  279. package/src/render/renderer.ts +52 -32
  280. package/src/request/context.ts +9 -0
  281. package/src/resolve/dynamic.ts +3 -1
  282. package/src/resolve/imports.ts +12 -52
  283. package/src/resolve/package-json.ts +56 -0
  284. package/src/resolve/scan-facts.ts +65 -0
  285. package/src/routing/href.ts +10 -3
  286. package/src/routing/match.ts +287 -0
  287. package/src/routing/metadata-files.ts +19 -5
  288. package/src/routing/proxy-config.ts +137 -0
  289. package/src/routing/proxy.ts +35 -134
  290. package/src/routing/routes.ts +22 -281
  291. package/src/runtime/fingerprint.ts +23 -8
  292. package/src/runtime/load.ts +170 -0
  293. package/src/runtime/loader.ts +215 -43
  294. package/src/runtime/module-cache.ts +13 -0
  295. package/src/runtime/modules.ts +370 -81
  296. package/src/runtime/prebundle.ts +81 -0
  297. package/src/runtime/production.ts +391 -0
  298. package/src/runtime/release-graph.ts +334 -0
  299. package/src/runtime/vendor-build.ts +724 -13
  300. package/src/runtime/vendor.ts +16 -3
  301. package/src/types.ts +2 -0
  302. package/src/utils/fs.ts +89 -3
@@ -0,0 +1,851 @@
1
+ // @bun
2
+ import {
3
+ scanRootParamTypes
4
+ } from "./index-v1ags1na.js";
5
+ import {
6
+ getNextConfig
7
+ } from "./index-6e4fqv30.js";
8
+ import {
9
+ ensureDir,
10
+ toPosixPath
11
+ } from "./index-20ppawv7.js";
12
+
13
+ // src/compat/typed-routes/generate.ts
14
+ import { existsSync as existsSync2 } from "fs";
15
+ import { readFile, writeFile } from "fs/promises";
16
+ import path2 from "path";
17
+
18
+ // src/compat/typed-routes/manifest.ts
19
+ import { existsSync } from "fs";
20
+ import { readdir } from "fs/promises";
21
+ import path from "path";
22
+ var PAGE_EXTENSIONS = ["tsx", "ts", "jsx", "js", "mdx", "md"];
23
+ var LAYOUT_NAMES = new Set(PAGE_EXTENSIONS.map((ext) => `layout.${ext}`));
24
+ function isGroupSegment(name) {
25
+ return name.startsWith("(") && name.endsWith(")");
26
+ }
27
+ function isSlotSegment(name) {
28
+ return name.startsWith("@");
29
+ }
30
+ function decodeLiteral(segment) {
31
+ return segment.replace(/%5[Ff]/g, "_");
32
+ }
33
+ function groupsFromBracketRoute(route) {
34
+ const groups = {};
35
+ let pos = 1;
36
+ for (const segment of route.split("/").filter(Boolean)) {
37
+ const optionalCatchAll = /^\[\[\.\.\.(.+)\]\]$/.exec(segment);
38
+ if (optionalCatchAll?.[1]) {
39
+ groups[optionalCatchAll[1]] = { pos: pos++, repeat: true, optional: true };
40
+ continue;
41
+ }
42
+ const catchAll = /^\[\.\.\.(.+)\]$/.exec(segment);
43
+ if (catchAll?.[1]) {
44
+ groups[catchAll[1]] = { pos: pos++, repeat: true, optional: false };
45
+ continue;
46
+ }
47
+ const param = /^\[(.+)\]$/.exec(segment);
48
+ if (param?.[1]) {
49
+ groups[param[1]] = { pos: pos++, repeat: false, optional: false };
50
+ }
51
+ }
52
+ return groups;
53
+ }
54
+ function bracketRouteFromEntry(entry) {
55
+ const segments = entry.route.split("/").filter(Boolean).map((segment) => {
56
+ const catchAll = /^:(.+)\*$/.exec(segment);
57
+ if (catchAll?.[1]) {
58
+ const name = catchAll[1];
59
+ return name === entry.catchAll && entry.catchAllOptional ? `[[...${name}]]` : `[...${name}]`;
60
+ }
61
+ const param = /^:(.+)$/.exec(segment);
62
+ if (param?.[1])
63
+ return `[${param[1]}]`;
64
+ return segment;
65
+ });
66
+ return `/${segments.join("/")}`.replace(/\/$/, "") || "/";
67
+ }
68
+ function bracketRouteFromDir(relativeDir) {
69
+ const segments = [];
70
+ for (const segment of relativeDir.split("/").filter(Boolean)) {
71
+ if (isGroupSegment(segment) || isSlotSegment(segment))
72
+ continue;
73
+ if (/^\[\[?\.\.\..+\]\]?$/.test(segment) || /^\[.+\]$/.test(segment)) {
74
+ segments.push(segment);
75
+ } else {
76
+ segments.push(decodeLiteral(segment));
77
+ }
78
+ }
79
+ return `/${segments.join("/")}`.replace(/\/$/, "") || "/";
80
+ }
81
+ function pagesRouteFromRelative(relative) {
82
+ const withoutExt = relative.replace(/\.[^.]+$/, "");
83
+ const trimmed = withoutExt.replace(/\/index$/, "").replace(/^index$/, "");
84
+ const route = `/${trimmed}`.replace(/\/$/, "") || "/";
85
+ return route;
86
+ }
87
+ async function walkFiles(dir) {
88
+ if (!existsSync(dir))
89
+ return [];
90
+ const out = [];
91
+ const entries = await readdir(dir, { withFileTypes: true });
92
+ for (const entry of entries) {
93
+ const full = path.join(dir, entry.name);
94
+ if (entry.isDirectory())
95
+ out.push(...await walkFiles(full));
96
+ else
97
+ out.push(full);
98
+ }
99
+ return out;
100
+ }
101
+ function isPrivate(relativeDir) {
102
+ return relativeDir.split("/").some((seg) => seg.startsWith("_") && !isGroupSegment(seg) && !isSlotSegment(seg));
103
+ }
104
+ function convertCustomRouteSource(source) {
105
+ const normalized = source.startsWith("/") ? source : `/${source}`;
106
+ const converted = normalized.split("/").map((segment) => {
107
+ const optional = /^:(.+)\*$/.exec(segment);
108
+ if (optional?.[1])
109
+ return `[[...${optional[1]}]]`;
110
+ const catchAll = /^:(.+)\+$/.exec(segment);
111
+ if (catchAll?.[1])
112
+ return `[...${catchAll[1]}]`;
113
+ const param = /^:([A-Za-z0-9_]+)$/.exec(segment);
114
+ if (param?.[1])
115
+ return `[${param[1]}]`;
116
+ return segment;
117
+ }).join("/");
118
+ return [converted.replace(/\/$/, "") || "/"];
119
+ }
120
+ async function buildRouteTypesManifest({
121
+ config,
122
+ routes,
123
+ nextConfig
124
+ }) {
125
+ const relApp = (file) => toPosixPath(path.relative(config.root, file));
126
+ const isHybrid = config.appPath.includes("pnext-pages-compat");
127
+ const sourceAppPath = (entry) => {
128
+ if (!isHybrid)
129
+ return entry.file;
130
+ const basename = entry.kind === "page" ? /^page\.(?:tsx?|jsx?|mdx?)$/ : /^route\.(?:tsx?|jsx?)$/;
131
+ const source = entry.sourceFiles.find((file) => {
132
+ const normalized = toPosixPath(file);
133
+ return normalized.includes("/source-app/") && basename.test(path.basename(normalized));
134
+ });
135
+ if (!source)
136
+ return;
137
+ const relative = toPosixPath(source).split("/source-app/")[1];
138
+ return relative ? path.join(config.root, "app", relative) : undefined;
139
+ };
140
+ const manifest = {
141
+ appRoutes: {},
142
+ pageRoutes: {},
143
+ layoutRoutes: {},
144
+ appRouteHandlerRoutes: {},
145
+ redirectRoutes: {},
146
+ rewriteRoutes: {},
147
+ appPagePaths: new Set,
148
+ pagesRouterPagePaths: new Set,
149
+ layoutPaths: new Set,
150
+ appRouteHandlers: new Set,
151
+ pageApiRoutes: new Set,
152
+ filePathToRoute: new Map
153
+ };
154
+ const hybridFilteredRoutes = isHybrid ? routes.filter((entry) => {
155
+ const file = entry.file;
156
+ if (!file.includes("pnext-pages-compat"))
157
+ return true;
158
+ const sourceFiles = entry.sourceFiles ?? [];
159
+ const isPagesWrapper = sourceFiles.some((sf) => sf.includes("source-pages"));
160
+ if (isPagesWrapper)
161
+ return false;
162
+ return true;
163
+ }) : routes;
164
+ for (const entry of hybridFilteredRoutes) {
165
+ if (entry.synthetic || entry.interception || entry.metadataRoute)
166
+ continue;
167
+ const source = sourceAppPath(entry);
168
+ if (!source)
169
+ continue;
170
+ const bracket = bracketRouteFromEntry(entry);
171
+ const rel = relApp(source);
172
+ const info = { path: rel, groups: groupsFromBracketRoute(bracket) };
173
+ if (entry.kind === "page") {
174
+ if (!manifest.appRoutes[bracket])
175
+ manifest.appRoutes[bracket] = info;
176
+ } else {
177
+ if (!manifest.appRouteHandlerRoutes[bracket])
178
+ manifest.appRouteHandlerRoutes[bracket] = info;
179
+ manifest.appRouteHandlers.add(rel);
180
+ manifest.filePathToRoute.set(rel, bracket);
181
+ }
182
+ }
183
+ const appFiles = await walkFiles(isHybrid ? path.join(config.root, "app") : config.appPath);
184
+ const appPath = isHybrid ? path.join(config.root, "app") : config.appPath;
185
+ for (const file of appFiles) {
186
+ const relative = toPosixPath(path.relative(appPath, file));
187
+ const base = path.basename(relative);
188
+ if (!LAYOUT_NAMES.has(base))
189
+ continue;
190
+ const dir = path.dirname(relative) === "." ? "" : path.dirname(relative);
191
+ if (isPrivate(dir))
192
+ continue;
193
+ const bracket = bracketRouteFromDir(dir);
194
+ const rel = relApp(file);
195
+ if (!manifest.layoutRoutes[bracket]) {
196
+ manifest.layoutRoutes[bracket] = {
197
+ path: rel,
198
+ groups: groupsFromBracketRoute(bracket),
199
+ slots: []
200
+ };
201
+ }
202
+ manifest.layoutPaths.add(rel);
203
+ manifest.filePathToRoute.set(rel, bracket);
204
+ }
205
+ for (const file of appFiles) {
206
+ const relative = toPosixPath(path.relative(appPath, file));
207
+ const segments = relative.split("/");
208
+ let slotIndex = -1;
209
+ for (let i = segments.length - 1;i >= 0; i--) {
210
+ if (isSlotSegment(segments[i])) {
211
+ slotIndex = i;
212
+ break;
213
+ }
214
+ }
215
+ if (slotIndex === -1)
216
+ continue;
217
+ const slotName = segments[slotIndex].slice(1);
218
+ const ownerDir = segments.slice(0, slotIndex).join("/");
219
+ if (isPrivate(ownerDir))
220
+ continue;
221
+ const ownerRoute = bracketRouteFromDir(ownerDir);
222
+ const layout = manifest.layoutRoutes[ownerRoute];
223
+ if (layout && !layout.slots.includes(slotName))
224
+ layout.slots.push(slotName);
225
+ }
226
+ const PAGE_BASENAMES = new Set(PAGE_EXTENSIONS.map((ext) => `page.${ext}`));
227
+ for (const file of appFiles) {
228
+ const relative = toPosixPath(path.relative(appPath, file));
229
+ if (!PAGE_BASENAMES.has(path.basename(relative)))
230
+ continue;
231
+ const dir = path.dirname(relative) === "." ? "" : path.dirname(relative);
232
+ if (isPrivate(dir))
233
+ continue;
234
+ const route = bracketRouteFromDir(dir);
235
+ if (!manifest.appRoutes[route])
236
+ continue;
237
+ const rel = relApp(file);
238
+ manifest.appPagePaths.add(rel);
239
+ manifest.filePathToRoute.set(rel, route);
240
+ }
241
+ const pagesDir = path.join(config.root, "pages");
242
+ for (const file of await walkFiles(pagesDir)) {
243
+ const relative = toPosixPath(path.relative(pagesDir, file));
244
+ if (!PAGE_EXTENSIONS.some((ext) => relative.endsWith(`.${ext}`)))
245
+ continue;
246
+ const base = path.basename(relative);
247
+ if (base.startsWith("_app.") || base.startsWith("_document.") || base.startsWith("_error.")) {
248
+ continue;
249
+ }
250
+ const rel = relApp(file);
251
+ const isApi = relative === "api" || relative.startsWith("api/");
252
+ const route = pagesRouteFromRelative(relative);
253
+ if (isApi) {
254
+ manifest.pageApiRoutes.add(rel);
255
+ manifest.filePathToRoute.set(rel, route);
256
+ } else {
257
+ manifest.pageRoutes[route] = { path: rel, groups: groupsFromBracketRoute(route) };
258
+ manifest.pagesRouterPagePaths.add(rel);
259
+ manifest.filePathToRoute.set(rel, route);
260
+ }
261
+ }
262
+ const redirects = nextConfig.redirects;
263
+ if (typeof redirects === "function") {
264
+ const list = await redirects();
265
+ for (const item of list ?? []) {
266
+ for (const route of convertCustomRouteSource(item.source)) {
267
+ manifest.redirectRoutes[route] = { path: route, groups: groupsFromBracketRoute(route) };
268
+ }
269
+ }
270
+ }
271
+ const rewrites = nextConfig.rewrites;
272
+ if (typeof rewrites === "function") {
273
+ const result = await rewrites();
274
+ const sources = Array.isArray(result) ? result : [...result?.beforeFiles ?? [], ...result?.afterFiles ?? [], ...result?.fallback ?? []];
275
+ for (const item of sources) {
276
+ for (const route of convertCustomRouteSource(item.source)) {
277
+ manifest.rewriteRoutes[route] = { path: route, groups: groupsFromBracketRoute(route) };
278
+ }
279
+ }
280
+ }
281
+ return manifest;
282
+ }
283
+
284
+ // src/compat/typed-routes/typegen.ts
285
+ function isDynamicRoute(route) {
286
+ return /\[.+\]/.test(route);
287
+ }
288
+ function generateRouteTypes(manifest) {
289
+ const appRoutes = Object.keys(manifest.appRoutes).sort();
290
+ const pageRoutes = Object.keys(manifest.pageRoutes).sort();
291
+ const layoutRoutes = Object.keys(manifest.layoutRoutes).sort();
292
+ const redirectRoutes = Object.keys(manifest.redirectRoutes).sort();
293
+ const rewriteRoutes = Object.keys(manifest.rewriteRoutes).sort();
294
+ const appRouteHandlerRoutes = Object.keys(manifest.appRouteHandlerRoutes).sort();
295
+ const hasAppRouteHandlers = appRouteHandlerRoutes.length > 0;
296
+ const union = (list) => list.map((route) => JSON.stringify(route)).join(" | ");
297
+ let result = "";
298
+ result += appRoutes.length > 0 ? `type AppRoutes = ${union(appRoutes)}
299
+ ` : `type AppRoutes = never
300
+ `;
301
+ if (hasAppRouteHandlers) {
302
+ result += `type AppRouteHandlerRoutes = ${union(appRouteHandlerRoutes)}
303
+ `;
304
+ }
305
+ result += pageRoutes.length > 0 ? `type PageRoutes = ${union(pageRoutes)}
306
+ ` : `type PageRoutes = never
307
+ `;
308
+ result += layoutRoutes.length > 0 ? `type LayoutRoutes = ${union(layoutRoutes)}
309
+ ` : `type LayoutRoutes = never
310
+ `;
311
+ result += redirectRoutes.length > 0 ? `type RedirectRoutes = ${union(redirectRoutes)}
312
+ ` : `type RedirectRoutes = never
313
+ `;
314
+ result += rewriteRoutes.length > 0 ? `type RewriteRoutes = ${union(rewriteRoutes)}
315
+ ` : `type RewriteRoutes = never
316
+ `;
317
+ const routeUnionParts = [
318
+ "AppRoutes",
319
+ "PageRoutes",
320
+ "LayoutRoutes",
321
+ "RedirectRoutes",
322
+ "RewriteRoutes"
323
+ ];
324
+ if (hasAppRouteHandlers)
325
+ routeUnionParts.push("AppRouteHandlerRoutes");
326
+ result += `type Routes = ${routeUnionParts.join(" | ")}
327
+ `;
328
+ return result;
329
+ }
330
+ function generateParamTypes(manifest) {
331
+ const allRoutes = {
332
+ ...manifest.appRoutes,
333
+ ...manifest.appRouteHandlerRoutes,
334
+ ...manifest.pageRoutes,
335
+ ...manifest.layoutRoutes,
336
+ ...manifest.redirectRoutes,
337
+ ...manifest.rewriteRoutes
338
+ };
339
+ let paramTypes = `interface ParamMap {
340
+ `;
341
+ const sortedRoutes = Object.entries(allRoutes).sort(([a], [b]) => a.localeCompare(b));
342
+ for (const [route, routeInfo] of sortedRoutes) {
343
+ const groups = routeInfo.groups;
344
+ if (!isDynamicRoute(route) || Object.keys(groups ?? {}).length === 0) {
345
+ paramTypes += ` ${JSON.stringify(route)}: {}
346
+ `;
347
+ continue;
348
+ }
349
+ let paramType = "{";
350
+ for (const [key, group] of Object.entries(groups)) {
351
+ const escapedKey = JSON.stringify(key);
352
+ if (group.repeat) {
353
+ paramType += group.optional ? ` ${escapedKey}?: string[];` : ` ${escapedKey}: string[];`;
354
+ } else {
355
+ paramType += group.optional ? ` ${escapedKey}?: string;` : ` ${escapedKey}: string;`;
356
+ }
357
+ }
358
+ paramType += " }";
359
+ paramTypes += ` ${JSON.stringify(route)}: ${paramType}
360
+ `;
361
+ }
362
+ paramTypes += `}
363
+ `;
364
+ return paramTypes;
365
+ }
366
+ function generateLayoutSlotMap(manifest) {
367
+ let slotMap = `interface LayoutSlotMap {
368
+ `;
369
+ const sorted = Object.entries(manifest.layoutRoutes).sort(([a], [b]) => a.localeCompare(b));
370
+ for (const [route, routeInfo] of sorted) {
371
+ const slots = [...routeInfo.slots].sort();
372
+ slotMap += slots.length > 0 ? ` ${JSON.stringify(route)}: ${slots.map((slot) => JSON.stringify(slot)).join(" | ")}
373
+ ` : ` ${JSON.stringify(route)}: never
374
+ `;
375
+ }
376
+ slotMap += `}
377
+ `;
378
+ return slotMap;
379
+ }
380
+ function formatRouteToRouteType(route) {
381
+ const isDynamic = isDynamicRoute(route);
382
+ let routeType = route;
383
+ if (isDynamic) {
384
+ routeType = route.split("/").map((part) => {
385
+ if (part.startsWith("[") && part.endsWith("]")) {
386
+ if (part.startsWith("[[...") && part.endsWith("]]"))
387
+ return "${OptionalCatchAllSlug<T>}";
388
+ if (part.startsWith("[..."))
389
+ return "${CatchAllSlug<T>}";
390
+ return "${SafeSlug<T>}";
391
+ }
392
+ return part;
393
+ }).join("/");
394
+ }
395
+ return { isDynamic, routeType };
396
+ }
397
+ function serializeRouteTypes(routeTypes) {
398
+ routeTypes.sort(([a], [b]) => a.localeCompare(b));
399
+ let union = "";
400
+ for (const [route, cause] of routeTypes) {
401
+ union += `
402
+ | \`${route}\` // ${cause}`;
403
+ }
404
+ return union;
405
+ }
406
+ function generateRouteTypesFile(manifest) {
407
+ const routeTypes = generateRouteTypes(manifest);
408
+ const paramTypes = generateParamTypes(manifest);
409
+ const layoutSlotMap = generateLayoutSlotMap(manifest);
410
+ const hasAppRouteHandlers = Object.keys(manifest.appRouteHandlerRoutes).length > 0;
411
+ const routeExports = [
412
+ "AppRoutes",
413
+ "PageRoutes",
414
+ "LayoutRoutes",
415
+ "RedirectRoutes",
416
+ "RewriteRoutes",
417
+ "ParamMap"
418
+ ];
419
+ if (hasAppRouteHandlers)
420
+ routeExports.push("AppRouteHandlerRoutes");
421
+ const exportStatement = `export type { ${routeExports.join(", ")} }`;
422
+ const routeContextInterface = hasAppRouteHandlers ? `
423
+
424
+ /**
425
+ * Context for Next.js App Router route handlers
426
+ * @example
427
+ * \`\`\`tsx
428
+ * export async function GET(request: NextRequest, context: RouteContext<'/api/users/[id]'>) {
429
+ * const { id } = await context.params
430
+ * return Response.json({ id })
431
+ * }
432
+ * \`\`\`
433
+ */
434
+ interface RouteContext<AppRouteHandlerRoute extends AppRouteHandlerRoutes> {
435
+ params: Promise<ParamMap[AppRouteHandlerRoute]>
436
+ }` : "";
437
+ return `// This file is generated automatically by Next.js
438
+ // Do not edit this file manually
439
+
440
+ ${routeTypes}
441
+
442
+ ${paramTypes}
443
+
444
+ export type ParamsOf<Route extends Routes> = ParamMap[Route]
445
+
446
+ ${layoutSlotMap}
447
+
448
+ ${exportStatement}
449
+
450
+ declare global {
451
+ /**
452
+ * Props for Next.js App Router page components
453
+ * @example
454
+ * \`\`\`tsx
455
+ * export default function Page(props: PageProps<'/blog/[slug]'>) {
456
+ * const { slug } = await props.params
457
+ * return <div>Blog post: {slug}</div>
458
+ * }
459
+ * \`\`\`
460
+ */
461
+ interface PageProps<AppRoute extends AppRoutes> {
462
+ params: Promise<ParamMap[AppRoute]>
463
+ searchParams: Promise<Record<string, string | string[] | undefined>>
464
+ }
465
+
466
+ /**
467
+ * Props for Next.js App Router layout components
468
+ * @example
469
+ * \`\`\`tsx
470
+ * export default function Layout(props: LayoutProps<'/dashboard'>) {
471
+ * return <div>{props.children}</div>
472
+ * }
473
+ * \`\`\`
474
+ */
475
+ type LayoutProps<LayoutRoute extends LayoutRoutes> = {
476
+ params: Promise<ParamMap[LayoutRoute]>
477
+ searchParams: Promise<Record<string, string | string[] | undefined>>
478
+ children: React.ReactNode
479
+ } & {
480
+ [K in LayoutSlotMap[LayoutRoute]]: React.ReactNode
481
+ }${routeContextInterface}
482
+ }
483
+ `;
484
+ }
485
+ function generateLinkTypesFile(manifest) {
486
+ const visited = new Set;
487
+ const staticRouteTypes = [];
488
+ const dynamicRouteTypes = [];
489
+ for (const routeMap of [
490
+ manifest.appRoutes,
491
+ manifest.pageRoutes,
492
+ manifest.redirectRoutes,
493
+ manifest.rewriteRoutes,
494
+ manifest.appRouteHandlerRoutes
495
+ ]) {
496
+ for (const route in routeMap) {
497
+ if (visited.has(route))
498
+ continue;
499
+ visited.add(route);
500
+ const { isDynamic, routeType } = formatRouteToRouteType(route);
501
+ const cause = routeMap[route].path;
502
+ (isDynamic ? dynamicRouteTypes : staticRouteTypes).push([routeType, cause]);
503
+ }
504
+ }
505
+ for (const filePath of manifest.pageApiRoutes) {
506
+ if (visited.has(filePath))
507
+ continue;
508
+ visited.add(filePath);
509
+ const { isDynamic, routeType } = formatRouteToRouteType(filePath);
510
+ (isDynamic ? dynamicRouteTypes : staticRouteTypes).push([routeType, filePath]);
511
+ }
512
+ const serializedStaticRouteTypes = serializeRouteTypes(staticRouteTypes);
513
+ const serializedDynamicRouteTypes = serializeRouteTypes(dynamicRouteTypes);
514
+ const routeTypesFallback = !serializedStaticRouteTypes && !serializedDynamicRouteTypes ? "string & {}" : "";
515
+ return `// This file is generated automatically by Next.js
516
+ // Do not edit this file manually
517
+
518
+ // Type definitions for Next.js routes
519
+
520
+ /**
521
+ * Internal types used by the Next.js router and Link component.
522
+ * These types are not meant to be used directly.
523
+ * @internal
524
+ */
525
+ declare namespace __next_route_internal_types__ {
526
+ type SearchOrHash = \`?\${string}\` | \`#\${string}\`
527
+ type WithProtocol = \`\${string}:\${string}\`
528
+
529
+ type Suffix = '' | SearchOrHash
530
+
531
+ type SafeSlug<S extends string> = S extends \`\${string}/\${string}\`
532
+ ? never
533
+ : S extends \`\${string}\${SearchOrHash}\`
534
+ ? never
535
+ : S extends ''
536
+ ? never
537
+ : S
538
+
539
+ type CatchAllSlug<S extends string> = S extends \`\${string}\${SearchOrHash}\`
540
+ ? never
541
+ : S extends ''
542
+ ? never
543
+ : S
544
+
545
+ type OptionalCatchAllSlug<S extends string> =
546
+ S extends \`\${string}\${SearchOrHash}\` ? never : S
547
+
548
+ type StaticRoutes = ${serializedStaticRouteTypes || "never"}
549
+ type DynamicRoutes<T extends string = string> = ${serializedDynamicRouteTypes || "never"}
550
+
551
+ type RouteImpl<T> = ${routeTypesFallback || `
552
+ ${"| StaticRoutes"}
553
+ | SearchOrHash
554
+ | WithProtocol
555
+ | \`\${StaticRoutes}\${SearchOrHash}\`
556
+ | (T extends \`\${DynamicRoutes<infer _>}\${Suffix}\` ? T : never)
557
+ `}
558
+ }
559
+
560
+ declare module 'next' {
561
+ export { default } from 'next/types.js'
562
+ export * from 'next/types.js'
563
+
564
+ export type Route<T extends string = string> =
565
+ __next_route_internal_types__.RouteImpl<T>
566
+ }
567
+
568
+ declare module 'next/link' {
569
+ export { useLinkStatus } from 'next/dist/client/link.js'
570
+
571
+ import type { LinkProps as OriginalLinkProps } from 'next/dist/client/link.js'
572
+ import type { AnchorHTMLAttributes, DetailedHTMLProps } from 'react'
573
+ import type { UrlObject } from 'url'
574
+
575
+ type LinkRestProps = Omit<
576
+ Omit<
577
+ DetailedHTMLProps<
578
+ AnchorHTMLAttributes<HTMLAnchorElement>,
579
+ HTMLAnchorElement
580
+ >,
581
+ keyof OriginalLinkProps
582
+ > &
583
+ OriginalLinkProps,
584
+ 'href'
585
+ >
586
+
587
+ export type LinkProps<RouteInferType> = LinkRestProps & {
588
+ /**
589
+ * The path or URL to navigate to. This is the only required prop. It can also be an object.
590
+ * @see https://nextjs.org/docs/api-reference/next/link
591
+ */
592
+ href: __next_route_internal_types__.RouteImpl<RouteInferType> | UrlObject
593
+ }
594
+
595
+ export default function Link<RouteType>(props: LinkProps<RouteType>): JSX.Element
596
+ }
597
+
598
+ declare module 'next/navigation' {
599
+ export * from 'next/dist/client/components/navigation.js'
600
+
601
+ import type { NavigateOptions, PrefetchOptions, AppRouterInstance as OriginalAppRouterInstance } from 'next/dist/shared/lib/app-router-context.shared-runtime.js'
602
+ import type { RedirectType } from 'next/dist/client/components/redirect-error.js'
603
+
604
+ interface AppRouterInstance extends OriginalAppRouterInstance {
605
+ /**
606
+ * Navigate to the provided href.
607
+ * Pushes a new history entry.
608
+ */
609
+ push<RouteType>(href: __next_route_internal_types__.RouteImpl<RouteType>, options?: NavigateOptions): void
610
+ /**
611
+ * Navigate to the provided href.
612
+ * Replaces the current history entry.
613
+ */
614
+ replace<RouteType>(href: __next_route_internal_types__.RouteImpl<RouteType>, options?: NavigateOptions): void
615
+ /**
616
+ * Prefetch the provided href.
617
+ */
618
+ prefetch<RouteType>(href: __next_route_internal_types__.RouteImpl<RouteType>, options?: PrefetchOptions): void
619
+ }
620
+
621
+ export function useRouter(): AppRouterInstance;
622
+
623
+ export function redirect<RouteType>(
624
+ url: __next_route_internal_types__.RouteImpl<RouteType>,
625
+ type?: RedirectType
626
+ ): never;
627
+
628
+ export function permanentRedirect<RouteType>(
629
+ url: __next_route_internal_types__.RouteImpl<RouteType>,
630
+ type?: RedirectType
631
+ ): never;
632
+ }
633
+
634
+ declare module 'next/form' {
635
+ import type { FormProps as OriginalFormProps } from 'next/dist/client/form.js'
636
+
637
+ type FormRestProps = Omit<OriginalFormProps, 'action'>
638
+
639
+ export type FormProps<RouteInferType> = {
640
+ action: __next_route_internal_types__.RouteImpl<RouteInferType> | ((formData: FormData) => void)
641
+ } & FormRestProps
642
+
643
+ export default function Form<RouteType>(props: FormProps<RouteType>): JSX.Element
644
+ }
645
+ `;
646
+ }
647
+ function generateValidatorFile(manifest, toImportSpecifier) {
648
+ const generateValidations = (paths, type, pathToRouteMap) => paths.sort().filter((filePath) => filePath.endsWith(".ts") || filePath.endsWith(".tsx")).filter((filePath) => type !== "AppPageConfig" || filePath.endsWith("page.ts") || filePath.endsWith("page.tsx")).map((filePath) => {
649
+ const importPath = toImportSpecifier(filePath);
650
+ const route = pathToRouteMap?.get(filePath);
651
+ const typeWithRoute = route && (type === "AppPageConfig" || type === "LayoutConfig" || type === "RouteHandlerConfig") ? `${type}<${JSON.stringify(route)}>` : type;
652
+ return `// Validate ${filePath}
653
+ {
654
+ type __IsExpected<Specific extends ${typeWithRoute}> = Specific
655
+ const handler = {} as typeof import(${JSON.stringify(importPath.replace(/\.tsx?$/, ".js"))})
656
+ type __Check = __IsExpected<typeof handler>
657
+ // @ts-ignore
658
+ type __Unused = __Check
659
+ }`;
660
+ }).join(`
661
+
662
+ `);
663
+ const appPageValidations = generateValidations([...manifest.appPagePaths].sort(), "AppPageConfig", manifest.filePathToRoute);
664
+ const appRouteHandlerValidations = generateValidations([...manifest.appRouteHandlers].sort(), "RouteHandlerConfig", manifest.filePathToRoute);
665
+ const pagesRouterPageValidations = generateValidations([...manifest.pagesRouterPagePaths].sort(), "PagesPageConfig");
666
+ const pagesApiRouteValidations = generateValidations([...manifest.pageApiRoutes].sort(), "ApiRouteConfig");
667
+ const layoutValidations = generateValidations([...manifest.layoutPaths].sort(), "LayoutConfig", manifest.filePathToRoute);
668
+ const hasAppRouteHandlers = Object.keys(manifest.appRouteHandlerRoutes).length > 0;
669
+ let typeDefinitions = "";
670
+ if (appPageValidations) {
671
+ typeDefinitions += `type AppPageConfig<Route extends AppRoutes = AppRoutes> = {
672
+ default: React.JSXElementConstructor<PageProps<Route>> | ((props: { params: Promise<ParamMap[Route]>, searchParams: Promise<any> }) => React.ReactNode | Promise<React.ReactNode> | never | void | Promise<void>)
673
+ generateStaticParams?: (props: { params: ParamMap[Route] }) => Promise<any[]> | any[]
674
+ generateMetadata?: (
675
+ props: { params: Promise<ParamMap[Route]> } & any,
676
+ parent: ResolvingMetadata
677
+ ) => Promise<any> | any
678
+ generateViewport?: (
679
+ props: { params: Promise<ParamMap[Route]> } & any,
680
+ parent: ResolvingViewport
681
+ ) => Promise<any> | any
682
+ metadata?: any
683
+ viewport?: any
684
+ }
685
+
686
+ `;
687
+ }
688
+ if (pagesRouterPageValidations) {
689
+ typeDefinitions += `type PagesPageConfig = {
690
+ default: React.ComponentType<any> | ((props: any) => React.ReactNode | Promise<React.ReactNode> | never | void)
691
+ getStaticProps?: (context: any) => Promise<any> | any
692
+ getStaticPaths?: (context: any) => Promise<any> | any
693
+ getServerSideProps?: (context: any) => Promise<any> | any
694
+ getInitialProps?: (context: any) => Promise<any> | any
695
+ /**
696
+ * Segment configuration for legacy Pages Router pages.
697
+ * Validated at build-time by parsePagesSegmentConfig.
698
+ */
699
+ config?: {
700
+ maxDuration?: number
701
+ runtime?: 'edge' | 'experimental-edge' | 'nodejs' | string // necessary unless config is exported as const
702
+ regions?: string[]
703
+ }
704
+ }
705
+
706
+ `;
707
+ }
708
+ if (layoutValidations) {
709
+ typeDefinitions += `type LayoutConfig<Route extends LayoutRoutes = LayoutRoutes> = {
710
+ default: React.ComponentType<LayoutProps<Route>> | ((props: LayoutProps<Route>) => React.ReactNode | Promise<React.ReactNode> | never | void | Promise<void>)
711
+ generateStaticParams?: (props: { params: ParamMap[Route] }) => Promise<any[]> | any[]
712
+ generateMetadata?: (
713
+ props: { params: Promise<ParamMap[Route]> } & any,
714
+ parent: ResolvingMetadata
715
+ ) => Promise<any> | any
716
+ generateViewport?: (
717
+ props: { params: Promise<ParamMap[Route]> } & any,
718
+ parent: ResolvingViewport
719
+ ) => Promise<any> | any
720
+ metadata?: any
721
+ viewport?: any
722
+ }
723
+
724
+ `;
725
+ }
726
+ if (appRouteHandlerValidations) {
727
+ typeDefinitions += `type RouteHandlerConfig<Route extends AppRouteHandlerRoutes = AppRouteHandlerRoutes> = {
728
+ GET?: (request: NextRequest, context: { params: Promise<ParamMap[Route]> }) => Promise<Response | void> | Response | void
729
+ POST?: (request: NextRequest, context: { params: Promise<ParamMap[Route]> }) => Promise<Response | void> | Response | void
730
+ PUT?: (request: NextRequest, context: { params: Promise<ParamMap[Route]> }) => Promise<Response | void> | Response | void
731
+ PATCH?: (request: NextRequest, context: { params: Promise<ParamMap[Route]> }) => Promise<Response | void> | Response | void
732
+ DELETE?: (request: NextRequest, context: { params: Promise<ParamMap[Route]> }) => Promise<Response | void> | Response | void
733
+ HEAD?: (request: NextRequest, context: { params: Promise<ParamMap[Route]> }) => Promise<Response | void> | Response | void
734
+ OPTIONS?: (request: NextRequest, context: { params: Promise<ParamMap[Route]> }) => Promise<Response | void> | Response | void
735
+ }
736
+
737
+ `;
738
+ }
739
+ if (pagesApiRouteValidations) {
740
+ typeDefinitions += `type ApiRouteConfig = {
741
+ default: (req: any, res: any) => ReturnType<NextApiHandler>
742
+ config?: {
743
+ api?: {
744
+ bodyParser?: boolean | { sizeLimit?: number | string }
745
+ responseLimit?: string | number | boolean
746
+ externalResolver?: boolean
747
+ }
748
+ runtime?: 'edge' | 'experimental-edge' | 'nodejs' | string // necessary unless config is exported as const
749
+ maxDuration?: number
750
+ }
751
+ }
752
+
753
+ `;
754
+ }
755
+ const routeImports = [];
756
+ if (appPageValidations)
757
+ routeImports.push("AppRoutes");
758
+ if (layoutValidations)
759
+ routeImports.push("LayoutRoutes");
760
+ if (appPageValidations || layoutValidations || appRouteHandlerValidations)
761
+ routeImports.push("ParamMap");
762
+ if (hasAppRouteHandlers)
763
+ routeImports.push("AppRouteHandlerRoutes");
764
+ const routeImportStatement = routeImports.length > 0 ? `import type { ${routeImports.join(", ")} } from "./routes.js"` : "";
765
+ const nextRequestImport = hasAppRouteHandlers ? `import type { NextRequest } from 'next/server.js'
766
+ ` : "";
767
+ const nextTypes = [];
768
+ if (pagesApiRouteValidations)
769
+ nextTypes.push("NextApiHandler");
770
+ if (appPageValidations || layoutValidations)
771
+ nextTypes.push("ResolvingMetadata", "ResolvingViewport");
772
+ const nextTypesImport = nextTypes.length > 0 ? `import type { ${nextTypes.join(", ")} } from "next/types.js"
773
+ ` : "";
774
+ return `// This file is generated automatically by Next.js
775
+ // Do not edit this file manually
776
+ // This file validates that all pages and layouts export the correct types
777
+
778
+ ${routeImportStatement}
779
+ ${nextTypesImport}${nextRequestImport}
780
+ ${typeDefinitions}
781
+ ${appPageValidations}
782
+
783
+ ${appRouteHandlerValidations}
784
+
785
+ ${pagesRouterPageValidations}
786
+
787
+ ${pagesApiRouteValidations}
788
+
789
+ ${layoutValidations}
790
+ `;
791
+ }
792
+
793
+ // src/compat/typed-routes/generate.ts
794
+ async function writeIfChanged(file, source) {
795
+ if (existsSync2(file) && await readFile(file, "utf8") === source)
796
+ return;
797
+ await ensureDir(path2.dirname(file));
798
+ await writeFile(file, source);
799
+ }
800
+ async function generateTypedRoutes(config, routes) {
801
+ const nextConfig = getNextConfig();
802
+ const typedRoutes = nextConfig.typedRoutes === true;
803
+ const manifest = await buildRouteTypesManifest({ config, routes, nextConfig });
804
+ const typesDir = path2.join(config.root, ".next", "types");
805
+ await writeIfChanged(path2.join(typesDir, "routes.d.ts"), generateRouteTypesFile(manifest));
806
+ const toImportSpecifier = (rootRelativePath) => {
807
+ const abs = path2.join(config.root, rootRelativePath);
808
+ const rel = toPosixPath(path2.relative(typesDir, abs));
809
+ return rel.startsWith(".") ? rel : `./${rel}`;
810
+ };
811
+ await writeIfChanged(path2.join(typesDir, "validator.ts"), generateValidatorFile(manifest, toImportSpecifier));
812
+ if (typedRoutes) {
813
+ await writeIfChanged(path2.join(typesDir, "link.d.ts"), generateLinkTypesFile(manifest));
814
+ }
815
+ await writeIfChanged(path2.join(typesDir, "root-params.d.ts"), rootParamsTypesFile(scanRootParamTypes(path2.join(config.root, "app"))));
816
+ await writeNextEnv(config.root, typedRoutes);
817
+ }
818
+ function rootParamsTypesFile(rootParams) {
819
+ if (rootParams.size === 0) {
820
+ return `// Type definitions for Next.js root params (next/root-params)
821
+ // No root params detected.
822
+ export {}
823
+ `;
824
+ }
825
+ const order = ["string", "string[]", "undefined"];
826
+ const getters = [...rootParams.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([name, types]) => {
827
+ const union = order.filter((type) => types.has(type)).join(" | ");
828
+ return ` export function ${name}(): Promise<${union}>`;
829
+ });
830
+ return `// Type definitions for Next.js root params (next/root-params)
831
+
832
+ declare module 'next/root-params' {
833
+ ${getters.join(`
834
+ `)}
835
+ }
836
+ `;
837
+ }
838
+ async function writeNextEnv(root, typedRoutes) {
839
+ const lines = [
840
+ '/// <reference types="next" />',
841
+ 'import "./.next/types/routes.d.ts";',
842
+ 'import "./.next/types/root-params.d.ts";'
843
+ ];
844
+ if (typedRoutes)
845
+ lines.push('import "./.next/types/link.d.ts";');
846
+ lines.push("", "// NOTE: This file should not be edited", "");
847
+ await writeIfChanged(path2.join(root, "next-env.d.ts"), lines.join(`
848
+ `));
849
+ }
850
+
851
+ export { generateTypedRoutes };