@rshono/core 1.0.0-rc.2 → 1.0.0-rc.21
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 +348 -158
- package/bin/rshono.mjs +3 -4
- package/dist/builder/env-shadow-loader.cjs +123 -8
- package/dist/builder/page-entry-loader.cjs +28 -1
- package/dist/builder/page-files.d.ts +0 -1
- package/dist/builder/page-files.js +7 -3
- package/dist/builder/page-files.js.map +1 -1
- package/dist/builder/public-env.d.ts +7 -1
- package/dist/builder/public-env.js +7 -0
- package/dist/builder/public-env.js.map +1 -1
- package/dist/builder/react-versions.d.ts +12 -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 +13 -4
- package/dist/builder/rspack-config.js +136 -53
- package/dist/builder/rspack-config.js.map +1 -1
- package/dist/builder/server-only-imports.d.ts +32 -0
- package/dist/builder/server-only-imports.js +51 -0
- package/dist/builder/server-only-imports.js.map +1 -0
- package/dist/cli/build.d.ts +2 -3
- package/dist/cli/build.js +51 -13
- package/dist/cli/build.js.map +1 -1
- package/dist/cli/dev.d.ts +2 -3
- package/dist/cli/dev.js +149 -45
- package/dist/cli/dev.js.map +1 -1
- package/dist/cli/exit.d.ts +12 -0
- package/dist/cli/exit.js +16 -0
- package/dist/cli/exit.js.map +1 -0
- package/dist/cli/index.d.ts +0 -1
- package/dist/cli/index.js +91 -30
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/start.d.ts +0 -1
- package/dist/cli/start.js +15 -18
- package/dist/cli/start.js.map +1 -1
- package/dist/config.d.ts +72 -78
- package/dist/config.js +17 -1
- package/dist/config.js.map +1 -1
- package/dist/deploy/aws-lambda/runtime.d.ts +4 -7
- 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 +9 -6
- package/dist/deploy/build-marker.js +8 -4
- package/dist/deploy/build-marker.js.map +1 -1
- package/dist/deploy/cloudflare/build.d.ts +0 -1
- package/dist/deploy/cloudflare/build.js +17 -13
- package/dist/deploy/cloudflare/build.js.map +1 -1
- package/dist/deploy/cloudflare/runtime.d.ts +2 -6
- package/dist/deploy/cloudflare/runtime.js +73 -68
- package/dist/deploy/cloudflare/runtime.js.map +1 -1
- package/dist/deploy/contract.d.ts +57 -41
- package/dist/deploy/contract.js.map +1 -1
- package/dist/deploy/filesystem.d.ts +3 -6
- package/dist/deploy/filesystem.js +23 -20
- package/dist/deploy/filesystem.js.map +1 -1
- package/dist/deploy/node/runtime.d.ts +5 -3
- package/dist/deploy/node/runtime.js +23 -9
- package/dist/deploy/node/runtime.js.map +1 -1
- package/dist/deploy/presets.d.ts +34 -30
- package/dist/deploy/presets.js +56 -44
- package/dist/deploy/presets.js.map +1 -1
- package/dist/deploy/public-paths.d.ts +42 -0
- package/dist/deploy/public-paths.js +66 -0
- package/dist/deploy/public-paths.js.map +1 -0
- package/dist/deploy/vercel/build.d.ts +0 -1
- package/dist/deploy/vercel/build.js +25 -16
- package/dist/deploy/vercel/build.js.map +1 -1
- package/dist/deploy/vercel/runtime.d.ts +10 -7
- package/dist/deploy/vercel/runtime.js +48 -11
- package/dist/deploy/vercel/runtime.js.map +1 -1
- package/dist/index.d.ts +19 -17
- package/dist/index.js +20 -10
- package/dist/index.js.map +1 -1
- package/dist/router.d.ts +212 -120
- package/dist/router.js +3 -8
- package/dist/router.js.map +1 -1
- package/dist/runtime/boundaries.d.ts +62 -48
- package/dist/runtime/boundaries.js +32 -34
- package/dist/runtime/boundaries.js.map +1 -1
- package/dist/runtime/client.d.ts +20 -11
- package/dist/runtime/client.js +20 -10
- package/dist/runtime/client.js.map +1 -1
- package/dist/runtime/context.d.ts +304 -123
- package/dist/runtime/context.js +377 -149
- package/dist/runtime/context.js.map +1 -1
- package/dist/runtime/control.d.ts +15 -1
- package/dist/runtime/control.js +24 -0
- package/dist/runtime/control.js.map +1 -1
- package/dist/runtime/dev-protocol.d.ts +4 -9
- package/dist/runtime/dev-protocol.js.map +1 -1
- package/dist/runtime/empty-server-app.d.ts +0 -1
- package/dist/runtime/entry.client.d.ts +4 -1
- package/dist/runtime/entry.client.js +455 -313
- package/dist/runtime/entry.client.js.map +1 -1
- package/dist/runtime/entry.rsc.d.ts +15 -7
- package/dist/runtime/entry.rsc.js +811 -252
- package/dist/runtime/entry.rsc.js.map +1 -1
- package/dist/runtime/entry.ssr.d.ts +27 -10
- package/dist/runtime/entry.ssr.js +30 -48
- package/dist/runtime/entry.ssr.js.map +1 -1
- package/dist/runtime/failure-document.d.ts +11 -0
- package/dist/runtime/failure-document.js +35 -0
- package/dist/runtime/failure-document.js.map +1 -0
- package/dist/runtime/flight-inject.d.ts +23 -0
- package/dist/runtime/flight-inject.js +403 -0
- package/dist/runtime/flight-inject.js.map +1 -0
- package/dist/runtime/hot-update.d.ts +44 -0
- package/dist/runtime/hot-update.js +44 -0
- package/dist/runtime/hot-update.js.map +1 -0
- package/dist/runtime/navigation.d.ts +46 -54
- package/dist/runtime/navigation.js +22 -63
- package/dist/runtime/navigation.js.map +1 -1
- package/dist/runtime/request.d.ts +42 -8
- package/dist/runtime/request.js +84 -7
- package/dist/runtime/request.js.map +1 -1
- package/dist/runtime/server.d.ts +20 -18
- package/dist/runtime/server.js +22 -17
- package/dist/runtime/server.js.map +1 -1
- package/dist/runtime/validate-entries.d.ts +77 -0
- package/dist/runtime/validate-entries.js +405 -0
- package/dist/runtime/validate-entries.js.map +1 -0
- package/dist/server/headers.d.ts +41 -15
- package/dist/server/headers.js +53 -24
- package/dist/server/headers.js.map +1 -1
- package/dist/server/load-config.d.ts +4 -5
- package/dist/server/load-config.js +22 -14
- package/dist/server/load-config.js.map +1 -1
- package/dist/server/load-env.d.ts +0 -1
- package/dist/server/prerendered.d.ts +88 -34
- package/dist/server/prerendered.js +184 -24
- package/dist/server/prerendered.js.map +1 -1
- package/dist/server/server-config.d.ts +35 -50
- package/dist/server/server-config.js +27 -74
- package/dist/server/server-config.js.map +1 -1
- package/dist/server/shutdown.d.ts +5 -4
- package/dist/server/shutdown.js +5 -3
- package/dist/server/shutdown.js.map +1 -1
- package/dist/server/ssg.d.ts +9 -7
- package/dist/server/ssg.js +209 -65
- package/dist/server/ssg.js.map +1 -1
- package/dist/server/static.d.ts +0 -1
- package/dist/server/static.js +7 -1
- package/dist/server/static.js.map +1 -1
- package/package.json +21 -23
- package/dist/builder/page-files.d.ts.map +0 -1
- package/dist/builder/public-env.d.ts.map +0 -1
- package/dist/builder/rspack-config.d.ts.map +0 -1
- package/dist/cli/build.d.ts.map +0 -1
- package/dist/cli/dev.d.ts.map +0 -1
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/start.d.ts.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/deploy/aws-lambda/runtime.d.ts.map +0 -1
- package/dist/deploy/build-marker.d.ts.map +0 -1
- package/dist/deploy/bun/runtime.d.ts +0 -11
- package/dist/deploy/bun/runtime.d.ts.map +0 -1
- package/dist/deploy/bun/runtime.js +0 -22
- package/dist/deploy/bun/runtime.js.map +0 -1
- package/dist/deploy/cloudflare/build.d.ts.map +0 -1
- package/dist/deploy/cloudflare/runtime.d.ts.map +0 -1
- package/dist/deploy/contract.d.ts.map +0 -1
- package/dist/deploy/deno/runtime.d.ts +0 -11
- package/dist/deploy/deno/runtime.d.ts.map +0 -1
- package/dist/deploy/deno/runtime.js +0 -16
- package/dist/deploy/deno/runtime.js.map +0 -1
- package/dist/deploy/filesystem.d.ts.map +0 -1
- package/dist/deploy/listen.d.ts +0 -20
- package/dist/deploy/listen.d.ts.map +0 -1
- package/dist/deploy/listen.js +0 -24
- package/dist/deploy/listen.js.map +0 -1
- package/dist/deploy/netlify/build.d.ts +0 -8
- package/dist/deploy/netlify/build.d.ts.map +0 -1
- package/dist/deploy/netlify/build.js +0 -52
- package/dist/deploy/netlify/build.js.map +0 -1
- package/dist/deploy/netlify/runtime.d.ts +0 -13
- package/dist/deploy/netlify/runtime.d.ts.map +0 -1
- package/dist/deploy/netlify/runtime.js +0 -24
- package/dist/deploy/netlify/runtime.js.map +0 -1
- package/dist/deploy/node/runtime.d.ts.map +0 -1
- package/dist/deploy/presets.d.ts.map +0 -1
- package/dist/deploy/vercel/build.d.ts.map +0 -1
- package/dist/deploy/vercel/runtime.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/router.d.ts.map +0 -1
- package/dist/runtime/boundaries.d.ts.map +0 -1
- package/dist/runtime/client.d.ts.map +0 -1
- package/dist/runtime/context.d.ts.map +0 -1
- package/dist/runtime/control.d.ts.map +0 -1
- package/dist/runtime/dev-protocol.d.ts.map +0 -1
- package/dist/runtime/empty-server-app.d.ts.map +0 -1
- package/dist/runtime/entry.client.d.ts.map +0 -1
- package/dist/runtime/entry.rsc.d.ts.map +0 -1
- package/dist/runtime/entry.ssr.d.ts.map +0 -1
- package/dist/runtime/navigation.d.ts.map +0 -1
- package/dist/runtime/request.d.ts.map +0 -1
- package/dist/runtime/server.d.ts.map +0 -1
- package/dist/server/compress.d.ts +0 -15
- package/dist/server/compress.d.ts.map +0 -1
- package/dist/server/compress.js +0 -76
- package/dist/server/compress.js.map +0 -1
- package/dist/server/headers.d.ts.map +0 -1
- package/dist/server/load-config.d.ts.map +0 -1
- package/dist/server/load-env.d.ts.map +0 -1
- package/dist/server/prerendered.d.ts.map +0 -1
- package/dist/server/server-config.d.ts.map +0 -1
- package/dist/server/shutdown.d.ts.map +0 -1
- package/dist/server/ssg.d.ts.map +0 -1
- package/dist/server/static.d.ts.map +0 -1
package/dist/server/headers.d.ts
CHANGED
|
@@ -1,24 +1,50 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* comparison subtly wrong is exactly the kind of thing that only shows up behind a CDN.
|
|
2
|
+
* Header utilities shared by the response-header defaults and the prerendered-page cache. Their own module
|
|
3
|
+
* because getting `Vary` and `ETag` comparison subtly wrong only shows up behind a CDN.
|
|
5
4
|
*/
|
|
6
5
|
/**
|
|
7
|
-
*
|
|
6
|
+
* What a 404 under the `/_static` mount must carry, on every deploy target.
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
8
|
+
* A 404 is heuristically cacheable under RFC 9111, and the miss this answers is the one a **rolling deploy**
|
|
9
|
+
* produces: an old instance 404s a content-hashed chunk the new one has. Without this a shared cache may
|
|
10
|
+
* store that answer against a URL that is about to become valid, and then serve it to everyone.
|
|
11
|
+
*
|
|
12
|
+
* Shared by the two mounts — `createStaticAssetsApp` for the filesystem targets and `mountStaticAssets` in
|
|
13
|
+
* `deploy/cloudflare/runtime.ts` — because it was written down in one of them and inherited by accident in
|
|
14
|
+
* the other, which is how the Workers mount came to have no terminal 404 at all. Here rather than in either,
|
|
15
|
+
* since `server/static.ts` reaches for `@hono/node-server` and a Worker bundle cannot import it.
|
|
16
|
+
*
|
|
17
|
+
* The same string as a page response's default (`PAGE_CACHE_CONTROL` in `entry.rsc.tsx`) and a separate
|
|
18
|
+
* constant on purpose: that one is about a logged-in user's page, this one about a hash that is about to
|
|
19
|
+
* resolve, and a change to either must not move the other.
|
|
13
20
|
*/
|
|
14
|
-
export declare
|
|
21
|
+
export declare const ASSET_MISS_CACHE_CONTROL = "private, no-cache";
|
|
15
22
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
23
|
+
* The `Vary` a response needs in order to carry `value`, or `null` when there is nothing to write — because it
|
|
24
|
+
* already lists it, or because it lists `*`, which means "never reuse this" and covers everything.
|
|
25
|
+
*
|
|
26
|
+
* What is already there is kept, spelling and all: a route, a middleware or a proxy may have added an entry of
|
|
27
|
+
* its own, and a plain `set` would drop it, leaving a cache free to serve one variant in place of another.
|
|
18
28
|
*
|
|
19
|
-
* The header
|
|
20
|
-
*
|
|
21
|
-
*
|
|
29
|
+
* The header is parsed into entries rather than tested as a string, because both of the questions it is asked
|
|
30
|
+
* are about the *list* and neither is about the text. `*` counts wherever it sits, not only alone — a cache
|
|
31
|
+
* told never to reuse a response is not told it harder by another field name. And an existing header with no
|
|
32
|
+
* entries in it (`vary: ''`, which an app writing one from a list that came out empty can produce, and which
|
|
33
|
+
* Hono keeps verbatim) is nothing to append to: `, RSC` is an empty list element, which RFC 9110 tells a
|
|
34
|
+
* sender not to generate, and a cache strict enough to reject the malformed header would drop the `Vary` that
|
|
35
|
+
* is the only thing keeping a page URL's two representations apart. That is the failure this header exists to
|
|
36
|
+
* prevent, reached through the header itself.
|
|
37
|
+
*
|
|
38
|
+
* Pure, and separate from {@link appendVary}, because the two callers cannot write the same way. One holds a
|
|
39
|
+
* `Response` it built itself; the response floor holds one the *app* may have returned, whose header bag can be
|
|
40
|
+
* immutable — see the floor in `entry.rsc.tsx`, which writes this answer through `c.header()`.
|
|
41
|
+
*/
|
|
42
|
+
export declare function varyWith(existing: string | null, value: string): string | null;
|
|
43
|
+
/** {@link varyWith}, written straight back — for a `Headers` the caller knows it can write to. */
|
|
44
|
+
export declare function appendVary(headers: Headers, value: string): void;
|
|
45
|
+
/**
|
|
46
|
+
* True when an `If-None-Match` matches `etag` — the client already holds this body and can be answered with a
|
|
47
|
+
* 304. The header carries a list, and the weak prefix is ignored on both sides: a CDN that gzips on the way out
|
|
48
|
+
* changes the bytes without changing the representation, and may weaken the validator when it does.
|
|
22
49
|
*/
|
|
23
50
|
export declare function etagMatches(ifNoneMatch: string | undefined, etag: string): boolean;
|
|
24
|
-
//# sourceMappingURL=headers.d.ts.map
|
package/dist/server/headers.js
CHANGED
|
@@ -1,35 +1,64 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* comparison subtly wrong is exactly the kind of thing that only shows up behind a CDN.
|
|
2
|
+
* Header utilities shared by the response-header defaults and the prerendered-page cache. Their own module
|
|
3
|
+
* because getting `Vary` and `ETag` comparison subtly wrong only shows up behind a CDN.
|
|
5
4
|
*/
|
|
6
5
|
/**
|
|
7
|
-
*
|
|
6
|
+
* What a 404 under the `/_static` mount must carry, on every deploy target.
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
8
|
+
* A 404 is heuristically cacheable under RFC 9111, and the miss this answers is the one a **rolling deploy**
|
|
9
|
+
* produces: an old instance 404s a content-hashed chunk the new one has. Without this a shared cache may
|
|
10
|
+
* store that answer against a URL that is about to become valid, and then serve it to everyone.
|
|
11
|
+
*
|
|
12
|
+
* Shared by the two mounts — `createStaticAssetsApp` for the filesystem targets and `mountStaticAssets` in
|
|
13
|
+
* `deploy/cloudflare/runtime.ts` — because it was written down in one of them and inherited by accident in
|
|
14
|
+
* the other, which is how the Workers mount came to have no terminal 404 at all. Here rather than in either,
|
|
15
|
+
* since `server/static.ts` reaches for `@hono/node-server` and a Worker bundle cannot import it.
|
|
16
|
+
*
|
|
17
|
+
* The same string as a page response's default (`PAGE_CACHE_CONTROL` in `entry.rsc.tsx`) and a separate
|
|
18
|
+
* constant on purpose: that one is about a logged-in user's page, this one about a hash that is about to
|
|
19
|
+
* resolve, and a change to either must not move the other.
|
|
13
20
|
*/
|
|
21
|
+
export const ASSET_MISS_CACHE_CONTROL = 'private, no-cache';
|
|
22
|
+
/**
|
|
23
|
+
* The `Vary` a response needs in order to carry `value`, or `null` when there is nothing to write — because it
|
|
24
|
+
* already lists it, or because it lists `*`, which means "never reuse this" and covers everything.
|
|
25
|
+
*
|
|
26
|
+
* What is already there is kept, spelling and all: a route, a middleware or a proxy may have added an entry of
|
|
27
|
+
* its own, and a plain `set` would drop it, leaving a cache free to serve one variant in place of another.
|
|
28
|
+
*
|
|
29
|
+
* The header is parsed into entries rather than tested as a string, because both of the questions it is asked
|
|
30
|
+
* are about the *list* and neither is about the text. `*` counts wherever it sits, not only alone — a cache
|
|
31
|
+
* told never to reuse a response is not told it harder by another field name. And an existing header with no
|
|
32
|
+
* entries in it (`vary: ''`, which an app writing one from a list that came out empty can produce, and which
|
|
33
|
+
* Hono keeps verbatim) is nothing to append to: `, RSC` is an empty list element, which RFC 9110 tells a
|
|
34
|
+
* sender not to generate, and a cache strict enough to reject the malformed header would drop the `Vary` that
|
|
35
|
+
* is the only thing keeping a page URL's two representations apart. That is the failure this header exists to
|
|
36
|
+
* prevent, reached through the header itself.
|
|
37
|
+
*
|
|
38
|
+
* Pure, and separate from {@link appendVary}, because the two callers cannot write the same way. One holds a
|
|
39
|
+
* `Response` it built itself; the response floor holds one the *app* may have returned, whose header bag can be
|
|
40
|
+
* immutable — see the floor in `entry.rsc.tsx`, which writes this answer through `c.header()`.
|
|
41
|
+
*/
|
|
42
|
+
export function varyWith(existing, value) {
|
|
43
|
+
if (existing === null)
|
|
44
|
+
return value;
|
|
45
|
+
const entries = existing.split(',').map((entry) => entry.trim());
|
|
46
|
+
if (entries.some((entry) => entry === '*' || entry.toLowerCase() === value.toLowerCase()))
|
|
47
|
+
return null;
|
|
48
|
+
// Appended to the original text, not to the parsed entries, so a header this has nothing to say about comes
|
|
49
|
+
// back exactly as its author wrote it.
|
|
50
|
+
return entries.some(Boolean) ? `${existing}, ${value}` : value;
|
|
51
|
+
}
|
|
52
|
+
/** {@link varyWith}, written straight back — for a `Headers` the caller knows it can write to. */
|
|
14
53
|
export function appendVary(headers, value) {
|
|
15
|
-
const
|
|
16
|
-
if (
|
|
17
|
-
headers.set('vary',
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
if (existing.trim() === '*')
|
|
21
|
-
return;
|
|
22
|
-
const already = existing.split(',').some((entry) => entry.trim().toLowerCase() === value.toLowerCase());
|
|
23
|
-
if (!already)
|
|
24
|
-
headers.set('vary', `${existing}, ${value}`);
|
|
54
|
+
const vary = varyWith(headers.get('vary'), value);
|
|
55
|
+
if (vary !== null)
|
|
56
|
+
headers.set('vary', vary);
|
|
25
57
|
}
|
|
26
58
|
/**
|
|
27
|
-
* True when an `If-None-Match`
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* The header carries a *list*, and each entry may be weak (`W/"…"`). The weak prefix is ignored on
|
|
31
|
-
* both sides because the compressor rewrites a strong tag to a weak one when it changes the bytes
|
|
32
|
-
* on the wire — the representation is still the same one the client cached.
|
|
59
|
+
* True when an `If-None-Match` matches `etag` — the client already holds this body and can be answered with a
|
|
60
|
+
* 304. The header carries a list, and the weak prefix is ignored on both sides: a CDN that gzips on the way out
|
|
61
|
+
* changes the bytes without changing the representation, and may weaken the validator when it does.
|
|
33
62
|
*/
|
|
34
63
|
export function etagMatches(ifNoneMatch, etag) {
|
|
35
64
|
if (!ifNoneMatch)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headers.js","sourceRoot":"","sources":["../../src/server/headers.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"headers.js","sourceRoot":"","sources":["../../src/server/headers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,mBAAmB,CAAC;AAE5D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,QAAQ,CAAC,QAAuB,EAAE,KAAa;IAC7D,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACpC,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IACjE,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,GAAG,IAAI,KAAK,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,WAAW,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IACvG,4GAA4G;IAC5G,uCAAuC;IACvC,OAAO,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;AACjE,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,UAAU,CAAC,OAAgB,EAAE,KAAa;IACxD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC;IAClD,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,WAA+B,EAAE,IAAY;IACvE,IAAI,CAAC,WAAW;QAAE,OAAO,KAAK,CAAC;IAC/B,MAAM,SAAS,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACtE,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC/B,OAAO,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;QAC3C,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;QACnC,OAAO,SAAS,KAAK,GAAG,IAAI,SAAS,KAAK,MAAM,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["/**\n * Header utilities shared by the response-header defaults and the prerendered-page cache. Their own module\n * because getting `Vary` and `ETag` comparison subtly wrong only shows up behind a CDN.\n */\n\n/**\n * What a 404 under the `/_static` mount must carry, on every deploy target.\n *\n * A 404 is heuristically cacheable under RFC 9111, and the miss this answers is the one a **rolling deploy**\n * produces: an old instance 404s a content-hashed chunk the new one has. Without this a shared cache may\n * store that answer against a URL that is about to become valid, and then serve it to everyone.\n *\n * Shared by the two mounts — `createStaticAssetsApp` for the filesystem targets and `mountStaticAssets` in\n * `deploy/cloudflare/runtime.ts` — because it was written down in one of them and inherited by accident in\n * the other, which is how the Workers mount came to have no terminal 404 at all. Here rather than in either,\n * since `server/static.ts` reaches for `@hono/node-server` and a Worker bundle cannot import it.\n *\n * The same string as a page response's default (`PAGE_CACHE_CONTROL` in `entry.rsc.tsx`) and a separate\n * constant on purpose: that one is about a logged-in user's page, this one about a hash that is about to\n * resolve, and a change to either must not move the other.\n */\nexport const ASSET_MISS_CACHE_CONTROL = 'private, no-cache';\n\n/**\n * The `Vary` a response needs in order to carry `value`, or `null` when there is nothing to write — because it\n * already lists it, or because it lists `*`, which means \"never reuse this\" and covers everything.\n *\n * What is already there is kept, spelling and all: a route, a middleware or a proxy may have added an entry of\n * its own, and a plain `set` would drop it, leaving a cache free to serve one variant in place of another.\n *\n * The header is parsed into entries rather than tested as a string, because both of the questions it is asked\n * are about the *list* and neither is about the text. `*` counts wherever it sits, not only alone — a cache\n * told never to reuse a response is not told it harder by another field name. And an existing header with no\n * entries in it (`vary: ''`, which an app writing one from a list that came out empty can produce, and which\n * Hono keeps verbatim) is nothing to append to: `, RSC` is an empty list element, which RFC 9110 tells a\n * sender not to generate, and a cache strict enough to reject the malformed header would drop the `Vary` that\n * is the only thing keeping a page URL's two representations apart. That is the failure this header exists to\n * prevent, reached through the header itself.\n *\n * Pure, and separate from {@link appendVary}, because the two callers cannot write the same way. One holds a\n * `Response` it built itself; the response floor holds one the *app* may have returned, whose header bag can be\n * immutable — see the floor in `entry.rsc.tsx`, which writes this answer through `c.header()`.\n */\nexport function varyWith(existing: string | null, value: string): string | null {\n if (existing === null) return value;\n const entries = existing.split(',').map((entry) => entry.trim());\n if (entries.some((entry) => entry === '*' || entry.toLowerCase() === value.toLowerCase())) return null;\n // Appended to the original text, not to the parsed entries, so a header this has nothing to say about comes\n // back exactly as its author wrote it.\n return entries.some(Boolean) ? `${existing}, ${value}` : value;\n}\n\n/** {@link varyWith}, written straight back — for a `Headers` the caller knows it can write to. */\nexport function appendVary(headers: Headers, value: string): void {\n const vary = varyWith(headers.get('vary'), value);\n if (vary !== null) headers.set('vary', vary);\n}\n\n/**\n * True when an `If-None-Match` matches `etag` — the client already holds this body and can be answered with a\n * 304. The header carries a list, and the weak prefix is ignored on both sides: a CDN that gzips on the way out\n * changes the bytes without changing the representation, and may weaken the validator when it does.\n */\nexport function etagMatches(ifNoneMatch: string | undefined, etag: string): boolean {\n if (!ifNoneMatch) return false;\n const normalize = (value: string) => value.trim().replace(/^W\\//, '');\n const wanted = normalize(etag);\n return ifNoneMatch.split(',').some((entry) => {\n const candidate = normalize(entry);\n return candidate === '*' || candidate === wanted;\n });\n}\n"]}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RshonoConfig } from '../config.js';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* Loads the project config, or `{}` if there is none: scans `rshono.config.{ts,js,mjs}` at `rootDir`, unless an
|
|
4
|
+
* explicit `configPath` is given (resolved relative to `cwd`).
|
|
5
5
|
*/
|
|
6
|
-
export declare function loadConfig(rootDir: string, configPath?: string): Promise<
|
|
7
|
-
//# sourceMappingURL=load-config.d.ts.map
|
|
6
|
+
export declare function loadConfig(rootDir: string, configPath?: string): Promise<RshonoConfig>;
|
|
@@ -3,23 +3,19 @@ import { isAbsolute, join, resolve } from 'node:path';
|
|
|
3
3
|
import { pathToFileURL } from 'node:url';
|
|
4
4
|
const CONFIG_FILES = ['rshono.config.ts', 'rshono.config.js', 'rshono.config.mjs'];
|
|
5
5
|
/**
|
|
6
|
-
* Imports the config module.
|
|
6
|
+
* Imports the config module. A `.ts` config needs no loader: Node strips types natively from 22.18 on, which is
|
|
7
|
+
* what the package's `engines` floor is for.
|
|
7
8
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* other command instead of paying for a TypeScript loader the whole CLI doesn't need.
|
|
9
|
+
* The one thing native stripping will not do is resolve a `.js` specifier to a `.ts` file, so a config
|
|
10
|
+
* importing a sibling has to name it with its real extension — {@link loadConfig} turns that resolution failure
|
|
11
|
+
* into the advice rather than letting a raw `ERR_MODULE_NOT_FOUND` out.
|
|
12
12
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (!/\.[cm]?ts$/.test(file))
|
|
16
|
-
return import(href);
|
|
17
|
-
const { tsImport } = await import('tsx/esm/api');
|
|
18
|
-
return tsImport(href, import.meta.url);
|
|
13
|
+
function importConfig(file) {
|
|
14
|
+
return import(pathToFileURL(file).href);
|
|
19
15
|
}
|
|
20
16
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
17
|
+
* Loads the project config, or `{}` if there is none: scans `rshono.config.{ts,js,mjs}` at `rootDir`, unless an
|
|
18
|
+
* explicit `configPath` is given (resolved relative to `cwd`).
|
|
23
19
|
*/
|
|
24
20
|
export async function loadConfig(rootDir, configPath) {
|
|
25
21
|
const file = configPath
|
|
@@ -32,7 +28,19 @@ export async function loadConfig(rootDir, configPath) {
|
|
|
32
28
|
if (!existsSync(file)) {
|
|
33
29
|
throw new Error(`[rshono] config file not found: ${file}`);
|
|
34
30
|
}
|
|
35
|
-
|
|
31
|
+
let mod;
|
|
32
|
+
try {
|
|
33
|
+
mod = await importConfig(file);
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
// The one failure mode native type stripping has that a TypeScript-aware loader does not.
|
|
37
|
+
if (/\.[cm]?ts$/.test(file) && error?.code === 'ERR_MODULE_NOT_FOUND') {
|
|
38
|
+
throw new Error(`[rshono] ${file} imports a module Node could not resolve: ${error.message}\n` +
|
|
39
|
+
' A .ts config is loaded by Node itself, which does not rewrite a .js specifier to the .ts file ' +
|
|
40
|
+
'beside it. Import it by its real extension, or move the config to rshono.config.mjs.', { cause: error });
|
|
41
|
+
}
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
36
44
|
if (!mod.default) {
|
|
37
45
|
throw new Error(`[rshono] ${file} must \`export default\` a config object (use \`defineConfig({ … })\`).`);
|
|
38
46
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-config.js","sourceRoot":"","sources":["../../src/server/load-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,MAAM,YAAY,GAAG,CAAC,kBAAkB,EAAE,kBAAkB,EAAE,mBAAmB,CAAC,CAAC;AAEnF;;;;;;;GAOG;AACH,
|
|
1
|
+
{"version":3,"file":"load-config.js","sourceRoot":"","sources":["../../src/server/load-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,MAAM,YAAY,GAAG,CAAC,kBAAkB,EAAE,kBAAkB,EAAE,mBAAmB,CAAC,CAAC;AAEnF;;;;;;;GAOG;AACH,SAAS,YAAY,CAAC,IAAY;IAChC,OAAO,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,CAAwC,CAAC;AACjF,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAe,EAAE,UAAmB;IACnE,MAAM,IAAI,GAAG,UAAU;QACrB,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC;YACtB,CAAC,CAAC,UAAU;YACZ,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,CAAC;QACtC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC/D,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,mCAAmC,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC;IACD,IAAI,GAA+B,CAAC;IACpC,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,0FAA0F;QAC1F,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAK,KAAkC,EAAE,IAAI,KAAK,sBAAsB,EAAE,CAAC;YACpG,MAAM,IAAI,KAAK,CACb,YAAY,IAAI,6CAA8C,KAAe,CAAC,OAAO,IAAI;gBACvF,kGAAkG;gBAClG,sFAAsF,EACxF,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,YAAY,IAAI,yEAAyE,CAAC,CAAC;IAC7G,CAAC;IACD,OAAO,GAAG,CAAC,OAAO,CAAC;AACrB,CAAC","sourcesContent":["import { existsSync } from 'node:fs';\nimport { isAbsolute, join, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { RshonoConfig } from '../config.js';\n\nconst CONFIG_FILES = ['rshono.config.ts', 'rshono.config.js', 'rshono.config.mjs'];\n\n/**\n * Imports the config module. A `.ts` config needs no loader: Node strips types natively from 22.18 on, which is\n * what the package's `engines` floor is for.\n *\n * The one thing native stripping will not do is resolve a `.js` specifier to a `.ts` file, so a config\n * importing a sibling has to name it with its real extension — {@link loadConfig} turns that resolution failure\n * into the advice rather than letting a raw `ERR_MODULE_NOT_FOUND` out.\n */\nfunction importConfig(file: string): Promise<{ default?: RshonoConfig }> {\n return import(pathToFileURL(file).href) as Promise<{ default?: RshonoConfig }>;\n}\n\n/**\n * Loads the project config, or `{}` if there is none: scans `rshono.config.{ts,js,mjs}` at `rootDir`, unless an\n * explicit `configPath` is given (resolved relative to `cwd`).\n */\nexport async function loadConfig(rootDir: string, configPath?: string): Promise<RshonoConfig> {\n const file = configPath\n ? isAbsolute(configPath)\n ? configPath\n : resolve(process.cwd(), configPath)\n : CONFIG_FILES.map((f) => join(rootDir, f)).find(existsSync);\n if (!file) return {};\n if (!existsSync(file)) {\n throw new Error(`[rshono] config file not found: ${file}`);\n }\n let mod: { default?: RshonoConfig };\n try {\n mod = await importConfig(file);\n } catch (error) {\n // The one failure mode native type stripping has that a TypeScript-aware loader does not.\n if (/\\.[cm]?ts$/.test(file) && (error as { code?: string } | null)?.code === 'ERR_MODULE_NOT_FOUND') {\n throw new Error(\n `[rshono] ${file} imports a module Node could not resolve: ${(error as Error).message}\\n` +\n ' A .ts config is loaded by Node itself, which does not rewrite a .js specifier to the .ts file ' +\n 'beside it. Import it by its real extension, or move the config to rshono.config.mjs.',\n { cause: error },\n );\n }\n throw error;\n }\n if (!mod.default) {\n throw new Error(`[rshono] ${file} must \\`export default\\` a config object (use \\`defineConfig({ … })\\`).`);\n }\n return mod.default;\n}\n"]}
|
|
@@ -1,67 +1,121 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Everything about a prerendered page that doesn't need a filesystem: where the build puts it, and
|
|
3
|
-
*
|
|
2
|
+
* Everything about a prerendered page that doesn't need a filesystem: where the build puts it, and what it
|
|
3
|
+
* looks like once read back.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* Apart from `ssg.ts`, which does the reading and writing through `node:fs`, because a deploy target without a
|
|
6
|
+
* filesystem reads the same layout out of an asset store — and importing it from there would drag `node:fs`
|
|
7
|
+
* into a bundle that has neither.
|
|
8
8
|
*/
|
|
9
9
|
/**
|
|
10
|
-
* The two representations of a page, prerendered side by side
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* Writing only the HTML meant every in-app click re-rendered a page that was already built, so the
|
|
14
|
-
* prerender only ever paid off for cold loads and crawlers.
|
|
10
|
+
* The two representations of a page, prerendered side by side: a hard load wants the HTML document, a soft
|
|
11
|
+
* navigation asks the same URL for a flight payload. Without both, every in-app click would re-render a page
|
|
12
|
+
* that was already built.
|
|
15
13
|
*/
|
|
16
14
|
export type PrerenderVariant = 'html' | 'flight';
|
|
17
15
|
export declare const VARIANTS: {
|
|
18
16
|
readonly html: {
|
|
19
17
|
readonly file: 'index.html';
|
|
20
|
-
readonly
|
|
18
|
+
readonly headers: {};
|
|
21
19
|
readonly contentType: 'text/html';
|
|
22
20
|
};
|
|
23
21
|
readonly flight: {
|
|
24
22
|
readonly file: 'index.rsc';
|
|
25
|
-
readonly
|
|
23
|
+
readonly headers: {
|
|
24
|
+
readonly RSC: '1';
|
|
25
|
+
};
|
|
26
26
|
readonly contentType: 'text/x-component';
|
|
27
27
|
};
|
|
28
28
|
};
|
|
29
29
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
30
|
+
* How a build-time document render tells the prerender pass that the app minted a CSP nonce for its path.
|
|
31
|
+
*
|
|
32
|
+
* The other half of the same contract as {@link VARIANTS}, and it exists because the pass cannot see the
|
|
33
|
+
* request it made: it renders through the app's own middleware inside the server bundle, in a module graph of
|
|
34
|
+
* its own, and keeps the body alone. What it needs to know is whether a *request* for this path will mint a
|
|
35
|
+
* nonce, because a document that will is one the framework re-renders per request — so the file the pass is
|
|
36
|
+
* about to write is one no deployment will read, and saying "prerendered" about it is a lie by omission.
|
|
37
|
+
*
|
|
38
|
+
* Set only while `RSHONO_PRERENDER` is in the environment, which is `rshono build`'s own process, so it never
|
|
39
|
+
* reaches a deployed response; and never stored, since only the body is.
|
|
40
|
+
*/
|
|
41
|
+
export declare const PRERENDER_NONCE_HEADER = "x-rshono-prerender-nonce";
|
|
42
|
+
/**
|
|
43
|
+
* The index the build leaves beside the pages, naming every file it wrote — one `files` array of
|
|
44
|
+
* {@link ssgFilePath} names.
|
|
32
45
|
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
46
|
+
* It exists so a reader can tell "this store has no page for that path" without asking the store, which is
|
|
47
|
+
* the difference between a `Map` lookup and a failed `readFile` (or, without a filesystem, a failed store
|
|
48
|
+
* fetch) on **every** request to a static route the build could not prerender — misses are deliberately not
|
|
49
|
+
* cached, so that one never warms up. Absent is not an error: a build from an older rshono has none, and a
|
|
50
|
+
* reader that finds none looks the way it always did.
|
|
36
51
|
*/
|
|
37
|
-
export declare
|
|
52
|
+
export declare const SSG_MANIFEST_FILE = "manifest.json";
|
|
38
53
|
/**
|
|
39
|
-
*
|
|
54
|
+
* Where a path's prerendered output lives, relative to the output root — or `null` for a path no single file
|
|
55
|
+
* can answer.
|
|
40
56
|
*
|
|
41
|
-
* The
|
|
42
|
-
*
|
|
57
|
+
* **The one canonical form**, shared by the build that writes the file and by every deploy target that reads
|
|
58
|
+
* it back, because the two drifting apart is invisible: the build reports the page as prerendered and every
|
|
59
|
+
* request afterwards falls through to SSR, forever. Each segment is stored *decoded*, so `/docs/café` is
|
|
60
|
+
* `docs/café` whether the caller holds the path percent-encoded — the build, which interpolates `staticPaths`
|
|
61
|
+
* values into a URL — or already decoded, as Hono's `c.req.path` is: it runs `decodeURI` over any path
|
|
62
|
+
* containing a `%`. Decoded is also the form every other static file server addresses, so the tree stays
|
|
63
|
+
* servable by something that is not this framework.
|
|
64
|
+
*
|
|
65
|
+
* Always `/`-separated: the same string addresses a file on a filesystem, which accepts forward slashes on
|
|
66
|
+
* Windows too, and a key in an asset store, where a backslash would be the wrong character.
|
|
67
|
+
*
|
|
68
|
+
* `null` is everything that is not one file: a `.` or `..` segment — so traversal is a miss rather than a
|
|
69
|
+
* lookup, which a store addressed by key, with no `resolve()` to fall back on, depends on — an empty segment,
|
|
70
|
+
* and any segment {@link isStorableSegment} refuses as unportable.
|
|
43
71
|
*/
|
|
44
|
-
export declare function
|
|
72
|
+
export declare function ssgFilePath(path: string, variant?: PrerenderVariant): string | null;
|
|
73
|
+
/**
|
|
74
|
+
* {@link ssgFilePath} as a URL path, for a store addressed by one rather than by key. Every segment is escaped
|
|
75
|
+
* on the way out and the store decodes it back, so a page reached through a URL lands on the same file a
|
|
76
|
+
* filesystem target opens by name.
|
|
77
|
+
*/
|
|
78
|
+
export declare function ssgAssetPath(relPath: string): string;
|
|
79
|
+
/**
|
|
80
|
+
* A bounded, insertion-ordered cache of prerendered pages, so a site with thousands of them keeps a working set
|
|
81
|
+
* rather than the whole build in memory. Only *hits* are stored — caching misses would let anyone mint entries
|
|
82
|
+
* by requesting paths that don't exist — and the files never change while the server is up.
|
|
83
|
+
*
|
|
84
|
+
* Bounded by **bytes**, not by entry count: a count says nothing about how much memory it stands for, and a
|
|
85
|
+
* page can be any size. At 128 entries — the previous limit — a documentation site with half-megabyte pages
|
|
86
|
+
* retained ~64 MB across the two variants, with nothing about the number to suggest it.
|
|
87
|
+
*
|
|
88
|
+
* A page larger than the whole budget is served and not stored, rather than evicting everything to hold one.
|
|
89
|
+
*/
|
|
90
|
+
export declare function createPageCache(maxBytes?: number): {
|
|
91
|
+
get(key: string): PrerenderedPage | undefined;
|
|
92
|
+
set(key: string, page: PrerenderedPage): void;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Assembles a {@link PrerenderedPage} from a body just read out of the build. `storeEtag` is the validator the
|
|
96
|
+
* store supplied, where it has one: it already describes these exact bytes, so it is weakened rather than
|
|
97
|
+
* replaced by a fresh hash.
|
|
98
|
+
*/
|
|
99
|
+
export declare function toPrerenderedPage(body: Uint8Array<ArrayBuffer>, storeEtag?: string | null): Promise<PrerenderedPage>;
|
|
45
100
|
/** A prerendered page, ready to serve: its body and a validator derived from those exact bytes. */
|
|
46
101
|
export interface PrerenderedPage {
|
|
47
|
-
/** The document or the flight payload, depending on which {@link PrerenderVariant} was read. */
|
|
48
|
-
body: string;
|
|
49
102
|
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
|
|
54
|
-
|
|
103
|
+
* The document or the flight payload, depending on which {@link PrerenderVariant} was read. Bytes rather
|
|
104
|
+
* than a string, because this cache entry is served verbatim to every request that hits it — as a string,
|
|
105
|
+
* each would pay a fresh UTF-8 encode of the whole page.
|
|
106
|
+
*/
|
|
107
|
+
body: Uint8Array<ArrayBuffer>;
|
|
108
|
+
/**
|
|
109
|
+
* `Content-Length` for {@link body}, in bytes. Served explicitly because Hono sets no length for an
|
|
110
|
+
* in-memory body, and a proxy in front is entitled to make decisions with it.
|
|
55
111
|
*/
|
|
56
112
|
contentLength: string;
|
|
57
113
|
/**
|
|
58
114
|
* `ETag` for the page, so a revalidating client can be answered with a 304 instead of the body.
|
|
59
115
|
*
|
|
60
|
-
* Deliberately **weak
|
|
61
|
-
* strong validator would
|
|
62
|
-
*
|
|
63
|
-
* says "the same representation", which is exactly what is true across content codings.
|
|
116
|
+
* Deliberately **weak**: the bytes on the wire depend on whether something in front re-encoded them, so a
|
|
117
|
+
* strong validator would differ per coding and a cache would treat the 200 and the 304 that revalidates it
|
|
118
|
+
* as different pages. A weak tag says "the same representation", which stays true across codings.
|
|
64
119
|
*/
|
|
65
120
|
etag: string;
|
|
66
121
|
}
|
|
67
|
-
//# sourceMappingURL=prerendered.d.ts.map
|