@rshono/core 1.0.0-rc.2 → 1.0.0-rc.4
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/README.md +45 -29
- package/dist/builder/rspack-config.d.ts +3 -3
- package/dist/builder/rspack-config.js +3 -3
- package/dist/builder/rspack-config.js.map +1 -1
- package/dist/cli/build.d.ts +2 -2
- package/dist/cli/build.js.map +1 -1
- package/dist/cli/dev.d.ts +2 -2
- package/dist/cli/dev.js.map +1 -1
- package/dist/cli/index.js +11 -10
- package/dist/cli/index.js.map +1 -1
- package/dist/config.d.ts +4 -17
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/deploy/cloudflare/build.js +1 -1
- package/dist/deploy/cloudflare/build.js.map +1 -1
- package/dist/deploy/cloudflare/runtime.d.ts.map +1 -1
- package/dist/deploy/cloudflare/runtime.js +7 -37
- package/dist/deploy/cloudflare/runtime.js.map +1 -1
- package/dist/deploy/contract.d.ts +14 -13
- package/dist/deploy/contract.d.ts.map +1 -1
- package/dist/deploy/contract.js.map +1 -1
- package/dist/deploy/filesystem.d.ts +1 -1
- package/dist/deploy/filesystem.d.ts.map +1 -1
- package/dist/deploy/filesystem.js +1 -3
- package/dist/deploy/filesystem.js.map +1 -1
- package/dist/deploy/node/runtime.d.ts +6 -2
- package/dist/deploy/node/runtime.d.ts.map +1 -1
- package/dist/deploy/node/runtime.js +30 -5
- package/dist/deploy/node/runtime.js.map +1 -1
- package/dist/deploy/presets.d.ts +5 -1
- package/dist/deploy/presets.d.ts.map +1 -1
- package/dist/deploy/presets.js +15 -28
- package/dist/deploy/presets.js.map +1 -1
- package/dist/deploy/vercel/runtime.d.ts.map +1 -1
- package/dist/deploy/vercel/runtime.js +0 -3
- package/dist/deploy/vercel/runtime.js.map +1 -1
- package/dist/index.d.ts +4 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/router.d.ts +14 -15
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +5 -6
- package/dist/router.js.map +1 -1
- package/dist/runtime/client.d.ts +5 -6
- package/dist/runtime/client.d.ts.map +1 -1
- package/dist/runtime/client.js +5 -6
- package/dist/runtime/client.js.map +1 -1
- package/dist/runtime/context.d.ts +36 -40
- package/dist/runtime/context.d.ts.map +1 -1
- package/dist/runtime/context.js +41 -53
- package/dist/runtime/context.js.map +1 -1
- package/dist/runtime/entry.client.d.ts +4 -0
- package/dist/runtime/entry.client.d.ts.map +1 -1
- package/dist/runtime/entry.client.js +161 -147
- package/dist/runtime/entry.client.js.map +1 -1
- package/dist/runtime/entry.rsc.d.ts.map +1 -1
- package/dist/runtime/entry.rsc.js +80 -63
- package/dist/runtime/entry.rsc.js.map +1 -1
- package/dist/runtime/entry.ssr.d.ts +9 -1
- package/dist/runtime/entry.ssr.d.ts.map +1 -1
- package/dist/runtime/entry.ssr.js +36 -18
- package/dist/runtime/entry.ssr.js.map +1 -1
- package/dist/runtime/flight-inject.d.ts +31 -0
- package/dist/runtime/flight-inject.d.ts.map +1 -0
- package/dist/runtime/flight-inject.js +221 -0
- package/dist/runtime/flight-inject.js.map +1 -0
- package/dist/runtime/navigation.d.ts +10 -39
- package/dist/runtime/navigation.d.ts.map +1 -1
- package/dist/runtime/navigation.js +7 -53
- package/dist/runtime/navigation.js.map +1 -1
- package/dist/runtime/request.d.ts +6 -0
- package/dist/runtime/request.d.ts.map +1 -1
- package/dist/runtime/request.js +8 -0
- package/dist/runtime/request.js.map +1 -1
- package/dist/runtime/server.d.ts +2 -2
- package/dist/runtime/server.d.ts.map +1 -1
- package/dist/runtime/server.js +2 -2
- package/dist/runtime/server.js.map +1 -1
- package/dist/server/headers.d.ts +9 -9
- package/dist/server/headers.js +9 -9
- 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 +22 -11
- package/dist/server/load-config.js.map +1 -1
- package/dist/server/prerendered.d.ts +52 -9
- package/dist/server/prerendered.d.ts.map +1 -1
- package/dist/server/prerendered.js +57 -0
- package/dist/server/prerendered.js.map +1 -1
- package/dist/server/server-config.d.ts +11 -18
- package/dist/server/server-config.d.ts.map +1 -1
- package/dist/server/server-config.js +9 -12
- package/dist/server/server-config.js.map +1 -1
- package/dist/server/ssg.d.ts +2 -2
- package/dist/server/ssg.d.ts.map +1 -1
- package/dist/server/ssg.js +11 -23
- package/dist/server/ssg.js.map +1 -1
- package/package.json +13 -16
- 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/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/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/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
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { MiddlewareHandler } from 'hono';
|
|
2
|
-
/**
|
|
3
|
-
* Gzips compressible responses, **without breaking streaming**.
|
|
4
|
-
*
|
|
5
|
-
* The obvious implementation — the platform's `CompressionStream`, which Hono's own `compress`
|
|
6
|
-
* middleware uses — buffers: zlib holds bytes back until it has a full block, so a streamed SSR
|
|
7
|
-
* shell would sit in the compressor instead of reaching the browser. That defeats the entire point
|
|
8
|
-
* of streaming a page. Node's zlib with `Z_SYNC_FLUSH` instead ends every write at a byte boundary
|
|
9
|
-
* the client can decode immediately, so each chunk the renderer flushes is a chunk the browser
|
|
10
|
-
* receives, at the cost of a few bytes of framing per chunk.
|
|
11
|
-
*
|
|
12
|
-
* Registered as the outermost middleware so it sees the finished response, headers and all.
|
|
13
|
-
*/
|
|
14
|
-
export declare function compress(): MiddlewareHandler;
|
|
15
|
-
//# sourceMappingURL=compress.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"compress.d.ts","sourceRoot":"","sources":["../../src/server/compress.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AA0B9C;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,IAAI,iBAAiB,CAsC5C"}
|
package/dist/server/compress.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { COMPRESSIBLE_CONTENT_TYPE_REGEX } from 'hono/utils/compress';
|
|
2
|
-
import { Duplex } from 'node:stream';
|
|
3
|
-
import { constants, createGzip } from 'node:zlib';
|
|
4
|
-
import { appendVary } from './headers.js';
|
|
5
|
-
/** Below this many uncompressed bytes the gzip framing costs more than it saves. Only applied when the length is known up front. */
|
|
6
|
-
const COMPRESSION_THRESHOLD_BYTES = 1024;
|
|
7
|
-
/** `Cache-Control: no-transform` is a proxy asking not to be re-encoded; honour it. */
|
|
8
|
-
const NO_TRANSFORM = /(?:^|,)\s*no-transform\s*(?:,|$)/i;
|
|
9
|
-
/** Every browser that sends `Accept-Encoding` at all accepts gzip, so one encoding covers the field. */
|
|
10
|
-
function acceptsGzip(acceptEncoding) {
|
|
11
|
-
if (!acceptEncoding)
|
|
12
|
-
return false;
|
|
13
|
-
// No `q=` anywhere (what every real browser sends) means there is no refusal to look for.
|
|
14
|
-
if (!acceptEncoding.includes('q='))
|
|
15
|
-
return acceptEncoding.includes('gzip') || acceptEncoding.includes('*');
|
|
16
|
-
return acceptEncoding.split(',').some((entry) => {
|
|
17
|
-
const [name, ...params] = entry.trim().split(';');
|
|
18
|
-
if (name.toLowerCase() !== 'gzip' && name.trim() !== '*')
|
|
19
|
-
return false;
|
|
20
|
-
// `gzip;q=0` is an explicit refusal, not an offer.
|
|
21
|
-
const q = params.map((p) => p.trim()).find((p) => p.startsWith('q='));
|
|
22
|
-
return q === undefined || Number(q.slice(2)) > 0;
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Gzips compressible responses, **without breaking streaming**.
|
|
27
|
-
*
|
|
28
|
-
* The obvious implementation — the platform's `CompressionStream`, which Hono's own `compress`
|
|
29
|
-
* middleware uses — buffers: zlib holds bytes back until it has a full block, so a streamed SSR
|
|
30
|
-
* shell would sit in the compressor instead of reaching the browser. That defeats the entire point
|
|
31
|
-
* of streaming a page. Node's zlib with `Z_SYNC_FLUSH` instead ends every write at a byte boundary
|
|
32
|
-
* the client can decode immediately, so each chunk the renderer flushes is a chunk the browser
|
|
33
|
-
* receives, at the cost of a few bytes of framing per chunk.
|
|
34
|
-
*
|
|
35
|
-
* Registered as the outermost middleware so it sees the finished response, headers and all.
|
|
36
|
-
*/
|
|
37
|
-
export function compress() {
|
|
38
|
-
return async (c, next) => {
|
|
39
|
-
await next();
|
|
40
|
-
const res = c.res;
|
|
41
|
-
if (c.req.method === 'HEAD')
|
|
42
|
-
return;
|
|
43
|
-
// 204/304 have no body to speak of; a 206 range is counted in *uncompressed* bytes.
|
|
44
|
-
if (res.status === 204 || res.status === 304 || res.status === 206)
|
|
45
|
-
return;
|
|
46
|
-
if (res.headers.has('content-encoding'))
|
|
47
|
-
return;
|
|
48
|
-
if (!COMPRESSIBLE_CONTENT_TYPE_REGEX.test(res.headers.get('content-type') ?? ''))
|
|
49
|
-
return;
|
|
50
|
-
if (NO_TRANSFORM.test(res.headers.get('cache-control') ?? ''))
|
|
51
|
-
return;
|
|
52
|
-
const contentLength = res.headers.get('content-length');
|
|
53
|
-
if (contentLength !== null && Number(contentLength) < COMPRESSION_THRESHOLD_BYTES)
|
|
54
|
-
return;
|
|
55
|
-
if (!acceptsGzip(c.req.header('accept-encoding')))
|
|
56
|
-
return;
|
|
57
|
-
// Read `.body` only once we know we're compressing: it is what makes @hono/node-server's
|
|
58
|
-
// lightweight Response materialize a real one, throwing away the [status, body, headers] tuple
|
|
59
|
-
// it would otherwise write straight to the socket. The guards above touch only `.status` and
|
|
60
|
-
// `.headers`, which leave that fast path intact for every response we decide to pass through.
|
|
61
|
-
const body = res.body;
|
|
62
|
-
if (!body)
|
|
63
|
-
return;
|
|
64
|
-
const gzip = Duplex.toWeb(createGzip({ flush: constants.Z_SYNC_FLUSH }));
|
|
65
|
-
c.res = new Response(body.pipeThrough(gzip), res);
|
|
66
|
-
c.res.headers.set('content-encoding', 'gzip');
|
|
67
|
-
c.res.headers.delete('content-length'); // no longer the length of what goes on the wire
|
|
68
|
-
appendVary(c.res.headers, 'Accept-Encoding');
|
|
69
|
-
// The bytes changed, so a strong validator no longer describes them — but it is still the same
|
|
70
|
-
// representation, which is exactly what a weak one means.
|
|
71
|
-
const etag = c.res.headers.get('etag');
|
|
72
|
-
if (etag && !etag.startsWith('W/'))
|
|
73
|
-
c.res.headers.set('etag', `W/${etag}`);
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
//# sourceMappingURL=compress.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"compress.js","sourceRoot":"","sources":["../../src/server/compress.ts"],"names":[],"mappings":"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","sourcesContent":["import type { MiddlewareHandler } from 'hono';\nimport { COMPRESSIBLE_CONTENT_TYPE_REGEX } from 'hono/utils/compress';\nimport { Duplex } from 'node:stream';\nimport { constants, createGzip } from 'node:zlib';\nimport { appendVary } from './headers.js';\n\n/** Below this many uncompressed bytes the gzip framing costs more than it saves. Only applied when the length is known up front. */\nconst COMPRESSION_THRESHOLD_BYTES = 1024;\n\n/** `Cache-Control: no-transform` is a proxy asking not to be re-encoded; honour it. */\nconst NO_TRANSFORM = /(?:^|,)\\s*no-transform\\s*(?:,|$)/i;\n\n/** Every browser that sends `Accept-Encoding` at all accepts gzip, so one encoding covers the field. */\nfunction acceptsGzip(acceptEncoding: string | undefined): boolean {\n if (!acceptEncoding) return false;\n // No `q=` anywhere (what every real browser sends) means there is no refusal to look for.\n if (!acceptEncoding.includes('q=')) return acceptEncoding.includes('gzip') || acceptEncoding.includes('*');\n return acceptEncoding.split(',').some((entry) => {\n const [name, ...params] = entry.trim().split(';');\n if (name.toLowerCase() !== 'gzip' && name.trim() !== '*') return false;\n // `gzip;q=0` is an explicit refusal, not an offer.\n const q = params.map((p) => p.trim()).find((p) => p.startsWith('q='));\n return q === undefined || Number(q.slice(2)) > 0;\n });\n}\n\n/**\n * Gzips compressible responses, **without breaking streaming**.\n *\n * The obvious implementation — the platform's `CompressionStream`, which Hono's own `compress`\n * middleware uses — buffers: zlib holds bytes back until it has a full block, so a streamed SSR\n * shell would sit in the compressor instead of reaching the browser. That defeats the entire point\n * of streaming a page. Node's zlib with `Z_SYNC_FLUSH` instead ends every write at a byte boundary\n * the client can decode immediately, so each chunk the renderer flushes is a chunk the browser\n * receives, at the cost of a few bytes of framing per chunk.\n *\n * Registered as the outermost middleware so it sees the finished response, headers and all.\n */\nexport function compress(): MiddlewareHandler {\n return async (c, next) => {\n await next();\n\n const res = c.res;\n if (c.req.method === 'HEAD') return;\n // 204/304 have no body to speak of; a 206 range is counted in *uncompressed* bytes.\n if (res.status === 204 || res.status === 304 || res.status === 206) return;\n if (res.headers.has('content-encoding')) return;\n if (!COMPRESSIBLE_CONTENT_TYPE_REGEX.test(res.headers.get('content-type') ?? '')) return;\n if (NO_TRANSFORM.test(res.headers.get('cache-control') ?? '')) return;\n\n const contentLength = res.headers.get('content-length');\n if (contentLength !== null && Number(contentLength) < COMPRESSION_THRESHOLD_BYTES) return;\n if (!acceptsGzip(c.req.header('accept-encoding'))) return;\n\n // Read `.body` only once we know we're compressing: it is what makes @hono/node-server's\n // lightweight Response materialize a real one, throwing away the [status, body, headers] tuple\n // it would otherwise write straight to the socket. The guards above touch only `.status` and\n // `.headers`, which leave that fast path intact for every response we decide to pass through.\n const body = res.body;\n if (!body) return;\n\n const gzip = Duplex.toWeb(createGzip({ flush: constants.Z_SYNC_FLUSH })) as unknown as {\n readable: ReadableStream<Uint8Array>;\n writable: WritableStream<Uint8Array>;\n };\n\n c.res = new Response(body.pipeThrough(gzip), res);\n c.res.headers.set('content-encoding', 'gzip');\n c.res.headers.delete('content-length'); // no longer the length of what goes on the wire\n appendVary(c.res.headers, 'Accept-Encoding');\n\n // The bytes changed, so a strong validator no longer describes them — but it is still the same\n // representation, which is exactly what a weak one means.\n const etag = c.res.headers.get('etag');\n if (etag && !etag.startsWith('W/')) c.res.headers.set('etag', `W/${etag}`);\n };\n}\n"]}
|