@rshono/core 1.0.0-rc.12 → 1.0.0-rc.14

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 (150) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +29 -8
  3. package/bin/rshono.mjs +3 -4
  4. package/dist/builder/env-shadow-loader.cjs +25 -6
  5. package/dist/builder/page-files.js +5 -5
  6. package/dist/builder/page-files.js.map +1 -1
  7. package/dist/builder/public-env.d.ts +5 -4
  8. package/dist/builder/public-env.d.ts.map +1 -1
  9. package/dist/builder/public-env.js +5 -4
  10. package/dist/builder/public-env.js.map +1 -1
  11. package/dist/builder/react-versions.d.ts +13 -0
  12. package/dist/builder/react-versions.d.ts.map +1 -0
  13. package/dist/builder/react-versions.js +74 -0
  14. package/dist/builder/react-versions.js.map +1 -0
  15. package/dist/builder/rspack-config.d.ts +5 -11
  16. package/dist/builder/rspack-config.d.ts.map +1 -1
  17. package/dist/builder/rspack-config.js +73 -55
  18. package/dist/builder/rspack-config.js.map +1 -1
  19. package/dist/cli/build.d.ts.map +1 -1
  20. package/dist/cli/build.js +6 -2
  21. package/dist/cli/build.js.map +1 -1
  22. package/dist/cli/dev.d.ts.map +1 -1
  23. package/dist/cli/dev.js +30 -40
  24. package/dist/cli/dev.js.map +1 -1
  25. package/dist/cli/index.js +5 -4
  26. package/dist/cli/index.js.map +1 -1
  27. package/dist/cli/start.d.ts.map +1 -1
  28. package/dist/cli/start.js +12 -16
  29. package/dist/cli/start.js.map +1 -1
  30. package/dist/config.d.ts +28 -31
  31. package/dist/config.d.ts.map +1 -1
  32. package/dist/config.js +2 -2
  33. package/dist/config.js.map +1 -1
  34. package/dist/deploy/aws-lambda/runtime.d.ts +4 -6
  35. package/dist/deploy/aws-lambda/runtime.d.ts.map +1 -1
  36. package/dist/deploy/aws-lambda/runtime.js +5 -8
  37. package/dist/deploy/aws-lambda/runtime.js.map +1 -1
  38. package/dist/deploy/build-marker.d.ts +3 -5
  39. package/dist/deploy/build-marker.d.ts.map +1 -1
  40. package/dist/deploy/build-marker.js +3 -5
  41. package/dist/deploy/build-marker.js.map +1 -1
  42. package/dist/deploy/cloudflare/build.d.ts.map +1 -1
  43. package/dist/deploy/cloudflare/build.js +6 -10
  44. package/dist/deploy/cloudflare/build.js.map +1 -1
  45. package/dist/deploy/cloudflare/runtime.d.ts +2 -5
  46. package/dist/deploy/cloudflare/runtime.d.ts.map +1 -1
  47. package/dist/deploy/cloudflare/runtime.js +19 -32
  48. package/dist/deploy/cloudflare/runtime.js.map +1 -1
  49. package/dist/deploy/contract.d.ts +25 -42
  50. package/dist/deploy/contract.d.ts.map +1 -1
  51. package/dist/deploy/contract.js.map +1 -1
  52. package/dist/deploy/filesystem.d.ts +3 -5
  53. package/dist/deploy/filesystem.d.ts.map +1 -1
  54. package/dist/deploy/filesystem.js +15 -11
  55. package/dist/deploy/filesystem.js.map +1 -1
  56. package/dist/deploy/node/runtime.d.ts +4 -5
  57. package/dist/deploy/node/runtime.d.ts.map +1 -1
  58. package/dist/deploy/node/runtime.js +9 -15
  59. package/dist/deploy/node/runtime.js.map +1 -1
  60. package/dist/deploy/presets.d.ts +19 -29
  61. package/dist/deploy/presets.d.ts.map +1 -1
  62. package/dist/deploy/presets.js +41 -24
  63. package/dist/deploy/presets.js.map +1 -1
  64. package/dist/deploy/vercel/build.d.ts.map +1 -1
  65. package/dist/deploy/vercel/build.js +19 -16
  66. package/dist/deploy/vercel/build.js.map +1 -1
  67. package/dist/deploy/vercel/runtime.d.ts +4 -7
  68. package/dist/deploy/vercel/runtime.d.ts.map +1 -1
  69. package/dist/deploy/vercel/runtime.js +13 -7
  70. package/dist/deploy/vercel/runtime.js.map +1 -1
  71. package/dist/index.d.ts +13 -9
  72. package/dist/index.d.ts.map +1 -1
  73. package/dist/index.js +15 -12
  74. package/dist/index.js.map +1 -1
  75. package/dist/router.d.ts +65 -93
  76. package/dist/router.d.ts.map +1 -1
  77. package/dist/router.js +2 -5
  78. package/dist/router.js.map +1 -1
  79. package/dist/runtime/boundaries.d.ts +24 -30
  80. package/dist/runtime/boundaries.d.ts.map +1 -1
  81. package/dist/runtime/boundaries.js +15 -22
  82. package/dist/runtime/boundaries.js.map +1 -1
  83. package/dist/runtime/client.d.ts +16 -7
  84. package/dist/runtime/client.d.ts.map +1 -1
  85. package/dist/runtime/client.js +16 -7
  86. package/dist/runtime/client.js.map +1 -1
  87. package/dist/runtime/context.d.ts +89 -118
  88. package/dist/runtime/context.d.ts.map +1 -1
  89. package/dist/runtime/context.js +122 -167
  90. package/dist/runtime/context.js.map +1 -1
  91. package/dist/runtime/control.js +3 -3
  92. package/dist/runtime/control.js.map +1 -1
  93. package/dist/runtime/dev-protocol.d.ts +4 -8
  94. package/dist/runtime/dev-protocol.d.ts.map +1 -1
  95. package/dist/runtime/dev-protocol.js.map +1 -1
  96. package/dist/runtime/entry.client.js +121 -113
  97. package/dist/runtime/entry.client.js.map +1 -1
  98. package/dist/runtime/entry.rsc.d.ts +5 -6
  99. package/dist/runtime/entry.rsc.d.ts.map +1 -1
  100. package/dist/runtime/entry.rsc.js +140 -129
  101. package/dist/runtime/entry.rsc.js.map +1 -1
  102. package/dist/runtime/entry.ssr.d.ts +7 -12
  103. package/dist/runtime/entry.ssr.d.ts.map +1 -1
  104. package/dist/runtime/entry.ssr.js +13 -24
  105. package/dist/runtime/entry.ssr.js.map +1 -1
  106. package/dist/runtime/flight-inject.d.ts +10 -17
  107. package/dist/runtime/flight-inject.d.ts.map +1 -1
  108. package/dist/runtime/flight-inject.js +63 -54
  109. package/dist/runtime/flight-inject.js.map +1 -1
  110. package/dist/runtime/hot-update.d.ts +20 -27
  111. package/dist/runtime/hot-update.d.ts.map +1 -1
  112. package/dist/runtime/hot-update.js +17 -23
  113. package/dist/runtime/hot-update.js.map +1 -1
  114. package/dist/runtime/navigation.d.ts +14 -19
  115. package/dist/runtime/navigation.d.ts.map +1 -1
  116. package/dist/runtime/navigation.js +9 -13
  117. package/dist/runtime/navigation.js.map +1 -1
  118. package/dist/runtime/request.d.ts +16 -10
  119. package/dist/runtime/request.d.ts.map +1 -1
  120. package/dist/runtime/request.js +30 -10
  121. package/dist/runtime/request.js.map +1 -1
  122. package/dist/runtime/server.d.ts +18 -10
  123. package/dist/runtime/server.d.ts.map +1 -1
  124. package/dist/runtime/server.js +21 -19
  125. package/dist/runtime/server.js.map +1 -1
  126. package/dist/server/headers.d.ts +8 -15
  127. package/dist/server/headers.d.ts.map +1 -1
  128. package/dist/server/headers.js +8 -15
  129. package/dist/server/headers.js.map +1 -1
  130. package/dist/server/load-config.d.ts +2 -2
  131. package/dist/server/load-config.d.ts.map +1 -1
  132. package/dist/server/load-config.js +6 -9
  133. package/dist/server/load-config.js.map +1 -1
  134. package/dist/server/prerendered.d.ts +40 -45
  135. package/dist/server/prerendered.d.ts.map +1 -1
  136. package/dist/server/prerendered.js +50 -33
  137. package/dist/server/prerendered.js.map +1 -1
  138. package/dist/server/server-config.d.ts +13 -28
  139. package/dist/server/server-config.d.ts.map +1 -1
  140. package/dist/server/server-config.js +5 -10
  141. package/dist/server/server-config.js.map +1 -1
  142. package/dist/server/shutdown.d.ts +5 -3
  143. package/dist/server/shutdown.d.ts.map +1 -1
  144. package/dist/server/shutdown.js +5 -3
  145. package/dist/server/shutdown.js.map +1 -1
  146. package/dist/server/ssg.d.ts +3 -6
  147. package/dist/server/ssg.d.ts.map +1 -1
  148. package/dist/server/ssg.js +12 -21
  149. package/dist/server/ssg.js.map +1 -1
  150. package/package.json +2 -2
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Lasse Tange
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 CHANGED
@@ -15,10 +15,12 @@ One required file (`src/routes.ts`), one optional file (`src/server.ts`), and yo
15
15
  streaming SSR with RSC hydration, server actions with progressive enhancement, soft navigation, build-time
