@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.
- package/LICENSE +21 -0
- package/README.md +29 -8
- package/bin/rshono.mjs +3 -4
- package/dist/builder/env-shadow-loader.cjs +25 -6
- package/dist/builder/page-files.js +5 -5
- package/dist/builder/page-files.js.map +1 -1
- package/dist/builder/public-env.d.ts +5 -4
- package/dist/builder/public-env.d.ts.map +1 -1
- package/dist/builder/public-env.js +5 -4
- package/dist/builder/public-env.js.map +1 -1
- package/dist/builder/react-versions.d.ts +13 -0
- package/dist/builder/react-versions.d.ts.map +1 -0
- package/dist/builder/react-versions.js +74 -0
- package/dist/builder/react-versions.js.map +1 -0
- package/dist/builder/rspack-config.d.ts +5 -11
- package/dist/builder/rspack-config.d.ts.map +1 -1
- package/dist/builder/rspack-config.js +73 -55
- package/dist/builder/rspack-config.js.map +1 -1
- package/dist/cli/build.d.ts.map +1 -1
- package/dist/cli/build.js +6 -2
- package/dist/cli/build.js.map +1 -1
- package/dist/cli/dev.d.ts.map +1 -1
- package/dist/cli/dev.js +30 -40
- package/dist/cli/dev.js.map +1 -1
- package/dist/cli/index.js +5 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/start.d.ts.map +1 -1
- package/dist/cli/start.js +12 -16
- package/dist/cli/start.js.map +1 -1
- package/dist/config.d.ts +28 -31
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -2
- package/dist/config.js.map +1 -1
- package/dist/deploy/aws-lambda/runtime.d.ts +4 -6
- package/dist/deploy/aws-lambda/runtime.d.ts.map +1 -1
- package/dist/deploy/aws-lambda/runtime.js +5 -8
- package/dist/deploy/aws-lambda/runtime.js.map +1 -1
- package/dist/deploy/build-marker.d.ts +3 -5
- package/dist/deploy/build-marker.d.ts.map +1 -1
- package/dist/deploy/build-marker.js +3 -5
- package/dist/deploy/build-marker.js.map +1 -1
- package/dist/deploy/cloudflare/build.d.ts.map +1 -1
- package/dist/deploy/cloudflare/build.js +6 -10
- package/dist/deploy/cloudflare/build.js.map +1 -1
- package/dist/deploy/cloudflare/runtime.d.ts +2 -5
- package/dist/deploy/cloudflare/runtime.d.ts.map +1 -1
- package/dist/deploy/cloudflare/runtime.js +19 -32
- package/dist/deploy/cloudflare/runtime.js.map +1 -1
- package/dist/deploy/contract.d.ts +25 -42
- package/dist/deploy/contract.d.ts.map +1 -1
- package/dist/deploy/contract.js.map +1 -1
- package/dist/deploy/filesystem.d.ts +3 -5
- package/dist/deploy/filesystem.d.ts.map +1 -1
- package/dist/deploy/filesystem.js +15 -11
- package/dist/deploy/filesystem.js.map +1 -1
- package/dist/deploy/node/runtime.d.ts +4 -5
- package/dist/deploy/node/runtime.d.ts.map +1 -1
- package/dist/deploy/node/runtime.js +9 -15
- package/dist/deploy/node/runtime.js.map +1 -1
- package/dist/deploy/presets.d.ts +19 -29
- package/dist/deploy/presets.d.ts.map +1 -1
- package/dist/deploy/presets.js +41 -24
- package/dist/deploy/presets.js.map +1 -1
- package/dist/deploy/vercel/build.d.ts.map +1 -1
- package/dist/deploy/vercel/build.js +19 -16
- package/dist/deploy/vercel/build.js.map +1 -1
- package/dist/deploy/vercel/runtime.d.ts +4 -7
- package/dist/deploy/vercel/runtime.d.ts.map +1 -1
- package/dist/deploy/vercel/runtime.js +13 -7
- package/dist/deploy/vercel/runtime.js.map +1 -1
- package/dist/index.d.ts +13 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -12
- package/dist/index.js.map +1 -1
- package/dist/router.d.ts +65 -93
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +2 -5
- package/dist/router.js.map +1 -1
- package/dist/runtime/boundaries.d.ts +24 -30
- package/dist/runtime/boundaries.d.ts.map +1 -1
- package/dist/runtime/boundaries.js +15 -22
- package/dist/runtime/boundaries.js.map +1 -1
- package/dist/runtime/client.d.ts +16 -7
- package/dist/runtime/client.d.ts.map +1 -1
- package/dist/runtime/client.js +16 -7
- package/dist/runtime/client.js.map +1 -1
- package/dist/runtime/context.d.ts +89 -118
- package/dist/runtime/context.d.ts.map +1 -1
- package/dist/runtime/context.js +122 -167
- package/dist/runtime/context.js.map +1 -1
- package/dist/runtime/control.js +3 -3
- package/dist/runtime/control.js.map +1 -1
- package/dist/runtime/dev-protocol.d.ts +4 -8
- package/dist/runtime/dev-protocol.d.ts.map +1 -1
- package/dist/runtime/dev-protocol.js.map +1 -1
- package/dist/runtime/entry.client.js +121 -113
- package/dist/runtime/entry.client.js.map +1 -1
- package/dist/runtime/entry.rsc.d.ts +5 -6
- package/dist/runtime/entry.rsc.d.ts.map +1 -1
- package/dist/runtime/entry.rsc.js +140 -129
- package/dist/runtime/entry.rsc.js.map +1 -1
- package/dist/runtime/entry.ssr.d.ts +7 -12
- package/dist/runtime/entry.ssr.d.ts.map +1 -1
- package/dist/runtime/entry.ssr.js +13 -24
- package/dist/runtime/entry.ssr.js.map +1 -1
- package/dist/runtime/flight-inject.d.ts +10 -17
- package/dist/runtime/flight-inject.d.ts.map +1 -1
- package/dist/runtime/flight-inject.js +63 -54
- package/dist/runtime/flight-inject.js.map +1 -1
- package/dist/runtime/hot-update.d.ts +20 -27
- package/dist/runtime/hot-update.d.ts.map +1 -1
- package/dist/runtime/hot-update.js +17 -23
- package/dist/runtime/hot-update.js.map +1 -1
- package/dist/runtime/navigation.d.ts +14 -19
- package/dist/runtime/navigation.d.ts.map +1 -1
- package/dist/runtime/navigation.js +9 -13
- package/dist/runtime/navigation.js.map +1 -1
- package/dist/runtime/request.d.ts +16 -10
- package/dist/runtime/request.d.ts.map +1 -1
- package/dist/runtime/request.js +30 -10
- package/dist/runtime/request.js.map +1 -1
- package/dist/runtime/server.d.ts +18 -10
- package/dist/runtime/server.d.ts.map +1 -1
- package/dist/runtime/server.js +21 -19
- package/dist/runtime/server.js.map +1 -1
- package/dist/server/headers.d.ts +8 -15
- package/dist/server/headers.d.ts.map +1 -1
- package/dist/server/headers.js +8 -15
- package/dist/server/headers.js.map +1 -1
- package/dist/server/load-config.d.ts +2 -2
- package/dist/server/load-config.d.ts.map +1 -1
- package/dist/server/load-config.js +6 -9
- package/dist/server/load-config.js.map +1 -1
- package/dist/server/prerendered.d.ts +40 -45
- package/dist/server/prerendered.d.ts.map +1 -1
- package/dist/server/prerendered.js +50 -33
- package/dist/server/prerendered.js.map +1 -1
- package/dist/server/server-config.d.ts +13 -28
- package/dist/server/server-config.d.ts.map +1 -1
- package/dist/server/server-config.js +5 -10
- package/dist/server/server-config.js.map +1 -1
- package/dist/server/shutdown.d.ts +5 -3
- package/dist/server/shutdown.d.ts.map +1 -1
- package/dist/server/shutdown.js +5 -3
- package/dist/server/shutdown.js.map +1 -1
- package/dist/server/ssg.d.ts +3 -6
- package/dist/server/ssg.d.ts.map +1 -1
- package/dist/server/ssg.js +12 -21
- package/dist/server/ssg.js.map +1 -1
- package/package.json +2 -2
package/dist/deploy/presets.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { finalizeCloudflareBuild } from './cloudflare/build.js';
|
|
2
2
|
import { finalizeVercelBuild } from './vercel/build.js';
|
|
3
3
|
/**
|
|
4
|
-
* Node: a long-lived server process. The generated config is already this shape
|
|
5
|
-
*
|
|
6
|
-
* policy, ESM chunk output) are the Node ones by default.
|
|
4
|
+
* Node: a long-lived server process. The generated config is already this shape — `target: 'node'`, the
|
|
5
|
+
* externals policy and ESM chunk output are all defaults — so the preset has nothing to contribute.
|
|
7
6
|
*/
|
|
8
7
|
export const NODE_PRESET = {
|
|
9
8
|
name: 'node',
|
|
@@ -13,12 +12,10 @@ export const NODE_PRESET = {
|
|
|
13
12
|
/**
|
|
14
13
|
* Cloudflare Workers: the host owns the process, the CDN owns the assets, and there is no filesystem.
|
|
15
14
|
*
|
|
16
|
-
* Every
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* computed specifier Rspack's ESM chunk loader emits — a split bundle would deploy and then fail on
|
|
21
|
-
* the first page render.
|
|
15
|
+
* Every setting here follows from `workerd` not being Node. Dependencies are bundled because nothing resolves
|
|
16
|
+
* `node_modules` at runtime; `node:` and `cloudflare:` imports stay external because the runtime provides
|
|
17
|
+
* them under `nodejs_compat`; and async chunks are inlined because Wrangler's bundler cannot follow the
|
|
18
|
+
* computed specifier Rspack's ESM chunk loader emits — a split bundle deploys and then fails on first render.
|
|
22
19
|
*/
|
|
23
20
|
const CLOUDFLARE_PRESET = {
|
|
24
21
|
name: 'cloudflare',
|
|
@@ -35,28 +32,50 @@ const CLOUDFLARE_PRESET = {
|
|
|
35
32
|
finalize: finalizeCloudflareBuild,
|
|
36
33
|
};
|
|
37
34
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
35
|
+
* Bundles the app's dependencies into the server output instead of importing them from `node_modules`.
|
|
36
|
+
*
|
|
37
|
+
* The generated config externalizes them, which is right where the bundle runs *inside* the project — but a
|
|
38
|
+
* serverless function is uploaded as a directory rather than installed into one, so nothing resolves
|
|
39
|
+
* `node_modules` at request time and an externalized `import 'some-package'` is a cold start that dies on
|
|
40
|
+
* `ERR_MODULE_NOT_FOUND`. Node's own builtins stay external either way, through the `node` externals preset
|
|
41
|
+
* that `target: 'node'` already enables.
|
|
42
|
+
*
|
|
43
|
+
* The cost is a dependency that cannot be bundled — a native addon, or one that reads its own files off disk
|
|
44
|
+
* relative to `__dirname`. Those now fail the build rather than the deploy, which is the same constraint
|
|
45
|
+
* `cloudflare` has always had; the `rspack` hook in `rshono.config.ts` is the way out.
|
|
46
|
+
*/
|
|
47
|
+
function bundleDependencies(config) {
|
|
48
|
+
config.externals = [];
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Vercel: one Node function behind the platform's CDN, which serves the assets and reaches the function only
|
|
52
|
+
* for a page. `finalize` assembles the Build Output API layout the platform uploads — including the
|
|
53
|
+
* `supportsResponseStreaming` flag, without which Vercel buffers the whole response and silently undoes
|
|
54
|
+
* streamed SSR.
|
|
55
|
+
*
|
|
56
|
+
* Only `dist/server` is uploaded with the function, which is why dependencies are bundled: see
|
|
57
|
+
* {@link bundleDependencies}.
|
|
43
58
|
*/
|
|
44
59
|
const VERCEL_PRESET = {
|
|
45
60
|
name: 'vercel',
|
|
46
61
|
runtimeModule: 'deploy/vercel/runtime.js',
|
|
47
62
|
deployHint: 'deploy with `vercel deploy --prebuilt`',
|
|
63
|
+
configureServer: bundleDependencies,
|
|
48
64
|
finalize: finalizeVercelBuild,
|
|
49
65
|
};
|
|
50
66
|
/**
|
|
51
|
-
* AWS Lambda behind a Function URL in `RESPONSE_STREAM` mode — the AWS shape that keeps streaming.
|
|
67
|
+
* AWS Lambda behind a Function URL in `RESPONSE_STREAM` mode — the AWS shape that keeps streaming. The
|
|
68
|
+
* runtime wraps the app in `awslambda.streamifyResponse`; the buffered alternative would deploy fine and then
|
|
69
|
+
* hold every page until its last byte rendered.
|
|
52
70
|
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
71
|
+
* The deployment package is `dist/` and nothing else, which is why dependencies are bundled: see
|
|
72
|
+
* {@link bundleDependencies}.
|
|
55
73
|
*/
|
|
56
74
|
const AWS_LAMBDA_PRESET = {
|
|
57
75
|
name: 'aws-lambda',
|
|
58
76
|
runtimeModule: 'deploy/aws-lambda/runtime.js',
|
|
59
77
|
deployHint: 'zip dist/ with the handler at dist/server/main.mjs',
|
|
78
|
+
configureServer: bundleDependencies,
|
|
60
79
|
};
|
|
61
80
|
const PRESETS = {
|
|
62
81
|
node: NODE_PRESET,
|
|
@@ -67,18 +86,16 @@ const PRESETS = {
|
|
|
67
86
|
/** Every target `deploy` accepts, for error messages and docs. */
|
|
68
87
|
export const DEPLOY_TARGETS = Object.keys(PRESETS);
|
|
69
88
|
/**
|
|
70
|
-
* How to deploy what a given target built, or `null` for a name this rshono does not know — which a
|
|
71
|
-
*
|
|
89
|
+
* How to deploy what a given target built, or `null` for a name this rshono does not know — which a `dist/`
|
|
90
|
+
* from a newer version can legitimately carry.
|
|
72
91
|
*/
|
|
73
92
|
export function deployHintFor(target) {
|
|
74
93
|
return PRESETS[target]?.deployHint ?? null;
|
|
75
94
|
}
|
|
76
95
|
/**
|
|
77
|
-
* Resolves the preset to build with: the flag wins over the environment, which wins over the config
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* Blank values are ignored at every level, so an unset-but-present `RSHONO_DEPLOY=` in a CI
|
|
81
|
-
* environment falls through to the config file instead of failing the build.
|
|
96
|
+
* Resolves the preset to build with: the flag wins over the environment, which wins over the config file,
|
|
97
|
+
* which wins over the `node` default. Blank values are ignored at every level, so an unset-but-present
|
|
98
|
+
* `RSHONO_DEPLOY=` in CI falls through rather than failing the build.
|
|
82
99
|
*/
|
|
83
100
|
export function resolveDeployPreset(sources = {}) {
|
|
84
101
|
const target = sources.flag?.trim() || sources.env?.trim() || sources.config?.trim();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presets.js","sourceRoot":"","sources":["../../src/deploy/presets.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AA2DxD;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAiB;IACvC,IAAI,EAAE,MAAM;IACZ,aAAa,EAAE,wBAAwB;IACvC,UAAU,EAAE,oBAAoB;CACjC,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,iBAAiB,GAAiB;IACtC,IAAI,EAAE,YAAY;IAClB,aAAa,EAAE,8BAA8B;IAC7C,UAAU,EAAE,+BAA+B;IAC3C,iBAAiB,EAAE,CAAC,SAAS,CAAC;IAC9B,aAAa,EAAE,CAAC,YAAY,CAAC;IAC7B,eAAe,CAAC,MAAM;QACpB,MAAM,CAAC,MAAM,GAAG,WAAW,CAAC;QAC5B,MAAM,CAAC,aAAa,GAAG,eAAe,CAAC;QACvC,MAAM,CAAC,SAAS,GAAG,CAAC,uBAAuB,CAAC,CAAC;QAC7C,MAAM,CAAC,MAAM,GAAG,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;IAC3D,CAAC;IACD,QAAQ,EAAE,uBAAuB;CAClC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,aAAa,GAAiB;IAClC,IAAI,EAAE,QAAQ;IACd,aAAa,EAAE,0BAA0B;IACzC,UAAU,EAAE,wCAAwC;IACpD,QAAQ,EAAE,mBAAmB;CAC9B,CAAC;AAEF;;;;;GAKG;AACH,MAAM,iBAAiB,GAAiB;IACtC,IAAI,EAAE,YAAY;IAClB,aAAa,EAAE,8BAA8B;IAC7C,UAAU,EAAE,oDAAoD;CACjE,CAAC;AAEF,MAAM,OAAO,GAAuC;IAClD,IAAI,EAAE,WAAW;IACjB,UAAU,EAAE,iBAAiB;IAC7B,MAAM,EAAE,aAAa;IACrB,YAAY,EAAE,iBAAiB;CAChC,CAAC;AAEF,kEAAkE;AAClE,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAmB,CAAC;AAErE;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,OAAQ,OAAoD,CAAC,MAAM,CAAC,EAAE,UAAU,IAAI,IAAI,CAAC;AAC3F,CAAC;AAYD;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAO,GAAkB,EAAE;IAC7D,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;IACrF,IAAI,CAAC,MAAM;QAAE,OAAO,WAAW,CAAC;IAEhC,MAAM,MAAM,GAAI,OAAoD,CAAC,MAAM,CAAC,CAAC;IAC7E,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,kCAAkC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,uBAAuB,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/H,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import type { RspackOptions } from '@rspack/core';\nimport { finalizeCloudflareBuild } from './cloudflare/build.js';\nimport type { DeployTarget } from './contract.js';\nimport { finalizeVercelBuild } from './vercel/build.js';\n\n/** What a preset's {@link DeployPreset.finalize} is told about the build it is arranging. */\nexport interface DeployBuildContext {\n /** The project root — where `rshono build` ran, and what a platform config file is written next to. */\n rootDir: string;\n /** `<root>/dist`. */\n distDir: string;\n /** The hashed client bundle, `<root>/dist/static` — served at `/_static`. */\n staticDir: string;\n /** The copy of the app's `public/`, or `null` when it has none. Served at the web root. */\n publicDir: string | null;\n /** Prerendered pages, `<root>/dist/ssg` — empty when the app has no `render: 'static'` routes. */\n ssgDir: string;\n}\n\n/**\n * The build-time half of a deploy target: which runtime module the bundle gets, how the server\n * compiler has to change to produce something the platform can run, and how the output is arranged\n * once it exists.\n *\n * The runtime half is {@link DeployRuntime}, in its own file because it is compiled *into* the app\n * bundle — this side only ever runs in the CLI.\n */\nexport interface DeployPreset {\n readonly name: DeployTarget;\n /**\n * The module `@rshono/deploy` resolves to, as a path relative to the framework's own `dist/`.\n * Slash-separated and split on use, so it stays a valid path on Windows too.\n */\n readonly runtimeModule: string;\n /** How to run what was just built, completing the \"build complete —\" line. */\n readonly deployHint: string;\n /**\n * Extra resolve conditions for the server bundle, most specific first.\n *\n * This is what picks the right build of React and the RSC runtime: both ship one per runtime behind\n * `workerd` / `deno` / `edge-light` / `node` conditions. Omit it to accept whatever the Rspack\n * target implies, which is correct for Node.\n */\n readonly resolveConditions?: readonly string[];\n /** browserslist-style targets for the server bundle's swc pass. Defaults to Node. */\n readonly syntaxTargets?: readonly string[];\n /**\n * Adjusts the generated server Rspack config for this platform — target, externals policy, output\n * shape. Mutates in place, and runs *before* the user's `rspack` hook so that hook keeps the last\n * word.\n */\n configureServer?(config: RspackOptions): void;\n /**\n * Arranges the finished build for the platform: assembles whatever directory layout it expects,\n * emits its config file, and prints how to deploy.\n *\n * Runs last — after both bundles, the `public/` copy and the prerender pass — so everything it\n * needs to move is already on disk.\n */\n finalize?(ctx: DeployBuildContext): Promise<void> | void;\n}\n\n/**\n * Node: a long-lived server process. The generated config is already this shape, so the preset has\n * nothing to contribute — the settings in `builder/rspack-config.ts` (`target: 'node'`, the externals\n * policy, ESM chunk output) are the Node ones by default.\n */\nexport const NODE_PRESET: DeployPreset = {\n name: 'node',\n runtimeModule: 'deploy/node/runtime.js',\n deployHint: 'run `rshono start`',\n};\n\n/**\n * Cloudflare Workers: the host owns the process, the CDN owns the assets, and there is no filesystem.\n *\n * Every compiler setting here follows from `workerd` not being Node. Dependencies are bundled because\n * nothing resolves `node_modules` at runtime; `node:` and `cloudflare:` imports stay external because\n * the runtime provides them (`nodejs_compat`, which the scaffolded config enables for\n * `AsyncLocalStorage`); and async chunks are inlined because Wrangler's bundler cannot follow the\n * computed specifier Rspack's ESM chunk loader emits — a split bundle would deploy and then fail on\n * the first page render.\n */\nconst CLOUDFLARE_PRESET: DeployPreset = {\n name: 'cloudflare',\n runtimeModule: 'deploy/cloudflare/runtime.js',\n deployHint: 'deploy with `wrangler deploy`',\n resolveConditions: ['workerd'],\n syntaxTargets: ['chrome 120'],\n configureServer(config) {\n config.target = 'webworker';\n config.externalsType = 'module-import';\n config.externals = [/^(?:node|cloudflare):/];\n config.output = { ...config.output, asyncChunks: false };\n },\n finalize: finalizeCloudflareBuild,\n};\n\n/**\n * Vercel: one Node function behind the platform's CDN, which serves the assets and reaches the function\n * only for a page. `finalize` assembles the Build Output API layout the platform uploads — including the\n * `supportsResponseStreaming` flag, without which Vercel buffers the whole response and streamed SSR is\n * silently undone. That flag, and the exact path the bundle has to keep, are the reason this is a preset\n * rather than a snippet in the docs.\n */\nconst VERCEL_PRESET: DeployPreset = {\n name: 'vercel',\n runtimeModule: 'deploy/vercel/runtime.js',\n deployHint: 'deploy with `vercel deploy --prebuilt`',\n finalize: finalizeVercelBuild,\n};\n\n/**\n * AWS Lambda behind a Function URL in `RESPONSE_STREAM` mode — the AWS shape that keeps streaming.\n *\n * Same reasoning as Vercel: the runtime wraps the app in `awslambda.streamifyResponse`, and the buffered\n * alternative would deploy fine and then hold every page until its last byte rendered.\n */\nconst AWS_LAMBDA_PRESET: DeployPreset = {\n name: 'aws-lambda',\n runtimeModule: 'deploy/aws-lambda/runtime.js',\n deployHint: 'zip dist/ with the handler at dist/server/main.mjs',\n};\n\nconst PRESETS: Record<DeployTarget, DeployPreset> = {\n node: NODE_PRESET,\n cloudflare: CLOUDFLARE_PRESET,\n vercel: VERCEL_PRESET,\n 'aws-lambda': AWS_LAMBDA_PRESET,\n};\n\n/** Every target `deploy` accepts, for error messages and docs. */\nexport const DEPLOY_TARGETS = Object.keys(PRESETS) as DeployTarget[];\n\n/**\n * How to deploy what a given target built, or `null` for a name this rshono does not know — which a\n * `dist/` produced by a newer version can legitimately carry.\n */\nexport function deployHintFor(target: string): string | null {\n return (PRESETS as Record<string, DeployPreset | undefined>)[target]?.deployHint ?? null;\n}\n\n/** Where a deploy target can be named, in precedence order. */\nexport interface DeploySources {\n /** The `--deploy` flag. */\n flag?: string;\n /** The `RSHONO_DEPLOY` env var — for a CI job that deploys the same app to more than one place. */\n env?: string;\n /** {@link RshonoConfig.deploy} from `rshono.config.ts`. */\n config?: string;\n}\n\n/**\n * Resolves the preset to build with: the flag wins over the environment, which wins over the config\n * file, which wins over the `node` default.\n *\n * Blank values are ignored at every level, so an unset-but-present `RSHONO_DEPLOY=` in a CI\n * environment falls through to the config file instead of failing the build.\n */\nexport function resolveDeployPreset(sources: DeploySources = {}): DeployPreset {\n const target = sources.flag?.trim() || sources.env?.trim() || sources.config?.trim();\n if (!target) return NODE_PRESET;\n\n const preset = (PRESETS as Record<string, DeployPreset | undefined>)[target];\n if (!preset) {\n throw new Error(`[rshono] unknown deploy target ${JSON.stringify(target)} — expected one of: ${DEPLOY_TARGETS.join(', ')}.`);\n }\n return preset;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"presets.js","sourceRoot":"","sources":["../../src/deploy/presets.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAoDxD;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAiB;IACvC,IAAI,EAAE,MAAM;IACZ,aAAa,EAAE,wBAAwB;IACvC,UAAU,EAAE,oBAAoB;CACjC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,iBAAiB,GAAiB;IACtC,IAAI,EAAE,YAAY;IAClB,aAAa,EAAE,8BAA8B;IAC7C,UAAU,EAAE,+BAA+B;IAC3C,iBAAiB,EAAE,CAAC,SAAS,CAAC;IAC9B,aAAa,EAAE,CAAC,YAAY,CAAC;IAC7B,eAAe,CAAC,MAAM;QACpB,MAAM,CAAC,MAAM,GAAG,WAAW,CAAC;QAC5B,MAAM,CAAC,aAAa,GAAG,eAAe,CAAC;QACvC,MAAM,CAAC,SAAS,GAAG,CAAC,uBAAuB,CAAC,CAAC;QAC7C,MAAM,CAAC,MAAM,GAAG,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;IAC3D,CAAC;IACD,QAAQ,EAAE,uBAAuB;CAClC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,SAAS,kBAAkB,CAAC,MAAqB;IAC/C,MAAM,CAAC,SAAS,GAAG,EAAE,CAAC;AACxB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,aAAa,GAAiB;IAClC,IAAI,EAAE,QAAQ;IACd,aAAa,EAAE,0BAA0B;IACzC,UAAU,EAAE,wCAAwC;IACpD,eAAe,EAAE,kBAAkB;IACnC,QAAQ,EAAE,mBAAmB;CAC9B,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,iBAAiB,GAAiB;IACtC,IAAI,EAAE,YAAY;IAClB,aAAa,EAAE,8BAA8B;IAC7C,UAAU,EAAE,oDAAoD;IAChE,eAAe,EAAE,kBAAkB;CACpC,CAAC;AAEF,MAAM,OAAO,GAAuC;IAClD,IAAI,EAAE,WAAW;IACjB,UAAU,EAAE,iBAAiB;IAC7B,MAAM,EAAE,aAAa;IACrB,YAAY,EAAE,iBAAiB;CAChC,CAAC;AAEF,kEAAkE;AAClE,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAmB,CAAC;AAErE;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,OAAQ,OAAoD,CAAC,MAAM,CAAC,EAAE,UAAU,IAAI,IAAI,CAAC;AAC3F,CAAC;AAYD;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAO,GAAkB,EAAE;IAC7D,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;IACrF,IAAI,CAAC,MAAM;QAAE,OAAO,WAAW,CAAC;IAEhC,MAAM,MAAM,GAAI,OAAoD,CAAC,MAAM,CAAC,CAAC;IAC7E,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,kCAAkC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,uBAAuB,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/H,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import type { RspackOptions } from '@rspack/core';\nimport { finalizeCloudflareBuild } from './cloudflare/build.js';\nimport type { DeployTarget } from './contract.js';\nimport { finalizeVercelBuild } from './vercel/build.js';\n\n/** What a preset's {@link DeployPreset.finalize} is told about the build it is arranging. */\nexport interface DeployBuildContext {\n /** The project root — where `rshono build` ran, and what a platform config file is written next to. */\n rootDir: string;\n /** `<root>/dist`. */\n distDir: string;\n /** The hashed client bundle, `<root>/dist/static` — served at `/_static`. */\n staticDir: string;\n /** The copy of the app's `public/`, or `null` when it has none. Served at the web root. */\n publicDir: string | null;\n /** Prerendered pages, `<root>/dist/ssg` — empty when the app has no `render: 'static'` routes. */\n ssgDir: string;\n}\n\n/**\n * The build-time half of a deploy target: which runtime module the bundle gets, how the server compiler has\n * to change to produce something the platform can run, and how the output is arranged once it exists.\n *\n * The runtime half is `DeployRuntime`, in its own file because it is compiled *into* the app bundle — this\n * side only ever runs in the CLI.\n */\nexport interface DeployPreset {\n readonly name: DeployTarget;\n /**\n * The module `@rshono/deploy` resolves to, as a path relative to the framework's own `dist/`.\n * Slash-separated and split on use, so it stays a valid path on Windows too.\n */\n readonly runtimeModule: string;\n /** How to run what was just built, completing the \"build complete —\" line. */\n readonly deployHint: string;\n /**\n * Extra resolve conditions for the server bundle, most specific first — what picks the right build of React\n * and the RSC runtime, both of which ship one per runtime. Omit to accept whatever the Rspack target\n * implies, which is correct for Node.\n */\n readonly resolveConditions?: readonly string[];\n /** browserslist-style targets for the server bundle's swc pass. Defaults to Node. */\n readonly syntaxTargets?: readonly string[];\n /**\n * Adjusts the generated server Rspack config for this platform — target, externals policy, output shape.\n * Mutates in place, and runs before the user's `rspack` hook so that hook keeps the last word.\n */\n configureServer?(config: RspackOptions): void;\n /**\n * Arranges the finished build for the platform: assembles the directory layout it expects, emits its config\n * file, and prints how to deploy. Runs last, so everything it needs to move is already on disk.\n */\n finalize?(ctx: DeployBuildContext): Promise<void> | void;\n}\n\n/**\n * Node: a long-lived server process. The generated config is already this shape — `target: 'node'`, the\n * externals policy and ESM chunk output are all defaults — so the preset has nothing to contribute.\n */\nexport const NODE_PRESET: DeployPreset = {\n name: 'node',\n runtimeModule: 'deploy/node/runtime.js',\n deployHint: 'run `rshono start`',\n};\n\n/**\n * Cloudflare Workers: the host owns the process, the CDN owns the assets, and there is no filesystem.\n *\n * Every setting here follows from `workerd` not being Node. Dependencies are bundled because nothing resolves\n * `node_modules` at runtime; `node:` and `cloudflare:` imports stay external because the runtime provides\n * them under `nodejs_compat`; and async chunks are inlined because Wrangler's bundler cannot follow the\n * computed specifier Rspack's ESM chunk loader emits — a split bundle deploys and then fails on first render.\n */\nconst CLOUDFLARE_PRESET: DeployPreset = {\n name: 'cloudflare',\n runtimeModule: 'deploy/cloudflare/runtime.js',\n deployHint: 'deploy with `wrangler deploy`',\n resolveConditions: ['workerd'],\n syntaxTargets: ['chrome 120'],\n configureServer(config) {\n config.target = 'webworker';\n config.externalsType = 'module-import';\n config.externals = [/^(?:node|cloudflare):/];\n config.output = { ...config.output, asyncChunks: false };\n },\n finalize: finalizeCloudflareBuild,\n};\n\n/**\n * Bundles the app's dependencies into the server output instead of importing them from `node_modules`.\n *\n * The generated config externalizes them, which is right where the bundle runs *inside* the project — but a\n * serverless function is uploaded as a directory rather than installed into one, so nothing resolves\n * `node_modules` at request time and an externalized `import 'some-package'` is a cold start that dies on\n * `ERR_MODULE_NOT_FOUND`. Node's own builtins stay external either way, through the `node` externals preset\n * that `target: 'node'` already enables.\n *\n * The cost is a dependency that cannot be bundled — a native addon, or one that reads its own files off disk\n * relative to `__dirname`. Those now fail the build rather than the deploy, which is the same constraint\n * `cloudflare` has always had; the `rspack` hook in `rshono.config.ts` is the way out.\n */\nfunction bundleDependencies(config: RspackOptions): void {\n config.externals = [];\n}\n\n/**\n * Vercel: one Node function behind the platform's CDN, which serves the assets and reaches the function only\n * for a page. `finalize` assembles the Build Output API layout the platform uploads — including the\n * `supportsResponseStreaming` flag, without which Vercel buffers the whole response and silently undoes\n * streamed SSR.\n *\n * Only `dist/server` is uploaded with the function, which is why dependencies are bundled: see\n * {@link bundleDependencies}.\n */\nconst VERCEL_PRESET: DeployPreset = {\n name: 'vercel',\n runtimeModule: 'deploy/vercel/runtime.js',\n deployHint: 'deploy with `vercel deploy --prebuilt`',\n configureServer: bundleDependencies,\n finalize: finalizeVercelBuild,\n};\n\n/**\n * AWS Lambda behind a Function URL in `RESPONSE_STREAM` mode — the AWS shape that keeps streaming. The\n * runtime wraps the app in `awslambda.streamifyResponse`; the buffered alternative would deploy fine and then\n * hold every page until its last byte rendered.\n *\n * The deployment package is `dist/` and nothing else, which is why dependencies are bundled: see\n * {@link bundleDependencies}.\n */\nconst AWS_LAMBDA_PRESET: DeployPreset = {\n name: 'aws-lambda',\n runtimeModule: 'deploy/aws-lambda/runtime.js',\n deployHint: 'zip dist/ with the handler at dist/server/main.mjs',\n configureServer: bundleDependencies,\n};\n\nconst PRESETS: Record<DeployTarget, DeployPreset> = {\n node: NODE_PRESET,\n cloudflare: CLOUDFLARE_PRESET,\n vercel: VERCEL_PRESET,\n 'aws-lambda': AWS_LAMBDA_PRESET,\n};\n\n/** Every target `deploy` accepts, for error messages and docs. */\nexport const DEPLOY_TARGETS = Object.keys(PRESETS) as DeployTarget[];\n\n/**\n * How to deploy what a given target built, or `null` for a name this rshono does not know — which a `dist/`\n * from a newer version can legitimately carry.\n */\nexport function deployHintFor(target: string): string | null {\n return (PRESETS as Record<string, DeployPreset | undefined>)[target]?.deployHint ?? null;\n}\n\n/** Where a deploy target can be named, in precedence order. */\nexport interface DeploySources {\n /** The `--deploy` flag. */\n flag?: string;\n /** The `RSHONO_DEPLOY` env var — for a CI job that deploys the same app to more than one place. */\n env?: string;\n /** The `deploy` field in `rshono.config.ts`. */\n config?: string;\n}\n\n/**\n * Resolves the preset to build with: the flag wins over the environment, which wins over the config file,\n * which wins over the `node` default. Blank values are ignored at every level, so an unset-but-present\n * `RSHONO_DEPLOY=` in CI falls through rather than failing the build.\n */\nexport function resolveDeployPreset(sources: DeploySources = {}): DeployPreset {\n const target = sources.flag?.trim() || sources.env?.trim() || sources.config?.trim();\n if (!target) return NODE_PRESET;\n\n const preset = (PRESETS as Record<string, DeployPreset | undefined>)[target];\n if (!preset) {\n throw new Error(`[rshono] unknown deploy target ${JSON.stringify(target)} — expected one of: ${DEPLOY_TARGETS.join(', ')}.`);\n }\n return preset;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/deploy/vercel/build.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/deploy/vercel/build.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AA0BxD,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4ChF"}
|
|
@@ -2,23 +2,20 @@ import { cpSync, existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
|
2
2
|
import { rm } from 'node:fs/promises';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
/**
|
|
5
|
-
* The Build Output API v3 layout, which
|
|
6
|
-
*
|
|
5
|
+
* The Build Output API v3 layout, which `vercel deploy --prebuilt` uploads verbatim — producing it directly
|
|
6
|
+
* means Vercel runs no build of its own.
|
|
7
7
|
*/
|
|
8
8
|
const OUTPUT_DIR = join('.vercel', 'output');
|
|
9
9
|
const FUNCTION_DIR = join('functions', 'index.func');
|
|
10
10
|
/**
|
|
11
|
-
* The function
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* project root from where the bundle sits (see `deploy/filesystem.ts`) — so `dist/ssg` and `dist/public`
|
|
15
|
-
* land where it already looks for them, and no runtime code needs to know it is on Vercel.
|
|
11
|
+
* The bundle keeps this exact path inside the function because the runtime derives the project root from where
|
|
12
|
+
* it sits (see `deploy/filesystem.ts`), so `dist/ssg` and `dist/public` land where it already looks — and no
|
|
13
|
+
* runtime code needs to know it is on Vercel.
|
|
16
14
|
*/
|
|
17
15
|
const HANDLER = 'dist/server/main.mjs';
|
|
18
16
|
/**
|
|
19
|
-
* Routes, in the order Vercel evaluates them: hashed assets get the immutable header the CDN cannot
|
|
20
|
-
*
|
|
21
|
-
* app's to render.
|
|
17
|
+
* Routes, in the order Vercel evaluates them: hashed assets get the immutable header the CDN cannot infer,
|
|
18
|
+
* then anything in the static output is served from it, and whatever is left is the app's to render.
|
|
22
19
|
*/
|
|
23
20
|
const ROUTES = [
|
|
24
21
|
{ src: '^/_static/(.*)$', headers: { 'cache-control': 'public, max-age=31536000, immutable' }, continue: true },
|
|
@@ -29,7 +26,7 @@ export async function finalizeVercelBuild(ctx) {
|
|
|
29
26
|
const outputDir = join(ctx.rootDir, OUTPUT_DIR);
|
|
30
27
|
const staticOut = join(outputDir, 'static');
|
|
31
28
|
const functionDir = join(outputDir, FUNCTION_DIR);
|
|
32
|
-
//
|
|
29
|
+
// From scratch, so a deleted page or asset cannot survive in the uploaded output.
|
|
33
30
|
await rm(outputDir, { recursive: true, force: true });
|
|
34
31
|
mkdirSync(staticOut, { recursive: true });
|
|
35
32
|
mkdirSync(functionDir, { recursive: true });
|
|
@@ -37,17 +34,23 @@ export async function finalizeVercelBuild(ctx) {
|
|
|
37
34
|
cpSync(ctx.staticDir, join(staticOut, '_static'), { recursive: true });
|
|
38
35
|
if (ctx.publicDir)
|
|
39
36
|
cpSync(ctx.publicDir, staticOut, { recursive: true });
|
|
40
|
-
// Shipped inside the function: the bundle,
|
|
37
|
+
// Shipped inside the function: the bundle, and the one thing it reads from disk at request time.
|
|
38
|
+
//
|
|
39
|
+
// `public/` is deliberately *not* among them, though it is on the filesystem targets. It went into the
|
|
40
|
+
// static output above, and `{ handle: 'filesystem' }` sits ahead of the catch-all route, so the platform
|
|
41
|
+
// answers those paths before the function is invoked — a copy here is bytes uploaded and unpacked on every
|
|
42
|
+
// cold start that nothing can ever read. `vercel/runtime.ts` turns the matching mount off to say so.
|
|
41
43
|
cpSync(join(ctx.distDir, 'server'), join(functionDir, 'dist', 'server'), { recursive: true });
|
|
42
44
|
if (existsSync(ctx.ssgDir))
|
|
43
45
|
cpSync(ctx.ssgDir, join(functionDir, 'dist', 'ssg'), { recursive: true });
|
|
44
|
-
if (ctx.publicDir)
|
|
45
|
-
cpSync(ctx.publicDir, join(functionDir, 'dist', 'public'), { recursive: true });
|
|
46
46
|
writeFileSync(join(functionDir, '.vc-config.json'), `${JSON.stringify({
|
|
47
|
-
runtime
|
|
47
|
+
// The Node the build ran on, so the function runs the runtime the app was tested against — and so
|
|
48
|
+
// this does not become a hard-coded version the platform retires on a date the framework does not
|
|
49
|
+
// control. A major Vercel does not offer is an explicit error from the deploy rather than a mismatch.
|
|
50
|
+
runtime: `nodejs${process.versions.node.split('.')[0]}.x`,
|
|
48
51
|
handler: HANDLER,
|
|
49
52
|
launcherType: 'Nodejs',
|
|
50
|
-
// Without this the platform buffers the whole response,
|
|
53
|
+
// Without this the platform buffers the whole response, undoing streamed SSR.
|
|
51
54
|
supportsResponseStreaming: true,
|
|
52
55
|
}, null, 2)}\n`);
|
|
53
56
|
writeFileSync(join(outputDir, 'config.json'), `${JSON.stringify({ version: 3, routes: ROUTES }, null, 2)}\n`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../../src/deploy/vercel/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACvE,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC;;;GAGG;AACH,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAC7C,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;AAErD
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../../src/deploy/vercel/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACvE,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC;;;GAGG;AACH,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAC7C,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;AAErD;;;;GAIG;AACH,MAAM,OAAO,GAAG,sBAAsB,CAAC;AAEvC;;;GAGG;AACH,MAAM,MAAM,GAAG;IACb,EAAE,GAAG,EAAE,iBAAiB,EAAE,OAAO,EAAE,EAAE,eAAe,EAAE,qCAAqC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC/G,EAAE,MAAM,EAAE,YAAY,EAAE;IACxB,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE;CACjC,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,GAAuB;IAC/D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAChD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC5C,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAElD,kFAAkF;IAClF,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE5C,6FAA6F;IAC7F,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvE,IAAI,GAAG,CAAC,SAAS;QAAE,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEzE,iGAAiG;IACjG,EAAE;IACF,uGAAuG;IACvG,yGAAyG;IACzG,2GAA2G;IAC3G,qGAAqG;IACrG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9F,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC;QAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEtG,aAAa,CACX,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,EACpC,GAAG,IAAI,CAAC,SAAS,CACf;QACE,kGAAkG;QAClG,kGAAkG;QAClG,sGAAsG;QACtG,OAAO,EAAE,SAAS,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI;QACzD,OAAO,EAAE,OAAO;QAChB,YAAY,EAAE,QAAQ;QACtB,8EAA8E;QAC9E,yBAAyB,EAAE,IAAI;KAChC,EACD,IAAI,EACJ,CAAC,CACF,IAAI,CACN,CAAC;IAEF,aAAa,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAE9G,OAAO,CAAC,GAAG,CAAC,iBAAiB,UAAU,wBAAwB,CAAC,CAAC;AACnE,CAAC","sourcesContent":["import { cpSync, existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { rm } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { DeployBuildContext } from '../presets.js';\n\n/**\n * The Build Output API v3 layout, which `vercel deploy --prebuilt` uploads verbatim — producing it directly\n * means Vercel runs no build of its own.\n */\nconst OUTPUT_DIR = join('.vercel', 'output');\nconst FUNCTION_DIR = join('functions', 'index.func');\n\n/**\n * The bundle keeps this exact path inside the function because the runtime derives the project root from where\n * it sits (see `deploy/filesystem.ts`), so `dist/ssg` and `dist/public` land where it already looks — and no\n * runtime code needs to know it is on Vercel.\n */\nconst HANDLER = 'dist/server/main.mjs';\n\n/**\n * Routes, in the order Vercel evaluates them: hashed assets get the immutable header the CDN cannot infer,\n * then anything in the static output is served from it, and whatever is left is the app's to render.\n */\nconst ROUTES = [\n { src: '^/_static/(.*)$', headers: { 'cache-control': 'public, max-age=31536000, immutable' }, continue: true },\n { handle: 'filesystem' },\n { src: '/(.*)', dest: '/index' },\n];\n\nexport async function finalizeVercelBuild(ctx: DeployBuildContext): Promise<void> {\n const outputDir = join(ctx.rootDir, OUTPUT_DIR);\n const staticOut = join(outputDir, 'static');\n const functionDir = join(outputDir, FUNCTION_DIR);\n\n // From scratch, so a deleted page or asset cannot survive in the uploaded output.\n await rm(outputDir, { recursive: true, force: true });\n mkdirSync(staticOut, { recursive: true });\n mkdirSync(functionDir, { recursive: true });\n\n // Served by the CDN: the hashed bundle under its public path, and `public/` at the web root.\n cpSync(ctx.staticDir, join(staticOut, '_static'), { recursive: true });\n if (ctx.publicDir) cpSync(ctx.publicDir, staticOut, { recursive: true });\n\n // Shipped inside the function: the bundle, and the one thing it reads from disk at request time.\n //\n // `public/` is deliberately *not* among them, though it is on the filesystem targets. It went into the\n // static output above, and `{ handle: 'filesystem' }` sits ahead of the catch-all route, so the platform\n // answers those paths before the function is invoked — a copy here is bytes uploaded and unpacked on every\n // cold start that nothing can ever read. `vercel/runtime.ts` turns the matching mount off to say so.\n cpSync(join(ctx.distDir, 'server'), join(functionDir, 'dist', 'server'), { recursive: true });\n if (existsSync(ctx.ssgDir)) cpSync(ctx.ssgDir, join(functionDir, 'dist', 'ssg'), { recursive: true });\n\n writeFileSync(\n join(functionDir, '.vc-config.json'),\n `${JSON.stringify(\n {\n // The Node the build ran on, so the function runs the runtime the app was tested against — and so\n // this does not become a hard-coded version the platform retires on a date the framework does not\n // control. A major Vercel does not offer is an explicit error from the deploy rather than a mismatch.\n runtime: `nodejs${process.versions.node.split('.')[0]}.x`,\n handler: HANDLER,\n launcherType: 'Nodejs',\n // Without this the platform buffers the whole response, undoing streamed SSR.\n supportsResponseStreaming: true,\n },\n null,\n 2,\n )}\\n`,\n );\n\n writeFileSync(join(outputDir, 'config.json'), `${JSON.stringify({ version: 3, routes: ROUTES }, null, 2)}\\n`);\n\n console.log(` • assembled ${OUTPUT_DIR} (Build Output API v3)`);\n}\n"]}
|
|
@@ -2,13 +2,10 @@ import type { DeployRuntime } from '../contract.js';
|
|
|
2
2
|
/**
|
|
3
3
|
* Vercel, as a single Node function fed by the platform's own router.
|
|
4
4
|
*
|
|
5
|
-
* `/_static` and `public/` are in the static output, and `config.json` puts the filesystem handler
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* Prerendered pages are *not* static output: one URL answers with a document or a flight payload
|
|
10
|
-
* depending on `Accept`, and a path-keyed CDN cannot choose. They ship inside the function instead and
|
|
11
|
-
* are read from its read-only disk, exactly as on a server.
|
|
5
|
+
* `/_static` and `public/` are in the static output, and `config.json` puts the filesystem handler ahead of the
|
|
6
|
+
* function, so mounting them here would be dead weight. Prerendered pages are *not* static output — one URL
|
|
7
|
+
* answers with a document or a flight payload on the `RSC` request header, and a path-keyed CDN cannot choose — so
|
|
8
|
+
* they ship inside the function and are read from its read-only disk, exactly as on a server.
|
|
12
9
|
*/
|
|
13
10
|
export declare const runtime: DeployRuntime;
|
|
14
11
|
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/deploy/vercel/runtime.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGpD
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/deploy/vercel/runtime.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGpD;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,EAAE,aAoBrB,CAAC"}
|
|
@@ -3,19 +3,25 @@ import { fileSystemRuntime } from '../filesystem.js';
|
|
|
3
3
|
/**
|
|
4
4
|
* Vercel, as a single Node function fed by the platform's own router.
|
|
5
5
|
*
|
|
6
|
-
* `/_static` and `public/` are in the static output, and `config.json` puts the filesystem handler
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* Prerendered pages are *not* static output: one URL answers with a document or a flight payload
|
|
11
|
-
* depending on `Accept`, and a path-keyed CDN cannot choose. They ship inside the function instead and
|
|
12
|
-
* are read from its read-only disk, exactly as on a server.
|
|
6
|
+
* `/_static` and `public/` are in the static output, and `config.json` puts the filesystem handler ahead of the
|
|
7
|
+
* function, so mounting them here would be dead weight. Prerendered pages are *not* static output — one URL
|
|
8
|
+
* answers with a document or a flight payload on the `RSC` request header, and a path-keyed CDN cannot choose — so
|
|
9
|
+
* they ship inside the function and are read from its read-only disk, exactly as on a server.
|
|
13
10
|
*/
|
|
14
11
|
export const runtime = {
|
|
15
12
|
...fileSystemRuntime,
|
|
16
13
|
mountStaticAssets() {
|
|
17
14
|
// Served from `.vercel/output/static` before the function runs.
|
|
18
15
|
},
|
|
16
|
+
mountPublicFallback() {
|
|
17
|
+
// As above: `public/` is in the static output and `{ handle: 'filesystem' }` is matched ahead of this
|
|
18
|
+
// function, so nothing here could ever answer for one of those paths. Stated as an override rather than
|
|
19
|
+
// left to fall out of `dist/public` not being uploaded, because that would make the behaviour incidental
|
|
20
|
+
// to a `cpSync` in `build.ts` instead of a decision.
|
|
21
|
+
//
|
|
22
|
+
// The one thing this hands to the platform: resolving a directory to its `index.html`. Vercel's static
|
|
23
|
+
// handler does that; `serveStatic`, which the filesystem targets use, is no longer in the path.
|
|
24
|
+
},
|
|
19
25
|
serveApp(app) {
|
|
20
26
|
return handle(app);
|
|
21
27
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/deploy/vercel/runtime.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/deploy/vercel/runtime.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,OAAO,GAAkB;IACpC,GAAG,iBAAiB;IAEpB,iBAAiB;QACf,gEAAgE;IAClE,CAAC;IAED,mBAAmB;QACjB,sGAAsG;QACtG,wGAAwG;QACxG,yGAAyG;QACzG,qDAAqD;QACrD,EAAE;QACF,uGAAuG;QACvG,gGAAgG;IAClG,CAAC;IAED,QAAQ,CAAC,GAAS;QAChB,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;CACF,CAAC","sourcesContent":["import type { Hono } from 'hono';\nimport { handle } from 'hono/vercel';\nimport type { DeployRuntime } from '../contract.js';\nimport { fileSystemRuntime } from '../filesystem.js';\n\n/**\n * Vercel, as a single Node function fed by the platform's own router.\n *\n * `/_static` and `public/` are in the static output, and `config.json` puts the filesystem handler ahead of the\n * function, so mounting them here would be dead weight. Prerendered pages are *not* static output — one URL\n * answers with a document or a flight payload on the `RSC` request header, and a path-keyed CDN cannot choose — so\n * they ship inside the function and are read from its read-only disk, exactly as on a server.\n */\nexport const runtime: DeployRuntime = {\n ...fileSystemRuntime,\n\n mountStaticAssets(): void {\n // Served from `.vercel/output/static` before the function runs.\n },\n\n mountPublicFallback(): void {\n // As above: `public/` is in the static output and `{ handle: 'filesystem' }` is matched ahead of this\n // function, so nothing here could ever answer for one of those paths. Stated as an override rather than\n // left to fall out of `dist/public` not being uploaded, because that would make the behaviour incidental\n // to a `cpSync` in `build.ts` instead of a decision.\n //\n // The one thing this hands to the platform: resolving a directory to its `index.html`. Vercel's static\n // handler does that; `serveStatic`, which the filesystem targets use, is no longer in the path.\n },\n\n serveApp(app: Hono): unknown {\n return handle(app);\n },\n};\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `@rshono/core` — the build-time surface: route and config declaration plus the types
|
|
3
|
-
* your pages and endpoints are written against.
|
|
4
|
-
* import from server code; none of it pulls in runtime machinery.
|
|
2
|
+
* `@rshono/core` — the build-time surface: route and config declaration, plus the types
|
|
3
|
+
* your pages and endpoints are written against. Nothing here pulls in runtime machinery.
|
|
5
4
|
*
|
|
6
|
-
*
|
|
7
|
-
* - `@rshono/core/server` —
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
5
|
+
* Two companion entry points are runtime-only:
|
|
6
|
+
* - `@rshono/core/server` — request context, `redirect`, `notFound`, `onServerError`.
|
|
7
|
+
* - `@rshono/core/client` — `useNavigation`, `AsyncBoundary`, `CatchBoundary`.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* // src/routes.ts
|
|
12
|
+
* import { defineRoutes } from '@rshono/core';
|
|
13
|
+
*
|
|
14
|
+
* export const routes = defineRoutes([{ path: '/', component: () => import('./components/home') }]);
|
|
15
|
+
* ```
|
|
12
16
|
*
|
|
13
17
|
* @see {@link https://www.rshono.com/docs/api | Docs — API reference}
|
|
14
18
|
*
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EACL,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,KAAK,EACV,KAAK,WAAW,GACjB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEtF,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `@rshono/core` — the build-time surface: route and config declaration plus the types
|
|
3
|
-
* your pages and endpoints are written against.
|
|
4
|
-
* import from server code; none of it pulls in runtime machinery.
|
|
2
|
+
* `@rshono/core` — the build-time surface: route and config declaration, plus the types
|
|
3
|
+
* your pages and endpoints are written against. Nothing here pulls in runtime machinery.
|
|
5
4
|
*
|
|
6
|
-
*
|
|
7
|
-
* - `@rshono/core/server` —
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
5
|
+
* Two companion entry points are runtime-only:
|
|
6
|
+
* - `@rshono/core/server` — request context, `redirect`, `notFound`, `onServerError`.
|
|
7
|
+
* - `@rshono/core/client` — `useNavigation`, `AsyncBoundary`, `CatchBoundary`.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* // src/routes.ts
|
|
12
|
+
* import { defineRoutes } from '@rshono/core';
|
|
13
|
+
*
|
|
14
|
+
* export const routes = defineRoutes([{ path: '/', component: () => import('./components/home') }]);
|
|
15
|
+
* ```
|
|
12
16
|
*
|
|
13
17
|
* @see {@link https://www.rshono.com/docs/api | Docs — API reference}
|
|
14
18
|
*
|
|
@@ -16,7 +20,6 @@
|
|
|
16
20
|
*/
|
|
17
21
|
export { defineRoutes, } from './router.js';
|
|
18
22
|
export { defineConfig } from './config.js';
|
|
19
|
-
// Hono's `Context` and `Handler` are deliberately not re-exported
|
|
20
|
-
//
|
|
21
|
-
// spellings of the same type.
|
|
23
|
+
// Hono's `Context` and `Handler` are deliberately not re-exported — `hono` is a peer dependency, so
|
|
24
|
+
// endpoints import them from there rather than from two spellings of the same type.
|
|
22
25
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EACL,YAAY,GAab,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,YAAY,EAA6C,MAAM,aAAa,CAAC;AAItF,oGAAoG;AACpG,oFAAoF","sourcesContent":["/**\n * `@rshono/core` — the build-time surface: route and config declaration, plus the types\n * your pages and endpoints are written against. Nothing here pulls in runtime machinery.\n *\n * Two companion entry points are runtime-only:\n * - `@rshono/core/server` — request context, `redirect`, `notFound`, `onServerError`.\n * - `@rshono/core/client` — `useNavigation`, `AsyncBoundary`, `CatchBoundary`.\n *\n * @example\n * ```ts\n * // src/routes.ts\n * import { defineRoutes } from '@rshono/core';\n *\n * export const routes = defineRoutes([{ path: '/', component: () => import('./components/home') }]);\n * ```\n *\n * @see {@link https://www.rshono.com/docs/api | Docs — API reference}\n *\n * @packageDocumentation\n */\n\nexport {\n defineRoutes,\n type EndpointRoute,\n type EndpointServerModule,\n type ErrorPageInfo,\n type ErrorPageProps,\n type FallbackPage,\n type HTTPMethod,\n type PageComponent,\n type PageProps,\n type PageRoute,\n type PathParams,\n type Route,\n type RouteConfig,\n} from './router.js';\n\nexport { defineConfig, type RshonoConfig, type RspackHookContext } from './config.js';\n\nexport type { DeployTarget } from './deploy/contract.js';\n\n// Hono's `Context` and `Handler` are deliberately not re-exported — `hono` is a peer dependency, so\n// endpoints import them from there rather than from two spellings of the same type.\n"]}
|