vinext 0.0.0 → 0.0.1

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 (272) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1 -0
  3. package/dist/build/static-export.d.ts +78 -0
  4. package/dist/build/static-export.d.ts.map +1 -0
  5. package/dist/build/static-export.js +553 -0
  6. package/dist/build/static-export.js.map +1 -0
  7. package/dist/check.d.ts +52 -0
  8. package/dist/check.d.ts.map +1 -0
  9. package/dist/check.js +483 -0
  10. package/dist/check.js.map +1 -0
  11. package/dist/cli.d.ts +15 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +565 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/client/entry.d.ts +2 -0
  16. package/dist/client/entry.d.ts.map +1 -0
  17. package/dist/client/entry.js +85 -0
  18. package/dist/client/entry.js.map +1 -0
  19. package/dist/cloudflare/index.d.ts +8 -0
  20. package/dist/cloudflare/index.d.ts.map +1 -0
  21. package/dist/cloudflare/index.js +8 -0
  22. package/dist/cloudflare/index.js.map +1 -0
  23. package/dist/cloudflare/kv-cache-handler.d.ts +68 -0
  24. package/dist/cloudflare/kv-cache-handler.d.ts.map +1 -0
  25. package/dist/cloudflare/kv-cache-handler.js +304 -0
  26. package/dist/cloudflare/kv-cache-handler.js.map +1 -0
  27. package/dist/cloudflare/tpr.d.ts +78 -0
  28. package/dist/cloudflare/tpr.d.ts.map +1 -0
  29. package/dist/cloudflare/tpr.js +672 -0
  30. package/dist/cloudflare/tpr.js.map +1 -0
  31. package/dist/config/config-matchers.d.ts +106 -0
  32. package/dist/config/config-matchers.d.ts.map +1 -0
  33. package/dist/config/config-matchers.js +499 -0
  34. package/dist/config/config-matchers.js.map +1 -0
  35. package/dist/config/next-config.d.ts +153 -0
  36. package/dist/config/next-config.d.ts.map +1 -0
  37. package/dist/config/next-config.js +274 -0
  38. package/dist/config/next-config.js.map +1 -0
  39. package/dist/deploy.d.ts +87 -0
  40. package/dist/deploy.d.ts.map +1 -0
  41. package/dist/deploy.js +644 -0
  42. package/dist/deploy.js.map +1 -0
  43. package/dist/index.d.ts +156 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +3287 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/init.d.ts +55 -0
  48. package/dist/init.d.ts.map +1 -0
  49. package/dist/init.js +201 -0
  50. package/dist/init.js.map +1 -0
  51. package/dist/routing/app-router.d.ts +96 -0
  52. package/dist/routing/app-router.d.ts.map +1 -0
  53. package/dist/routing/app-router.js +815 -0
  54. package/dist/routing/app-router.js.map +1 -0
  55. package/dist/routing/pages-router.d.ts +52 -0
  56. package/dist/routing/pages-router.d.ts.map +1 -0
  57. package/dist/routing/pages-router.js +239 -0
  58. package/dist/routing/pages-router.js.map +1 -0
  59. package/dist/server/api-handler.d.ts +18 -0
  60. package/dist/server/api-handler.d.ts.map +1 -0
  61. package/dist/server/api-handler.js +169 -0
  62. package/dist/server/api-handler.js.map +1 -0
  63. package/dist/server/app-dev-server.d.ts +42 -0
  64. package/dist/server/app-dev-server.d.ts.map +1 -0
  65. package/dist/server/app-dev-server.js +2718 -0
  66. package/dist/server/app-dev-server.js.map +1 -0
  67. package/dist/server/app-router-entry.d.ts +18 -0
  68. package/dist/server/app-router-entry.d.ts.map +1 -0
  69. package/dist/server/app-router-entry.js +34 -0
  70. package/dist/server/app-router-entry.js.map +1 -0
  71. package/dist/server/dev-server.d.ts +40 -0
  72. package/dist/server/dev-server.d.ts.map +1 -0
  73. package/dist/server/dev-server.js +758 -0
  74. package/dist/server/dev-server.js.map +1 -0
  75. package/dist/server/html.d.ts +22 -0
  76. package/dist/server/html.d.ts.map +1 -0
  77. package/dist/server/html.js +29 -0
  78. package/dist/server/html.js.map +1 -0
  79. package/dist/server/image-optimization.d.ts +56 -0
  80. package/dist/server/image-optimization.d.ts.map +1 -0
  81. package/dist/server/image-optimization.js +103 -0
  82. package/dist/server/image-optimization.js.map +1 -0
  83. package/dist/server/instrumentation.d.ts +68 -0
  84. package/dist/server/instrumentation.d.ts.map +1 -0
  85. package/dist/server/instrumentation.js +90 -0
  86. package/dist/server/instrumentation.js.map +1 -0
  87. package/dist/server/isr-cache.d.ts +61 -0
  88. package/dist/server/isr-cache.d.ts.map +1 -0
  89. package/dist/server/isr-cache.js +134 -0
  90. package/dist/server/isr-cache.js.map +1 -0
  91. package/dist/server/metadata-routes.d.ts +103 -0
  92. package/dist/server/metadata-routes.d.ts.map +1 -0
  93. package/dist/server/metadata-routes.js +270 -0
  94. package/dist/server/metadata-routes.js.map +1 -0
  95. package/dist/server/middleware.d.ts +77 -0
  96. package/dist/server/middleware.d.ts.map +1 -0
  97. package/dist/server/middleware.js +228 -0
  98. package/dist/server/middleware.js.map +1 -0
  99. package/dist/server/prod-server.d.ts +78 -0
  100. package/dist/server/prod-server.d.ts.map +1 -0
  101. package/dist/server/prod-server.js +712 -0
  102. package/dist/server/prod-server.js.map +1 -0
  103. package/dist/shims/amp.d.ts +17 -0
  104. package/dist/shims/amp.d.ts.map +1 -0
  105. package/dist/shims/amp.js +21 -0
  106. package/dist/shims/amp.js.map +1 -0
  107. package/dist/shims/app.d.ts +12 -0
  108. package/dist/shims/app.d.ts.map +1 -0
  109. package/dist/shims/app.js +2 -0
  110. package/dist/shims/app.js.map +1 -0
  111. package/dist/shims/cache-runtime.d.ts +68 -0
  112. package/dist/shims/cache-runtime.d.ts.map +1 -0
  113. package/dist/shims/cache-runtime.js +437 -0
  114. package/dist/shims/cache-runtime.js.map +1 -0
  115. package/dist/shims/cache.d.ts +243 -0
  116. package/dist/shims/cache.d.ts.map +1 -0
  117. package/dist/shims/cache.js +415 -0
  118. package/dist/shims/cache.js.map +1 -0
  119. package/dist/shims/client-only.d.ts +18 -0
  120. package/dist/shims/client-only.d.ts.map +1 -0
  121. package/dist/shims/client-only.js +18 -0
  122. package/dist/shims/client-only.js.map +1 -0
  123. package/dist/shims/config.d.ts +27 -0
  124. package/dist/shims/config.d.ts.map +1 -0
  125. package/dist/shims/config.js +30 -0
  126. package/dist/shims/config.js.map +1 -0
  127. package/dist/shims/constants.d.ts +13 -0
  128. package/dist/shims/constants.d.ts.map +1 -0
  129. package/dist/shims/constants.js +13 -0
  130. package/dist/shims/constants.js.map +1 -0
  131. package/dist/shims/document.d.ts +33 -0
  132. package/dist/shims/document.d.ts.map +1 -0
  133. package/dist/shims/document.js +32 -0
  134. package/dist/shims/document.js.map +1 -0
  135. package/dist/shims/dynamic.d.ts +33 -0
  136. package/dist/shims/dynamic.d.ts.map +1 -0
  137. package/dist/shims/dynamic.js +148 -0
  138. package/dist/shims/dynamic.js.map +1 -0
  139. package/dist/shims/error-boundary.d.ts +33 -0
  140. package/dist/shims/error-boundary.d.ts.map +1 -0
  141. package/dist/shims/error-boundary.js +88 -0
  142. package/dist/shims/error-boundary.js.map +1 -0
  143. package/dist/shims/error.d.ts +16 -0
  144. package/dist/shims/error.d.ts.map +1 -0
  145. package/dist/shims/error.js +45 -0
  146. package/dist/shims/error.js.map +1 -0
  147. package/dist/shims/fetch-cache.d.ts +61 -0
  148. package/dist/shims/fetch-cache.d.ts.map +1 -0
  149. package/dist/shims/fetch-cache.js +307 -0
  150. package/dist/shims/fetch-cache.js.map +1 -0
  151. package/dist/shims/font-google.d.ts +122 -0
  152. package/dist/shims/font-google.d.ts.map +1 -0
  153. package/dist/shims/font-google.js +387 -0
  154. package/dist/shims/font-google.js.map +1 -0
  155. package/dist/shims/font-local.d.ts +61 -0
  156. package/dist/shims/font-local.d.ts.map +1 -0
  157. package/dist/shims/font-local.js +303 -0
  158. package/dist/shims/font-local.js.map +1 -0
  159. package/dist/shims/form.d.ts +30 -0
  160. package/dist/shims/form.d.ts.map +1 -0
  161. package/dist/shims/form.js +78 -0
  162. package/dist/shims/form.js.map +1 -0
  163. package/dist/shims/head-state.d.ts +11 -0
  164. package/dist/shims/head-state.d.ts.map +1 -0
  165. package/dist/shims/head-state.js +47 -0
  166. package/dist/shims/head-state.js.map +1 -0
  167. package/dist/shims/head.d.ts +28 -0
  168. package/dist/shims/head.d.ts.map +1 -0
  169. package/dist/shims/head.js +148 -0
  170. package/dist/shims/head.js.map +1 -0
  171. package/dist/shims/headers.d.ts +150 -0
  172. package/dist/shims/headers.d.ts.map +1 -0
  173. package/dist/shims/headers.js +412 -0
  174. package/dist/shims/headers.js.map +1 -0
  175. package/dist/shims/image-config.d.ts +30 -0
  176. package/dist/shims/image-config.d.ts.map +1 -0
  177. package/dist/shims/image-config.js +91 -0
  178. package/dist/shims/image-config.js.map +1 -0
  179. package/dist/shims/image.d.ts +63 -0
  180. package/dist/shims/image.d.ts.map +1 -0
  181. package/dist/shims/image.js +284 -0
  182. package/dist/shims/image.js.map +1 -0
  183. package/dist/shims/internal/api-utils.d.ts +12 -0
  184. package/dist/shims/internal/api-utils.d.ts.map +1 -0
  185. package/dist/shims/internal/api-utils.js +7 -0
  186. package/dist/shims/internal/api-utils.js.map +1 -0
  187. package/dist/shims/internal/app-router-context.d.ts +21 -0
  188. package/dist/shims/internal/app-router-context.d.ts.map +1 -0
  189. package/dist/shims/internal/app-router-context.js +15 -0
  190. package/dist/shims/internal/app-router-context.js.map +1 -0
  191. package/dist/shims/internal/cookies.d.ts +9 -0
  192. package/dist/shims/internal/cookies.d.ts.map +1 -0
  193. package/dist/shims/internal/cookies.js +9 -0
  194. package/dist/shims/internal/cookies.js.map +1 -0
  195. package/dist/shims/internal/router-context.d.ts +2 -0
  196. package/dist/shims/internal/router-context.d.ts.map +1 -0
  197. package/dist/shims/internal/router-context.js +9 -0
  198. package/dist/shims/internal/router-context.js.map +1 -0
  199. package/dist/shims/internal/utils.d.ts +48 -0
  200. package/dist/shims/internal/utils.d.ts.map +1 -0
  201. package/dist/shims/internal/utils.js +35 -0
  202. package/dist/shims/internal/utils.js.map +1 -0
  203. package/dist/shims/internal/work-unit-async-storage.d.ts +12 -0
  204. package/dist/shims/internal/work-unit-async-storage.d.ts.map +1 -0
  205. package/dist/shims/internal/work-unit-async-storage.js +13 -0
  206. package/dist/shims/internal/work-unit-async-storage.js.map +1 -0
  207. package/dist/shims/layout-segment-context.d.ts +21 -0
  208. package/dist/shims/layout-segment-context.d.ts.map +1 -0
  209. package/dist/shims/layout-segment-context.js +27 -0
  210. package/dist/shims/layout-segment-context.js.map +1 -0
  211. package/dist/shims/legacy-image.d.ts +52 -0
  212. package/dist/shims/legacy-image.d.ts.map +1 -0
  213. package/dist/shims/legacy-image.js +46 -0
  214. package/dist/shims/legacy-image.js.map +1 -0
  215. package/dist/shims/link.d.ts +48 -0
  216. package/dist/shims/link.d.ts.map +1 -0
  217. package/dist/shims/link.js +395 -0
  218. package/dist/shims/link.js.map +1 -0
  219. package/dist/shims/metadata.d.ts +184 -0
  220. package/dist/shims/metadata.d.ts.map +1 -0
  221. package/dist/shims/metadata.js +472 -0
  222. package/dist/shims/metadata.js.map +1 -0
  223. package/dist/shims/navigation-state.d.ts +14 -0
  224. package/dist/shims/navigation-state.d.ts.map +1 -0
  225. package/dist/shims/navigation-state.js +77 -0
  226. package/dist/shims/navigation-state.js.map +1 -0
  227. package/dist/shims/navigation.d.ts +201 -0
  228. package/dist/shims/navigation.d.ts.map +1 -0
  229. package/dist/shims/navigation.js +672 -0
  230. package/dist/shims/navigation.js.map +1 -0
  231. package/dist/shims/og.d.ts +20 -0
  232. package/dist/shims/og.d.ts.map +1 -0
  233. package/dist/shims/og.js +19 -0
  234. package/dist/shims/og.js.map +1 -0
  235. package/dist/shims/router-state.d.ts +11 -0
  236. package/dist/shims/router-state.d.ts.map +1 -0
  237. package/dist/shims/router-state.js +56 -0
  238. package/dist/shims/router-state.js.map +1 -0
  239. package/dist/shims/router.d.ts +103 -0
  240. package/dist/shims/router.d.ts.map +1 -0
  241. package/dist/shims/router.js +536 -0
  242. package/dist/shims/router.js.map +1 -0
  243. package/dist/shims/script.d.ts +58 -0
  244. package/dist/shims/script.d.ts.map +1 -0
  245. package/dist/shims/script.js +163 -0
  246. package/dist/shims/script.js.map +1 -0
  247. package/dist/shims/server-only.d.ts +19 -0
  248. package/dist/shims/server-only.d.ts.map +1 -0
  249. package/dist/shims/server-only.js +19 -0
  250. package/dist/shims/server-only.js.map +1 -0
  251. package/dist/shims/server.d.ts +178 -0
  252. package/dist/shims/server.d.ts.map +1 -0
  253. package/dist/shims/server.js +377 -0
  254. package/dist/shims/server.js.map +1 -0
  255. package/dist/shims/web-vitals.d.ts +24 -0
  256. package/dist/shims/web-vitals.d.ts.map +1 -0
  257. package/dist/shims/web-vitals.js +17 -0
  258. package/dist/shims/web-vitals.js.map +1 -0
  259. package/dist/utils/hash.d.ts +6 -0
  260. package/dist/utils/hash.d.ts.map +1 -0
  261. package/dist/utils/hash.js +20 -0
  262. package/dist/utils/hash.js.map +1 -0
  263. package/dist/utils/project.d.ts +36 -0
  264. package/dist/utils/project.d.ts.map +1 -0
  265. package/dist/utils/project.js +112 -0
  266. package/dist/utils/project.js.map +1 -0
  267. package/dist/utils/query.d.ts +10 -0
  268. package/dist/utils/query.d.ts.map +1 -0
  269. package/dist/utils/query.js +27 -0
  270. package/dist/utils/query.js.map +1 -0
  271. package/package.json +65 -7
  272. package/index.js +0 -1
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Vinext contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # vinext
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Static export for `output: 'export'`.
3
+ *
4
+ * Renders all pages to static HTML files at build time. Produces a directory
5
+ * of HTML + client JS/CSS that can be deployed to any static file host
6
+ * (S3, Cloudflare Pages, GitHub Pages, Nginx, etc.) with no server required.
7
+ *
8
+ * Pages Router:
9
+ * - Static pages → render to HTML
10
+ * - getStaticProps pages → call at build time, render with props
11
+ * - Dynamic routes → call getStaticPaths (must be fallback: false), render each
12
+ * - getServerSideProps → build error
13
+ * - API routes → skipped with warning
14
+ *
15
+ * App Router:
16
+ * - Static pages → run Server Components at build time, render to HTML
17
+ * - Dynamic routes → call generateStaticParams(), render each
18
+ * - Dynamic routes without generateStaticParams → build error
19
+ */
20
+ import type { ViteDevServer } from "vite";
21
+ import type { Route } from "../routing/pages-router.js";
22
+ import type { AppRoute } from "../routing/app-router.js";
23
+ import type { ResolvedNextConfig } from "../config/next-config.js";
24
+ export interface StaticExportOptions {
25
+ /** Vite dev server (for SSR module loading) */
26
+ server: ViteDevServer;
27
+ /** Discovered page routes (excludes API routes) */
28
+ routes: Route[];
29
+ /** Discovered API routes */
30
+ apiRoutes: Route[];
31
+ /** Pages directory path */
32
+ pagesDir: string;
33
+ /** Output directory for static files */
34
+ outDir: string;
35
+ /** Resolved next.config.js */
36
+ config: ResolvedNextConfig;
37
+ }
38
+ export interface StaticExportResult {
39
+ /** Number of HTML files generated */
40
+ pageCount: number;
41
+ /** Generated file paths (relative to outDir) */
42
+ files: string[];
43
+ /** Warnings encountered */
44
+ warnings: string[];
45
+ /** Errors encountered (non-fatal, specific pages) */
46
+ errors: Array<{
47
+ route: string;
48
+ error: string;
49
+ }>;
50
+ }
51
+ /**
52
+ * Run static export for Pages Router.
53
+ *
54
+ * Creates a directory of static HTML files by rendering each route at build time.
55
+ */
56
+ export declare function staticExportPages(options: StaticExportOptions): Promise<StaticExportResult>;
57
+ export interface AppStaticExportOptions {
58
+ /** Base URL of a running dev server (e.g. "http://localhost:5173") */
59
+ baseUrl: string;
60
+ /** Discovered app routes */
61
+ routes: AppRoute[];
62
+ /** App directory path (for loading modules to call generateStaticParams) */
63
+ appDir: string;
64
+ /** Vite dev server (for loading page modules) */
65
+ server: ViteDevServer;
66
+ /** Output directory */
67
+ outDir: string;
68
+ /** Resolved next.config.js */
69
+ config: ResolvedNextConfig;
70
+ }
71
+ /**
72
+ * Run static export for App Router.
73
+ *
74
+ * Fetches each route from a running dev server and writes the HTML to disk.
75
+ * For dynamic routes, calls generateStaticParams() to expand all paths.
76
+ */
77
+ export declare function staticExportApp(options: AppStaticExportOptions): Promise<StaticExportResult>;
78
+ //# sourceMappingURL=static-export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static-export.d.ts","sourceRoot":"","sources":["../../src/build/static-export.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAwBnE,MAAM,WAAW,mBAAmB;IAClC,+CAA+C;IAC/C,MAAM,EAAE,aAAa,CAAC;IACtB,mDAAmD;IACnD,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,4BAA4B;IAC5B,SAAS,EAAE,KAAK,EAAE,CAAC;IACnB,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,8BAA8B;IAC9B,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,qDAAqD;IACrD,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjD;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,kBAAkB,CAAC,CAmK7B;AAiXD,MAAM,WAAW,sBAAsB;IACrC,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,MAAM,EAAE,aAAa,CAAC;IACtB,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,8BAA8B;IAC9B,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,kBAAkB,CAAC,CAgI7B"}
@@ -0,0 +1,553 @@
1
+ import { safeJsonStringify } from "../server/html.js";
2
+ import { escapeAttr } from "../shims/head.js";
3
+ import path from "node:path";
4
+ import fs from "node:fs";
5
+ import React from "react";
6
+ import { renderToReadableStream } from "react-dom/server.edge";
7
+ const PAGE_EXTENSIONS = [".tsx", ".ts", ".jsx", ".js"];
8
+ function findFileWithExtensions(basePath) {
9
+ return PAGE_EXTENSIONS.some((ext) => fs.existsSync(basePath + ext));
10
+ }
11
+ /**
12
+ * Render a React element to string using renderToReadableStream (Suspense support).
13
+ * Uses Web Streams API — works in Node.js 18+ and Cloudflare Workers.
14
+ */
15
+ async function renderToStringAsync(element) {
16
+ const stream = await renderToReadableStream(element);
17
+ await stream.allReady;
18
+ return new Response(stream).text();
19
+ }
20
+ /**
21
+ * Run static export for Pages Router.
22
+ *
23
+ * Creates a directory of static HTML files by rendering each route at build time.
24
+ */
25
+ export async function staticExportPages(options) {
26
+ const { server, routes, apiRoutes, pagesDir, outDir, config } = options;
27
+ const result = {
28
+ pageCount: 0,
29
+ files: [],
30
+ warnings: [],
31
+ errors: [],
32
+ };
33
+ // Ensure output directory exists
34
+ fs.mkdirSync(outDir, { recursive: true });
35
+ // Warn about API routes
36
+ if (apiRoutes.length > 0) {
37
+ result.warnings.push(`${apiRoutes.length} API route(s) skipped — API routes are not supported with output: 'export'`);
38
+ }
39
+ // Gather all pages to render (expand dynamic routes via getStaticPaths)
40
+ const pagesToRender = [];
41
+ for (const route of routes) {
42
+ // Skip internal pages
43
+ const routeName = path.basename(route.filePath, path.extname(route.filePath));
44
+ if (routeName.startsWith("_"))
45
+ continue;
46
+ const pageModule = await server.ssrLoadModule(route.filePath);
47
+ // Validate: getServerSideProps is not allowed with static export
48
+ if (typeof pageModule.getServerSideProps === "function") {
49
+ result.errors.push({
50
+ route: route.pattern,
51
+ error: `Page uses getServerSideProps which is not supported with output: 'export'. Use getStaticProps instead.`,
52
+ });
53
+ continue;
54
+ }
55
+ if (route.isDynamic) {
56
+ // Dynamic route — must have getStaticPaths
57
+ if (typeof pageModule.getStaticPaths !== "function") {
58
+ result.errors.push({
59
+ route: route.pattern,
60
+ error: `Dynamic route requires getStaticPaths with output: 'export'`,
61
+ });
62
+ continue;
63
+ }
64
+ const pathsResult = await pageModule.getStaticPaths({
65
+ locales: [],
66
+ defaultLocale: "",
67
+ });
68
+ const fallback = pathsResult?.fallback ?? false;
69
+ if (fallback !== false) {
70
+ result.errors.push({
71
+ route: route.pattern,
72
+ error: `getStaticPaths must return fallback: false with output: 'export' (got: ${JSON.stringify(fallback)})`,
73
+ });
74
+ continue;
75
+ }
76
+ const paths = pathsResult?.paths ?? [];
77
+ for (const { params } of paths) {
78
+ // Build the URL path from the route pattern and params
79
+ const urlPath = buildUrlFromParams(route.pattern, params);
80
+ pagesToRender.push({ route, urlPath, params });
81
+ }
82
+ }
83
+ else {
84
+ // Static route — render directly
85
+ pagesToRender.push({ route, urlPath: route.pattern, params: {} });
86
+ }
87
+ }
88
+ // Load shared components (_app, _document, head shim, dynamic shim)
89
+ let AppComponent = null;
90
+ const appPath = path.join(pagesDir, "_app");
91
+ if (findFileWithExtensions(appPath)) {
92
+ try {
93
+ const appModule = await server.ssrLoadModule(appPath);
94
+ AppComponent = appModule.default ?? null;
95
+ }
96
+ catch {
97
+ // _app exists but failed to load
98
+ }
99
+ }
100
+ let DocumentComponent = null;
101
+ const docPath = path.join(pagesDir, "_document");
102
+ if (findFileWithExtensions(docPath)) {
103
+ try {
104
+ const docModule = await server.ssrLoadModule(docPath);
105
+ DocumentComponent = docModule.default ?? null;
106
+ }
107
+ catch {
108
+ // _document exists but failed to load
109
+ }
110
+ }
111
+ const headShim = await server.ssrLoadModule("next/head");
112
+ const dynamicShim = await server.ssrLoadModule("next/dynamic");
113
+ const routerShim = await server.ssrLoadModule("next/router");
114
+ // Render each page
115
+ for (const { route, urlPath, params } of pagesToRender) {
116
+ try {
117
+ const html = await renderStaticPage({
118
+ server,
119
+ route,
120
+ urlPath,
121
+ params,
122
+ pagesDir,
123
+ config,
124
+ AppComponent,
125
+ DocumentComponent,
126
+ headShim,
127
+ dynamicShim,
128
+ routerShim,
129
+ });
130
+ const outputPath = getOutputPath(urlPath, config.trailingSlash);
131
+ const fullPath = path.join(outDir, outputPath);
132
+ fs.mkdirSync(path.dirname(fullPath), { recursive: true });
133
+ fs.writeFileSync(fullPath, html, "utf-8");
134
+ result.files.push(outputPath);
135
+ result.pageCount++;
136
+ }
137
+ catch (e) {
138
+ result.errors.push({
139
+ route: urlPath,
140
+ error: e.message,
141
+ });
142
+ }
143
+ }
144
+ // Render 404 page
145
+ try {
146
+ const html404 = await renderErrorPage({
147
+ server,
148
+ pagesDir,
149
+ statusCode: 404,
150
+ AppComponent,
151
+ DocumentComponent,
152
+ headShim,
153
+ });
154
+ if (html404) {
155
+ const fullPath = path.join(outDir, "404.html");
156
+ fs.writeFileSync(fullPath, html404, "utf-8");
157
+ result.files.push("404.html");
158
+ result.pageCount++;
159
+ }
160
+ }
161
+ catch {
162
+ // No custom 404, skip
163
+ }
164
+ return result;
165
+ }
166
+ async function renderStaticPage(options) {
167
+ const { server, route, urlPath, params, config: _config, AppComponent, DocumentComponent, headShim, dynamicShim, routerShim, } = options;
168
+ // Set SSR context for router shim
169
+ if (typeof routerShim.setSSRContext === "function") {
170
+ routerShim.setSSRContext({
171
+ pathname: urlPath,
172
+ query: params,
173
+ asPath: urlPath,
174
+ });
175
+ }
176
+ const pageModule = await server.ssrLoadModule(route.filePath);
177
+ const PageComponent = pageModule.default;
178
+ if (!PageComponent) {
179
+ throw new Error(`Page ${route.filePath} has no default export`);
180
+ }
181
+ // Collect page props
182
+ let pageProps = {};
183
+ if (typeof pageModule.getStaticProps === "function") {
184
+ const result = await pageModule.getStaticProps({ params });
185
+ if (result && "props" in result) {
186
+ pageProps = result.props;
187
+ }
188
+ if (result && "redirect" in result) {
189
+ // Static export can't handle redirects — write a meta redirect
190
+ const redirect = result.redirect;
191
+ return `<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0;url=${escapeAttr(redirect.destination)}" /></head><body></body></html>`;
192
+ }
193
+ if (result && "notFound" in result && result.notFound) {
194
+ throw new Error(`Page ${urlPath} returned notFound: true`);
195
+ }
196
+ }
197
+ // Build element
198
+ const createElement = React.createElement;
199
+ let element;
200
+ if (AppComponent) {
201
+ element = createElement(AppComponent, {
202
+ Component: PageComponent,
203
+ pageProps,
204
+ });
205
+ }
206
+ else {
207
+ element = createElement(PageComponent, pageProps);
208
+ }
209
+ // Reset head collector and flush dynamic preloads
210
+ if (typeof headShim.resetSSRHead === "function") {
211
+ headShim.resetSSRHead();
212
+ }
213
+ if (typeof dynamicShim.flushPreloads === "function") {
214
+ await dynamicShim.flushPreloads();
215
+ }
216
+ // Render page body
217
+ const bodyHtml = await renderToStringAsync(element);
218
+ // Collect head tags
219
+ const ssrHeadHTML = typeof headShim.getSSRHeadHTML === "function"
220
+ ? headShim.getSSRHeadHTML()
221
+ : "";
222
+ // __NEXT_DATA__ for client hydration
223
+ const nextDataScript = `<script>window.__NEXT_DATA__ = ${safeJsonStringify({
224
+ props: { pageProps },
225
+ page: route.pattern,
226
+ query: params,
227
+ })}</script>`;
228
+ // Build HTML shell
229
+ let html;
230
+ if (DocumentComponent) {
231
+ const docElement = createElement(DocumentComponent);
232
+ // renderToReadableStream auto-prepends <!DOCTYPE html> when root is <html>
233
+ let docHtml = await renderToStringAsync(docElement);
234
+ docHtml = docHtml.replace("__NEXT_MAIN__", bodyHtml);
235
+ if (ssrHeadHTML) {
236
+ docHtml = docHtml.replace("</head>", ` ${ssrHeadHTML}\n</head>`);
237
+ }
238
+ docHtml = docHtml.replace("<!-- __NEXT_SCRIPTS__ -->", nextDataScript);
239
+ if (!docHtml.includes("__NEXT_DATA__")) {
240
+ docHtml = docHtml.replace("</body>", ` ${nextDataScript}\n</body>`);
241
+ }
242
+ html = docHtml;
243
+ }
244
+ else {
245
+ html = `<!DOCTYPE html>
246
+ <html>
247
+ <head>
248
+ <meta charset="utf-8" />
249
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
250
+ ${ssrHeadHTML}
251
+ </head>
252
+ <body>
253
+ <div id="__next">${bodyHtml}</div>
254
+ ${nextDataScript}
255
+ </body>
256
+ </html>`;
257
+ }
258
+ // Clear SSR context
259
+ if (typeof routerShim.setSSRContext === "function") {
260
+ routerShim.setSSRContext(null);
261
+ }
262
+ return html;
263
+ }
264
+ async function renderErrorPage(options) {
265
+ const { server, pagesDir, statusCode, AppComponent, DocumentComponent, headShim } = options;
266
+ const candidates = statusCode === 404
267
+ ? ["404", "_error"]
268
+ : statusCode === 500
269
+ ? ["500", "_error"]
270
+ : ["_error"];
271
+ for (const candidate of candidates) {
272
+ const candidatePath = path.join(pagesDir, candidate);
273
+ if (!findFileWithExtensions(candidatePath))
274
+ continue;
275
+ const errorModule = await server.ssrLoadModule(candidatePath);
276
+ const ErrorComponent = errorModule.default;
277
+ if (!ErrorComponent)
278
+ continue;
279
+ const createElement = React.createElement;
280
+ const errorProps = { statusCode };
281
+ let element;
282
+ if (AppComponent) {
283
+ element = createElement(AppComponent, {
284
+ Component: ErrorComponent,
285
+ pageProps: errorProps,
286
+ });
287
+ }
288
+ else {
289
+ element = createElement(ErrorComponent, errorProps);
290
+ }
291
+ if (typeof headShim.resetSSRHead === "function") {
292
+ headShim.resetSSRHead();
293
+ }
294
+ const bodyHtml = await renderToStringAsync(element);
295
+ let html;
296
+ if (DocumentComponent) {
297
+ const docElement = createElement(DocumentComponent);
298
+ let docHtml = await renderToStringAsync(docElement);
299
+ docHtml = docHtml.replace("__NEXT_MAIN__", bodyHtml);
300
+ docHtml = docHtml.replace("<!-- __NEXT_SCRIPTS__ -->", "");
301
+ html = docHtml;
302
+ }
303
+ else {
304
+ html = `<!DOCTYPE html>
305
+ <html>
306
+ <head>
307
+ <meta charset="utf-8" />
308
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
309
+ </head>
310
+ <body>
311
+ <div id="__next">${bodyHtml}</div>
312
+ </body>
313
+ </html>`;
314
+ }
315
+ return html;
316
+ }
317
+ return null;
318
+ }
319
+ /**
320
+ * Build a URL path from a route pattern and params.
321
+ * E.g., "/posts/:id" + { id: "42" } → "/posts/42"
322
+ * E.g., "/docs/:slug+" + { slug: ["a", "b"] } → "/docs/a/b"
323
+ */
324
+ function buildUrlFromParams(pattern, params) {
325
+ const parts = pattern.split("/").filter(Boolean);
326
+ const result = [];
327
+ for (const part of parts) {
328
+ if (part.endsWith("+") || part.endsWith("*")) {
329
+ // Catch-all: :slug+ or :slug*
330
+ const paramName = part.slice(1, -1);
331
+ const value = params[paramName];
332
+ if (Array.isArray(value)) {
333
+ result.push(...value);
334
+ }
335
+ else if (value) {
336
+ result.push(String(value));
337
+ }
338
+ }
339
+ else if (part.startsWith(":")) {
340
+ // Dynamic segment: :id
341
+ const paramName = part.slice(1);
342
+ const value = params[paramName];
343
+ result.push(String(value));
344
+ }
345
+ else {
346
+ result.push(part);
347
+ }
348
+ }
349
+ return "/" + result.join("/");
350
+ }
351
+ /**
352
+ * Determine the output file path for a given URL.
353
+ * Respects trailingSlash config.
354
+ */
355
+ function getOutputPath(urlPath, trailingSlash) {
356
+ if (urlPath === "/") {
357
+ return "index.html";
358
+ }
359
+ // Remove leading slash
360
+ const clean = urlPath.replace(/^\//, "");
361
+ if (trailingSlash) {
362
+ return `${clean}/index.html`;
363
+ }
364
+ return `${clean}.html`;
365
+ }
366
+ /**
367
+ * Resolve parent dynamic segment params for a route.
368
+ *
369
+ * Implements Next.js's top-down params passing for generateStaticParams().
370
+ * Walks up the route hierarchy to find parent dynamic segments that have their
371
+ * own generateStaticParams. Collects parent params by calling each parent's
372
+ * generateStaticParams in order, merging results top-down.
373
+ *
374
+ * Returns an array of parent param combinations. If empty, the child should
375
+ * be called with `{ params: {} }` (bottom-up approach).
376
+ */
377
+ async function resolveParentParams(childRoute, allRoutes, server) {
378
+ // Extract the dynamic segment names from the pattern
379
+ const patternParts = childRoute.pattern.split("/").filter(Boolean);
380
+ const parentSegments = [];
381
+ // Walk pattern parts to find intermediate dynamic segments
382
+ // For /products/:category/:id, we look for a route or layout at /products/:category
383
+ // that has generateStaticParams
384
+ for (let i = 0; i < patternParts.length; i++) {
385
+ const part = patternParts[i];
386
+ if (!part.startsWith(":"))
387
+ continue;
388
+ // Check if this is not the last dynamic param (i.e., it's a parent segment)
389
+ const isLastDynamicPart = !patternParts.slice(i + 1).some((p) => p.startsWith(":"));
390
+ if (isLastDynamicPart)
391
+ break; // This is the child's own segment
392
+ // Build the prefix pattern up to this segment
393
+ const prefixPattern = "/" + patternParts.slice(0, i + 1).join("/");
394
+ // Find a route at this prefix that has generateStaticParams
395
+ const parentRoute = allRoutes.find((r) => r.pattern === prefixPattern);
396
+ if (parentRoute?.pagePath) {
397
+ try {
398
+ const parentModule = await server.ssrLoadModule(parentRoute.pagePath);
399
+ if (typeof parentModule.generateStaticParams === "function") {
400
+ const paramName = part.replace(/^:/, "").replace(/[+*]$/, "");
401
+ parentSegments.push({
402
+ params: [paramName],
403
+ generateStaticParams: parentModule.generateStaticParams,
404
+ });
405
+ }
406
+ }
407
+ catch {
408
+ // Skip — parent module couldn't be loaded
409
+ }
410
+ }
411
+ }
412
+ if (parentSegments.length === 0)
413
+ return [];
414
+ // Top-down resolution: call each parent's generateStaticParams in order,
415
+ // accumulating params
416
+ let currentParams = [{}];
417
+ for (const segment of parentSegments) {
418
+ const nextParams = [];
419
+ for (const parentParams of currentParams) {
420
+ const results = await segment.generateStaticParams({ params: parentParams });
421
+ if (Array.isArray(results)) {
422
+ for (const result of results) {
423
+ nextParams.push({ ...parentParams, ...result });
424
+ }
425
+ }
426
+ }
427
+ currentParams = nextParams;
428
+ }
429
+ return currentParams;
430
+ }
431
+ /**
432
+ * Run static export for App Router.
433
+ *
434
+ * Fetches each route from a running dev server and writes the HTML to disk.
435
+ * For dynamic routes, calls generateStaticParams() to expand all paths.
436
+ */
437
+ export async function staticExportApp(options) {
438
+ const { baseUrl, routes, server, outDir, config } = options;
439
+ const result = {
440
+ pageCount: 0,
441
+ files: [],
442
+ warnings: [],
443
+ errors: [],
444
+ };
445
+ fs.mkdirSync(outDir, { recursive: true });
446
+ // Collect all URLs to render
447
+ const urlsToRender = [];
448
+ for (const route of routes) {
449
+ // Skip API route handlers — not supported in static export
450
+ if (route.routePath && !route.pagePath) {
451
+ result.warnings.push(`Route handler ${route.pattern} skipped — API routes are not supported with output: 'export'`);
452
+ continue;
453
+ }
454
+ if (!route.pagePath)
455
+ continue;
456
+ if (route.isDynamic) {
457
+ // Dynamic route — must have generateStaticParams
458
+ try {
459
+ const pageModule = await server.ssrLoadModule(route.pagePath);
460
+ if (typeof pageModule.generateStaticParams !== "function") {
461
+ result.errors.push({
462
+ route: route.pattern,
463
+ error: `Dynamic route requires generateStaticParams() with output: 'export'`,
464
+ });
465
+ continue;
466
+ }
467
+ // Resolve parent dynamic segments for top-down params passing.
468
+ // Find all other routes whose patterns are prefixes of this route's pattern
469
+ // and that have dynamic params, then collect their generateStaticParams.
470
+ const parentParamSets = await resolveParentParams(route, routes, server);
471
+ let paramSets;
472
+ if (parentParamSets.length > 0) {
473
+ // Top-down: call child's generateStaticParams for each parent param set
474
+ paramSets = [];
475
+ for (const parentParams of parentParamSets) {
476
+ const childResults = await pageModule.generateStaticParams({ params: parentParams });
477
+ if (Array.isArray(childResults)) {
478
+ for (const childParams of childResults) {
479
+ paramSets.push({ ...parentParams, ...childParams });
480
+ }
481
+ }
482
+ }
483
+ }
484
+ else {
485
+ // Bottom-up: no parent params, call with empty params
486
+ paramSets = await pageModule.generateStaticParams({ params: {} });
487
+ }
488
+ if (!Array.isArray(paramSets) || paramSets.length === 0) {
489
+ result.warnings.push(`generateStaticParams() for ${route.pattern} returned empty array — no pages generated`);
490
+ continue;
491
+ }
492
+ for (const params of paramSets) {
493
+ const urlPath = buildUrlFromParams(route.pattern, params);
494
+ urlsToRender.push(urlPath);
495
+ }
496
+ }
497
+ catch (e) {
498
+ result.errors.push({
499
+ route: route.pattern,
500
+ error: `Failed to call generateStaticParams(): ${e.message}`,
501
+ });
502
+ }
503
+ }
504
+ else {
505
+ // Static route
506
+ urlsToRender.push(route.pattern);
507
+ }
508
+ }
509
+ // Fetch each URL from the dev server and write HTML
510
+ for (const urlPath of urlsToRender) {
511
+ try {
512
+ const res = await fetch(`${baseUrl}${urlPath}`);
513
+ if (!res.ok) {
514
+ result.errors.push({
515
+ route: urlPath,
516
+ error: `Server returned ${res.status}`,
517
+ });
518
+ continue;
519
+ }
520
+ const html = await res.text();
521
+ const outputPath = getOutputPath(urlPath, config.trailingSlash);
522
+ const fullPath = path.join(outDir, outputPath);
523
+ fs.mkdirSync(path.dirname(fullPath), { recursive: true });
524
+ fs.writeFileSync(fullPath, html, "utf-8");
525
+ result.files.push(outputPath);
526
+ result.pageCount++;
527
+ }
528
+ catch (e) {
529
+ result.errors.push({
530
+ route: urlPath,
531
+ error: e.message,
532
+ });
533
+ }
534
+ }
535
+ // Render 404 page
536
+ try {
537
+ const res = await fetch(`${baseUrl}/__nonexistent_page_for_404__`);
538
+ if (res.status === 404) {
539
+ const html = await res.text();
540
+ if (html.length > 0) {
541
+ const fullPath = path.join(outDir, "404.html");
542
+ fs.writeFileSync(fullPath, html, "utf-8");
543
+ result.files.push("404.html");
544
+ result.pageCount++;
545
+ }
546
+ }
547
+ }
548
+ catch {
549
+ // No custom 404, skip
550
+ }
551
+ return result;
552
+ }
553
+ //# sourceMappingURL=static-export.js.map