16
16
  prerendering, and hard env/secret safety.
17
17
 
18
- > **Alpha.** The framework has an end-to-end suite of its own (see [Testing](#testing)), but it is built on
19
- > Rspack's experimental RSC support (`rspack.experiments.rsc`) and `react-server-dom-rspack`, which is still
20
- > `0.0.x`. Those two move underneath us, so `@rspack/core` and `react-server-dom-rspack` are pinned to exact
21
- > versions and a release of rshono is what moves them.
18
+ > **Release candidate.** The framework itself is covered end to end (see [Testing](#testing)) and its API is
19
+ > settled. What is not settled underneath it: Rspack's RSC support is an experimental API
20
+ > (`rspack.experiments.rsc`) and `react-server-dom-rspack` is still `0.0.x`. Both are pinned to exact
21
+ > versions — in the manifests and in workspace overrides — and a release of rshono is what moves them, so an
22
+ > upstream change reaches you as a tested release rather than as a broken install. That is the whole of the
23
+ > caveat, and it is the reason to read the [changelog](../../CHANGELOG.md) before upgrading.
22
24
 
23
25
  **Full documentation: [rshono.com/docs](https://www.rshono.com/docs).**
24
26
 
@@ -221,7 +223,7 @@ that runs this, the environment is what sets them. [Configuration docs](https://
221
223
 
222
224
  The defaults, in short: untrusted proxy headers, `nosniff` / `Referrer-Policy` / `X-Frame-Options` on
223
225
  every response (a floor your own `secureHeaders()` overrides),
224
- `private, no-cache` plus `Vary: Accept` on dynamic pages, `public, max-age=300` and a weak `ETag` on
226
+ `private, no-cache` plus `Vary: RSC` on dynamic pages, `public, max-age=300` and a weak `ETag` on
225
227
  prerendered ones, and errors redacted in production — with one `onServerError()` funnel for reporting them
226
228
  and three fallbacks (a fatal client overlay, a visible 500 document, a reported bootstrap failure) so a
227
229
  failure is never a blank screen.
@@ -263,7 +265,19 @@ Every target streams, which is the bar a new one has to clear.
263
265
  on Vercel, `streamifyResponse` plus a `RESPONSE_STREAM` Function URL on Lambda. Getting those right is what
264
266
  the presets are for.
265
267
  - **Prerendered pages are never CDN-served**: one URL answers with a document or a flight payload depending on
266
- `Accept`, and a path-keyed CDN cannot choose. `/_static` and `public/` do go straight to the CDN.
268
+ the `RSC` request header, and a path-keyed CDN cannot choose. `/_static` and `public/` do go straight to the
269
+ CDN.
270
+ - **The serverless targets bundle your dependencies**; `node` bundles only the ones a `'use client'` component
271
+ pulls in. A function is an uploaded directory with no `node_modules` to resolve against, so `vercel`,
272
+ `aws-lambda` and `cloudflare` compile everything in. The cost is that a native addon — or a package that
273
+ reads its own files off disk — fails the build on those targets rather than the deploy; reach for the
274
+ `rspack` hook, or deploy to `node`.
275
+
276
+ On `node` a server component's dependencies stay external and resolve from `node_modules`, but anything
277
+ reachable from a `'use client'` component is compiled in on every target. It has to be: the `PUBLIC_`-only
278
+ `process.env` view is applied by a loader, and a loader cannot run on a module the bundle only imports by
279
+ name — an external third-party client component would be SSR'd against the real environment. Nothing is
280
+ given up, since the same module is in the browser bundle and so was always required to be bundleable.
267
281
 
268
282
  [Deployment docs](https://www.rshono.com/docs/deployment), including Cloudflare bindings and the AWS setup.
269
283
 
@@ -274,6 +288,11 @@ Every target streams, which is the bar a new one has to clear.
274
288
  `react-server-dom-rspack` requires).
275
289
  - No response compression, no base path (`siteUrl` is a bare origin), and wildcard, optional and regex
276
290
  params cannot be prerendered.
291
+ - **No link prefetching**, by choice: a link is one fetch at click time and nothing before it. Speculative
292
+ fetching on hover spends every visitor's bandwidth to help some of them — so a navigation here costs a
293
+ round trip that Next.js and TanStack Start have usually already paid.
294
+ - No incremental static regeneration: `render: 'static'` is decided at build time, and a static page changes
295
+ when you rebuild.
277
296
  - Scroll restoration is the browser's (`history.scrollRestoration = 'auto'`).
278
297
  - The dev proxy doesn't forward WebSocket upgrades to a custom sub-app; production is unaffected.
279
298
  - Dev source maps embed the original source of `'use server'` modules (dev binds 127.0.0.1 only, and
@@ -313,5 +332,7 @@ Two coordinated Rspack compilers, using native RSC support (`rspack.experiments.
313
332
  In dev the CLI watches both bundles, runs the server bundle in a worker thread (restarted per rebuild,
314
333
  requests gated on readiness so nothing drops), and fronts everything on one port with static serving and an
315
334
  SSE channel: client edits hot-apply via react-refresh, server component edits re-fetch the payload in place,
316
- and browser state survives both. In production `dist/server/main.mjs` is self-contained — React, Hono and the
317
- framework are bundled in; your other dependencies resolve from `node_modules`.
335
+ and browser state survives both. In production `dist/server/main.mjs` has React, Hono and the framework
336
+ bundled in. On `node` your server-side dependencies still resolve from `node_modules` beside it; on the
337
+ serverless targets they are bundled too, because nothing installs them there. Whatever a `'use client'`
338
+ component reaches is bundled on every target, which is what lets the env shadow cover it.
package/bin/rshono.mjs CHANGED
@@ -1,10 +1,9 @@
1
1
  #!/usr/bin/env node
2
- // Thin launcher for the compiled CLI. Everything it does has to happen *before* the CLI module
3
- // graph loads, which is why the import below is dynamic rather than a static one at the top.
2
+ // Thin launcher for the compiled CLI. Everything here has to happen before the CLI module graph loads, which is
3
+ // why the import at the bottom is dynamic.
4
4
  const args = process.argv.slice(2);
5
5
 
6
- // `build` and `start` are the production commands, so they default NODE_ENV accordingly the
7
- // value is read during config resolution and baked into the bundle, so it has to be set this early.
6
+ // The production commands default NODE_ENV, which is read during config resolution and baked into the bundle.
8
7
  if ((args[0] === 'build' || args[0] === 'start') && !process.env.NODE_ENV) {
9
8
  process.env.NODE_ENV = 'production';
10
9
  }
@@ -1,14 +1,33 @@
1
1
  'use strict';
2
- const DIRECTIVE_PROLOGUE = /^(?:\s|\/\/[^\n]*(?:\n|$)|\/\*[\s\S]*?\*\/)*(?:(['"])use [a-z -]+\1\s*;?)?/;
2
+
3
+ /** Whitespace and comments — what may sit before or between directives without ending the prologue. */
4
+ const TRIVIA = '(?:\\s|//[^\\n]*(?:\\n|$)|/\\*[\\s\\S]*?\\*/)*';
5
+ /** One directive: `'use strict'`, `"use client"`, `'use server'`. The backreference keeps the quotes matched. */
6
+ const DIRECTIVE = '([\'"])use [a-z -]+\\1\\s*;?';
7
+
8
+ /**
9
+ * The whole directive prologue, so the prelude below is inserted *after* every directive rather than after the
10
+ * first one.
11
+ *
12
+ * The repetition is load-bearing. A module with two directives — `"use strict"` beside `'use client'`, which is
13
+ * ordinary output from a published component library, in either order — would otherwise take the prelude
14
+ * *between* them, and a directive preceded by a statement is just an expression: whichever came second would
15
+ * silently stop being a directive. That was survivable while this loader only saw the app's own hand-written
16
+ * source, where `'use client'` comes first and alone; it stopped being survivable when the rule widened to
17
+ * cover `node_modules` (see the SSR-layer rule in `rspack-config.ts`).
18
+ *
19
+ * Each repetition has to consume a whole directive, so the nested quantifiers cannot loop on an empty match.
20
+ */
21
+ const DIRECTIVE_PROLOGUE = new RegExp(`^${TRIVIA}(?:${DIRECTIVE}${TRIVIA})*`);
3
22
 
4
23
  /**
5
24
  * Shadows `process.env` with the PUBLIC_-only view inside SSR-layer modules, so a secret read from a
6
- * `'use client'` component renders empty on the server instead of leaking into the HTML stream (and
7
- * SSR output keeps agreeing with hydration, which sees the same view via DefinePlugin).
25
+ * `'use client'` component renders empty on the server rather than leaking into the HTML stream and SSR
26
+ * keeps agreeing with hydration, which sees the same view via DefinePlugin.
8
27
  *
9
- * This is a security control, so it fails the build rather than passing source through when it can't
10
- * confirm which layer a module is in — `_module` is a private Rspack field, and silently no-op'ing
11
- * if a future version renames it would drop the guarantee with nothing to notice it.
28
+ * A security control, so it fails the build rather than passing source through when it cannot confirm a
29
+ * module's layer: `_module` is a private Rspack field, and a silent no-op if it were renamed would drop the
30
+ * guarantee with nothing to notice.
12
31
  */
13
32
  module.exports = function envShadowLoader(source) {
14
33
  if (!source.includes('process.env')) return source;
@@ -1,14 +1,14 @@
1
1
  /**
2
- * Finds the page modules named by inline `component: () => import('…')` thunks in `routes.ts`, so the
3
- * server compiler can put `page-entry-loader.cjs` in front of exactly those files and inject their
4
- * `'use server-entry'` directive. A page wired up any other way declares the directive itself.
2
+ * Finds the page modules named by inline `component: () => import('…')` thunks in `routes.ts`, so the server
3
+ * compiler can put `page-entry-loader.cjs` in front of exactly those files. A page wired up any other way
4
+ * declares its `'use server-entry'` directive itself.
5
5
  */
6
6
  import { readFileSync, statSync } from 'node:fs';
7
7
  import { dirname, join, resolve } from 'node:path';
8
8
  const COMPONENT_THUNK = /component:\s*(?:async\s*)?\(\s*\)\s*=>\s*import\(\s*(['"])([^'"]+)\1\s*\)/g;
9
9
  const EXTENSIONS = ['.tsx', '.ts', '.jsx', '.js'];
10
- // Index candidates go through `join` rather than `base + '/index…'`: these paths are compared against
11
- // Rspack's own resource paths, and a hardcoded `/` stores one no Windows resource will ever equal.
10
+ // `join` rather than `base + '/index…'`: these are compared against Rspack's own resource paths, which on
11
+ // Windows carry backslashes.
12
12
  function resolveCandidates(base) {
13
13
  return [...EXTENSIONS.map((ext) => base + ext), ...EXTENSIONS.map((ext) => join(base, `index${ext}`)), base];
14
14
  }
@@ -1 +1 @@
1
- {"version":3,"file":"page-files.js","sourceRoot":"","sources":["../../src/builder/page-files.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEnD,MAAM,eAAe,GAAG,4EAA4E,CAAC;AAErG,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AAElD,sGAAsG;AACtG,mGAAmG;AACnG,SAAS,iBAAiB,CAAC,IAAY;IACrC,OAAO,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AAC/G,CAAC;AAED,SAAS,MAAM,CAAC,IAAY;IAC1B,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,UAAkB,EAAE,MAAc,EAAE,IAAiB;IACjF,IAAI,CAAC,KAAK,EAAE,CAAC;IACb,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,IAAwB,CAAC;QAC7B,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,CAAC;aAC/D,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACtE,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,KAAK,MAAM,SAAS,IAAI,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;YAChD,IAAI,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;gBACtB,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBACpB,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["/**\n * Finds the page modules named by inline `component: () => import('…')` thunks in `routes.ts`, so the\n * server compiler can put `page-entry-loader.cjs` in front of exactly those files and inject their\n * `'use server-entry'` directive. A page wired up any other way declares the directive itself.\n */\nimport { readFileSync, statSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\n\nconst COMPONENT_THUNK = /component:\\s*(?:async\\s*)?\\(\\s*\\)\\s*=>\\s*import\\(\\s*(['\"])([^'\"]+)\\1\\s*\\)/g;\n\nconst EXTENSIONS = ['.tsx', '.ts', '.jsx', '.js'];\n\n// Index candidates go through `join` rather than `base + '/index…'`: these paths are compared against\n// Rspack's own resource paths, and a hardcoded `/` stores one no Windows resource will ever equal.\nfunction resolveCandidates(base: string): string[] {\n return [...EXTENSIONS.map((ext) => base + ext), ...EXTENSIONS.map((ext) => join(base, `index${ext}`)), base];\n}\n\nfunction isFile(path: string): boolean {\n try {\n return statSync(path).isFile();\n } catch {\n return false;\n }\n}\n\nexport function scanPageFiles(routesFile: string, srcDir: string, into: Set<string>): void {\n into.clear();\n let source: string;\n try {\n source = readFileSync(routesFile, 'utf8');\n } catch {\n return;\n }\n for (const match of source.matchAll(COMPONENT_THUNK)) {\n const spec = match[2];\n let base: string | undefined;\n if (spec.startsWith('.')) base = resolve(dirname(routesFile), spec);\n else if (spec.startsWith('@/')) base = resolve(srcDir, spec.slice(2));\n if (!base) continue;\n for (const candidate of resolveCandidates(base)) {\n if (isFile(candidate)) {\n into.add(candidate);\n break;\n }\n }\n }\n}\n"]}
1
+ {"version":3,"file":"page-files.js","sourceRoot":"","sources":["../../src/builder/page-files.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEnD,MAAM,eAAe,GAAG,4EAA4E,CAAC;AAErG,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AAElD,0GAA0G;AAC1G,6BAA6B;AAC7B,SAAS,iBAAiB,CAAC,IAAY;IACrC,OAAO,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AAC/G,CAAC;AAED,SAAS,MAAM,CAAC,IAAY;IAC1B,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,UAAkB,EAAE,MAAc,EAAE,IAAiB;IACjF,IAAI,CAAC,KAAK,EAAE,CAAC;IACb,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,IAAwB,CAAC;QAC7B,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,CAAC;aAC/D,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACtE,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,KAAK,MAAM,SAAS,IAAI,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;YAChD,IAAI,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;gBACtB,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBACpB,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["/**\n * Finds the page modules named by inline `component: () => import('…')` thunks in `routes.ts`, so the server\n * compiler can put `page-entry-loader.cjs` in front of exactly those files. A page wired up any other way\n * declares its `'use server-entry'` directive itself.\n */\nimport { readFileSync, statSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\n\nconst COMPONENT_THUNK = /component:\\s*(?:async\\s*)?\\(\\s*\\)\\s*=>\\s*import\\(\\s*(['\"])([^'\"]+)\\1\\s*\\)/g;\n\nconst EXTENSIONS = ['.tsx', '.ts', '.jsx', '.js'];\n\n// `join` rather than `base + '/index…'`: these are compared against Rspack's own resource paths, which on\n// Windows carry backslashes.\nfunction resolveCandidates(base: string): string[] {\n return [...EXTENSIONS.map((ext) => base + ext), ...EXTENSIONS.map((ext) => join(base, `index${ext}`)), base];\n}\n\nfunction isFile(path: string): boolean {\n try {\n return statSync(path).isFile();\n } catch {\n return false;\n }\n}\n\nexport function scanPageFiles(routesFile: string, srcDir: string, into: Set<string>): void {\n into.clear();\n let source: string;\n try {\n source = readFileSync(routesFile, 'utf8');\n } catch {\n return;\n }\n for (const match of source.matchAll(COMPONENT_THUNK)) {\n const spec = match[2];\n let base: string | undefined;\n if (spec.startsWith('.')) base = resolve(dirname(routesFile), spec);\n else if (spec.startsWith('@/')) base = resolve(srcDir, spec.slice(2));\n if (!base) continue;\n for (const candidate of resolveCandidates(base)) {\n if (isFile(candidate)) {\n into.add(candidate);\n break;\n }\n }\n }\n}\n"]}
@@ -1,8 +1,9 @@
1
1
  /**
2
- * The `process.env` view compiled into the browser bundle: `NODE_ENV` plus the `PUBLIC_`-prefixed
3
- * variables. Everything else stays server-only — a stray read of it in client code becomes
4
- * `undefined` rather than shipping the value. Also what `env-shadow-loader.cjs` shadows SSR-layer
5
- * modules with, so the server renders the same thing the browser hydrates.
2
+ * The `process.env` view compiled into the browser bundle: `NODE_ENV` plus the `PUBLIC_`-prefixed variables.
3
+ * A stray read of anything else in client code becomes `undefined` rather than shipping the value.
4
+ *
5
+ * Also what `env-shadow-loader.cjs` shadows SSR-layer modules with, so the server renders what the browser
6
+ * hydrates.
6
7
  */
7
8
  export declare function publicEnv(isDev: boolean): Record<string, string>;
8
9
  //# sourceMappingURL=public-env.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"public-env.d.ts","sourceRoot":"","sources":["../../src/builder/public-env.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAGhE"}
1
+ {"version":3,"file":"public-env.d.ts","sourceRoot":"","sources":["../../src/builder/public-env.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAGhE"}
@@ -1,8 +1,9 @@
1
1
  /**
2
- * The `process.env` view compiled into the browser bundle: `NODE_ENV` plus the `PUBLIC_`-prefixed
3
- * variables. Everything else stays server-only — a stray read of it in client code becomes
4
- * `undefined` rather than shipping the value. Also what `env-shadow-loader.cjs` shadows SSR-layer
5
- * modules with, so the server renders the same thing the browser hydrates.
2
+ * The `process.env` view compiled into the browser bundle: `NODE_ENV` plus the `PUBLIC_`-prefixed variables.
3
+ * A stray read of anything else in client code becomes `undefined` rather than shipping the value.
4
+ *
5
+ * Also what `env-shadow-loader.cjs` shadows SSR-layer modules with, so the server renders what the browser
6
+ * hydrates.
6
7
  */
7
8
  export function publicEnv(isDev) {
8
9
  const entries = Object.entries(process.env).filter((entry) => entry[0].startsWith('PUBLIC_') && entry[1] !== undefined);
@@ -1 +1 @@
1
- {"version":3,"file":"public-env.js","sourceRoot":"","sources":["../../src/builder/public-env.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAA6B,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;IACnJ,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;AAC5F,CAAC","sourcesContent":["/**\n * The `process.env` view compiled into the browser bundle: `NODE_ENV` plus the `PUBLIC_`-prefixed\n * variables. Everything else stays server-only — a stray read of it in client code becomes\n * `undefined` rather than shipping the value. Also what `env-shadow-loader.cjs` shadows SSR-layer\n * modules with, so the server renders the same thing the browser hydrates.\n */\nexport function publicEnv(isDev: boolean): Record<string, string> {\n const entries = Object.entries(process.env).filter((entry): entry is [string, string] => entry[0].startsWith('PUBLIC_') && entry[1] !== undefined);\n return { NODE_ENV: isDev ? 'development' : 'production', ...Object.fromEntries(entries) };\n}\n"]}
1
+ {"version":3,"file":"public-env.js","sourceRoot":"","sources":["../../src/builder/public-env.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAA6B,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;IACnJ,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;AAC5F,CAAC","sourcesContent":["/**\n * The `process.env` view compiled into the browser bundle: `NODE_ENV` plus the `PUBLIC_`-prefixed variables.\n * A stray read of anything else in client code becomes `undefined` rather than shipping the value.\n *\n * Also what `env-shadow-loader.cjs` shadows SSR-layer modules with, so the server renders what the browser\n * hydrates.\n */\nexport function publicEnv(isDev: boolean): Record<string, string> {\n const entries = Object.entries(process.env).filter((entry): entry is [string, string] => entry[0].startsWith('PUBLIC_') && entry[1] !== undefined);\n return { NODE_ENV: isDev ? 'development' : 'production', ...Object.fromEntries(entries) };\n}\n"]}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Fails the build when `react` and `react-dom` resolve to different versions, and warns when they are not the
3
+ * version this release was tested with.
4
+ *
5
+ * The mismatch is an error because it never works. A different minor is only a warning: upstream declares
6
+ * `^19.1.0` and may well be right, and refusing to build would make rshono the reason an app cannot take a
7
+ * React release — a worse failure than the one it would prevent.
8
+ *
9
+ * @param rootDir - The project root, so resolution follows the *app's* `node_modules` rather than the
10
+ * framework's.
11
+ */
12
+ export declare function checkReactVersions(rootDir: string): void;
13
+ //# sourceMappingURL=react-versions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-versions.d.ts","sourceRoot":"","sources":["../../src/builder/react-versions.ts"],"names":[],"mappings":"AA6CA;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAyBxD"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * The one dependency check the framework makes on an app: that `react` and `react-dom` are the same build.
3
+ *
4
+ * React Server Components couple the two across bundles — `react-server-dom-rspack` reaches into
5
+ * `ReactSharedInternals` and emits a flight payload the *matching* `react-dom` has to parse — so a split
6
+ * resolution is not version skew to be tolerated. It is a crash inside minified React at render time, with
7
+ * nothing in the message pointing at the cause.
8
+ *
9
+ * The monorepo prevents it with `overrides` in `pnpm-workspace.yaml` and `packages/create` pins both exactly
10
+ * for the same reason, because a generated app has no overrides to rely on. Neither helps an app that grew
11
+ * past its scaffold, which is why the check lives here — on the one path every `dev` and `build` takes.
12
+ */
13
+ import { createRequire } from 'node:module';
14
+ import { join } from 'node:path';
15
+ /**
16
+ * The React this release was tested against, read off the framework's own manifest rather than restated as a
17
+ * constant — the pin and the check cannot drift apart that way. `undefined` if it cannot be read, which only
18
+ * turns the advisory warning off.
19
+ */
20
+ function testedReactVersion() {
21
+ try {
22
+ const manifest = createRequire(import.meta.url)('../../package.json');
23
+ return manifest.devDependencies?.react;
24
+ }
25
+ catch {
26
+ return undefined;
27
+ }
28
+ }
29
+ /** The version of an installed package as the *app* resolves it, or `undefined` if it has none. */
30
+ function installedVersion(require, name) {
31
+ try {
32
+ return require(`${name}/package.json`).version;
33
+ }
34
+ catch {
35
+ return undefined;
36
+ }
37
+ }
38
+ /** `19.2.8` → `19.2`, for comparing minors without pulling in a semver parser. */
39
+ function minor(version) {
40
+ return version.split('.', 2).join('.');
41
+ }
42
+ /**
43
+ * Fails the build when `react` and `react-dom` resolve to different versions, and warns when they are not the
44
+ * version this release was tested with.
45
+ *
46
+ * The mismatch is an error because it never works. A different minor is only a warning: upstream declares
47
+ * `^19.1.0` and may well be right, and refusing to build would make rshono the reason an app cannot take a
48
+ * React release — a worse failure than the one it would prevent.
49
+ *
50
+ * @param rootDir - The project root, so resolution follows the *app's* `node_modules` rather than the
51
+ * framework's.
52
+ */
53
+ export function checkReactVersions(rootDir) {
54
+ // Resolved from the project's manifest, so a pnpm layout answers with what the app actually gets.
55
+ const require = createRequire(join(rootDir, 'package.json'));
56
+ const react = installedVersion(require, 'react');
57
+ const reactDom = installedVersion(require, 'react-dom');
58
+ // Missing altogether is the resolver's to report, against the import that needed it and with the path.
59
+ if (!react || !reactDom)
60
+ return;
61
+ if (react !== reactDom) {
62
+ throw new Error(`[rshono] react ${react} and react-dom ${reactDom} resolve to different versions.\n` +
63
+ ' React Server Components couple them: the RSC runtime emits a payload the matching react-dom parses, ' +
64
+ 'so a split resolution fails inside React while rendering rather than here.\n' +
65
+ ' Install both at the same version. If a transitive dependency is what split them, pin them — ' +
66
+ '`overrides` in npm, `pnpm.overrides` in pnpm, `resolutions` in yarn.');
67
+ }
68
+ const tested = testedReactVersion();
69
+ if (tested && minor(tested) !== minor(react)) {
70
+ console.warn(` ⚠ react ${react} is not the ${minor(tested)}.x this rshono was tested against. The RSC runtime is pinned\n` +
71
+ ' to an exact version and reaches into React internals, so a different minor can fail at render time.');
72
+ }
73
+ }
74
+ //# sourceMappingURL=react-versions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-versions.js","sourceRoot":"","sources":["../../src/builder/react-versions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;;;GAIG;AACH,SAAS,kBAAkB;IACzB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,oBAAoB,CAEnE,CAAC;QACF,OAAO,QAAQ,CAAC,eAAe,EAAE,KAAK,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,mGAAmG;AACnG,SAAS,gBAAgB,CAAC,OAAuB,EAAE,IAAY;IAC7D,IAAI,CAAC;QACH,OAAQ,OAAO,CAAC,GAAG,IAAI,eAAe,CAA0B,CAAC,OAAO,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,kFAAkF;AAClF,SAAS,KAAK,CAAC,OAAe;IAC5B,OAAO,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,kGAAkG;IAClG,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAG,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACxD,uGAAuG;IACvG,IAAI,CAAC,KAAK,IAAI,CAAC,QAAQ;QAAE,OAAO;IAEhC,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,kBAAkB,KAAK,kBAAkB,QAAQ,mCAAmC;YAClF,wGAAwG;YACxG,8EAA8E;YAC9E,gGAAgG;YAChG,sEAAsE,CACzE,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,kBAAkB,EAAE,CAAC;IACpC,IAAI,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7C,OAAO,CAAC,IAAI,CACV,aAAa,KAAK,eAAe,KAAK,CAAC,MAAM,CAAC,gEAAgE;YAC5G,yGAAyG,CAC5G,CAAC;IACJ,CAAC;AACH,CAAC","sourcesContent":["/**\n * The one dependency check the framework makes on an app: that `react` and `react-dom` are the same build.\n *\n * React Server Components couple the two across bundles — `react-server-dom-rspack` reaches into\n * `ReactSharedInternals` and emits a flight payload the *matching* `react-dom` has to parse — so a split\n * resolution is not version skew to be tolerated. It is a crash inside minified React at render time, with\n * nothing in the message pointing at the cause.\n *\n * The monorepo prevents it with `overrides` in `pnpm-workspace.yaml` and `packages/create` pins both exactly\n * for the same reason, because a generated app has no overrides to rely on. Neither helps an app that grew\n * past its scaffold, which is why the check lives here — on the one path every `dev` and `build` takes.\n */\nimport { createRequire } from 'node:module';\nimport { join } from 'node:path';\n\n/**\n * The React this release was tested against, read off the framework's own manifest rather than restated as a\n * constant — the pin and the check cannot drift apart that way. `undefined` if it cannot be read, which only\n * turns the advisory warning off.\n */\nfunction testedReactVersion(): string | undefined {\n try {\n const manifest = createRequire(import.meta.url)('../../package.json') as {\n devDependencies?: Record<string, string>;\n };\n return manifest.devDependencies?.react;\n } catch {\n return undefined;\n }\n}\n\n/** The version of an installed package as the *app* resolves it, or `undefined` if it has none. */\nfunction installedVersion(require: NodeJS.Require, name: string): string | undefined {\n try {\n return (require(`${name}/package.json`) as { version?: string }).version;\n } catch {\n return undefined;\n }\n}\n\n/** `19.2.8` → `19.2`, for comparing minors without pulling in a semver parser. */\nfunction minor(version: string): string {\n return version.split('.', 2).join('.');\n}\n\n/**\n * Fails the build when `react` and `react-dom` resolve to different versions, and warns when they are not the\n * version this release was tested with.\n *\n * The mismatch is an error because it never works. A different minor is only a warning: upstream declares\n * `^19.1.0` and may well be right, and refusing to build would make rshono the reason an app cannot take a\n * React release — a worse failure than the one it would prevent.\n *\n * @param rootDir - The project root, so resolution follows the *app's* `node_modules` rather than the\n * framework's.\n */\nexport function checkReactVersions(rootDir: string): void {\n // Resolved from the project's manifest, so a pnpm layout answers with what the app actually gets.\n const require = createRequire(join(rootDir, 'package.json'));\n const react = installedVersion(require, 'react');\n const reactDom = installedVersion(require, 'react-dom');\n // Missing altogether is the resolver's to report, against the import that needed it and with the path.\n if (!react || !reactDom) return;\n\n if (react !== reactDom) {\n throw new Error(\n `[rshono] react ${react} and react-dom ${reactDom} resolve to different versions.\\n` +\n ' React Server Components couple them: the RSC runtime emits a payload the matching react-dom parses, ' +\n 'so a split resolution fails inside React while rendering rather than here.\\n' +\n ' Install both at the same version. If a transitive dependency is what split them, pin them — ' +\n '`overrides` in npm, `pnpm.overrides` in pnpm, `resolutions` in yarn.',\n );\n }\n\n const tested = testedReactVersion();\n if (tested && minor(tested) !== minor(react)) {\n console.warn(\n ` ⚠ react ${react} is not the ${minor(tested)}.x this rshono was tested against. The RSC runtime is pinned\\n` +\n ' to an exact version and reaches into React internals, so a different minor can fail at render time.',\n );\n }\n}\n"]}
@@ -2,18 +2,12 @@ import { type RspackOptions } from '@rspack/core';
2
2
  import type { RshonoConfig } from '../config.js';
3
3
  import type { DeployPreset } from '../deploy/presets.js';
4
4
  /**
5
- * The directory a command writes its bundles to, relative to the project root — one per command,
6
- * never shared.
5
+ * The directory a command writes its bundles to, relative to the project root — one per command, never
6
+ * shared: a `rshono build` alongside a running `rshono dev` would `clean` away the route chunks that
7
+ * server imports lazily, and Rspack's watch-mode emit never re-emits a file it believes it wrote.
7
8
  *
8
- * `rshono build` run while `rshono dev` is up would otherwise write over the dev server's own
9
- * output: the build's `clean` empties `<out>/server`, and the route chunks it deletes are exactly
10
- * the ones the running server worker imports *lazily, at request time*. Every route the worker had
11
- * not already loaded then fails with `ERR_MODULE_NOT_FOUND`, and no later edit repairs it, because
12
- * Rspack's watch-mode emit compares against what it believes it already wrote rather than against
13
- * the disk — so it never re-emits the deleted files. The dev server 500s until it is restarted.
14
- *
15
- * Both names are a single level under the root, which {@link ../deploy/filesystem.ts} relies on: it
16
- * derives the project root from where the bundle ended up, `<out>/server/main.mjs` → `../..`.
9
+ * Both names are a single level under the root, which `deploy/filesystem.ts` relies on to derive the
10
+ * project root from where the bundle ended up.
17
11
  */
18
12
  export declare const BUILD_OUT_DIR = "dist";
19
13
  export declare const DEV_OUT_DIR = ".rshono";
@@ -1 +1 @@
1
- {"version":3,"file":"rspack-config.d.ts","sourceRoot":"","sources":["../../src/builder/rspack-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,aAAa,EAAoB,MAAM,cAAc,CAAC;AAK3F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAYzD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,aAAa,SAAS,CAAC;AACpC,eAAO,MAAM,WAAW,YAAY,CAAC;AAgFrC,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,2IAA2I;IAC3I,MAAM,EAAE,YAAY,CAAC;IACrB,4GAA4G;IAC5G,MAAM,EAAE,YAAY,CAAC;IACrB,wBAAwB,CAAC,EAAE,MAAM,IAAI,CAAC;CACvC;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,mBAAmB,GAAG,CAAC,aAAa,EAAE,aAAa,CAAC,CAgN1F"}
1
+ {"version":3,"file":"rspack-config.d.ts","sourceRoot":"","sources":["../../src/builder/rspack-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,aAAa,EAAoB,MAAM,cAAc,CAAC;AAK3F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAYzD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,SAAS,CAAC;AACpC,eAAO,MAAM,WAAW,YAAY,CAAC;AAqErC,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,2IAA2I;IAC3I,MAAM,EAAE,YAAY,CAAC;IACrB,4GAA4G;IAC5G,MAAM,EAAE,YAAY,CAAC;IACrB,wBAAwB,CAAC,EAAE,MAAM,IAAI,CAAC;CACvC;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,mBAAmB,GAAG,CAAC,aAAa,EAAE,aAAa,CAAC,CAsP1F"}