@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,252 @@
|
|
|
1
|
+
import { Context, Hono } from 'hono';
|
|
2
|
+
import { P as Policy, G as GatewayAdapter } from '../protocol-2fD3DJrL.js';
|
|
3
|
+
import { MetricsCollector } from '../observability/metrics.js';
|
|
4
|
+
import { TracingConfig } from '../observability/tracing.js';
|
|
5
|
+
import '../policies/sdk/trace.js';
|
|
6
|
+
import '@vivero/stoma-core';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Core type definitions for the stoma gateway.
|
|
10
|
+
*
|
|
11
|
+
* All gateway configuration is expressed through these types. The main entry
|
|
12
|
+
* point is {@link GatewayConfig}, which composes {@link RouteConfig},
|
|
13
|
+
* {@link PipelineConfig}, and {@link UpstreamConfig} into a fully declarative
|
|
14
|
+
* gateway specification.
|
|
15
|
+
*
|
|
16
|
+
* @module types
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Top-level gateway configuration.
|
|
21
|
+
*
|
|
22
|
+
* @typeParam TBindings - Worker bindings type (e.g. your `Env` interface).
|
|
23
|
+
* Defaults to `Record<string, unknown>` so `service` on
|
|
24
|
+
* {@link ServiceBindingUpstream} accepts any string. When you pass your
|
|
25
|
+
* own Env type, `service` autocompletes to valid binding names.
|
|
26
|
+
*/
|
|
27
|
+
interface GatewayConfig<TBindings = Record<string, unknown>> {
|
|
28
|
+
/** Gateway name, used in logs and metrics */
|
|
29
|
+
name?: string;
|
|
30
|
+
/** Base path prefix for all routes (e.g. "/api") */
|
|
31
|
+
basePath?: string;
|
|
32
|
+
/** Route definitions */
|
|
33
|
+
routes: RouteConfig<TBindings>[];
|
|
34
|
+
/** Global policies applied to all routes */
|
|
35
|
+
policies?: Policy[];
|
|
36
|
+
/** Global error handler */
|
|
37
|
+
onError?: (error: Error, c: Context) => Response | Promise<Response>;
|
|
38
|
+
/**
|
|
39
|
+
* Enable internal debug logging for gateway operators.
|
|
40
|
+
*
|
|
41
|
+
* - `true` - log all namespaces
|
|
42
|
+
* - `false` / `undefined` - disabled (default, zero overhead)
|
|
43
|
+
* - `string` - comma-separated glob patterns to filter namespaces
|
|
44
|
+
*
|
|
45
|
+
* Namespaces: `stoma:gateway`, `stoma:pipeline`, `stoma:upstream`,
|
|
46
|
+
* `stoma:policy:*` (e.g. `stoma:policy:cache`, `stoma:policy:jwt-auth`)
|
|
47
|
+
*
|
|
48
|
+
* Output goes to `console.debug()` which is captured by `wrangler tail`
|
|
49
|
+
* and Cloudflare Workers Logs.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* createGateway({ debug: true, ... }) // everything
|
|
54
|
+
* createGateway({ debug: "stoma:gateway,stoma:upstream", ... }) // core only
|
|
55
|
+
* createGateway({ debug: "stoma:policy:*", ... }) // policies only
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
debug?: boolean | string;
|
|
59
|
+
/** Response header name for the request ID. Default: `"x-request-id"`. */
|
|
60
|
+
requestIdHeader?: string;
|
|
61
|
+
/**
|
|
62
|
+
* Default HTTP methods for routes that don't specify `methods`.
|
|
63
|
+
* Default: `["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]`.
|
|
64
|
+
*/
|
|
65
|
+
defaultMethods?: HttpMethod[];
|
|
66
|
+
/** Default error message for unexpected (non-GatewayError) errors. Default: `"An unexpected error occurred"`. */
|
|
67
|
+
defaultErrorMessage?: string;
|
|
68
|
+
/** Default priority for policies that don't specify one. Default: `100`. */
|
|
69
|
+
defaultPolicyPriority?: number;
|
|
70
|
+
/**
|
|
71
|
+
* Runtime adapter providing store implementations and runtime-specific capabilities
|
|
72
|
+
* (e.g. `waitUntil`, `dispatchBinding`). Created via adapter factories like
|
|
73
|
+
* `cloudflareAdapter()`, `memoryAdapter()`, etc.
|
|
74
|
+
*/
|
|
75
|
+
adapter?: GatewayAdapter;
|
|
76
|
+
/**
|
|
77
|
+
* Admin introspection API. Exposes `___gateway/*` routes for operational visibility.
|
|
78
|
+
*
|
|
79
|
+
* - `true` - enable with defaults (no auth)
|
|
80
|
+
* - `AdminConfig` object - full customization
|
|
81
|
+
* - `false` / `undefined` - disabled (default)
|
|
82
|
+
*/
|
|
83
|
+
admin?: boolean | AdminConfig;
|
|
84
|
+
/**
|
|
85
|
+
* Enable client-requested debug headers.
|
|
86
|
+
*
|
|
87
|
+
* When enabled, clients can send an `x-stoma-debug` request header listing
|
|
88
|
+
* the debug values they want returned as response headers. Policies contribute
|
|
89
|
+
* debug data via {@link setDebugHeader} from the SDK - only requested values
|
|
90
|
+
* are included in the response.
|
|
91
|
+
*
|
|
92
|
+
* - `true` - enable with defaults
|
|
93
|
+
* - `DebugHeadersConfig` - full customization (request header name, allowlist)
|
|
94
|
+
* - `false` / `undefined` - disabled (default, zero overhead)
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```
|
|
98
|
+
* // Client request:
|
|
99
|
+
* GET /api/users
|
|
100
|
+
* x-stoma-debug: x-stoma-cache-key, x-stoma-cache-ttl
|
|
101
|
+
*
|
|
102
|
+
* // Response includes:
|
|
103
|
+
* x-stoma-cache-key: GET:http://example.com/api/users
|
|
104
|
+
* x-stoma-cache-ttl: 300
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
debugHeaders?: boolean | DebugHeadersConfig;
|
|
108
|
+
/**
|
|
109
|
+
* OpenTelemetry-compatible distributed tracing.
|
|
110
|
+
*
|
|
111
|
+
* When configured, the gateway creates a root SERVER span per request,
|
|
112
|
+
* INTERNAL child spans per policy, and CLIENT child spans for upstream
|
|
113
|
+
* calls. Spans are exported asynchronously via `adapter.waitUntil()`.
|
|
114
|
+
*
|
|
115
|
+
* Zero overhead when not configured - no span objects are allocated.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```ts
|
|
119
|
+
* import { createGateway, OTLPSpanExporter } from "@vivero/stoma";
|
|
120
|
+
*
|
|
121
|
+
* createGateway({
|
|
122
|
+
* tracing: {
|
|
123
|
+
* exporter: new OTLPSpanExporter({ endpoint: "https://otel-collector/v1/traces" }),
|
|
124
|
+
* serviceName: "my-api",
|
|
125
|
+
* sampleRate: 0.1,
|
|
126
|
+
* },
|
|
127
|
+
* // ...routes
|
|
128
|
+
* });
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
tracing?: TracingConfig;
|
|
132
|
+
}
|
|
133
|
+
/** Configuration for client-requested debug headers. */
|
|
134
|
+
interface DebugHeadersConfig {
|
|
135
|
+
/** Request header name clients use to request debug values. Default: `"x-stoma-debug"`. */
|
|
136
|
+
requestHeader?: string;
|
|
137
|
+
/** Allowlist of debug header names clients can request. When set, only these headers are emitted. Default: all. */
|
|
138
|
+
allow?: string[];
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Individual route configuration.
|
|
142
|
+
*
|
|
143
|
+
* @typeParam TBindings - Worker bindings type, propagated from {@link GatewayConfig}.
|
|
144
|
+
*/
|
|
145
|
+
interface RouteConfig<TBindings = Record<string, unknown>> {
|
|
146
|
+
/** Route path pattern (Hono syntax, e.g. "/users/:id") */
|
|
147
|
+
path: string;
|
|
148
|
+
/** Allowed HTTP methods. Defaults to all. */
|
|
149
|
+
methods?: HttpMethod[];
|
|
150
|
+
/** Pipeline to process this route */
|
|
151
|
+
pipeline: PipelineConfig<TBindings>;
|
|
152
|
+
/** Route-level metadata for logging/observability */
|
|
153
|
+
metadata?: Record<string, unknown>;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Pipeline: ordered chain of policies leading to an upstream.
|
|
157
|
+
*
|
|
158
|
+
* @typeParam TBindings - Worker bindings type, propagated from {@link RouteConfig}.
|
|
159
|
+
*/
|
|
160
|
+
interface PipelineConfig<TBindings = Record<string, unknown>> {
|
|
161
|
+
/** Policies executed in order before the upstream */
|
|
162
|
+
policies?: Policy[];
|
|
163
|
+
/** Upstream target configuration */
|
|
164
|
+
upstream: UpstreamConfig<TBindings>;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Upstream target - where the request is forwarded.
|
|
168
|
+
*
|
|
169
|
+
* @typeParam TBindings - Worker bindings type, constrains {@link ServiceBindingUpstream.service}.
|
|
170
|
+
*/
|
|
171
|
+
type UpstreamConfig<TBindings = Record<string, unknown>> = UrlUpstream | ServiceBindingUpstream<TBindings> | HandlerUpstream;
|
|
172
|
+
/**
|
|
173
|
+
* Proxy to a remote URL. The gateway clones the request, rewrites headers,
|
|
174
|
+
* and forwards it via `fetch()`. SSRF protection ensures the rewritten URL
|
|
175
|
+
* stays on the same origin as the target.
|
|
176
|
+
*/
|
|
177
|
+
interface UrlUpstream {
|
|
178
|
+
type: "url";
|
|
179
|
+
/** Target URL (e.g. `"https://api.example.com"`). Validated at config time. */
|
|
180
|
+
target: string;
|
|
181
|
+
/** Rewrite the path before forwarding. Must not change the origin. */
|
|
182
|
+
rewritePath?: (path: string) => string;
|
|
183
|
+
/** Headers to add/override on the forwarded request. */
|
|
184
|
+
headers?: Record<string, string>;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Forward to another Cloudflare Worker via a Service Binding.
|
|
188
|
+
* The binding must be configured in the consumer's `wrangler.jsonc`.
|
|
189
|
+
*
|
|
190
|
+
* @typeParam TBindings - Worker bindings type. When provided, `service`
|
|
191
|
+
* autocompletes to valid binding names from your Env interface.
|
|
192
|
+
*/
|
|
193
|
+
interface ServiceBindingUpstream<TBindings = Record<string, unknown>> {
|
|
194
|
+
type: "service-binding";
|
|
195
|
+
/** Name of the Service Binding in `wrangler.jsonc` (e.g. `"AUTH_SERVICE"`). */
|
|
196
|
+
service: Extract<keyof TBindings, string>;
|
|
197
|
+
/** Rewrite the path before forwarding to the bound service. */
|
|
198
|
+
rewritePath?: (path: string) => string;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Invoke a custom handler function directly. Useful for health checks,
|
|
202
|
+
* mock responses, or routes that don't proxy to an upstream.
|
|
203
|
+
*/
|
|
204
|
+
interface HandlerUpstream {
|
|
205
|
+
type: "handler";
|
|
206
|
+
/** Handler function receiving the Hono context and returning a Response. */
|
|
207
|
+
handler: (c: Context) => Response | Promise<Response>;
|
|
208
|
+
}
|
|
209
|
+
/** HTTP methods supported by gateway route registration. */
|
|
210
|
+
type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS";
|
|
211
|
+
/** Configuration for the admin introspection API. */
|
|
212
|
+
interface AdminConfig {
|
|
213
|
+
/** Enable admin routes. Default: `false`. */
|
|
214
|
+
enabled: boolean;
|
|
215
|
+
/** Path prefix for admin routes. Default: `"___gateway"`. */
|
|
216
|
+
prefix?: string;
|
|
217
|
+
/** Optional auth check - return `false` to deny access. */
|
|
218
|
+
auth?: (c: Context) => boolean | Promise<boolean>;
|
|
219
|
+
/** MetricsCollector instance for the `/metrics` endpoint. */
|
|
220
|
+
metrics?: MetricsCollector;
|
|
221
|
+
}
|
|
222
|
+
/** Registered route information for admin introspection. */
|
|
223
|
+
interface RegisteredRoute {
|
|
224
|
+
path: string;
|
|
225
|
+
methods: string[];
|
|
226
|
+
policyNames: string[];
|
|
227
|
+
upstreamType: string;
|
|
228
|
+
}
|
|
229
|
+
/** Registered policy information for admin introspection. */
|
|
230
|
+
interface RegisteredPolicy {
|
|
231
|
+
name: string;
|
|
232
|
+
priority: number;
|
|
233
|
+
}
|
|
234
|
+
/** Internal registry for admin introspection. */
|
|
235
|
+
interface GatewayRegistry {
|
|
236
|
+
routes: RegisteredRoute[];
|
|
237
|
+
policies: RegisteredPolicy[];
|
|
238
|
+
gatewayName: string;
|
|
239
|
+
}
|
|
240
|
+
/** The instantiated gateway - a configured Hono app */
|
|
241
|
+
interface GatewayInstance {
|
|
242
|
+
/** The underlying Hono app, ready to be exported as a Worker */
|
|
243
|
+
app: Hono;
|
|
244
|
+
/** Registered route count */
|
|
245
|
+
routeCount: number;
|
|
246
|
+
/** Gateway name */
|
|
247
|
+
name: string;
|
|
248
|
+
/** Internal registry for admin introspection */
|
|
249
|
+
_registry: GatewayRegistry;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export type { AdminConfig, DebugHeadersConfig, GatewayConfig, GatewayInstance, GatewayRegistry, HandlerUpstream, HttpMethod, PipelineConfig, RegisteredPolicy, RegisteredRoute, RouteConfig, ServiceBindingUpstream, UpstreamConfig, UrlUpstream };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export { A as AttributeMutation, B as BodyMutation, C as CacheStore, a as CircuitBreakerSnapshot, b as CircuitBreakerStore, c as CircuitState, G as GatewayAdapter, H as HeaderMutation, I as InMemoryCacheStore, d as InMemoryCacheStoreOptions, e as InMemoryCircuitBreakerStore, f as InMemoryRateLimitStoreOptions, M as Mutation, P as Policy, g as PolicyConfig, h as PolicyContext, i as PolicyContinue, j as PolicyEvalContext, k as PolicyEvaluator, l as PolicyImmediateResponse, m as PolicyInput, n as PolicyReject, o as PolicyResult, p as ProcessingPhase, q as ProtocolType, R as RateLimitStore, S as StatusMutation, r as cache, s as circuitBreaker, t as rateLimit } from './protocol-2fD3DJrL.js';
|
|
2
|
+
export { ErrorResponse, GatewayError, defaultErrorResponse, errorToResponse } from './core/errors.js';
|
|
3
|
+
export { createGateway } from './core/gateway.js';
|
|
4
|
+
export { getGatewayContext } from './core/pipeline.js';
|
|
5
|
+
export { ScopeConfig, scope } from './core/scope.js';
|
|
6
|
+
export { AdminConfig, DebugHeadersConfig, GatewayConfig, GatewayInstance, GatewayRegistry, HandlerUpstream, HttpMethod, PipelineConfig, RegisteredPolicy, RegisteredRoute, RouteConfig, ServiceBindingUpstream, UpstreamConfig, UrlUpstream } from './core/types.js';
|
|
7
|
+
export { mock } from './policies/mock.js';
|
|
8
|
+
export { proxy } from './policies/proxy.js';
|
|
9
|
+
export { apiKeyAuth } from './policies/auth/api-key-auth.js';
|
|
10
|
+
export { basicAuth } from './policies/auth/basic-auth.js';
|
|
11
|
+
export { clearJwksCache } from './policies/auth/crypto.js';
|
|
12
|
+
export { generateHttpSignature } from './policies/auth/generate-http-signature.js';
|
|
13
|
+
export { generateJwt } from './policies/auth/generate-jwt.js';
|
|
14
|
+
export { jws } from './policies/auth/jws.js';
|
|
15
|
+
export { jwtAuth } from './policies/auth/jwt-auth.js';
|
|
16
|
+
export { oauth2 } from './policies/auth/oauth2.js';
|
|
17
|
+
export { rbac } from './policies/auth/rbac.js';
|
|
18
|
+
export { verifyHttpSignature } from './policies/auth/verify-http-signature.js';
|
|
19
|
+
export { dynamicRouting } from './policies/traffic/dynamic-routing.js';
|
|
20
|
+
export { geoIpFilter } from './policies/traffic/geo-ip-filter.js';
|
|
21
|
+
export { httpCallout } from './policies/traffic/http-callout.js';
|
|
22
|
+
export { interrupt } from './policies/traffic/interrupt.js';
|
|
23
|
+
export { ipFilter } from './policies/traffic/ip-filter.js';
|
|
24
|
+
export { jsonThreatProtection } from './policies/traffic/json-threat-protection.js';
|
|
25
|
+
export { regexThreatProtection } from './policies/traffic/regex-threat-protection.js';
|
|
26
|
+
export { requestLimit } from './policies/traffic/request-limit.js';
|
|
27
|
+
export { resourceFilter } from './policies/traffic/resource-filter.js';
|
|
28
|
+
export { sslEnforce } from './policies/traffic/ssl-enforce.js';
|
|
29
|
+
export { trafficShadow } from './policies/traffic/traffic-shadow.js';
|
|
30
|
+
export { latencyInjection } from './policies/resilience/latency-injection.js';
|
|
31
|
+
export { retry } from './policies/resilience/retry.js';
|
|
32
|
+
export { timeout } from './policies/resilience/timeout.js';
|
|
33
|
+
export { assignAttributes } from './policies/transform/assign-attributes.js';
|
|
34
|
+
export { assignContent } from './policies/transform/assign-content.js';
|
|
35
|
+
export { cors } from './policies/transform/cors.js';
|
|
36
|
+
export { jsonValidation } from './policies/transform/json-validation.js';
|
|
37
|
+
export { overrideMethod } from './policies/transform/override-method.js';
|
|
38
|
+
export { requestValidation } from './policies/transform/request-validation.js';
|
|
39
|
+
export { requestTransform, responseTransform } from './policies/transform/transform.js';
|
|
40
|
+
export { health } from './core/health.js';
|
|
41
|
+
export { assignMetrics } from './policies/observability/assign-metrics.js';
|
|
42
|
+
export { MetricsReporterConfig, metricsReporter } from './policies/observability/metrics-reporter.js';
|
|
43
|
+
export { requestLog } from './policies/observability/request-log.js';
|
|
44
|
+
export { ServerTimingConfig, ServerTimingVisibility, serverTiming } from './policies/observability/server-timing.js';
|
|
45
|
+
export { HistogramEntry, InMemoryMetricsCollector, MetricsCollector, MetricsSnapshot, TaggedValue, toPrometheusText } from './observability/metrics.js';
|
|
46
|
+
export { ConsoleSpanExporter, OTLPSpanExporter, ReadableSpan, SemConv, SpanBuilder, SpanEvent, SpanExporter, SpanKind, SpanStatusCode, TracingConfig } from './observability/tracing.js';
|
|
47
|
+
export { Priority, PriorityLevel } from './policies/sdk/priority.js';
|
|
48
|
+
export { isDebugRequested, policyDebug, resolveConfig, safeCall, setDebugHeader, withSkip } from './policies/sdk/helpers.js';
|
|
49
|
+
export { PolicyDefinition, PolicyEvalHandlerContext, PolicyFactory, PolicyHandlerContext, definePolicy } from './policies/sdk/define-policy.js';
|
|
50
|
+
export { PolicyTestHarnessOptions, createPolicyTestHarness } from './policies/sdk/testing.js';
|
|
51
|
+
export { PolicyTrace, PolicyTraceDetail, PolicyTraceEntry, TraceReporter, isTraceRequested, noopTraceReporter, policyTrace } from './policies/sdk/trace.js';
|
|
52
|
+
export { DebugLogger } from '@vivero/stoma-core';
|
|
53
|
+
export { DEFAULT_IP_HEADERS, extractClientIp } from './utils/ip.js';
|
|
54
|
+
export { timingSafeEqual } from './utils/timing-safe.js';
|
|
55
|
+
import 'hono';
|
|
56
|
+
import 'hono/types';
|
|
57
|
+
import './adapters/testing.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defaultErrorResponse,
|
|
3
|
+
errorToResponse,
|
|
4
|
+
GatewayError
|
|
5
|
+
} from "./core/errors";
|
|
6
|
+
import { createGateway } from "./core/gateway";
|
|
7
|
+
import { getGatewayContext } from "./core/pipeline";
|
|
8
|
+
import { scope } from "./core/scope";
|
|
9
|
+
import { mock } from "./policies/mock";
|
|
10
|
+
import { proxy } from "./policies/proxy";
|
|
11
|
+
import { apiKeyAuth } from "./policies/auth/api-key-auth";
|
|
12
|
+
import { basicAuth } from "./policies/auth/basic-auth";
|
|
13
|
+
import { clearJwksCache } from "./policies/auth/crypto";
|
|
14
|
+
import { generateHttpSignature } from "./policies/auth/generate-http-signature";
|
|
15
|
+
import { generateJwt } from "./policies/auth/generate-jwt";
|
|
16
|
+
import { jws } from "./policies/auth/jws";
|
|
17
|
+
import { jwtAuth } from "./policies/auth/jwt-auth";
|
|
18
|
+
import { oauth2 } from "./policies/auth/oauth2";
|
|
19
|
+
import { rbac } from "./policies/auth/rbac";
|
|
20
|
+
import { verifyHttpSignature } from "./policies/auth/verify-http-signature";
|
|
21
|
+
import { cache, InMemoryCacheStore } from "./policies/traffic/cache";
|
|
22
|
+
import { dynamicRouting } from "./policies/traffic/dynamic-routing";
|
|
23
|
+
import { geoIpFilter } from "./policies/traffic/geo-ip-filter";
|
|
24
|
+
import { httpCallout } from "./policies/traffic/http-callout";
|
|
25
|
+
import { interrupt } from "./policies/traffic/interrupt";
|
|
26
|
+
import { ipFilter } from "./policies/traffic/ip-filter";
|
|
27
|
+
import { jsonThreatProtection } from "./policies/traffic/json-threat-protection";
|
|
28
|
+
import { rateLimit } from "./policies/traffic/rate-limit";
|
|
29
|
+
import { regexThreatProtection } from "./policies/traffic/regex-threat-protection";
|
|
30
|
+
import { requestLimit } from "./policies/traffic/request-limit";
|
|
31
|
+
import { resourceFilter } from "./policies/traffic/resource-filter";
|
|
32
|
+
import { sslEnforce } from "./policies/traffic/ssl-enforce";
|
|
33
|
+
import { trafficShadow } from "./policies/traffic/traffic-shadow";
|
|
34
|
+
import {
|
|
35
|
+
circuitBreaker,
|
|
36
|
+
InMemoryCircuitBreakerStore
|
|
37
|
+
} from "./policies/resilience/circuit-breaker";
|
|
38
|
+
import { latencyInjection } from "./policies/resilience/latency-injection";
|
|
39
|
+
import { retry } from "./policies/resilience/retry";
|
|
40
|
+
import { timeout } from "./policies/resilience/timeout";
|
|
41
|
+
import { assignAttributes } from "./policies/transform/assign-attributes";
|
|
42
|
+
import { assignContent } from "./policies/transform/assign-content";
|
|
43
|
+
import { cors } from "./policies/transform/cors";
|
|
44
|
+
import { jsonValidation } from "./policies/transform/json-validation";
|
|
45
|
+
import { overrideMethod } from "./policies/transform/override-method";
|
|
46
|
+
import { requestValidation } from "./policies/transform/request-validation";
|
|
47
|
+
import {
|
|
48
|
+
requestTransform,
|
|
49
|
+
responseTransform
|
|
50
|
+
} from "./policies/transform/transform";
|
|
51
|
+
import { health } from "./core/health";
|
|
52
|
+
import { assignMetrics } from "./policies/observability/assign-metrics";
|
|
53
|
+
import { metricsReporter } from "./policies/observability/metrics-reporter";
|
|
54
|
+
import { requestLog } from "./policies/observability/request-log";
|
|
55
|
+
import { serverTiming } from "./policies/observability/server-timing";
|
|
56
|
+
import {
|
|
57
|
+
InMemoryMetricsCollector,
|
|
58
|
+
toPrometheusText
|
|
59
|
+
} from "./observability/metrics";
|
|
60
|
+
import {
|
|
61
|
+
ConsoleSpanExporter,
|
|
62
|
+
OTLPSpanExporter,
|
|
63
|
+
SemConv,
|
|
64
|
+
SpanBuilder
|
|
65
|
+
} from "./observability/tracing";
|
|
66
|
+
import {
|
|
67
|
+
createPolicyTestHarness,
|
|
68
|
+
definePolicy,
|
|
69
|
+
isDebugRequested,
|
|
70
|
+
isTraceRequested,
|
|
71
|
+
noopTraceReporter,
|
|
72
|
+
Priority,
|
|
73
|
+
policyDebug,
|
|
74
|
+
policyTrace,
|
|
75
|
+
resolveConfig,
|
|
76
|
+
safeCall,
|
|
77
|
+
setDebugHeader,
|
|
78
|
+
withSkip
|
|
79
|
+
} from "./policies/sdk";
|
|
80
|
+
import {
|
|
81
|
+
DEFAULT_IP_HEADERS,
|
|
82
|
+
extractClientIp
|
|
83
|
+
} from "./utils/ip";
|
|
84
|
+
import { timingSafeEqual } from "./utils/timing-safe";
|
|
85
|
+
export {
|
|
86
|
+
ConsoleSpanExporter,
|
|
87
|
+
DEFAULT_IP_HEADERS,
|
|
88
|
+
GatewayError,
|
|
89
|
+
InMemoryCacheStore,
|
|
90
|
+
InMemoryCircuitBreakerStore,
|
|
91
|
+
InMemoryMetricsCollector,
|
|
92
|
+
OTLPSpanExporter,
|
|
93
|
+
Priority,
|
|
94
|
+
SemConv,
|
|
95
|
+
SpanBuilder,
|
|
96
|
+
apiKeyAuth,
|
|
97
|
+
assignAttributes,
|
|
98
|
+
assignContent,
|
|
99
|
+
assignMetrics,
|
|
100
|
+
basicAuth,
|
|
101
|
+
cache,
|
|
102
|
+
circuitBreaker,
|
|
103
|
+
clearJwksCache,
|
|
104
|
+
cors,
|
|
105
|
+
createGateway,
|
|
106
|
+
createPolicyTestHarness,
|
|
107
|
+
defaultErrorResponse,
|
|
108
|
+
definePolicy,
|
|
109
|
+
dynamicRouting,
|
|
110
|
+
errorToResponse,
|
|
111
|
+
extractClientIp,
|
|
112
|
+
generateHttpSignature,
|
|
113
|
+
generateJwt,
|
|
114
|
+
geoIpFilter,
|
|
115
|
+
getGatewayContext,
|
|
116
|
+
health,
|
|
117
|
+
httpCallout,
|
|
118
|
+
interrupt,
|
|
119
|
+
ipFilter,
|
|
120
|
+
isDebugRequested,
|
|
121
|
+
isTraceRequested,
|
|
122
|
+
jsonThreatProtection,
|
|
123
|
+
jsonValidation,
|
|
124
|
+
jws,
|
|
125
|
+
jwtAuth,
|
|
126
|
+
latencyInjection,
|
|
127
|
+
metricsReporter,
|
|
128
|
+
mock,
|
|
129
|
+
noopTraceReporter,
|
|
130
|
+
oauth2,
|
|
131
|
+
overrideMethod,
|
|
132
|
+
policyDebug,
|
|
133
|
+
policyTrace,
|
|
134
|
+
proxy,
|
|
135
|
+
rateLimit,
|
|
136
|
+
rbac,
|
|
137
|
+
regexThreatProtection,
|
|
138
|
+
requestLimit,
|
|
139
|
+
requestLog,
|
|
140
|
+
requestTransform,
|
|
141
|
+
requestValidation,
|
|
142
|
+
resolveConfig,
|
|
143
|
+
resourceFilter,
|
|
144
|
+
responseTransform,
|
|
145
|
+
retry,
|
|
146
|
+
safeCall,
|
|
147
|
+
scope,
|
|
148
|
+
serverTiming,
|
|
149
|
+
setDebugHeader,
|
|
150
|
+
sslEnforce,
|
|
151
|
+
timeout,
|
|
152
|
+
timingSafeEqual,
|
|
153
|
+
toPrometheusText,
|
|
154
|
+
trafficShadow,
|
|
155
|
+
verifyHttpSignature,
|
|
156
|
+
withSkip
|
|
157
|
+
};
|
|
158
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Stoma - declarative API gateway as a TypeScript library.\n *\n * Built on Hono for Cloudflare Workers and edge runtimes. Define routes,\n * compose policies (auth, rate limiting, caching, transforms), and proxy\n * to upstream services - all from a single configuration object.\n *\n * @packageDocumentation\n *\n * @example\n * ```ts\n * import {\n * createGateway,\n * cors,\n * jwtAuth,\n * rateLimit,\n * cache,\n * requestLog,\n * health,\n * } from \"@vivero/stoma\";\n *\n * const gateway = createGateway({\n * name: \"my-api\",\n * basePath: \"/api\",\n * debug: env.DEBUG,\n * policies: [cors(), requestLog(), rateLimit({ max: 100 })],\n * routes: [\n * health(),\n * {\n * path: \"/users/*\",\n * pipeline: {\n * policies: [\n * jwtAuth({ secret: env.JWT_SECRET }),\n * cache({ ttlSeconds: 60 }),\n * ],\n * upstream: { type: \"url\", target: \"https://users.internal\" },\n * },\n * },\n * ],\n * });\n *\n * export default gateway.app;\n * ```\n */\n\n// ── Protocol - multi-runtime policy evaluation ──────────────────────────\n\nexport type {\n /** Set a cross-policy attribute in PolicyResult mutations. */\n AttributeMutation,\n /** Replace or clear the message body in PolicyResult mutations. */\n BodyMutation,\n /** Add, remove, or append a header in PolicyResult mutations. */\n HeaderMutation,\n /** A discrete modification (header, body, status, attribute) applied via PolicyResult. */\n Mutation,\n /** Allow processing to continue, optionally with mutations. */\n PolicyContinue,\n /** Runtime-facing evaluation context (no typed config - see PolicyEvalHandlerContext for typed version). */\n PolicyEvalContext,\n /** Protocol-agnostic policy evaluation entry point (onRequest, onResponse). */\n PolicyEvaluator,\n /** Short-circuit with a complete non-error response (cache hit, mock, redirect). */\n PolicyImmediateResponse,\n /** Protocol-agnostic view of what's being processed - constructed by each runtime. */\n PolicyInput,\n /** Reject the request with a structured error response. */\n PolicyReject,\n /** The outcome of a policy evaluation: continue, reject, or immediate-response. */\n PolicyResult,\n /** Lifecycle phase a policy participates in (request-headers, response-body, etc.). */\n ProcessingPhase,\n /** Identifies the protocol runtime (http, grpc, websocket). */\n ProtocolType,\n /** Modify the response status code in PolicyResult mutations. */\n StatusMutation,\n} from \"./core/protocol\";\n\n// ── Core ────────────────────────────────────────────────────────────────\n\n/** Standard JSON error response shape returned by all gateway errors. */\nexport type { ErrorResponse } from \"./core/errors\";\n/** Structured error with HTTP status, machine-readable code, and optional response headers. */\n/** Build a JSON Response from a GatewayError, merging custom headers and request ID. */\n/** Produce a generic 500 error response for unexpected (non-GatewayError) errors. */\nexport {\n defaultErrorResponse,\n errorToResponse,\n GatewayError,\n} from \"./core/errors\";\n/** Compile a declarative {@link GatewayConfig} into a Hono app with policy pipelines and upstream dispatch. */\nexport { createGateway } from \"./core/gateway\";\n/** Retrieve the {@link PolicyContext} (request ID, trace ID, timing) from a Hono context. */\nexport { getGatewayContext } from \"./core/pipeline\";\nexport type {\n /** Configuration for a route scope: prefix, shared policies, child routes, and metadata. */\n ScopeConfig,\n} from \"./core/scope\";\n/** Group routes under a shared path prefix with shared policies and metadata. */\nexport { scope } from \"./core/scope\";\nexport type {\n /** Admin introspection API configuration (auth, prefix, metrics collector). */\n AdminConfig,\n /** Configuration for client-requested debug headers (request header name, allowlist). */\n DebugHeadersConfig,\n /** Top-level gateway configuration: routes, global policies, error handling, debug, and adapter. */\n GatewayConfig,\n /** The instantiated gateway: a configured Hono app, route count, name, and internal registry. */\n GatewayInstance,\n /** Internal registry of all routes and policies, used by the admin introspection API. */\n GatewayRegistry,\n /** Invoke a custom handler function directly (no upstream proxy). */\n HandlerUpstream,\n /** HTTP methods supported by gateway route registration. */\n HttpMethod,\n /** Pipeline definition: ordered policy chain leading to an upstream target. */\n PipelineConfig,\n /** Policy metadata (name + priority) recorded in the gateway registry. */\n RegisteredPolicy,\n /** Route metadata recorded in the gateway registry for admin introspection. */\n RegisteredRoute,\n /** Individual route definition: path, methods, and pipeline (policies + upstream). */\n RouteConfig,\n /** Forward to a Cloudflare Worker via a named Service Binding. */\n ServiceBindingUpstream,\n /** Discriminated union of upstream types: URL proxy, Service Binding, or custom handler. */\n UpstreamConfig,\n /** Proxy to a remote URL with optional path rewriting and header overrides. */\n UrlUpstream,\n} from \"./core/types\";\n\n// ── Policies - root-level ───────────────────────────────────────────────\n\n/** Return a static mock response, bypassing the upstream entirely (priority 999). */\nexport { mock } from \"./policies/mock\";\n/** Per-route header manipulation, timeout control, and Host header preservation (priority 95). */\nexport { proxy } from \"./policies/proxy\";\n\n// ── Policies - auth ─────────────────────────────────────────────────────\n\n/** Validate API keys from headers or query parameters using a custom validator function (priority 10). */\nexport { apiKeyAuth } from \"./policies/auth/api-key-auth\";\n/** Validate HTTP Basic credentials with a custom validator and WWW-Authenticate challenge (priority 10). */\nexport { basicAuth } from \"./policies/auth/basic-auth\";\n/** Clear the shared JWKS cache used by jwt-auth and jws. Intended for testing. */\nexport { clearJwksCache } from \"./policies/auth/crypto\";\n/** Generate RFC 9421 HTTP Message Signatures on outbound requests (priority 95). */\nexport { generateHttpSignature } from \"./policies/auth/generate-http-signature\";\n/** Mint JWTs (HMAC or RSA) and attach them to outgoing requests for upstream consumption (priority 50). */\nexport { generateJwt } from \"./policies/auth/generate-jwt\";\n/** Verify JWS compact serialization signatures - embedded or detached payloads, HMAC or JWKS (priority 10). */\nexport { jws } from \"./policies/auth/jws\";\n/** Validate JWT bearer tokens via HMAC secret or JWKS endpoint, with optional claim forwarding (priority 10). */\nexport { jwtAuth } from \"./policies/auth/jwt-auth\";\n/** Validate OAuth2 tokens via RFC 7662 introspection or a local validation function (priority 10). */\nexport { oauth2 } from \"./policies/auth/oauth2\";\n/** Role-based access control using claims forwarded as request headers by auth policies (priority 10). */\nexport { rbac } from \"./policies/auth/rbac\";\n\n/** Verify RFC 9421 HTTP Message Signatures on inbound requests with key ID lookup (priority 10). */\nexport { verifyHttpSignature } from \"./policies/auth/verify-http-signature\";\n\n// ── Policies - traffic ──────────────────────────────────────────────────\n\n/** Response caching with pluggable storage, TTL, and automatic cache-control headers (priority 40). */\nexport { cache, InMemoryCacheStore } from \"./policies/traffic/cache\";\n/** Evaluate ordered routing rules and expose the first match on context for downstream consumption (priority 50). */\nexport { dynamicRouting } from \"./policies/traffic/dynamic-routing\";\n\n/** Block or allow requests by geographic country code from a configurable header (priority 1). */\nexport { geoIpFilter } from \"./policies/traffic/geo-ip-filter\";\n/** Make an external HTTP call mid-pipeline for authorization, enrichment, or webhook notification (priority 50). */\nexport { httpCallout } from \"./policies/traffic/http-callout\";\n/** Conditionally short-circuit the pipeline and return a static response based on a predicate (priority 100). */\nexport { interrupt } from \"./policies/traffic/interrupt\";\n/** Block or allow requests by client IP address or CIDR range in allowlist/denylist mode (priority 1). */\nexport { ipFilter } from \"./policies/traffic/ip-filter\";\n\n/** Enforce structural limits on JSON request bodies - depth, key count, string length, array size (priority 5). */\nexport { jsonThreatProtection } from \"./policies/traffic/json-threat-protection\";\n/** Sliding-window rate limiting with pluggable counter storage and configurable key extraction (priority 20). */\nexport { rateLimit } from \"./policies/traffic/rate-limit\";\n/** Block requests matching regex patterns (SQL injection, XSS, etc.) in path, query, headers, or body (priority 5). */\nexport { regexThreatProtection } from \"./policies/traffic/regex-threat-protection\";\n/** Reject requests whose Content-Length exceeds a byte limit (priority 5). */\nexport { requestLimit } from \"./policies/traffic/request-limit\";\n/** Strip or allow fields from JSON responses using dot-notation paths in allow/deny mode (priority 92). */\nexport { resourceFilter } from \"./policies/traffic/resource-filter\";\n/** Enforce HTTPS with optional redirect (301) and HSTS header injection (priority 5). */\nexport { sslEnforce } from \"./policies/traffic/ssl-enforce\";\n/** Mirror a percentage of traffic to a secondary upstream without affecting the primary response (priority 92). */\nexport { trafficShadow } from \"./policies/traffic/traffic-shadow\";\n\n// ── Policies - resilience ───────────────────────────────────────────────\n\n/** Three-state circuit breaker (closed/open/half-open) with pluggable state storage (priority 30). */\nexport {\n circuitBreaker,\n InMemoryCircuitBreakerStore,\n} from \"./policies/resilience/circuit-breaker\";\n/** Inject artificial latency for chaos/resilience testing with jitter and probability controls (priority 5). */\nexport { latencyInjection } from \"./policies/resilience/latency-injection\";\n/** Retry failed upstream calls with exponential or fixed backoff, jitter, and method filtering (priority 90). */\nexport { retry } from \"./policies/resilience/retry\";\n/** Enforce a response time budget - races downstream execution against a configurable timer (priority 85). */\nexport { timeout } from \"./policies/resilience/timeout\";\n\n// ── Policies - transform ────────────────────────────────────────────────\n\n/** Set key-value attributes on the Hono request context for downstream middleware consumption (priority 50). */\nexport { assignAttributes } from \"./policies/transform/assign-attributes\";\n/** Inject or override fields in JSON request and/or response bodies with static or dynamic values (priority 50). */\nexport { assignContent } from \"./policies/transform/assign-content\";\n/** Add CORS headers to responses, wrapping Hono's built-in CORS middleware as a composable policy (priority 5). */\nexport { cors } from \"./policies/transform/cors\";\n/** Pluggable JSON body validation - wrap Zod, AJV, or any validator; falls back to JSON parse check (priority 10). */\nexport { jsonValidation } from \"./policies/transform/json-validation\";\n/** Override the HTTP method of POST requests via a configurable header (priority 5). */\nexport { overrideMethod } from \"./policies/transform/override-method\";\n\n/** Pluggable request body validation using a user-provided sync or async function (priority 10). */\nexport { requestValidation } from \"./policies/transform/request-validation\";\n/** Modify request headers (set/remove/rename) before the upstream call (priority 50). */\nexport {\n requestTransform,\n /** Modify response headers (set/remove/rename) after the upstream responds (priority 92). */\n responseTransform,\n} from \"./policies/transform/transform\";\n\n// ── Policies - observability ────────────────────────────────────────────\n\n/** Create a health check route with optional upstream probing (returns a RouteConfig, not a Policy). */\nexport { health } from \"./core/health\";\n/** Attach metric tags/dimensions to the request context for consumption by metricsReporter (priority 0). */\nexport { assignMetrics } from \"./policies/observability/assign-metrics\";\n/** Record request counts, latencies, and errors to a pluggable {@link MetricsCollector} (priority 1). */\nexport { metricsReporter } from \"./policies/observability/metrics-reporter\";\n/** Structured JSON request logging with W3C trace context, body capture, and field redaction (priority 0). */\nexport { requestLog } from \"./policies/observability/request-log\";\n/** Emit W3C Server-Timing and X-Response-Time response headers with per-policy breakdown (priority 1). */\nexport { serverTiming } from \"./policies/observability/server-timing\";\n\n// ── Observability ───────────────────────────────────────────────────────\n\n/** In-memory metrics collector for testing and development. */\nexport {\n InMemoryMetricsCollector,\n /** Serialize a {@link MetricsSnapshot} to Prometheus text exposition format. */\n toPrometheusText,\n} from \"./observability/metrics\";\nexport type {\n /** An immutable representation of a completed span. */\n ReadableSpan,\n /** A timestamped event recorded during a span's lifetime. */\n SpanEvent,\n /** Pluggable span exporter interface. */\n SpanExporter,\n /** Span kind: SERVER, CLIENT, or INTERNAL. */\n SpanKind,\n /** Span status code: UNSET, OK, or ERROR. */\n SpanStatusCode,\n /** Configuration for gateway-level tracing. */\n TracingConfig,\n} from \"./observability/tracing\";\n/** Console span exporter for development and debugging. */\nexport {\n ConsoleSpanExporter,\n /** OTLP/HTTP JSON span exporter for OpenTelemetry Collectors. */\n OTLPSpanExporter,\n /** OTel semantic convention attribute keys (HTTP subset). */\n SemConv,\n /** Mutable span builder - accumulates attributes, events, and status during a request lifecycle. */\n SpanBuilder,\n} from \"./observability/tracing\";\n\n// ── Policy SDK - shared primitives for built-in and custom policies ─────\n\nexport type {\n /** Declarative policy definition passed to {@link definePolicy}. */\n PolicyDefinition,\n /** Context injected into `definePolicy` evaluate handlers (protocol-agnostic, with typed config). */\n PolicyEvalHandlerContext,\n /** Conditional factory type - config required when TConfig has required keys. */\n PolicyFactory,\n /** Context injected into `definePolicy` handlers: merged config, debug logger, and gateway context. */\n PolicyHandlerContext,\n /** Options for {@link createPolicyTestHarness}: custom upstream, path, gateway name, adapter. */\n PolicyTestHarnessOptions,\n /** Full trace payload emitted as `x-stoma-trace`. */\n PolicyTrace,\n /** Policy-reported trace detail. */\n PolicyTraceDetail,\n /** Combined trace entry (baseline + detail). */\n PolicyTraceEntry,\n /** Union of all named priority level values. */\n PriorityLevel,\n /** Trace reporter function type. */\n TraceReporter,\n} from \"./policies/sdk\";\nexport {\n /** Create a minimal test harness for a policy with error handling, context injection, and configurable upstream. */\n createPolicyTestHarness,\n /** Create a policy factory from a declarative definition - combines resolveConfig, policyDebug, and withSkip. */\n definePolicy,\n /** Check whether the client requested debug output via the `x-stoma-debug` header. */\n isDebugRequested,\n /** Fast-path check: is tracing requested for this request? */\n isTraceRequested,\n /** Shared no-op trace reporter instance. */\n noopTraceReporter,\n /** Named priority constants (OBSERVABILITY, AUTH, RATE_LIMIT, etc.) for policy ordering. */\n Priority,\n /** Get a debug logger pre-namespaced to `stoma:policy:{name}` from the gateway context. */\n policyDebug,\n /** Get a trace reporter for a specific policy - always callable, no-op when not tracing. */\n policyTrace,\n /** Shallow-merge default config values with user-provided config. */\n resolveConfig,\n /** Execute an async operation with graceful error handling - returns a fallback value on failure. */\n safeCall,\n /** Set a debug header value for client-requested debug output. */\n setDebugHeader,\n /** Wrap a middleware handler with `PolicyConfig.skip` conditional bypass logic. */\n withSkip,\n} from \"./policies/sdk\";\n\n// ── Debug ───────────────────────────────────────────────────────────────\n\n/** A debug logging function - call with a message and optional structured data. */\nexport type { DebugLogger } from \"./utils/debug\";\n\n// ── Utilities ───────────────────────────────────────────────────────────\n\n/** Extract the client IP from request headers using a configurable header priority list. */\nexport {\n /** Default ordered list of headers inspected for client IP (`cf-connecting-ip`, `x-forwarded-for`). */\n DEFAULT_IP_HEADERS,\n extractClientIp,\n} from \"./utils/ip\";\n\n/** Constant-time string comparison for secrets and API keys - prevents timing side-channel attacks. */\nexport { timingSafeEqual } from \"./utils/timing-safe\";\n\n// ── Types ───────────────────────────────────────────────────────────────\n\n/** Runtime adapter providing store implementations and platform-specific capabilities. */\nexport type { GatewayAdapter } from \"./adapters/types\";\n\nexport type {\n /** A histogram data point with accumulated numeric values. */\n HistogramEntry,\n /** Pluggable metrics collector interface - increment counters, record histograms, set gauges. */\n MetricsCollector,\n /** Point-in-time snapshot of all collected metrics (counters, histograms, gauges). */\n MetricsSnapshot,\n /** A single tagged metric data point with a numeric value. */\n TaggedValue,\n} from \"./observability/metrics\";\n\n/** Configuration for the {@link metricsReporter} policy. */\nexport type { MetricsReporterConfig } from \"./policies/observability/metrics-reporter\";\n\n/** Configuration for the {@link serverTiming} policy. */\nexport type {\n ServerTimingConfig,\n /** Visibility mode for the serverTiming policy. */\n ServerTimingVisibility,\n} from \"./policies/observability/server-timing\";\nexport type {\n /** Point-in-time snapshot of a circuit's state, failure/success counts, and timestamps. */\n CircuitBreakerSnapshot,\n /** Pluggable storage backend for circuit breaker state. */\n CircuitBreakerStore,\n /** The three circuit breaker states: `\"closed\"`, `\"open\"`, `\"half-open\"`. */\n CircuitState,\n} from \"./policies/resilience/circuit-breaker\";\n/** Pluggable cache storage backend - get, put, and delete cached responses. */\nexport type {\n CacheStore,\n InMemoryCacheStoreOptions,\n} from \"./policies/traffic/cache\";\n/** Pluggable storage backend for rate limit counters. */\nexport type {\n /** Options for the built-in in-memory rate limit store (max keys, cleanup interval). */\n InMemoryRateLimitStoreOptions,\n RateLimitStore,\n} from \"./policies/traffic/rate-limit\";\nexport type {\n /** A composable policy: name, priority, and Hono middleware handler. */\n Policy,\n /** Base configuration interface for all policies - includes the `skip` conditional bypass. */\n PolicyConfig,\n /** Per-request gateway context: request ID, trace ID, span ID, timing, debug factory, and adapter. */\n PolicyContext,\n} from \"./policies/types\";\n"],"mappings":"AAqFA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,qBAAqB;AAE9B,SAAS,yBAAyB;AAMlC,SAAS,aAAa;AAmCtB,SAAS,YAAY;AAErB,SAAS,aAAa;AAKtB,SAAS,kBAAkB;AAE3B,SAAS,iBAAiB;AAE1B,SAAS,sBAAsB;AAE/B,SAAS,6BAA6B;AAEtC,SAAS,mBAAmB;AAE5B,SAAS,WAAW;AAEpB,SAAS,eAAe;AAExB,SAAS,cAAc;AAEvB,SAAS,YAAY;AAGrB,SAAS,2BAA2B;AAKpC,SAAS,OAAO,0BAA0B;AAE1C,SAAS,sBAAsB;AAG/B,SAAS,mBAAmB;AAE5B,SAAS,mBAAmB;AAE5B,SAAS,iBAAiB;AAE1B,SAAS,gBAAgB;AAGzB,SAAS,4BAA4B;AAErC,SAAS,iBAAiB;AAE1B,SAAS,6BAA6B;AAEtC,SAAS,oBAAoB;AAE7B,SAAS,sBAAsB;AAE/B,SAAS,kBAAkB;AAE3B,SAAS,qBAAqB;AAK9B;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEP,SAAS,wBAAwB;AAEjC,SAAS,aAAa;AAEtB,SAAS,eAAe;AAKxB,SAAS,wBAAwB;AAEjC,SAAS,qBAAqB;AAE9B,SAAS,YAAY;AAErB,SAAS,sBAAsB;AAE/B,SAAS,sBAAsB;AAG/B,SAAS,yBAAyB;AAElC;AAAA,EACE;AAAA,EAEA;AAAA,OACK;AAKP,SAAS,cAAc;AAEvB,SAAS,qBAAqB;AAE9B,SAAS,uBAAuB;AAEhC,SAAS,kBAAkB;AAE3B,SAAS,oBAAoB;AAK7B;AAAA,EACE;AAAA,EAEA;AAAA,OACK;AAgBP;AAAA,EACE;AAAA,EAEA;AAAA,EAEA;AAAA,EAEA;AAAA,OACK;AA0BP;AAAA,EAEE;AAAA,EAEA;AAAA,EAEA;AAAA,EAEA;AAAA,EAEA;AAAA,EAEA;AAAA,EAEA;AAAA,EAEA;AAAA,EAEA;AAAA,EAEA;AAAA,EAEA;AAAA,EAEA;AAAA,OACK;AAUP;AAAA,EAEE;AAAA,EACA;AAAA,OACK;AAGP,SAAS,uBAAuB;","names":[]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import { AdminConfig, GatewayRegistry } from '../core/types.js';
|
|
3
|
+
import '../protocol-2fD3DJrL.js';
|
|
4
|
+
import '../policies/sdk/trace.js';
|
|
5
|
+
import '@vivero/stoma-core';
|
|
6
|
+
import './metrics.js';
|
|
7
|
+
import './tracing.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Admin introspection API - auto-registered `___gateway/*` routes.
|
|
11
|
+
*
|
|
12
|
+
* Exposes gateway internals for operational visibility: registered routes,
|
|
13
|
+
* active policies, redacted config, Prometheus metrics, and health status.
|
|
14
|
+
*
|
|
15
|
+
* @module admin
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Register admin introspection routes on the Hono app.
|
|
20
|
+
*
|
|
21
|
+
* @param app - The Hono app to register routes on.
|
|
22
|
+
* @param config - Admin configuration (auth, prefix, metrics).
|
|
23
|
+
* @param registry - The gateway registry containing route and policy data.
|
|
24
|
+
*/
|
|
25
|
+
declare function registerAdminRoutes(app: Hono, config: AdminConfig, registry: GatewayRegistry): void;
|
|
26
|
+
/**
|
|
27
|
+
* Redact values of keys that look like secrets in a config object.
|
|
28
|
+
* Used internally by the `/config` endpoint.
|
|
29
|
+
*/
|
|
30
|
+
declare function redactConfig(obj: unknown): unknown;
|
|
31
|
+
|
|
32
|
+
export { redactConfig, registerAdminRoutes };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { toPrometheusText } from "./metrics";
|
|
2
|
+
const SECRET_PATTERNS = ["secret", "key", "token", "password", "credential"];
|
|
3
|
+
function registerAdminRoutes(app, config, registry) {
|
|
4
|
+
const prefix = `/${config.prefix ?? "___gateway"}`;
|
|
5
|
+
const authMiddleware = async (c, next) => {
|
|
6
|
+
if (config.auth) {
|
|
7
|
+
const allowed = await config.auth(c);
|
|
8
|
+
if (!allowed) {
|
|
9
|
+
return c.json(
|
|
10
|
+
{ error: "unauthorized", message: "Admin access denied" },
|
|
11
|
+
403
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
await next();
|
|
16
|
+
};
|
|
17
|
+
app.get(`${prefix}/routes`, authMiddleware, (c) => {
|
|
18
|
+
return c.json({
|
|
19
|
+
gateway: registry.gatewayName,
|
|
20
|
+
routes: registry.routes
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
app.get(`${prefix}/policies`, authMiddleware, (c) => {
|
|
24
|
+
return c.json({
|
|
25
|
+
gateway: registry.gatewayName,
|
|
26
|
+
policies: registry.policies
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
app.get(`${prefix}/config`, authMiddleware, (c) => {
|
|
30
|
+
return c.json(
|
|
31
|
+
redactConfig({
|
|
32
|
+
gateway: registry.gatewayName,
|
|
33
|
+
routes: registry.routes,
|
|
34
|
+
policies: registry.policies
|
|
35
|
+
})
|
|
36
|
+
);
|
|
37
|
+
});
|
|
38
|
+
app.get(`${prefix}/metrics`, authMiddleware, (c) => {
|
|
39
|
+
if (!config.metrics) {
|
|
40
|
+
return c.json(
|
|
41
|
+
{
|
|
42
|
+
error: "not_configured",
|
|
43
|
+
message: "No metrics collector configured. Pass a MetricsCollector to admin.metrics."
|
|
44
|
+
},
|
|
45
|
+
404
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
const snapshot = config.metrics.snapshot();
|
|
49
|
+
const text = toPrometheusText(snapshot);
|
|
50
|
+
return c.text(text, 200, {
|
|
51
|
+
"content-type": "text/plain; version=0.0.4; charset=utf-8"
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
app.get(`${prefix}/health`, authMiddleware, (c) => {
|
|
55
|
+
return c.json({
|
|
56
|
+
status: "healthy",
|
|
57
|
+
gateway: registry.gatewayName,
|
|
58
|
+
routeCount: registry.routes.length,
|
|
59
|
+
policyCount: registry.policies.length,
|
|
60
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function redactConfig(obj) {
|
|
65
|
+
if (typeof obj !== "object" || obj === null) return obj;
|
|
66
|
+
if (Array.isArray(obj)) return obj.map(redactConfig);
|
|
67
|
+
const result = {};
|
|
68
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
69
|
+
if (SECRET_PATTERNS.some((p) => key.toLowerCase().includes(p))) {
|
|
70
|
+
result[key] = "[REDACTED]";
|
|
71
|
+
} else if (typeof value === "function") {
|
|
72
|
+
result[key] = "[Function]";
|
|
73
|
+
} else if (typeof value === "object" && value !== null) {
|
|
74
|
+
result[key] = redactConfig(value);
|
|
75
|
+
} else {
|
|
76
|
+
result[key] = value;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
export {
|
|
82
|
+
redactConfig,
|
|
83
|
+
registerAdminRoutes
|
|
84
|
+
};
|
|
85
|
+
//# sourceMappingURL=admin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/observability/admin.ts"],"sourcesContent":["/**\n * Admin introspection API - auto-registered `___gateway/*` routes.\n *\n * Exposes gateway internals for operational visibility: registered routes,\n * active policies, redacted config, Prometheus metrics, and health status.\n *\n * @module admin\n */\nimport type { Context, Hono } from \"hono\";\nimport type { AdminConfig, GatewayRegistry } from \"../core/types\";\nimport { toPrometheusText } from \"./metrics\";\n\n/** Secret-like keys that should be redacted in config output. */\nconst SECRET_PATTERNS = [\"secret\", \"key\", \"token\", \"password\", \"credential\"];\n\n/**\n * Register admin introspection routes on the Hono app.\n *\n * @param app - The Hono app to register routes on.\n * @param config - Admin configuration (auth, prefix, metrics).\n * @param registry - The gateway registry containing route and policy data.\n */\nexport function registerAdminRoutes(\n app: Hono,\n config: AdminConfig,\n registry: GatewayRegistry\n): void {\n const prefix = `/${config.prefix ?? \"___gateway\"}`;\n\n // Auth middleware for all admin routes\n const authMiddleware = async (c: Context, next: () => Promise<void>) => {\n if (config.auth) {\n const allowed = await config.auth(c);\n if (!allowed) {\n return c.json(\n { error: \"unauthorized\", message: \"Admin access denied\" },\n 403\n );\n }\n }\n await next();\n };\n\n // GET /___gateway/routes - list all registered routes\n app.get(`${prefix}/routes`, authMiddleware, (c) => {\n return c.json({\n gateway: registry.gatewayName,\n routes: registry.routes,\n });\n });\n\n // GET /___gateway/policies - list all unique policies with priority\n app.get(`${prefix}/policies`, authMiddleware, (c) => {\n return c.json({\n gateway: registry.gatewayName,\n policies: registry.policies,\n });\n });\n\n // GET /___gateway/config - serialized config with secrets redacted\n app.get(`${prefix}/config`, authMiddleware, (c) => {\n return c.json(\n redactConfig({\n gateway: registry.gatewayName,\n routes: registry.routes,\n policies: registry.policies,\n })\n );\n });\n\n // GET /___gateway/metrics - Prometheus text format\n app.get(`${prefix}/metrics`, authMiddleware, (c) => {\n if (!config.metrics) {\n return c.json(\n {\n error: \"not_configured\",\n message:\n \"No metrics collector configured. Pass a MetricsCollector to admin.metrics.\",\n },\n 404\n );\n }\n\n const snapshot = config.metrics.snapshot();\n const text = toPrometheusText(snapshot);\n return c.text(text, 200, {\n \"content-type\": \"text/plain; version=0.0.4; charset=utf-8\",\n });\n });\n\n // GET /___gateway/health - basic health check\n app.get(`${prefix}/health`, authMiddleware, (c) => {\n return c.json({\n status: \"healthy\",\n gateway: registry.gatewayName,\n routeCount: registry.routes.length,\n policyCount: registry.policies.length,\n timestamp: new Date().toISOString(),\n });\n });\n}\n\n/**\n * Redact values of keys that look like secrets in a config object.\n * Used internally by the `/config` endpoint.\n */\nexport function redactConfig(obj: unknown): unknown {\n if (typeof obj !== \"object\" || obj === null) return obj;\n if (Array.isArray(obj)) return obj.map(redactConfig);\n\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n if (SECRET_PATTERNS.some((p) => key.toLowerCase().includes(p))) {\n result[key] = \"[REDACTED]\";\n } else if (typeof value === \"function\") {\n result[key] = \"[Function]\";\n } else if (typeof value === \"object\" && value !== null) {\n result[key] = redactConfig(value);\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n"],"mappings":"AAUA,SAAS,wBAAwB;AAGjC,MAAM,kBAAkB,CAAC,UAAU,OAAO,SAAS,YAAY,YAAY;AASpE,SAAS,oBACd,KACA,QACA,UACM;AACN,QAAM,SAAS,IAAI,OAAO,UAAU,YAAY;AAGhD,QAAM,iBAAiB,OAAO,GAAY,SAA8B;AACtE,QAAI,OAAO,MAAM;AACf,YAAM,UAAU,MAAM,OAAO,KAAK,CAAC;AACnC,UAAI,CAAC,SAAS;AACZ,eAAO,EAAE;AAAA,UACP,EAAE,OAAO,gBAAgB,SAAS,sBAAsB;AAAA,UACxD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,UAAM,KAAK;AAAA,EACb;AAGA,MAAI,IAAI,GAAG,MAAM,WAAW,gBAAgB,CAAC,MAAM;AACjD,WAAO,EAAE,KAAK;AAAA,MACZ,SAAS,SAAS;AAAA,MAClB,QAAQ,SAAS;AAAA,IACnB,CAAC;AAAA,EACH,CAAC;AAGD,MAAI,IAAI,GAAG,MAAM,aAAa,gBAAgB,CAAC,MAAM;AACnD,WAAO,EAAE,KAAK;AAAA,MACZ,SAAS,SAAS;AAAA,MAClB,UAAU,SAAS;AAAA,IACrB,CAAC;AAAA,EACH,CAAC;AAGD,MAAI,IAAI,GAAG,MAAM,WAAW,gBAAgB,CAAC,MAAM;AACjD,WAAO,EAAE;AAAA,MACP,aAAa;AAAA,QACX,SAAS,SAAS;AAAA,QAClB,QAAQ,SAAS;AAAA,QACjB,UAAU,SAAS;AAAA,MACrB,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAGD,MAAI,IAAI,GAAG,MAAM,YAAY,gBAAgB,CAAC,MAAM;AAClD,QAAI,CAAC,OAAO,SAAS;AACnB,aAAO,EAAE;AAAA,QACP;AAAA,UACE,OAAO;AAAA,UACP,SACE;AAAA,QACJ;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,WAAW,OAAO,QAAQ,SAAS;AACzC,UAAM,OAAO,iBAAiB,QAAQ;AACtC,WAAO,EAAE,KAAK,MAAM,KAAK;AAAA,MACvB,gBAAgB;AAAA,IAClB,CAAC;AAAA,EACH,CAAC;AAGD,MAAI,IAAI,GAAG,MAAM,WAAW,gBAAgB,CAAC,MAAM;AACjD,WAAO,EAAE,KAAK;AAAA,MACZ,QAAQ;AAAA,MACR,SAAS,SAAS;AAAA,MAClB,YAAY,SAAS,OAAO;AAAA,MAC5B,aAAa,SAAS,SAAS;AAAA,MAC/B,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC,CAAC;AAAA,EACH,CAAC;AACH;AAMO,SAAS,aAAa,KAAuB;AAClD,MAAI,OAAO,QAAQ,YAAY,QAAQ,KAAM,QAAO;AACpD,MAAI,MAAM,QAAQ,GAAG,EAAG,QAAO,IAAI,IAAI,YAAY;AAEnD,QAAM,SAAkC,CAAC;AACzC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAA8B,GAAG;AACzE,QAAI,gBAAgB,KAAK,CAAC,MAAM,IAAI,YAAY,EAAE,SAAS,CAAC,CAAC,GAAG;AAC9D,aAAO,GAAG,IAAI;AAAA,IAChB,WAAW,OAAO,UAAU,YAAY;AACtC,aAAO,GAAG,IAAI;AAAA,IAChB,WAAW,OAAO,UAAU,YAAY,UAAU,MAAM;AACtD,aAAO,GAAG,IAAI,aAAa,KAAK;AAAA,IAClC,OAAO;AACL,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
|