@vivero/stoma 0.1.0-rc.10
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/CHANGELOG.md +196 -0
- package/LICENSE +21 -0
- package/README.md +325 -0
- package/dist/adapters/bun.d.ts +9 -0
- package/dist/adapters/bun.js +8 -0
- package/dist/adapters/bun.js.map +1 -0
- package/dist/adapters/cloudflare.d.ts +49 -0
- package/dist/adapters/cloudflare.js +85 -0
- package/dist/adapters/cloudflare.js.map +1 -0
- package/dist/adapters/deno.d.ts +9 -0
- package/dist/adapters/deno.js +8 -0
- package/dist/adapters/deno.js.map +1 -0
- package/dist/adapters/durable-object.d.ts +63 -0
- package/dist/adapters/durable-object.js +46 -0
- package/dist/adapters/durable-object.js.map +1 -0
- package/dist/adapters/index.d.ts +13 -0
- package/dist/adapters/index.js +53 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/memory.d.ts +9 -0
- package/dist/adapters/memory.js +14 -0
- package/dist/adapters/memory.js.map +1 -0
- package/dist/adapters/node.d.ts +9 -0
- package/dist/adapters/node.js +8 -0
- package/dist/adapters/node.js.map +1 -0
- package/dist/adapters/postgres.d.ts +109 -0
- package/dist/adapters/postgres.js +242 -0
- package/dist/adapters/postgres.js.map +1 -0
- package/dist/adapters/redis.d.ts +116 -0
- package/dist/adapters/redis.js +194 -0
- package/dist/adapters/redis.js.map +1 -0
- package/dist/adapters/testing.d.ts +32 -0
- package/dist/adapters/testing.js +33 -0
- package/dist/adapters/testing.js.map +1 -0
- package/dist/adapters/types.d.ts +4 -0
- package/dist/adapters/types.js +1 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/config/index.d.ts +11 -0
- package/dist/config/index.js +21 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/merge.d.ts +48 -0
- package/dist/config/merge.js +83 -0
- package/dist/config/merge.js.map +1 -0
- package/dist/config/schema.d.ts +254 -0
- package/dist/config/schema.js +109 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/core/errors.d.ts +66 -0
- package/dist/core/errors.js +47 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/gateway.d.ts +44 -0
- package/dist/core/gateway.js +400 -0
- package/dist/core/gateway.js.map +1 -0
- package/dist/core/health.d.ts +78 -0
- package/dist/core/health.js +65 -0
- package/dist/core/health.js.map +1 -0
- package/dist/core/pipeline.d.ts +62 -0
- package/dist/core/pipeline.js +214 -0
- package/dist/core/pipeline.js.map +1 -0
- package/dist/core/protocol.d.ts +4 -0
- package/dist/core/protocol.js +1 -0
- package/dist/core/protocol.js.map +1 -0
- package/dist/core/scope.d.ts +67 -0
- package/dist/core/scope.js +44 -0
- package/dist/core/scope.js.map +1 -0
- package/dist/core/types.d.ts +252 -0
- package/dist/core/types.js +1 -0
- package/dist/core/types.js.map +1 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.js +158 -0
- package/dist/index.js.map +1 -0
- package/dist/observability/admin.d.ts +32 -0
- package/dist/observability/admin.js +85 -0
- package/dist/observability/admin.js.map +1 -0
- package/dist/observability/metrics.d.ts +78 -0
- package/dist/observability/metrics.js +107 -0
- package/dist/observability/metrics.js.map +1 -0
- package/dist/observability/tracing.d.ts +149 -0
- package/dist/observability/tracing.js +191 -0
- package/dist/observability/tracing.js.map +1 -0
- package/dist/policies/auth/api-key-auth.d.ts +64 -0
- package/dist/policies/auth/api-key-auth.js +93 -0
- package/dist/policies/auth/api-key-auth.js.map +1 -0
- package/dist/policies/auth/basic-auth.d.ts +33 -0
- package/dist/policies/auth/basic-auth.js +96 -0
- package/dist/policies/auth/basic-auth.js.map +1 -0
- package/dist/policies/auth/crypto.d.ts +29 -0
- package/dist/policies/auth/crypto.js +100 -0
- package/dist/policies/auth/crypto.js.map +1 -0
- package/dist/policies/auth/generate-http-signature.d.ts +30 -0
- package/dist/policies/auth/generate-http-signature.js +79 -0
- package/dist/policies/auth/generate-http-signature.js.map +1 -0
- package/dist/policies/auth/generate-jwt.d.ts +44 -0
- package/dist/policies/auth/generate-jwt.js +99 -0
- package/dist/policies/auth/generate-jwt.js.map +1 -0
- package/dist/policies/auth/http-signature-base.d.ts +55 -0
- package/dist/policies/auth/http-signature-base.js +140 -0
- package/dist/policies/auth/http-signature-base.js.map +1 -0
- package/dist/policies/auth/jws.d.ts +46 -0
- package/dist/policies/auth/jws.js +317 -0
- package/dist/policies/auth/jws.js.map +1 -0
- package/dist/policies/auth/jwt-auth.d.ts +64 -0
- package/dist/policies/auth/jwt-auth.js +266 -0
- package/dist/policies/auth/jwt-auth.js.map +1 -0
- package/dist/policies/auth/oauth2.d.ts +38 -0
- package/dist/policies/auth/oauth2.js +254 -0
- package/dist/policies/auth/oauth2.js.map +1 -0
- package/dist/policies/auth/rbac.d.ts +30 -0
- package/dist/policies/auth/rbac.js +115 -0
- package/dist/policies/auth/rbac.js.map +1 -0
- package/dist/policies/auth/verify-http-signature.d.ts +30 -0
- package/dist/policies/auth/verify-http-signature.js +147 -0
- package/dist/policies/auth/verify-http-signature.js.map +1 -0
- package/dist/policies/index.d.ts +51 -0
- package/dist/policies/index.js +109 -0
- package/dist/policies/index.js.map +1 -0
- package/dist/policies/mock.d.ts +60 -0
- package/dist/policies/mock.js +29 -0
- package/dist/policies/mock.js.map +1 -0
- package/dist/policies/observability/assign-metrics.d.ts +37 -0
- package/dist/policies/observability/assign-metrics.js +29 -0
- package/dist/policies/observability/assign-metrics.js.map +1 -0
- package/dist/policies/observability/metrics-reporter.d.ts +25 -0
- package/dist/policies/observability/metrics-reporter.js +62 -0
- package/dist/policies/observability/metrics-reporter.js.map +1 -0
- package/dist/policies/observability/request-log.d.ts +135 -0
- package/dist/policies/observability/request-log.js +134 -0
- package/dist/policies/observability/request-log.js.map +1 -0
- package/dist/policies/observability/server-timing.d.ts +35 -0
- package/dist/policies/observability/server-timing.js +89 -0
- package/dist/policies/observability/server-timing.js.map +1 -0
- package/dist/policies/proxy.d.ts +59 -0
- package/dist/policies/proxy.js +47 -0
- package/dist/policies/proxy.js.map +1 -0
- package/dist/policies/resilience/circuit-breaker.d.ts +4 -0
- package/dist/policies/resilience/circuit-breaker.js +280 -0
- package/dist/policies/resilience/circuit-breaker.js.map +1 -0
- package/dist/policies/resilience/latency-injection.d.ts +35 -0
- package/dist/policies/resilience/latency-injection.js +26 -0
- package/dist/policies/resilience/latency-injection.js.map +1 -0
- package/dist/policies/resilience/retry.d.ts +71 -0
- package/dist/policies/resilience/retry.js +79 -0
- package/dist/policies/resilience/retry.js.map +1 -0
- package/dist/policies/resilience/timeout.d.ts +32 -0
- package/dist/policies/resilience/timeout.js +46 -0
- package/dist/policies/resilience/timeout.js.map +1 -0
- package/dist/policies/sdk/define-policy.d.ts +176 -0
- package/dist/policies/sdk/define-policy.js +42 -0
- package/dist/policies/sdk/define-policy.js.map +1 -0
- package/dist/policies/sdk/helpers.d.ts +132 -0
- package/dist/policies/sdk/helpers.js +87 -0
- package/dist/policies/sdk/helpers.js.map +1 -0
- package/dist/policies/sdk/index.d.ts +10 -0
- package/dist/policies/sdk/index.js +35 -0
- package/dist/policies/sdk/index.js.map +1 -0
- package/dist/policies/sdk/priority.d.ts +44 -0
- package/dist/policies/sdk/priority.js +36 -0
- package/dist/policies/sdk/priority.js.map +1 -0
- package/dist/policies/sdk/testing.d.ts +53 -0
- package/dist/policies/sdk/testing.js +41 -0
- package/dist/policies/sdk/testing.js.map +1 -0
- package/dist/policies/sdk/trace.d.ts +73 -0
- package/dist/policies/sdk/trace.js +25 -0
- package/dist/policies/sdk/trace.js.map +1 -0
- package/dist/policies/traffic/cache.d.ts +4 -0
- package/dist/policies/traffic/cache.js +224 -0
- package/dist/policies/traffic/cache.js.map +1 -0
- package/dist/policies/traffic/dynamic-routing.d.ts +54 -0
- package/dist/policies/traffic/dynamic-routing.js +36 -0
- package/dist/policies/traffic/dynamic-routing.js.map +1 -0
- package/dist/policies/traffic/geo-ip-filter.d.ts +37 -0
- package/dist/policies/traffic/geo-ip-filter.js +74 -0
- package/dist/policies/traffic/geo-ip-filter.js.map +1 -0
- package/dist/policies/traffic/http-callout.d.ts +59 -0
- package/dist/policies/traffic/http-callout.js +69 -0
- package/dist/policies/traffic/http-callout.js.map +1 -0
- package/dist/policies/traffic/interrupt.d.ts +46 -0
- package/dist/policies/traffic/interrupt.js +38 -0
- package/dist/policies/traffic/interrupt.js.map +1 -0
- package/dist/policies/traffic/ip-filter.d.ts +47 -0
- package/dist/policies/traffic/ip-filter.js +57 -0
- package/dist/policies/traffic/ip-filter.js.map +1 -0
- package/dist/policies/traffic/json-threat-protection.d.ts +51 -0
- package/dist/policies/traffic/json-threat-protection.js +173 -0
- package/dist/policies/traffic/json-threat-protection.js.map +1 -0
- package/dist/policies/traffic/rate-limit.d.ts +4 -0
- package/dist/policies/traffic/rate-limit.js +145 -0
- package/dist/policies/traffic/rate-limit.js.map +1 -0
- package/dist/policies/traffic/regex-threat-protection.d.ts +54 -0
- package/dist/policies/traffic/regex-threat-protection.js +109 -0
- package/dist/policies/traffic/regex-threat-protection.js.map +1 -0
- package/dist/policies/traffic/request-limit.d.ts +27 -0
- package/dist/policies/traffic/request-limit.js +41 -0
- package/dist/policies/traffic/request-limit.js.map +1 -0
- package/dist/policies/traffic/resource-filter.d.ts +38 -0
- package/dist/policies/traffic/resource-filter.js +184 -0
- package/dist/policies/traffic/resource-filter.js.map +1 -0
- package/dist/policies/traffic/ssl-enforce.d.ts +27 -0
- package/dist/policies/traffic/ssl-enforce.js +38 -0
- package/dist/policies/traffic/ssl-enforce.js.map +1 -0
- package/dist/policies/traffic/traffic-shadow.d.ts +40 -0
- package/dist/policies/traffic/traffic-shadow.js +87 -0
- package/dist/policies/traffic/traffic-shadow.js.map +1 -0
- package/dist/policies/transform/assign-attributes.d.ts +33 -0
- package/dist/policies/transform/assign-attributes.js +38 -0
- package/dist/policies/transform/assign-attributes.js.map +1 -0
- package/dist/policies/transform/assign-content.d.ts +40 -0
- package/dist/policies/transform/assign-content.js +185 -0
- package/dist/policies/transform/assign-content.js.map +1 -0
- package/dist/policies/transform/cors.d.ts +57 -0
- package/dist/policies/transform/cors.js +23 -0
- package/dist/policies/transform/cors.js.map +1 -0
- package/dist/policies/transform/json-validation.d.ts +50 -0
- package/dist/policies/transform/json-validation.js +125 -0
- package/dist/policies/transform/json-validation.js.map +1 -0
- package/dist/policies/transform/override-method.d.ts +33 -0
- package/dist/policies/transform/override-method.js +48 -0
- package/dist/policies/transform/override-method.js.map +1 -0
- package/dist/policies/transform/request-validation.d.ts +59 -0
- package/dist/policies/transform/request-validation.js +121 -0
- package/dist/policies/transform/request-validation.js.map +1 -0
- package/dist/policies/transform/transform.d.ts +75 -0
- package/dist/policies/transform/transform.js +116 -0
- package/dist/policies/transform/transform.js.map +1 -0
- package/dist/policies/types.d.ts +4 -0
- package/dist/policies/types.js +1 -0
- package/dist/policies/types.js.map +1 -0
- package/dist/protocol-2fD3DJrL.d.ts +725 -0
- package/dist/utils/cidr.d.ts +58 -0
- package/dist/utils/cidr.js +107 -0
- package/dist/utils/cidr.js.map +1 -0
- package/dist/utils/debug.d.ts +1 -0
- package/dist/utils/debug.js +13 -0
- package/dist/utils/debug.js.map +1 -0
- package/dist/utils/headers.d.ts +68 -0
- package/dist/utils/headers.js +25 -0
- package/dist/utils/headers.js.map +1 -0
- package/dist/utils/ip.d.ts +64 -0
- package/dist/utils/ip.js +29 -0
- package/dist/utils/ip.js.map +1 -0
- package/dist/utils/redact.d.ts +30 -0
- package/dist/utils/redact.js +52 -0
- package/dist/utils/redact.js.map +1 -0
- package/dist/utils/request-id.d.ts +11 -0
- package/dist/utils/request-id.js +7 -0
- package/dist/utils/request-id.js.map +1 -0
- package/dist/utils/timing-safe.d.ts +31 -0
- package/dist/utils/timing-safe.js +17 -0
- package/dist/utils/timing-safe.js.map +1 -0
- package/dist/utils/timing.d.ts +27 -0
- package/dist/utils/timing.js +12 -0
- package/dist/utils/timing.js.map +1 -0
- package/dist/utils/trace-context.d.ts +51 -0
- package/dist/utils/trace-context.js +37 -0
- package/dist/utils/trace-context.js.map +1 -0
- package/package.json +213 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { GatewayError } from "../../core/errors";
|
|
2
|
+
import { definePolicy, Priority } from "../sdk";
|
|
3
|
+
function normalizeResult(result) {
|
|
4
|
+
if (typeof result === "boolean") {
|
|
5
|
+
return { valid: result };
|
|
6
|
+
}
|
|
7
|
+
return result;
|
|
8
|
+
}
|
|
9
|
+
const requestValidation = /* @__PURE__ */ definePolicy({
|
|
10
|
+
name: "request-validation",
|
|
11
|
+
priority: Priority.AUTH,
|
|
12
|
+
phases: ["request-body"],
|
|
13
|
+
defaults: {
|
|
14
|
+
contentTypes: ["application/json"],
|
|
15
|
+
errorMessage: "Request validation failed"
|
|
16
|
+
},
|
|
17
|
+
handler: async (c, next, { config, debug }) => {
|
|
18
|
+
const contentType = c.req.header("content-type") ?? "";
|
|
19
|
+
const matchedType = config.contentTypes.some(
|
|
20
|
+
(ct) => contentType.includes(ct)
|
|
21
|
+
);
|
|
22
|
+
if (!matchedType) {
|
|
23
|
+
debug(
|
|
24
|
+
"skipping - content type %s not in %o",
|
|
25
|
+
contentType,
|
|
26
|
+
config.contentTypes
|
|
27
|
+
);
|
|
28
|
+
await next();
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
let parsed;
|
|
32
|
+
try {
|
|
33
|
+
const cloned = c.req.raw.clone();
|
|
34
|
+
const text = await cloned.text();
|
|
35
|
+
parsed = JSON.parse(text);
|
|
36
|
+
} catch {
|
|
37
|
+
debug("body parse failed");
|
|
38
|
+
throw new GatewayError(
|
|
39
|
+
400,
|
|
40
|
+
"validation_failed",
|
|
41
|
+
`${config.errorMessage}: invalid JSON`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
const validatorFn = config.validateAsync ?? config.validate;
|
|
45
|
+
if (!validatorFn) {
|
|
46
|
+
debug("no validator configured - passing through");
|
|
47
|
+
await next();
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const rawResult = await validatorFn(parsed);
|
|
51
|
+
const result = normalizeResult(rawResult);
|
|
52
|
+
if (!result.valid) {
|
|
53
|
+
const details = result.errors && result.errors.length > 0 ? `${config.errorMessage}: ${result.errors.join("; ")}` : config.errorMessage;
|
|
54
|
+
debug("validation failed: %s", details);
|
|
55
|
+
throw new GatewayError(400, "validation_failed", details);
|
|
56
|
+
}
|
|
57
|
+
debug("validation passed");
|
|
58
|
+
await next();
|
|
59
|
+
},
|
|
60
|
+
evaluate: {
|
|
61
|
+
onRequest: async (input, { config, debug }) => {
|
|
62
|
+
const contentType = input.headers.get("content-type") ?? "";
|
|
63
|
+
const matchedType = config.contentTypes.some(
|
|
64
|
+
(ct) => contentType.includes(ct)
|
|
65
|
+
);
|
|
66
|
+
if (!matchedType) {
|
|
67
|
+
debug(
|
|
68
|
+
"skipping - content type %s not in %o",
|
|
69
|
+
contentType,
|
|
70
|
+
config.contentTypes
|
|
71
|
+
);
|
|
72
|
+
return { action: "continue" };
|
|
73
|
+
}
|
|
74
|
+
let parsed;
|
|
75
|
+
try {
|
|
76
|
+
if (!input.body) {
|
|
77
|
+
debug("body parse failed");
|
|
78
|
+
return {
|
|
79
|
+
action: "reject",
|
|
80
|
+
status: 400,
|
|
81
|
+
code: "validation_failed",
|
|
82
|
+
message: `${config.errorMessage}: invalid JSON`
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
const bodyStr = typeof input.body === "string" ? input.body : new TextDecoder().decode(input.body);
|
|
86
|
+
parsed = JSON.parse(bodyStr);
|
|
87
|
+
} catch {
|
|
88
|
+
debug("body parse failed");
|
|
89
|
+
return {
|
|
90
|
+
action: "reject",
|
|
91
|
+
status: 400,
|
|
92
|
+
code: "validation_failed",
|
|
93
|
+
message: `${config.errorMessage}: invalid JSON`
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const validatorFn = config.validateAsync ?? config.validate;
|
|
97
|
+
if (!validatorFn) {
|
|
98
|
+
debug("no validator configured - passing through");
|
|
99
|
+
return { action: "continue" };
|
|
100
|
+
}
|
|
101
|
+
const rawResult = await validatorFn(parsed);
|
|
102
|
+
const result = normalizeResult(rawResult);
|
|
103
|
+
if (!result.valid) {
|
|
104
|
+
const details = result.errors && result.errors.length > 0 ? `${config.errorMessage}: ${result.errors.join("; ")}` : config.errorMessage;
|
|
105
|
+
debug("validation failed: %s", details);
|
|
106
|
+
return {
|
|
107
|
+
action: "reject",
|
|
108
|
+
status: 400,
|
|
109
|
+
code: "validation_failed",
|
|
110
|
+
message: details
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
debug("validation passed");
|
|
114
|
+
return { action: "continue" };
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
export {
|
|
119
|
+
requestValidation
|
|
120
|
+
};
|
|
121
|
+
//# sourceMappingURL=request-validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/policies/transform/request-validation.ts"],"sourcesContent":["/**\n * Request validation policy - pluggable body validation with zero dependencies.\n *\n * The gateway library has no validation dependencies (no ajv, no zod at runtime).\n * The user provides their own `validate` or `validateAsync` function. This keeps\n * the library dependency-free while supporting any schema validation approach.\n *\n * @module request-validation\n */\n\nimport { GatewayError } from \"../../core/errors\";\nimport { definePolicy, Priority } from \"../sdk\";\nimport type { PolicyConfig } from \"../types\";\n\n/** Result shape returned by validation functions that provide error details. */\ninterface ValidationResult {\n valid: boolean;\n errors?: string[];\n}\n\nexport interface RequestValidationConfig extends PolicyConfig {\n /**\n * Synchronous validation function.\n * Return `true`/`false` or an object with optional error details.\n */\n validate?: (body: unknown) => boolean | ValidationResult;\n /**\n * Async validation function (e.g., for remote schema validation).\n * If both `validate` and `validateAsync` are provided, `validateAsync` takes precedence.\n */\n validateAsync?: (body: unknown) => Promise<boolean | ValidationResult>;\n /**\n * Only validate these content types.\n * Requests with other content types pass through without validation.\n * Default: `[\"application/json\"]`.\n */\n contentTypes?: string[];\n /** Custom error message prefix. Default: `\"Request validation failed\"`. */\n errorMessage?: string;\n}\n\n/**\n * Normalize a validation return value into a `{ valid, errors? }` shape.\n */\nfunction normalizeResult(result: boolean | ValidationResult): ValidationResult {\n if (typeof result === \"boolean\") {\n return { valid: result };\n }\n return result;\n}\n\n/**\n * Pluggable request body validation policy.\n *\n * Validates the request body using a user-provided sync or async function.\n * Requests with content types not in the configured list pass through\n * without validation.\n *\n * @example\n * ```ts\n * import { requestValidation } from \"@vivero/stoma\";\n *\n * // Simple boolean validator\n * requestValidation({\n * validate: (body) => body != null && typeof body === \"object\",\n * });\n *\n * // Detailed validation with error messages\n * requestValidation({\n * validate: (body) => {\n * const errors: string[] = [];\n * if (!body || typeof body !== \"object\") errors.push(\"Body must be an object\");\n * return { valid: errors.length === 0, errors };\n * },\n * });\n * ```\n */\nexport const requestValidation =\n /*#__PURE__*/ definePolicy<RequestValidationConfig>({\n name: \"request-validation\",\n priority: Priority.AUTH,\n phases: [\"request-body\"],\n defaults: {\n contentTypes: [\"application/json\"],\n errorMessage: \"Request validation failed\",\n },\n handler: async (c, next, { config, debug }) => {\n const contentType = c.req.header(\"content-type\") ?? \"\";\n const matchedType = config.contentTypes!.some((ct) =>\n contentType.includes(ct)\n );\n\n if (!matchedType) {\n debug(\n \"skipping - content type %s not in %o\",\n contentType,\n config.contentTypes\n );\n await next();\n return;\n }\n\n // Clone the request to avoid consuming the body stream for downstream handlers\n let parsed: unknown;\n try {\n const cloned = c.req.raw.clone();\n const text = await cloned.text();\n parsed = JSON.parse(text);\n } catch {\n debug(\"body parse failed\");\n throw new GatewayError(\n 400,\n \"validation_failed\",\n `${config.errorMessage!}: invalid JSON`\n );\n }\n\n // Run async validator if provided, otherwise sync\n const validatorFn = config.validateAsync ?? config.validate;\n if (!validatorFn) {\n debug(\"no validator configured - passing through\");\n await next();\n return;\n }\n\n const rawResult = await validatorFn(parsed);\n const result = normalizeResult(rawResult);\n\n if (!result.valid) {\n const details =\n result.errors && result.errors.length > 0\n ? `${config.errorMessage!}: ${result.errors.join(\"; \")}`\n : config.errorMessage!;\n debug(\"validation failed: %s\", details);\n throw new GatewayError(400, \"validation_failed\", details);\n }\n\n debug(\"validation passed\");\n await next();\n },\n evaluate: {\n onRequest: async (input, { config, debug }) => {\n const contentType = input.headers.get(\"content-type\") ?? \"\";\n const matchedType = config.contentTypes!.some((ct) =>\n contentType.includes(ct)\n );\n\n if (!matchedType) {\n debug(\n \"skipping - content type %s not in %o\",\n contentType,\n config.contentTypes\n );\n return { action: \"continue\" };\n }\n\n // Parse body\n let parsed: unknown;\n try {\n if (!input.body) {\n debug(\"body parse failed\");\n return {\n action: \"reject\",\n status: 400,\n code: \"validation_failed\",\n message: `${config.errorMessage!}: invalid JSON`,\n };\n }\n const bodyStr =\n typeof input.body === \"string\"\n ? input.body\n : new TextDecoder().decode(input.body);\n parsed = JSON.parse(bodyStr);\n } catch {\n debug(\"body parse failed\");\n return {\n action: \"reject\",\n status: 400,\n code: \"validation_failed\",\n message: `${config.errorMessage!}: invalid JSON`,\n };\n }\n\n // Run async validator if provided, otherwise sync\n const validatorFn = config.validateAsync ?? config.validate;\n if (!validatorFn) {\n debug(\"no validator configured - passing through\");\n return { action: \"continue\" };\n }\n\n const rawResult = await validatorFn(parsed);\n const result = normalizeResult(rawResult);\n\n if (!result.valid) {\n const details =\n result.errors && result.errors.length > 0\n ? `${config.errorMessage!}: ${result.errors.join(\"; \")}`\n : config.errorMessage!;\n debug(\"validation failed: %s\", details);\n return {\n action: \"reject\",\n status: 400,\n code: \"validation_failed\",\n message: details,\n };\n }\n\n debug(\"validation passed\");\n return { action: \"continue\" };\n },\n },\n });\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { g as PolicyConfig, P as Policy } from '../../protocol-2fD3DJrL.js';
|
|
2
|
+
import 'hono';
|
|
3
|
+
import '../sdk/trace.js';
|
|
4
|
+
import '@vivero/stoma-core';
|
|
5
|
+
|
|
6
|
+
interface RequestTransformConfig extends PolicyConfig {
|
|
7
|
+
/** Headers to add or overwrite on the outgoing request. */
|
|
8
|
+
setHeaders?: Record<string, string>;
|
|
9
|
+
/** Header names to remove from the outgoing request. */
|
|
10
|
+
removeHeaders?: string[];
|
|
11
|
+
/** Rename headers: keys are old names, values are new names. */
|
|
12
|
+
renameHeaders?: Record<string, string>;
|
|
13
|
+
}
|
|
14
|
+
interface ResponseTransformConfig extends PolicyConfig {
|
|
15
|
+
/** Headers to add or overwrite on the response. */
|
|
16
|
+
setHeaders?: Record<string, string>;
|
|
17
|
+
/** Header names to remove from the response. */
|
|
18
|
+
removeHeaders?: string[];
|
|
19
|
+
/** Rename headers: keys are old names, values are new names. */
|
|
20
|
+
renameHeaders?: Record<string, string>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Modify request headers before they reach the upstream service.
|
|
24
|
+
*
|
|
25
|
+
* Applies header transformations in order: rename → set → remove. Handles
|
|
26
|
+
* Cloudflare Workers' immutable `Request.headers` by cloning the request
|
|
27
|
+
* with modified headers.
|
|
28
|
+
*
|
|
29
|
+
* @param config - Header set/remove/rename operations. At least one should be provided.
|
|
30
|
+
* @returns A {@link Policy} at priority 50 (mid-pipeline, after auth, before upstream).
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* import { requestTransform } from "@vivero/stoma/policies";
|
|
35
|
+
*
|
|
36
|
+
* // Add API version header and strip cookies
|
|
37
|
+
* requestTransform({
|
|
38
|
+
* setHeaders: { "x-api-version": "2024-01-01" },
|
|
39
|
+
* removeHeaders: ["cookie"],
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* // Rename a legacy header to the new convention
|
|
43
|
+
* requestTransform({
|
|
44
|
+
* renameHeaders: { "x-old-auth": "authorization" },
|
|
45
|
+
* });
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
declare const requestTransform: (config?: RequestTransformConfig | undefined) => Policy;
|
|
49
|
+
/**
|
|
50
|
+
* Modify response headers after the upstream service returns.
|
|
51
|
+
*
|
|
52
|
+
* Applies header transformations in order: rename → set → remove. Runs at
|
|
53
|
+
* priority 92 (late in the pipeline) so it can modify headers set by the
|
|
54
|
+
* upstream or earlier policies.
|
|
55
|
+
*
|
|
56
|
+
* @param config - Header set/remove/rename operations. At least one should be provided.
|
|
57
|
+
* @returns A {@link Policy} at priority 92 (runs late, after upstream responds).
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* import { responseTransform } from "@vivero/stoma/policies";
|
|
62
|
+
*
|
|
63
|
+
* // Add security headers and strip server info
|
|
64
|
+
* responseTransform({
|
|
65
|
+
* setHeaders: {
|
|
66
|
+
* "strict-transport-security": "max-age=31536000; includeSubDomains",
|
|
67
|
+
* "x-content-type-options": "nosniff",
|
|
68
|
+
* },
|
|
69
|
+
* removeHeaders: ["server", "x-powered-by"],
|
|
70
|
+
* });
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
declare const responseTransform: (config?: ResponseTransformConfig | undefined) => Policy;
|
|
74
|
+
|
|
75
|
+
export { type RequestTransformConfig, type ResponseTransformConfig, requestTransform, responseTransform };
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { withModifiedHeaders } from "../../utils/headers";
|
|
2
|
+
import { definePolicy, Priority } from "../sdk";
|
|
3
|
+
const requestTransform = /* @__PURE__ */ definePolicy({
|
|
4
|
+
name: "request-transform",
|
|
5
|
+
priority: Priority.REQUEST_TRANSFORM,
|
|
6
|
+
phases: ["request-headers"],
|
|
7
|
+
handler: async (c, next, { config }) => {
|
|
8
|
+
const setHeaders = config.setHeaders;
|
|
9
|
+
const removeHeaders = config.removeHeaders;
|
|
10
|
+
const renameHeaders = config.renameHeaders;
|
|
11
|
+
withModifiedHeaders(c, (headers) => {
|
|
12
|
+
if (renameHeaders) {
|
|
13
|
+
for (const [oldName, newName] of Object.entries(renameHeaders)) {
|
|
14
|
+
const value = headers.get(oldName);
|
|
15
|
+
if (value !== null) {
|
|
16
|
+
headers.set(newName, value);
|
|
17
|
+
headers.delete(oldName);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (setHeaders) {
|
|
22
|
+
for (const [name, value] of Object.entries(setHeaders)) {
|
|
23
|
+
headers.set(name, value);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (removeHeaders) {
|
|
27
|
+
for (const name of removeHeaders) {
|
|
28
|
+
headers.delete(name);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
await next();
|
|
33
|
+
},
|
|
34
|
+
evaluate: {
|
|
35
|
+
onRequest: async (_input, { config }) => {
|
|
36
|
+
const mutations = [];
|
|
37
|
+
if (config.setHeaders) {
|
|
38
|
+
for (const [name, value] of Object.entries(config.setHeaders)) {
|
|
39
|
+
mutations.push({
|
|
40
|
+
type: "header",
|
|
41
|
+
op: "set",
|
|
42
|
+
name,
|
|
43
|
+
value
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (config.removeHeaders) {
|
|
48
|
+
for (const name of config.removeHeaders) {
|
|
49
|
+
mutations.push({
|
|
50
|
+
type: "header",
|
|
51
|
+
op: "remove",
|
|
52
|
+
name
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return mutations.length > 0 ? { action: "continue", mutations } : { action: "continue" };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
const responseTransform = /* @__PURE__ */ definePolicy({
|
|
61
|
+
name: "response-transform",
|
|
62
|
+
priority: Priority.RESPONSE_TRANSFORM,
|
|
63
|
+
phases: ["response-headers"],
|
|
64
|
+
handler: async (c, next, { config }) => {
|
|
65
|
+
await next();
|
|
66
|
+
if (config.renameHeaders) {
|
|
67
|
+
for (const [oldName, newName] of Object.entries(config.renameHeaders)) {
|
|
68
|
+
const value = c.res.headers.get(oldName);
|
|
69
|
+
if (value !== null) {
|
|
70
|
+
c.res.headers.set(newName, value);
|
|
71
|
+
c.res.headers.delete(oldName);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (config.setHeaders) {
|
|
76
|
+
for (const [name, value] of Object.entries(config.setHeaders)) {
|
|
77
|
+
c.res.headers.set(name, value);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (config.removeHeaders) {
|
|
81
|
+
for (const name of config.removeHeaders) {
|
|
82
|
+
c.res.headers.delete(name);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
evaluate: {
|
|
87
|
+
onResponse: async (_input, { config }) => {
|
|
88
|
+
const mutations = [];
|
|
89
|
+
if (config.setHeaders) {
|
|
90
|
+
for (const [name, value] of Object.entries(config.setHeaders)) {
|
|
91
|
+
mutations.push({
|
|
92
|
+
type: "header",
|
|
93
|
+
op: "set",
|
|
94
|
+
name,
|
|
95
|
+
value
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (config.removeHeaders) {
|
|
100
|
+
for (const name of config.removeHeaders) {
|
|
101
|
+
mutations.push({
|
|
102
|
+
type: "header",
|
|
103
|
+
op: "remove",
|
|
104
|
+
name
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return mutations.length > 0 ? { action: "continue", mutations } : { action: "continue" };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
export {
|
|
113
|
+
requestTransform,
|
|
114
|
+
responseTransform
|
|
115
|
+
};
|
|
116
|
+
//# sourceMappingURL=transform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/policies/transform/transform.ts"],"sourcesContent":["/**\n * Request and response header transformation policies.\n *\n * @module transform\n */\n\nimport type { Mutation } from \"../../core/protocol\";\nimport { withModifiedHeaders } from \"../../utils/headers\";\nimport { definePolicy, Priority } from \"../sdk\";\nimport type { PolicyConfig } from \"../types\";\n\nexport interface RequestTransformConfig extends PolicyConfig {\n /** Headers to add or overwrite on the outgoing request. */\n setHeaders?: Record<string, string>;\n /** Header names to remove from the outgoing request. */\n removeHeaders?: string[];\n /** Rename headers: keys are old names, values are new names. */\n renameHeaders?: Record<string, string>;\n}\n\nexport interface ResponseTransformConfig extends PolicyConfig {\n /** Headers to add or overwrite on the response. */\n setHeaders?: Record<string, string>;\n /** Header names to remove from the response. */\n removeHeaders?: string[];\n /** Rename headers: keys are old names, values are new names. */\n renameHeaders?: Record<string, string>;\n}\n\n/**\n * Modify request headers before they reach the upstream service.\n *\n * Applies header transformations in order: rename → set → remove. Handles\n * Cloudflare Workers' immutable `Request.headers` by cloning the request\n * with modified headers.\n *\n * @param config - Header set/remove/rename operations. At least one should be provided.\n * @returns A {@link Policy} at priority 50 (mid-pipeline, after auth, before upstream).\n *\n * @example\n * ```ts\n * import { requestTransform } from \"@vivero/stoma/policies\";\n *\n * // Add API version header and strip cookies\n * requestTransform({\n * setHeaders: { \"x-api-version\": \"2024-01-01\" },\n * removeHeaders: [\"cookie\"],\n * });\n *\n * // Rename a legacy header to the new convention\n * requestTransform({\n * renameHeaders: { \"x-old-auth\": \"authorization\" },\n * });\n * ```\n */\nexport const requestTransform =\n /*#__PURE__*/ definePolicy<RequestTransformConfig>({\n name: \"request-transform\",\n priority: Priority.REQUEST_TRANSFORM,\n phases: [\"request-headers\"],\n handler: async (c, next, { config }) => {\n const setHeaders = config.setHeaders;\n const removeHeaders = config.removeHeaders;\n const renameHeaders = config.renameHeaders;\n\n withModifiedHeaders(c, (headers) => {\n // Rename before set/remove so renames don't collide\n if (renameHeaders) {\n for (const [oldName, newName] of Object.entries(renameHeaders)) {\n const value = headers.get(oldName);\n if (value !== null) {\n headers.set(newName, value);\n headers.delete(oldName);\n }\n }\n }\n\n if (setHeaders) {\n for (const [name, value] of Object.entries(setHeaders)) {\n headers.set(name, value);\n }\n }\n\n if (removeHeaders) {\n for (const name of removeHeaders) {\n headers.delete(name);\n }\n }\n });\n\n await next();\n },\n evaluate: {\n onRequest: async (_input, { config }) => {\n const mutations: Mutation[] = [];\n\n // Set headers\n if (config.setHeaders) {\n for (const [name, value] of Object.entries(config.setHeaders)) {\n mutations.push({\n type: \"header\",\n op: \"set\" as const,\n name,\n value,\n });\n }\n }\n\n // Remove headers\n if (config.removeHeaders) {\n for (const name of config.removeHeaders) {\n mutations.push({\n type: \"header\",\n op: \"remove\" as const,\n name,\n });\n }\n }\n\n return mutations.length > 0\n ? { action: \"continue\", mutations }\n : { action: \"continue\" };\n },\n },\n });\n\n/**\n * Modify response headers after the upstream service returns.\n *\n * Applies header transformations in order: rename → set → remove. Runs at\n * priority 92 (late in the pipeline) so it can modify headers set by the\n * upstream or earlier policies.\n *\n * @param config - Header set/remove/rename operations. At least one should be provided.\n * @returns A {@link Policy} at priority 92 (runs late, after upstream responds).\n *\n * @example\n * ```ts\n * import { responseTransform } from \"@vivero/stoma/policies\";\n *\n * // Add security headers and strip server info\n * responseTransform({\n * setHeaders: {\n * \"strict-transport-security\": \"max-age=31536000; includeSubDomains\",\n * \"x-content-type-options\": \"nosniff\",\n * },\n * removeHeaders: [\"server\", \"x-powered-by\"],\n * });\n * ```\n */\nexport const responseTransform =\n /*#__PURE__*/ definePolicy<ResponseTransformConfig>({\n name: \"response-transform\",\n priority: Priority.RESPONSE_TRANSFORM,\n phases: [\"response-headers\"],\n handler: async (c, next, { config }) => {\n await next();\n\n // Response headers are mutable (we create the Response ourselves\n // in the upstream handler), so direct mutation is safe here.\n // Note: Request headers need cloning because Workers makes them immutable.\n\n // Rename before set/remove\n if (config.renameHeaders) {\n for (const [oldName, newName] of Object.entries(config.renameHeaders)) {\n const value = c.res.headers.get(oldName);\n if (value !== null) {\n c.res.headers.set(newName, value);\n c.res.headers.delete(oldName);\n }\n }\n }\n\n if (config.setHeaders) {\n for (const [name, value] of Object.entries(config.setHeaders)) {\n c.res.headers.set(name, value);\n }\n }\n\n if (config.removeHeaders) {\n for (const name of config.removeHeaders) {\n c.res.headers.delete(name);\n }\n }\n },\n evaluate: {\n onResponse: async (_input, { config }) => {\n const mutations: Mutation[] = [];\n\n // Set headers\n if (config.setHeaders) {\n for (const [name, value] of Object.entries(config.setHeaders)) {\n mutations.push({\n type: \"header\",\n op: \"set\" as const,\n name,\n value,\n });\n }\n }\n\n // Remove headers\n if (config.removeHeaders) {\n for (const name of config.removeHeaders) {\n mutations.push({\n type: \"header\",\n op: \"remove\" as const,\n name,\n });\n }\n }\n\n return mutations.length > 0\n ? { action: \"continue\", mutations }\n : { action: \"continue\" };\n },\n },\n });\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|