@zuplo/cli 6.70.27 → 6.70.29
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/dist/cmds/project/index.d.ts.map +1 -1
- package/dist/cmds/project/index.js +2 -1
- package/dist/cmds/project/index.js.map +1 -1
- package/dist/cmds/project/list.d.ts +9 -0
- package/dist/cmds/project/list.d.ts.map +1 -0
- package/dist/cmds/project/list.js +52 -0
- package/dist/cmds/project/list.js.map +1 -0
- package/dist/cmds/test.d.ts.map +1 -1
- package/dist/cmds/test.js +4 -0
- package/dist/cmds/test.js.map +1 -1
- package/dist/project/list/handler.d.ts +7 -0
- package/dist/project/list/handler.d.ts.map +1 -0
- package/dist/project/list/handler.js +49 -0
- package/dist/project/list/handler.js.map +1 -0
- package/dist/test/handler.d.ts +1 -0
- package/dist/test/handler.d.ts.map +1 -1
- package/dist/test/handler.js.map +1 -1
- package/dist/test/invoke-test.d.ts.map +1 -1
- package/dist/test/invoke-test.js +46 -19
- package/dist/test/invoke-test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/node_modules/@zuplo/core/package.json +1 -1
- package/node_modules/@zuplo/graphql/package.json +1 -1
- package/node_modules/@zuplo/openapi-tools/package.json +1 -1
- package/node_modules/@zuplo/otel/package.json +1 -1
- package/node_modules/@zuplo/runtime/out/esm/{chunk-H7UGARU6.js → chunk-F7DJMBWH.js} +1 -1
- package/node_modules/@zuplo/runtime/out/esm/{chunk-H7UGARU6.js.map → chunk-F7DJMBWH.js.map} +1 -1
- package/node_modules/@zuplo/runtime/out/esm/{chunk-P4G7GA42.js → chunk-TEXCCTJT.js} +63 -63
- package/node_modules/@zuplo/runtime/out/esm/chunk-TEXCCTJT.js.map +1 -0
- package/node_modules/@zuplo/runtime/out/esm/index.js +1 -1
- package/node_modules/@zuplo/runtime/out/esm/index.js.map +1 -1
- package/node_modules/@zuplo/runtime/out/esm/mcp-gateway/index.js +19 -21
- package/node_modules/@zuplo/runtime/out/esm/mcp-gateway/index.js.map +1 -1
- package/node_modules/@zuplo/runtime/out/esm/mocks/index.js +1 -1
- package/node_modules/@zuplo/runtime/out/types/index.d.ts +36 -0
- package/node_modules/@zuplo/runtime/out/types/mcp-gateway/index.d.ts +4 -4
- package/node_modules/@zuplo/runtime/package.json +1 -1
- package/node_modules/hono/dist/adapter/bun/serve-static.js +1 -1
- package/node_modules/hono/dist/adapter/cloudflare-workers/serve-static.js +1 -1
- package/node_modules/hono/dist/adapter/deno/serve-static.js +1 -1
- package/node_modules/hono/dist/cjs/adapter/bun/serve-static.js +1 -1
- package/node_modules/hono/dist/cjs/adapter/cloudflare-workers/serve-static.js +1 -1
- package/node_modules/hono/dist/cjs/adapter/deno/serve-static.js +1 -1
- package/node_modules/hono/dist/cjs/middleware/cache/index.js +30 -25
- package/node_modules/hono/dist/cjs/request.js +15 -0
- package/node_modules/hono/dist/cjs/utils/cookie.js +3 -3
- package/node_modules/hono/dist/cjs/utils/stream.js +4 -2
- package/node_modules/hono/dist/middleware/cache/index.js +30 -25
- package/node_modules/hono/dist/request.js +15 -0
- package/node_modules/hono/dist/tsconfig.build.tsbuildinfo +1 -1
- package/node_modules/hono/dist/types/adapter/bun/serve-static.d.ts +1 -1
- package/node_modules/hono/dist/types/adapter/cloudflare-workers/serve-static.d.ts +2 -2
- package/node_modules/hono/dist/types/adapter/deno/serve-static.d.ts +1 -1
- package/node_modules/hono/dist/types/middleware/bearer-auth/index.d.ts +6 -5
- package/node_modules/hono/dist/types/middleware/cache/index.d.ts +1 -1
- package/node_modules/hono/dist/types/request.d.ts +13 -0
- package/node_modules/hono/dist/utils/cookie.js +3 -3
- package/node_modules/hono/dist/utils/stream.js +4 -2
- package/node_modules/hono/package.json +2 -2
- package/node_modules/pino-http/node_modules/thread-stream/.claude/settings.local.json +15 -0
- package/node_modules/pino-http/node_modules/thread-stream/index.js +92 -87
- package/node_modules/pino-http/node_modules/thread-stream/lib/indexes.js +3 -1
- package/node_modules/pino-http/node_modules/thread-stream/lib/wait.js +11 -2
- package/node_modules/pino-http/node_modules/thread-stream/lib/worker.js +27 -9
- package/node_modules/pino-http/node_modules/thread-stream/package.json +2 -2
- package/node_modules/pino-http/node_modules/thread-stream/test/multibyte-overrun.test.mjs +33 -0
- package/package.json +6 -6
- package/node_modules/@zuplo/runtime/out/esm/chunk-P4G7GA42.js.map +0 -1
- /package/node_modules/@zuplo/runtime/out/esm/{chunk-P4G7GA42.js.LEGAL.txt → chunk-TEXCCTJT.js.LEGAL.txt} +0 -0
|
@@ -22,5 +22,5 @@
|
|
|
22
22
|
* DEALINGS IN THE SOFTWARE.
|
|
23
23
|
*--------------------------------------------------------------------------------------------*/
|
|
24
24
|
|
|
25
|
-
import{b as d}from"../chunk-
|
|
25
|
+
import{b as d}from"../chunk-F7DJMBWH.js";import{_ as n,a as t}from"../chunk-JAEQKE5H.js";function g(u={request:new Request("https://api.example.com")}){let e=[];function o(i){e.push(Promise.resolve(i))}return t(o,"waitUntil"),{context:new s({event:{waitUntil:o},route:u.route}),invokeResponse:t(async()=>{await Promise.all(e)},"invokeResponse")}}t(g,"createMockContext");var p={path:"/",methods:["GET"],handler:{module:{},export:"default"},raw:t(()=>({}),"raw")},s=class extends EventTarget{static{t(this,"MockZuploContext")}#e;contextId;requestId;log;route;custom;incomingRequestProperties;parentContext;analyticsContext;constructor({event:e,route:o=p,parentContext:r}){super(),this.requestId=crypto.randomUUID(),this.contextId=crypto.randomUUID(),this.log={info:n.console.info,log:n.console.log,debug:n.console.debug,warn:n.console.warn,error:n.console.error,setLogProperties:t(()=>{},"setLogProperties")},this.custom={},this.route=o,this.incomingRequestProperties={asn:1234,asOrganization:"ORGANIZATION",city:"Seattle",region:"Washington",regionCode:"WA",colo:"SEA",continent:"NA",country:"US",postalCode:"98004",metroCode:"SEA",latitude:void 0,longitude:void 0,timezone:void 0,httpProtocol:void 0,clientCert:void 0,clientMtlsVerificationStatus:void 0,clientMtlsVerificationReason:void 0},this.parentContext=r,this.#e=e,this.analyticsContext=new d(this.requestId)}waitUntil(e){this.#e.waitUntil(e)}invokeInboundPolicy(e,o){throw new Error("Not implemented")}invokeOutboundPolicy(e,o,r){throw new Error("Not implemented")}invokeRoute(e,o){throw new Error("Not implemented")}addResponseSendingHook(e){throw new Error("Not implemented")}addResponseSendingFinalHook(e){throw new Error("Not implemented")}addEventListener(e,o,r){let l=t(i=>{try{typeof o=="function"?o(i):o.handleEvent(i)}catch(a){throw this.log.error(`Error invoking event ${e}. See following logs for details.`),a}},"wrapped");super.addEventListener(e,l,r)}};export{s as MockZuploContext,g as createMockContext};
|
|
26
26
|
//# sourceMappingURL=index.js.map
|
|
@@ -8957,6 +8957,42 @@ export declare interface SetStatusOutboundPolicyOptions {
|
|
|
8957
8957
|
statusText?: string;
|
|
8958
8958
|
}
|
|
8959
8959
|
|
|
8960
|
+
/**
|
|
8961
|
+
* Sets a single header on the incoming request, typically used to attach an
|
|
8962
|
+
* API key for the upstream service. A more directed version of the
|
|
8963
|
+
* `SetHeadersInboundPolicy` that defaults the header name to `Authorization`
|
|
8964
|
+
* and is intended to be used with an `$env()` reference for the value.
|
|
8965
|
+
*
|
|
8966
|
+
* @title Set Upstream API Key
|
|
8967
|
+
* @product api-gateway
|
|
8968
|
+
* @public
|
|
8969
|
+
* @param request - The ZuploRequest
|
|
8970
|
+
* @param context - The ZuploContext
|
|
8971
|
+
* @param options - The policy options set in policies.json
|
|
8972
|
+
* @param policyName - The name of the policy as set in policies.json
|
|
8973
|
+
* @returns A Request or a Response
|
|
8974
|
+
*/
|
|
8975
|
+
export declare const SetUpstreamApiKeyInboundPolicy: InboundPolicyHandler<SetUpstreamApiKeyInboundPolicyOptions>;
|
|
8976
|
+
|
|
8977
|
+
/**
|
|
8978
|
+
* The options for this policy.
|
|
8979
|
+
* @public
|
|
8980
|
+
*/
|
|
8981
|
+
export declare interface SetUpstreamApiKeyInboundPolicyOptions {
|
|
8982
|
+
/**
|
|
8983
|
+
* The name of the header to set on the request. Defaults to `Authorization`.
|
|
8984
|
+
*/
|
|
8985
|
+
header?: string;
|
|
8986
|
+
/**
|
|
8987
|
+
* The value of the header. Most commonly an environment variable reference such as `Bearer $env(UPSTREAM_API_KEY)` so the secret is sourced from your environment.
|
|
8988
|
+
*/
|
|
8989
|
+
value: string;
|
|
8990
|
+
/**
|
|
8991
|
+
* Overwrite the value if the header is already present in the request.
|
|
8992
|
+
*/
|
|
8993
|
+
overwrite?: boolean;
|
|
8994
|
+
}
|
|
8995
|
+
|
|
8960
8996
|
/**
|
|
8961
8997
|
* Function type for determining if a request should be logged
|
|
8962
8998
|
* @public
|
|
@@ -973,7 +973,7 @@ export declare interface McpAuth0OAuthInboundPolicyOptions {
|
|
|
973
973
|
/**
|
|
974
974
|
* The Auth0 client_secret. Use $env(...) to source from a secret environment variable.
|
|
975
975
|
*/
|
|
976
|
-
clientSecret
|
|
976
|
+
clientSecret: string;
|
|
977
977
|
/**
|
|
978
978
|
* OIDC scopes requested during browser login.
|
|
979
979
|
*/
|
|
@@ -1076,9 +1076,9 @@ export declare interface McpOAuthInboundPolicyOptions {
|
|
|
1076
1076
|
*/
|
|
1077
1077
|
jwksUrl: string;
|
|
1078
1078
|
/**
|
|
1079
|
-
*
|
|
1079
|
+
* Optional IdP audience value. Leave unset when browser login ID tokens use the OIDC client_id as their audience.
|
|
1080
1080
|
*/
|
|
1081
|
-
audience
|
|
1081
|
+
audience?: string;
|
|
1082
1082
|
};
|
|
1083
1083
|
/**
|
|
1084
1084
|
* Browser-side OAuth/OIDC settings used when the gateway redirects the user to the identity provider for login.
|
|
@@ -1097,7 +1097,7 @@ export declare interface McpOAuthInboundPolicyOptions {
|
|
|
1097
1097
|
*/
|
|
1098
1098
|
clientId?: string;
|
|
1099
1099
|
/**
|
|
1100
|
-
* The OIDC client_secret. Use $env(...) to source from a secret environment variable.
|
|
1100
|
+
* The OIDC client_secret. Required for federated browser login. Use $env(...) to source from a secret environment variable.
|
|
1101
1101
|
*/
|
|
1102
1102
|
clientSecret?: string;
|
|
1103
1103
|
/**
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { stat } from "node:fs/promises";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { serveStatic as baseServeStatic } from "../../middleware/serve-static/index.js";
|
|
5
|
-
var serveStatic = (options) => {
|
|
5
|
+
var serveStatic = (options = {}) => {
|
|
6
6
|
return async function serveStatic2(c, next) {
|
|
7
7
|
const getContent = async (path) => {
|
|
8
8
|
const file = Bun.file(path);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/adapter/cloudflare-workers/serve-static.ts
|
|
2
2
|
import { serveStatic as baseServeStatic } from "../../middleware/serve-static/index.js";
|
|
3
3
|
import { getContentFromKVAsset } from "./utils.js";
|
|
4
|
-
var serveStatic = (options) => {
|
|
4
|
+
var serveStatic = (options = {}) => {
|
|
5
5
|
return async function serveStatic2(c, next) {
|
|
6
6
|
const getContent = async (path) => {
|
|
7
7
|
return getContentFromKVAsset(path, {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { serveStatic as baseServeStatic } from "../../middleware/serve-static/index.js";
|
|
4
4
|
var { open, lstatSync, errors } = Deno;
|
|
5
|
-
var serveStatic = (options) => {
|
|
5
|
+
var serveStatic = (options = {}) => {
|
|
6
6
|
return async function serveStatic2(c, next) {
|
|
7
7
|
const getContent = async (path) => {
|
|
8
8
|
try {
|
|
@@ -23,7 +23,7 @@ module.exports = __toCommonJS(serve_static_exports);
|
|
|
23
23
|
var import_promises = require("node:fs/promises");
|
|
24
24
|
var import_node_path = require("node:path");
|
|
25
25
|
var import_serve_static = require("../../middleware/serve-static");
|
|
26
|
-
const serveStatic = (options) => {
|
|
26
|
+
const serveStatic = (options = {}) => {
|
|
27
27
|
return async function serveStatic2(c, next) {
|
|
28
28
|
const getContent = async (path) => {
|
|
29
29
|
const file = Bun.file(path);
|
|
@@ -22,7 +22,7 @@ __export(serve_static_exports, {
|
|
|
22
22
|
module.exports = __toCommonJS(serve_static_exports);
|
|
23
23
|
var import_serve_static = require("../../middleware/serve-static");
|
|
24
24
|
var import_utils = require("./utils");
|
|
25
|
-
const serveStatic = (options) => {
|
|
25
|
+
const serveStatic = (options = {}) => {
|
|
26
26
|
return async function serveStatic2(c, next) {
|
|
27
27
|
const getContent = async (path) => {
|
|
28
28
|
return (0, import_utils.getContentFromKVAsset)(path, {
|
|
@@ -23,7 +23,7 @@ module.exports = __toCommonJS(serve_static_exports);
|
|
|
23
23
|
var import_node_path = require("node:path");
|
|
24
24
|
var import_serve_static = require("../../middleware/serve-static");
|
|
25
25
|
const { open, lstatSync, errors } = Deno;
|
|
26
|
-
const serveStatic = (options) => {
|
|
26
|
+
const serveStatic = (options = {}) => {
|
|
27
27
|
return async function serveStatic2(c, next) {
|
|
28
28
|
const getContent = async (path) => {
|
|
29
29
|
try {
|
|
@@ -21,19 +21,14 @@ __export(cache_exports, {
|
|
|
21
21
|
});
|
|
22
22
|
module.exports = __toCommonJS(cache_exports);
|
|
23
23
|
const defaultCacheableStatusCodes = [200];
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
const shouldSkipCacheControl = (cacheControl) => !!cacheControl && /(?:^|,\s*)(?:private|no-(?:store|cache))(?:\s*(?:=|,|$))/i.test(cacheControl);
|
|
25
|
+
const parseVaryDirectives = (vary) => {
|
|
26
|
+
if (vary == null) {
|
|
27
|
+
return [];
|
|
27
28
|
}
|
|
28
|
-
|
|
29
|
-
if (cacheControl && /(?:^|,\s*)(?:private|no-(?:store|cache))(?:\s*(?:=|,|$))/i.test(cacheControl)) {
|
|
30
|
-
return true;
|
|
31
|
-
}
|
|
32
|
-
if (res.headers.has("Set-Cookie")) {
|
|
33
|
-
return true;
|
|
34
|
-
}
|
|
35
|
-
return false;
|
|
29
|
+
return (Array.isArray(vary) ? vary : vary.split(",")).map((directive) => directive.trim().toLowerCase()).filter(Boolean);
|
|
36
30
|
};
|
|
31
|
+
const shouldSkipCache = (res, optionsVaryDirectives, responseVary) => responseVary.length && (!optionsVaryDirectives || responseVary.some((name) => !optionsVaryDirectives.has(name))) || shouldSkipCacheControl(res.headers.get("Cache-Control")) || res.headers.has("Set-Cookie");
|
|
37
32
|
const cache = (options) => {
|
|
38
33
|
if (!globalThis.caches) {
|
|
39
34
|
if (options.onCacheNotAvailable === false) {
|
|
@@ -48,8 +43,9 @@ const cache = (options) => {
|
|
|
48
43
|
options.wait = false;
|
|
49
44
|
}
|
|
50
45
|
const cacheControlDirectives = options.cacheControl?.split(",").map((directive) => directive.toLowerCase());
|
|
51
|
-
const
|
|
52
|
-
|
|
46
|
+
const optionsVaryList = parseVaryDirectives(options.vary);
|
|
47
|
+
const varyDirectives = optionsVaryList.length ? new Set(optionsVaryList) : void 0;
|
|
48
|
+
if (varyDirectives?.has("*")) {
|
|
53
49
|
throw new Error(
|
|
54
50
|
'Middleware vary configuration cannot include "*", as it disallows effective caching.'
|
|
55
51
|
);
|
|
@@ -57,7 +53,7 @@ const cache = (options) => {
|
|
|
57
53
|
const cacheableStatusCodes = new Set(
|
|
58
54
|
options.cacheableStatusCodes ?? defaultCacheableStatusCodes
|
|
59
55
|
);
|
|
60
|
-
const addHeader = (c) => {
|
|
56
|
+
const addHeader = (c, responseVary) => {
|
|
61
57
|
if (cacheControlDirectives) {
|
|
62
58
|
const existingDirectives = c.res.headers.get("Cache-Control")?.split(",").map((d) => d.trim().split("=", 1)[0]) ?? [];
|
|
63
59
|
for (const directive of cacheControlDirectives) {
|
|
@@ -69,16 +65,18 @@ const cache = (options) => {
|
|
|
69
65
|
}
|
|
70
66
|
}
|
|
71
67
|
if (varyDirectives) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
new Set(
|
|
75
|
-
[...existingDirectives, ...varyDirectives].map((directive) => directive.toLowerCase())
|
|
76
|
-
)
|
|
77
|
-
).sort();
|
|
78
|
-
if (vary.includes("*")) {
|
|
79
|
-
c.header("Vary", "*");
|
|
68
|
+
if (responseVary.length === 0) {
|
|
69
|
+
c.header("Vary", Array.from(varyDirectives).join(", "));
|
|
80
70
|
} else {
|
|
81
|
-
|
|
71
|
+
const merged = new Set(varyDirectives);
|
|
72
|
+
for (const directive of responseVary) {
|
|
73
|
+
merged.add(directive);
|
|
74
|
+
}
|
|
75
|
+
if (merged.has("*")) {
|
|
76
|
+
c.header("Vary", "*");
|
|
77
|
+
} else {
|
|
78
|
+
c.header("Vary", Array.from(merged).join(", "));
|
|
79
|
+
}
|
|
82
80
|
}
|
|
83
81
|
}
|
|
84
82
|
};
|
|
@@ -91,6 +89,12 @@ const cache = (options) => {
|
|
|
91
89
|
if (options.keyGenerator) {
|
|
92
90
|
key = await options.keyGenerator(c);
|
|
93
91
|
}
|
|
92
|
+
if (varyDirectives) {
|
|
93
|
+
for (const directive of varyDirectives) {
|
|
94
|
+
const value = c.req.raw.headers.get(directive) ?? "";
|
|
95
|
+
key += `::${directive}=${encodeURIComponent(value)}`;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
94
98
|
const cacheName = typeof options.cacheName === "function" ? await options.cacheName(c) : options.cacheName;
|
|
95
99
|
const cache3 = await caches.open(cacheName);
|
|
96
100
|
const response = await cache3.match(key);
|
|
@@ -101,8 +105,9 @@ const cache = (options) => {
|
|
|
101
105
|
if (!cacheableStatusCodes.has(c.res.status)) {
|
|
102
106
|
return;
|
|
103
107
|
}
|
|
104
|
-
|
|
105
|
-
|
|
108
|
+
const responseVary = parseVaryDirectives(c.res.headers.get("Vary"));
|
|
109
|
+
addHeader(c, responseVary);
|
|
110
|
+
if (shouldSkipCache(c.res, varyDirectives, responseVary)) {
|
|
106
111
|
return;
|
|
107
112
|
}
|
|
108
113
|
const res = c.res.clone();
|
|
@@ -169,6 +169,21 @@ class HonoRequest {
|
|
|
169
169
|
arrayBuffer() {
|
|
170
170
|
return this.#cachedBody("arrayBuffer");
|
|
171
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* `.bytes()` parses the request body as a `Uint8Array`.
|
|
174
|
+
*
|
|
175
|
+
* @see {@link https://hono.dev/docs/api/request#bytes}
|
|
176
|
+
*
|
|
177
|
+
* @example
|
|
178
|
+
* ```ts
|
|
179
|
+
* app.post('/entry', async (c) => {
|
|
180
|
+
* const body = await c.req.bytes()
|
|
181
|
+
* })
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
bytes() {
|
|
185
|
+
return this.#cachedBody("arrayBuffer").then((buffer) => new Uint8Array(buffer));
|
|
186
|
+
}
|
|
172
187
|
/**
|
|
173
188
|
* Parses the request body as a `Blob`.
|
|
174
189
|
* @example
|
|
@@ -72,14 +72,14 @@ const parse = (cookie, name) => {
|
|
|
72
72
|
return {};
|
|
73
73
|
}
|
|
74
74
|
const pairs = cookie.split(";");
|
|
75
|
-
const parsedCookie =
|
|
75
|
+
const parsedCookie = /* @__PURE__ */ Object.create(null);
|
|
76
76
|
for (const pairStr of pairs) {
|
|
77
77
|
const valueStartPos = pairStr.indexOf("=");
|
|
78
78
|
if (valueStartPos === -1) {
|
|
79
79
|
continue;
|
|
80
80
|
}
|
|
81
81
|
const cookieName = trimCookieWhitespace(pairStr.substring(0, valueStartPos));
|
|
82
|
-
if (name && name !== cookieName || !validCookieNameRegEx.test(cookieName)) {
|
|
82
|
+
if (name && name !== cookieName || !validCookieNameRegEx.test(cookieName) || cookieName in parsedCookie) {
|
|
83
83
|
continue;
|
|
84
84
|
}
|
|
85
85
|
let cookieValue = trimCookieWhitespace(pairStr.substring(valueStartPos + 1));
|
|
@@ -96,7 +96,7 @@ const parse = (cookie, name) => {
|
|
|
96
96
|
return parsedCookie;
|
|
97
97
|
};
|
|
98
98
|
const parseSigned = async (cookie, secret, name) => {
|
|
99
|
-
const parsedCookie =
|
|
99
|
+
const parsedCookie = /* @__PURE__ */ Object.create(null);
|
|
100
100
|
const secretKey = await getCryptoKey(secret);
|
|
101
101
|
for (const [key, value] of Object.entries(parse(cookie, name))) {
|
|
102
102
|
const signatureStartPos = value.lastIndexOf(".");
|
|
@@ -48,7 +48,9 @@ class StreamingApi {
|
|
|
48
48
|
done ? controller.close() : controller.enqueue(value);
|
|
49
49
|
},
|
|
50
50
|
cancel: () => {
|
|
51
|
-
this.
|
|
51
|
+
if (!this.closed) {
|
|
52
|
+
this.abort();
|
|
53
|
+
}
|
|
52
54
|
}
|
|
53
55
|
});
|
|
54
56
|
}
|
|
@@ -70,11 +72,11 @@ class StreamingApi {
|
|
|
70
72
|
return new Promise((res) => setTimeout(res, ms));
|
|
71
73
|
}
|
|
72
74
|
async close() {
|
|
75
|
+
this.closed = true;
|
|
73
76
|
try {
|
|
74
77
|
await this.writer.close();
|
|
75
78
|
} catch {
|
|
76
79
|
}
|
|
77
|
-
this.closed = true;
|
|
78
80
|
}
|
|
79
81
|
async pipe(body) {
|
|
80
82
|
this.writer.releaseLock();
|
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
// src/middleware/cache/index.ts
|
|
2
2
|
var defaultCacheableStatusCodes = [200];
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
var shouldSkipCacheControl = (cacheControl) => !!cacheControl && /(?:^|,\s*)(?:private|no-(?:store|cache))(?:\s*(?:=|,|$))/i.test(cacheControl);
|
|
4
|
+
var parseVaryDirectives = (vary) => {
|
|
5
|
+
if (vary == null) {
|
|
6
|
+
return [];
|
|
6
7
|
}
|
|
7
|
-
|
|
8
|
-
if (cacheControl && /(?:^|,\s*)(?:private|no-(?:store|cache))(?:\s*(?:=|,|$))/i.test(cacheControl)) {
|
|
9
|
-
return true;
|
|
10
|
-
}
|
|
11
|
-
if (res.headers.has("Set-Cookie")) {
|
|
12
|
-
return true;
|
|
13
|
-
}
|
|
14
|
-
return false;
|
|
8
|
+
return (Array.isArray(vary) ? vary : vary.split(",")).map((directive) => directive.trim().toLowerCase()).filter(Boolean);
|
|
15
9
|
};
|
|
10
|
+
var shouldSkipCache = (res, optionsVaryDirectives, responseVary) => responseVary.length && (!optionsVaryDirectives || responseVary.some((name) => !optionsVaryDirectives.has(name))) || shouldSkipCacheControl(res.headers.get("Cache-Control")) || res.headers.has("Set-Cookie");
|
|
16
11
|
var cache = (options) => {
|
|
17
12
|
if (!globalThis.caches) {
|
|
18
13
|
if (options.onCacheNotAvailable === false) {
|
|
@@ -27,8 +22,9 @@ var cache = (options) => {
|
|
|
27
22
|
options.wait = false;
|
|
28
23
|
}
|
|
29
24
|
const cacheControlDirectives = options.cacheControl?.split(",").map((directive) => directive.toLowerCase());
|
|
30
|
-
const
|
|
31
|
-
|
|
25
|
+
const optionsVaryList = parseVaryDirectives(options.vary);
|
|
26
|
+
const varyDirectives = optionsVaryList.length ? new Set(optionsVaryList) : void 0;
|
|
27
|
+
if (varyDirectives?.has("*")) {
|
|
32
28
|
throw new Error(
|
|
33
29
|
'Middleware vary configuration cannot include "*", as it disallows effective caching.'
|
|
34
30
|
);
|
|
@@ -36,7 +32,7 @@ var cache = (options) => {
|
|
|
36
32
|
const cacheableStatusCodes = new Set(
|
|
37
33
|
options.cacheableStatusCodes ?? defaultCacheableStatusCodes
|
|
38
34
|
);
|
|
39
|
-
const addHeader = (c) => {
|
|
35
|
+
const addHeader = (c, responseVary) => {
|
|
40
36
|
if (cacheControlDirectives) {
|
|
41
37
|
const existingDirectives = c.res.headers.get("Cache-Control")?.split(",").map((d) => d.trim().split("=", 1)[0]) ?? [];
|
|
42
38
|
for (const directive of cacheControlDirectives) {
|
|
@@ -48,16 +44,18 @@ var cache = (options) => {
|
|
|
48
44
|
}
|
|
49
45
|
}
|
|
50
46
|
if (varyDirectives) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
new Set(
|
|
54
|
-
[...existingDirectives, ...varyDirectives].map((directive) => directive.toLowerCase())
|
|
55
|
-
)
|
|
56
|
-
).sort();
|
|
57
|
-
if (vary.includes("*")) {
|
|
58
|
-
c.header("Vary", "*");
|
|
47
|
+
if (responseVary.length === 0) {
|
|
48
|
+
c.header("Vary", Array.from(varyDirectives).join(", "));
|
|
59
49
|
} else {
|
|
60
|
-
|
|
50
|
+
const merged = new Set(varyDirectives);
|
|
51
|
+
for (const directive of responseVary) {
|
|
52
|
+
merged.add(directive);
|
|
53
|
+
}
|
|
54
|
+
if (merged.has("*")) {
|
|
55
|
+
c.header("Vary", "*");
|
|
56
|
+
} else {
|
|
57
|
+
c.header("Vary", Array.from(merged).join(", "));
|
|
58
|
+
}
|
|
61
59
|
}
|
|
62
60
|
}
|
|
63
61
|
};
|
|
@@ -70,6 +68,12 @@ var cache = (options) => {
|
|
|
70
68
|
if (options.keyGenerator) {
|
|
71
69
|
key = await options.keyGenerator(c);
|
|
72
70
|
}
|
|
71
|
+
if (varyDirectives) {
|
|
72
|
+
for (const directive of varyDirectives) {
|
|
73
|
+
const value = c.req.raw.headers.get(directive) ?? "";
|
|
74
|
+
key += `::${directive}=${encodeURIComponent(value)}`;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
73
77
|
const cacheName = typeof options.cacheName === "function" ? await options.cacheName(c) : options.cacheName;
|
|
74
78
|
const cache3 = await caches.open(cacheName);
|
|
75
79
|
const response = await cache3.match(key);
|
|
@@ -80,8 +84,9 @@ var cache = (options) => {
|
|
|
80
84
|
if (!cacheableStatusCodes.has(c.res.status)) {
|
|
81
85
|
return;
|
|
82
86
|
}
|
|
83
|
-
|
|
84
|
-
|
|
87
|
+
const responseVary = parseVaryDirectives(c.res.headers.get("Vary"));
|
|
88
|
+
addHeader(c, responseVary);
|
|
89
|
+
if (shouldSkipCache(c.res, varyDirectives, responseVary)) {
|
|
85
90
|
return;
|
|
86
91
|
}
|
|
87
92
|
const res = c.res.clone();
|
|
@@ -147,6 +147,21 @@ var HonoRequest = class {
|
|
|
147
147
|
arrayBuffer() {
|
|
148
148
|
return this.#cachedBody("arrayBuffer");
|
|
149
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* `.bytes()` parses the request body as a `Uint8Array`.
|
|
152
|
+
*
|
|
153
|
+
* @see {@link https://hono.dev/docs/api/request#bytes}
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```ts
|
|
157
|
+
* app.post('/entry', async (c) => {
|
|
158
|
+
* const body = await c.req.bytes()
|
|
159
|
+
* })
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
bytes() {
|
|
163
|
+
return this.#cachedBody("arrayBuffer").then((buffer) => new Uint8Array(buffer));
|
|
164
|
+
}
|
|
150
165
|
/**
|
|
151
166
|
* Parses the request body as a `Blob`.
|
|
152
167
|
* @example
|