@databehave/server 0.1.0
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 +28 -0
- package/LICENSE +21 -0
- package/README.md +87 -0
- package/dist/admin/admin-routes.d.ts +42 -0
- package/dist/admin/admin-routes.d.ts.map +1 -0
- package/dist/admin/admin-routes.js +472 -0
- package/dist/admin/admin-routes.js.map +1 -0
- package/dist/admin/admin-types.d.ts +170 -0
- package/dist/admin/admin-types.d.ts.map +1 -0
- package/dist/admin/admin-types.js +30 -0
- package/dist/admin/admin-types.js.map +1 -0
- package/dist/admin/banner.d.ts +11 -0
- package/dist/admin/banner.d.ts.map +1 -0
- package/dist/admin/banner.js +5 -0
- package/dist/admin/banner.js.map +1 -0
- package/dist/admin/header-parser.d.ts +14 -0
- package/dist/admin/header-parser.d.ts.map +1 -0
- package/dist/admin/header-parser.js +171 -0
- package/dist/admin/header-parser.js.map +1 -0
- package/dist/admin/inject.d.ts +48 -0
- package/dist/admin/inject.d.ts.map +1 -0
- package/dist/admin/inject.js +167 -0
- package/dist/admin/inject.js.map +1 -0
- package/dist/admin/overrides-store.d.ts +18 -0
- package/dist/admin/overrides-store.d.ts.map +1 -0
- package/dist/admin/overrides-store.js +100 -0
- package/dist/admin/overrides-store.js.map +1 -0
- package/dist/admin/resolve-cors.d.ts +22 -0
- package/dist/admin/resolve-cors.d.ts.map +1 -0
- package/dist/admin/resolve-cors.js +28 -0
- package/dist/admin/resolve-cors.js.map +1 -0
- package/dist/admin/scenarios-store.d.ts +15 -0
- package/dist/admin/scenarios-store.d.ts.map +1 -0
- package/dist/admin/scenarios-store.js +109 -0
- package/dist/admin/scenarios-store.js.map +1 -0
- package/dist/admin/ui.css +2 -0
- package/dist/admin/ui.html +13 -0
- package/dist/admin/ui.js +240 -0
- package/dist/bin-helpers.d.ts +46 -0
- package/dist/bin-helpers.d.ts.map +1 -0
- package/dist/bin-helpers.js +61 -0
- package/dist/bin-helpers.js.map +1 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +57 -0
- package/dist/bin.js.map +1 -0
- package/dist/cors.d.ts +57 -0
- package/dist/cors.d.ts.map +1 -0
- package/dist/cors.js +167 -0
- package/dist/cors.js.map +1 -0
- package/dist/define.d.ts +26 -0
- package/dist/define.d.ts.map +1 -0
- package/dist/define.js +55 -0
- package/dist/define.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/json-config.d.ts +170 -0
- package/dist/json-config.d.ts.map +1 -0
- package/dist/json-config.js +684 -0
- package/dist/json-config.js.map +1 -0
- package/dist/jsonc.d.ts +24 -0
- package/dist/jsonc.d.ts.map +1 -0
- package/dist/jsonc.js +125 -0
- package/dist/jsonc.js.map +1 -0
- package/dist/log.d.ts +57 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +103 -0
- package/dist/log.js.map +1 -0
- package/dist/middleware/request-validation.d.ts +58 -0
- package/dist/middleware/request-validation.d.ts.map +1 -0
- package/dist/middleware/request-validation.js +328 -0
- package/dist/middleware/request-validation.js.map +1 -0
- package/dist/mock-mode.d.ts +95 -0
- package/dist/mock-mode.d.ts.map +1 -0
- package/dist/mock-mode.js +95 -0
- package/dist/mock-mode.js.map +1 -0
- package/dist/openapi/auto-schema.d.ts +83 -0
- package/dist/openapi/auto-schema.d.ts.map +1 -0
- package/dist/openapi/auto-schema.js +232 -0
- package/dist/openapi/auto-schema.js.map +1 -0
- package/dist/openapi/generate.d.ts +20 -0
- package/dist/openapi/generate.d.ts.map +1 -0
- package/dist/openapi/generate.js +121 -0
- package/dist/openapi/generate.js.map +1 -0
- package/dist/openapi/loader.d.ts +18 -0
- package/dist/openapi/loader.d.ts.map +1 -0
- package/dist/openapi/loader.js +25 -0
- package/dist/openapi/loader.js.map +1 -0
- package/dist/openapi/register.d.ts +58 -0
- package/dist/openapi/register.d.ts.map +1 -0
- package/dist/openapi/register.js +166 -0
- package/dist/openapi/register.js.map +1 -0
- package/dist/openapi/seed.d.ts +16 -0
- package/dist/openapi/seed.d.ts.map +1 -0
- package/dist/openapi/seed.js +58 -0
- package/dist/openapi/seed.js.map +1 -0
- package/dist/openapi/translate.d.ts +55 -0
- package/dist/openapi/translate.d.ts.map +1 -0
- package/dist/openapi/translate.js +319 -0
- package/dist/openapi/translate.js.map +1 -0
- package/dist/openapi/walker.d.ts +44 -0
- package/dist/openapi/walker.d.ts.map +1 -0
- package/dist/openapi/walker.js +15 -0
- package/dist/openapi/walker.js.map +1 -0
- package/dist/request.d.ts +19 -0
- package/dist/request.d.ts.map +1 -0
- package/dist/request.js +66 -0
- package/dist/request.js.map +1 -0
- package/dist/response.d.ts +13 -0
- package/dist/response.d.ts.map +1 -0
- package/dist/response.js +43 -0
- package/dist/response.js.map +1 -0
- package/dist/route-key.d.ts +60 -0
- package/dist/route-key.d.ts.map +1 -0
- package/dist/route-key.js +105 -0
- package/dist/route-key.js.map +1 -0
- package/dist/run.d.ts +27 -0
- package/dist/run.d.ts.map +1 -0
- package/dist/run.js +87 -0
- package/dist/run.js.map +1 -0
- package/dist/server.d.ts +60 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +497 -0
- package/dist/server.js.map +1 -0
- package/dist/types.d.ts +274 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/validation/validate.d.ts +38 -0
- package/dist/validation/validate.d.ts.map +1 -0
- package/dist/validation/validate.js +372 -0
- package/dist/validation/validate.js.map +1 -0
- package/docs/admin/error-mode.md +14 -0
- package/docs/admin/headers.md +63 -0
- package/docs/admin/index.md +111 -0
- package/docs/admin/overrides.md +23 -0
- package/docs/admin/rest-api.md +90 -0
- package/docs/admin/scenarios.md +28 -0
- package/docs/cli.md +76 -0
- package/docs/config/admin.md +62 -0
- package/docs/config/cors.md +72 -0
- package/docs/config/endpoints.md +162 -0
- package/docs/config/index.md +107 -0
- package/docs/config/log.md +43 -0
- package/docs/config/mock-mode.md +84 -0
- package/docs/config/openapi.md +8 -0
- package/docs/config/schema.md +34 -0
- package/docs/config/server.md +32 -0
- package/docs/config/validation.md +161 -0
- package/docs/design.md +517 -0
- package/docs/errors.md +192 -0
- package/docs/getting-started.md +146 -0
- package/docs/index.md +23 -0
- package/docs/openapi/auto-schema.md +146 -0
- package/docs/openapi/fallback.md +242 -0
- package/docs/openapi/keywords.md +78 -0
- package/docs/recipes.md +258 -0
- package/docs/stability.md +118 -0
- package/docs/troubleshooting.md +191 -0
- package/package.json +80 -0
package/dist/server.js
ADDED
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
import { createServer as createNodeHttpServer, } from 'node:http';
|
|
2
|
+
import { Readable } from 'node:stream';
|
|
3
|
+
import { createAdminRoutes } from './admin/admin-routes.js';
|
|
4
|
+
import { AdminDestroySocketSignal, } from './admin/admin-types.js';
|
|
5
|
+
import { emitAdminBanner } from './admin/banner.js';
|
|
6
|
+
import { createInjectHook, isDestroySocketSentinel } from './admin/inject.js';
|
|
7
|
+
import { createOverridesStore } from './admin/overrides-store.js';
|
|
8
|
+
import { resolveAdminCors } from './admin/resolve-cors.js';
|
|
9
|
+
import { createScenariosStore } from './admin/scenarios-store.js';
|
|
10
|
+
import { buildCorsResponseHeaders, buildPreflightResponse, mergeVary } from './cors.js';
|
|
11
|
+
import { createAccessLogger } from './log.js';
|
|
12
|
+
import { createRequestValidationContext, validateRequest, } from './middleware/request-validation.js';
|
|
13
|
+
import { parseOpenApi } from './openapi/loader.js';
|
|
14
|
+
import { buildOpenApiRoutes } from './openapi/register.js';
|
|
15
|
+
import { buildRequest } from './request.js';
|
|
16
|
+
import { buildResponse } from './response.js';
|
|
17
|
+
import { matchPattern, parseRouteKey, parseRoutePattern } from './route-key.js';
|
|
18
|
+
const LOOPBACK_HOSTS = new Set(['127.0.0.1', '::1', 'localhost']);
|
|
19
|
+
/**
|
|
20
|
+
* Resolve admin config defaults + validate inputs that don't
|
|
21
|
+
* depend on listen() host. Returns `null` when admin is absent or
|
|
22
|
+
* `enabled !== true`. Pure — no side effects.
|
|
23
|
+
*/
|
|
24
|
+
export const resolveAdminMode = (cfg) => {
|
|
25
|
+
if (!cfg || cfg.enabled !== true)
|
|
26
|
+
return null;
|
|
27
|
+
const path = cfg.path ?? '/databehave';
|
|
28
|
+
if (!path.startsWith('/')) {
|
|
29
|
+
throw new Error(`@databehave/server: admin.path must start with "/" (got ${JSON.stringify(path)})`);
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
path,
|
|
33
|
+
ui: cfg.ui !== false,
|
|
34
|
+
headers: cfg.headers !== false,
|
|
35
|
+
bind: cfg.bind ?? 'loopback-only',
|
|
36
|
+
cors: cfg.cors ?? 'auto',
|
|
37
|
+
allowDestroy: cfg.allowDestroy !== false,
|
|
38
|
+
openapiBody: cfg.openapiBody,
|
|
39
|
+
scenariosDir: cfg.scenariosDir ?? `${process.cwd()}/mock-scenarios`,
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Compose two onRequest hooks (user-first per spec H13): if the user
|
|
44
|
+
* hook returned a response, skip the admin inject hook; else call
|
|
45
|
+
* inject. Exported for unit testability.
|
|
46
|
+
*/
|
|
47
|
+
export const composeAdminOnRequest = (userHook, adminHook) => {
|
|
48
|
+
if (!userHook)
|
|
49
|
+
return adminHook;
|
|
50
|
+
return async (req) => {
|
|
51
|
+
const first = await userHook(req);
|
|
52
|
+
if (first)
|
|
53
|
+
return first;
|
|
54
|
+
return adminHook(req);
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
const buildRouteIndex = (config) => {
|
|
58
|
+
const statik = new Map();
|
|
59
|
+
const dynamic = [];
|
|
60
|
+
const declared = new Set();
|
|
61
|
+
const declaredKeys = new Set();
|
|
62
|
+
const entries = Object.entries(config.routes ?? {});
|
|
63
|
+
for (const [key, handler] of entries) {
|
|
64
|
+
if (!handler)
|
|
65
|
+
continue;
|
|
66
|
+
const { method, path } = parseRouteKey(key);
|
|
67
|
+
const pattern = parseRoutePattern(path);
|
|
68
|
+
const dispatchKey = `${method} ${path}`;
|
|
69
|
+
if (declared.has(dispatchKey)) {
|
|
70
|
+
throw new Error(`@databehave/server: duplicate route declared: ${dispatchKey}`);
|
|
71
|
+
}
|
|
72
|
+
declared.add(dispatchKey);
|
|
73
|
+
declaredKeys.add(`${method.toUpperCase()} ${path}`);
|
|
74
|
+
if (pattern.isStatic) {
|
|
75
|
+
statik.set(dispatchKey, handler);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
dynamic.push({ method, pattern, handler });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// OpenAPI walker fills only the gaps the user did NOT declare.
|
|
82
|
+
// Declared (hand-written) routes always win — no error, just skip.
|
|
83
|
+
if (config.openapi !== undefined) {
|
|
84
|
+
const doc = parseOpenApi(config.openapi);
|
|
85
|
+
const oasRoutes = buildOpenApiRoutes(doc, {
|
|
86
|
+
skip: declaredKeys,
|
|
87
|
+
...(config.onOpenApiWalkError !== undefined
|
|
88
|
+
? { onWalkError: config.onOpenApiWalkError }
|
|
89
|
+
: {}),
|
|
90
|
+
...(config.onOpenApiEmptySchema !== undefined
|
|
91
|
+
? { onEmptySchema: config.onOpenApiEmptySchema }
|
|
92
|
+
: {}),
|
|
93
|
+
});
|
|
94
|
+
for (const [key, handler] of oasRoutes) {
|
|
95
|
+
const { method, path } = parseRouteKey(key);
|
|
96
|
+
const pattern = parseRoutePattern(path);
|
|
97
|
+
const dispatchKey = `${method} ${path}`;
|
|
98
|
+
if (declared.has(dispatchKey))
|
|
99
|
+
continue;
|
|
100
|
+
declared.add(dispatchKey);
|
|
101
|
+
if (pattern.isStatic) {
|
|
102
|
+
statik.set(dispatchKey, handler);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
dynamic.push({ method, pattern, handler });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return { statik, dynamic };
|
|
110
|
+
};
|
|
111
|
+
const dispatch = (index, method, path) => {
|
|
112
|
+
const staticHit = index.statik.get(`${method} ${path}`);
|
|
113
|
+
if (staticHit)
|
|
114
|
+
return { handler: staticHit, params: {} };
|
|
115
|
+
for (const route of index.dynamic) {
|
|
116
|
+
if (route.method !== method)
|
|
117
|
+
continue;
|
|
118
|
+
const params = matchPattern(route.pattern, path);
|
|
119
|
+
if (params)
|
|
120
|
+
return { handler: route.handler, params };
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* Build a @databehave/server server.
|
|
126
|
+
*
|
|
127
|
+
* Construction validates every route key and pre-computes a dispatch
|
|
128
|
+
* index (static lookups are O(1), `:param` patterns are linear). The
|
|
129
|
+
* returned object exposes:
|
|
130
|
+
*
|
|
131
|
+
* - `fetch(Request)` for in-process testing — no socket is opened.
|
|
132
|
+
* - `listen({port, host})` to bind a Node HTTP server. Port `0`
|
|
133
|
+
* asks the OS for a free port; the resolved port/host come back in
|
|
134
|
+
* the handle.
|
|
135
|
+
*
|
|
136
|
+
* Request flow per call:
|
|
137
|
+
* 1. CORS preflight (OPTIONS) → short-circuit when `cors` is set
|
|
138
|
+
* 2. `hooks.onRequest` → may short-circuit
|
|
139
|
+
* 3. Route dispatch → handler / OAS walker / 404
|
|
140
|
+
* 4. `hooks.onResponse` → may replace the result
|
|
141
|
+
* 5. CORS response headers merged on top (don't override the user)
|
|
142
|
+
* 6. Handler errors funnel through `hooks.onError` or fall back
|
|
143
|
+
* to a 500 JSON envelope.
|
|
144
|
+
*/
|
|
145
|
+
/**
|
|
146
|
+
* Route a runtime `'error'` event from a bound Node `http.Server` to
|
|
147
|
+
* the user-supplied `onServerError` hook (when present), with a
|
|
148
|
+
* `console.error` fallback. Exported so the branching is unit-testable
|
|
149
|
+
* without standing up a real socket and provoking EMFILE/EACCES.
|
|
150
|
+
*
|
|
151
|
+
* Branch contract:
|
|
152
|
+
* - no hook → log via `console.error`
|
|
153
|
+
* - hook returns → silent (hook owns reporting)
|
|
154
|
+
* - hook itself throws → log the *hook* failure AND the original
|
|
155
|
+
* error, so a misbehaving logger never
|
|
156
|
+
* silently swallows a real server fault.
|
|
157
|
+
*/
|
|
158
|
+
export const handleRuntimeServerError = (err, onServerError) => {
|
|
159
|
+
if (onServerError) {
|
|
160
|
+
try {
|
|
161
|
+
onServerError(err);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
catch (hookErr) {
|
|
165
|
+
// eslint-disable-next-line no-console
|
|
166
|
+
console.error('[@databehave/server] onServerError hook threw:', hookErr);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// eslint-disable-next-line no-console
|
|
170
|
+
console.error('[@databehave/server] server error:', err);
|
|
171
|
+
};
|
|
172
|
+
export const createServer = (config) => {
|
|
173
|
+
const admin = resolveAdminMode(config.admin);
|
|
174
|
+
let effectiveConfig = config;
|
|
175
|
+
if (admin) {
|
|
176
|
+
const store = createOverridesStore({
|
|
177
|
+
warn: (m) => console.warn(m),
|
|
178
|
+
});
|
|
179
|
+
const corsHeaders = resolveAdminCors(admin.bind, admin.cors);
|
|
180
|
+
const scenarios = createScenariosStore({ dir: admin.scenariosDir });
|
|
181
|
+
// Surface hand-written routes to the admin UI so handler-only
|
|
182
|
+
// endpoints (those not in the OAS doc, or projects without one)
|
|
183
|
+
// still appear in the operation list. OAS entries win on dedupe
|
|
184
|
+
// inside `buildAdminRoutesList`; admin's own routes are filtered
|
|
185
|
+
// there too. OAS-walker output is already covered by `openapiBody`.
|
|
186
|
+
const handlerRoutes = [];
|
|
187
|
+
for (const key of Object.keys(config.routes ?? {})) {
|
|
188
|
+
try {
|
|
189
|
+
const { method, path } = parseRouteKey(key);
|
|
190
|
+
handlerRoutes.push({ method: method.toUpperCase(), path });
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// buildRouteIndex below will surface invalid keys with a real error.
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
const adminRouteEntries = createAdminRoutes({
|
|
197
|
+
store,
|
|
198
|
+
basePath: admin.path,
|
|
199
|
+
ui: admin.ui,
|
|
200
|
+
corsHeaders,
|
|
201
|
+
scenarios,
|
|
202
|
+
handlerRoutes,
|
|
203
|
+
...(admin.openapiBody !== undefined
|
|
204
|
+
? { openapiBody: admin.openapiBody }
|
|
205
|
+
: {}),
|
|
206
|
+
});
|
|
207
|
+
// Fail-fast on conflict between admin routes and user routes —
|
|
208
|
+
// duplicates would silently shadow each other otherwise.
|
|
209
|
+
const userRoutes = config.routes ?? {};
|
|
210
|
+
for (const key of Object.keys(adminRouteEntries)) {
|
|
211
|
+
if (Object.prototype.hasOwnProperty.call(userRoutes, key)) {
|
|
212
|
+
throw new Error(`@databehave/server: admin route ${key} collides with a user-declared route. ` +
|
|
213
|
+
`Move admin.path to a free prefix or rename the user route.`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
// Inject hook is only registered when `headers` is true OR there
|
|
217
|
+
// can be sticky overrides — and stickies require the admin REST
|
|
218
|
+
// endpoints, which are always present, so the hook is always
|
|
219
|
+
// useful here. The `headers` flag is honored inside the inject
|
|
220
|
+
// hook by feeding it an empty-header view when disabled.
|
|
221
|
+
const adminHookCore = createInjectHook({
|
|
222
|
+
store,
|
|
223
|
+
allowDestroy: admin.allowDestroy,
|
|
224
|
+
// Bypass both the bare base path (admin HTML) and any descendant
|
|
225
|
+
// (`/overrides`, `/ui.js`, …) so the inject hook never injects on
|
|
226
|
+
// admin-owned URLs.
|
|
227
|
+
bypassPathPrefixes: [admin.path],
|
|
228
|
+
logger: { warn: (m) => console.warn(m) },
|
|
229
|
+
});
|
|
230
|
+
const adminHook = admin.headers
|
|
231
|
+
? adminHookCore
|
|
232
|
+
: async (req) => adminHookCore({ ...req, headers: {} });
|
|
233
|
+
const userHook = config.hooks?.onRequest;
|
|
234
|
+
const composed = composeAdminOnRequest(userHook, adminHook);
|
|
235
|
+
effectiveConfig = {
|
|
236
|
+
...config,
|
|
237
|
+
routes: { ...userRoutes, ...adminRouteEntries },
|
|
238
|
+
hooks: { ...(config.hooks ?? {}), onRequest: composed },
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
const index = buildRouteIndex(effectiveConfig);
|
|
242
|
+
const hooks = effectiveConfig.hooks ?? {};
|
|
243
|
+
const cors = effectiveConfig.cors;
|
|
244
|
+
const accessLogger = createAccessLogger(effectiveConfig.log, admin?.path);
|
|
245
|
+
// Build the request-validation context once per server boot. When
|
|
246
|
+
// `validation.request !== true` (the default) the context is null
|
|
247
|
+
// and the per-request hot path short-circuits.
|
|
248
|
+
//
|
|
249
|
+
// Schema-level errors (unsupported keyword, $ref cycle, ReDoS-sized
|
|
250
|
+
// pattern, depth-cap exceeded) throw at boot from
|
|
251
|
+
// `createRequestValidationContext` so a misconfigured spec is a
|
|
252
|
+
// fail-fast — never a silent runtime degradation.
|
|
253
|
+
let validationCtx = null;
|
|
254
|
+
if (effectiveConfig.validation?.request === true && effectiveConfig.openapi !== undefined) {
|
|
255
|
+
const doc = parseOpenApi(effectiveConfig.openapi);
|
|
256
|
+
const maxBodyBytes = effectiveConfig.validation?.maxBodyBytes;
|
|
257
|
+
validationCtx = createRequestValidationContext(doc, maxBodyBytes !== undefined ? { maxBodyBytes } : {});
|
|
258
|
+
}
|
|
259
|
+
const decorateWithCors = (res, req) => {
|
|
260
|
+
if (!cors)
|
|
261
|
+
return res;
|
|
262
|
+
const corsHeaders = buildCorsResponseHeaders(cors, req);
|
|
263
|
+
// Handler-supplied headers win — CORS only fills the gaps. `Vary`
|
|
264
|
+
// is the deliberate exception: HTTP semantics require it to be
|
|
265
|
+
// additive, so a handler-set `Vary: Accept-Encoding` is merged
|
|
266
|
+
// with the CORS `Vary: Origin` (case-insensitive dedupe) rather
|
|
267
|
+
// than silently replacing it.
|
|
268
|
+
const merged = { ...corsHeaders };
|
|
269
|
+
if (res.headers) {
|
|
270
|
+
for (const [k, v] of Object.entries(res.headers)) {
|
|
271
|
+
const lk = k.toLowerCase();
|
|
272
|
+
if (lk === 'vary') {
|
|
273
|
+
merged.vary = mergeVary(merged.vary, v);
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
merged[lk] = v;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return { ...res, headers: merged };
|
|
281
|
+
};
|
|
282
|
+
const fetchImpl = async (req, suppressLog = false) => {
|
|
283
|
+
const probe = buildRequest(req);
|
|
284
|
+
const logStart = accessLogger && !suppressLog ? Date.now() : 0;
|
|
285
|
+
const finalize = (res, errorMsg) => {
|
|
286
|
+
if (!accessLogger || suppressLog)
|
|
287
|
+
return res;
|
|
288
|
+
accessLogger.emit({
|
|
289
|
+
method: probe.method.toUpperCase(),
|
|
290
|
+
path: probe.path,
|
|
291
|
+
status: res.status,
|
|
292
|
+
ms: Date.now() - logStart,
|
|
293
|
+
bytes: res.headers.get('content-length') ?? '-',
|
|
294
|
+
override: res.headers.get('x-mock-injected')?.split(':')[0],
|
|
295
|
+
error: errorMsg,
|
|
296
|
+
});
|
|
297
|
+
return res;
|
|
298
|
+
};
|
|
299
|
+
// 1. CORS preflight bypasses everything below.
|
|
300
|
+
if (cors && req.method.toUpperCase() === 'OPTIONS') {
|
|
301
|
+
return finalize(buildResponse(buildPreflightResponse(cors, probe)));
|
|
302
|
+
}
|
|
303
|
+
// 1a. Inbound request validation (opt-in via
|
|
304
|
+
// `config.validation.request`). Runs BEFORE mock/handler
|
|
305
|
+
// resolution so a request that fails the OAS contract is rejected
|
|
306
|
+
// with an RFC 7807 envelope without invoking handlers, hooks, or
|
|
307
|
+
// mock-mode injection. When `validationCtx` is null (the default)
|
|
308
|
+
// the function short-circuits and behaviour is byte-identical to
|
|
309
|
+
// pre-validation builds.
|
|
310
|
+
if (validationCtx) {
|
|
311
|
+
const violation = await validateRequest(req, validationCtx);
|
|
312
|
+
if (violation)
|
|
313
|
+
return finalize(violation);
|
|
314
|
+
}
|
|
315
|
+
// 1b. RFC 7231 HEAD semantics: if the HEAD route is not declared,
|
|
316
|
+
// run the GET pipeline once and strip the body from the response.
|
|
317
|
+
// Hooks (`onRequest`, `onResponse`, mock-mode) fire on the inner
|
|
318
|
+
// GET call only — the outer HEAD short-circuits here before the
|
|
319
|
+
// `try` block, so they aren't observed twice for one logical
|
|
320
|
+
// request. Explicit `head` routes still take precedence (handled
|
|
321
|
+
// by `dispatch` for the original method).
|
|
322
|
+
if (req.method.toUpperCase() === 'HEAD' &&
|
|
323
|
+
!dispatch(index, 'head', probe.path)) {
|
|
324
|
+
const asGet = new Request(req.url, {
|
|
325
|
+
method: 'GET',
|
|
326
|
+
headers: req.headers,
|
|
327
|
+
});
|
|
328
|
+
// Inner GET is recursed with logging suppressed so the access
|
|
329
|
+
// logger emits one line per logical request — for the outer
|
|
330
|
+
// HEAD method, not the synthetic GET probe.
|
|
331
|
+
const fullResponse = await fetchImpl(asGet, true);
|
|
332
|
+
return finalize(new Response(null, {
|
|
333
|
+
status: fullResponse.status,
|
|
334
|
+
headers: fullResponse.headers,
|
|
335
|
+
}));
|
|
336
|
+
}
|
|
337
|
+
try {
|
|
338
|
+
// 2. onRequest may short-circuit (e.g. mock-mode error injection).
|
|
339
|
+
if (hooks.onRequest) {
|
|
340
|
+
const short = await hooks.onRequest(probe);
|
|
341
|
+
if (short) {
|
|
342
|
+
// admin destroy sentinel: bubble up so `listen()` can drop the
|
|
343
|
+
// underlying socket. `server.fetch()` callers observe the
|
|
344
|
+
// throw — destroy is a transport-level signal, not a body.
|
|
345
|
+
if (isDestroySocketSentinel(short)) {
|
|
346
|
+
throw new AdminDestroySocketSignal();
|
|
347
|
+
}
|
|
348
|
+
const final = hooks.onResponse
|
|
349
|
+
? (await hooks.onResponse(probe, short)) ?? short
|
|
350
|
+
: short;
|
|
351
|
+
return finalize(buildResponse(decorateWithCors(final, probe)));
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
// 3. Dispatch.
|
|
355
|
+
const matched = dispatch(index, probe.method, probe.path);
|
|
356
|
+
if (!matched) {
|
|
357
|
+
const notFound = {
|
|
358
|
+
status: 404,
|
|
359
|
+
json: { error: 'not_found', method: probe.method, path: probe.path },
|
|
360
|
+
};
|
|
361
|
+
const final = hooks.onResponse
|
|
362
|
+
? (await hooks.onResponse(probe, notFound)) ?? notFound
|
|
363
|
+
: notFound;
|
|
364
|
+
return finalize(buildResponse(decorateWithCors(final, probe)));
|
|
365
|
+
}
|
|
366
|
+
const kitReq = Object.keys(matched.params).length === 0
|
|
367
|
+
? probe
|
|
368
|
+
: buildRequest(req, matched.params);
|
|
369
|
+
const raw = await matched.handler(kitReq);
|
|
370
|
+
// 4. onResponse may replace the body / status / headers.
|
|
371
|
+
const final = hooks.onResponse
|
|
372
|
+
? (await hooks.onResponse(kitReq, raw)) ?? raw
|
|
373
|
+
: raw;
|
|
374
|
+
return finalize(buildResponse(decorateWithCors(final, kitReq)));
|
|
375
|
+
}
|
|
376
|
+
catch (err) {
|
|
377
|
+
// Admin destroy signal must escape — hooks.onError must NOT see
|
|
378
|
+
// it (it's transport-level, not a user error). `listen()` catches
|
|
379
|
+
// it specifically. `server.fetch()` callers also receive the throw.
|
|
380
|
+
if (err instanceof AdminDestroySocketSignal)
|
|
381
|
+
throw err;
|
|
382
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
383
|
+
const errRes = hooks.onError
|
|
384
|
+
? await hooks.onError(probe, err)
|
|
385
|
+
: {
|
|
386
|
+
status: 500,
|
|
387
|
+
json: {
|
|
388
|
+
error: 'internal_error',
|
|
389
|
+
message: errMsg,
|
|
390
|
+
},
|
|
391
|
+
};
|
|
392
|
+
return finalize(buildResponse(decorateWithCors(errRes, probe)), errMsg);
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
const fetch = (req) => fetchImpl(req);
|
|
396
|
+
const listen = async (opts = {}) => {
|
|
397
|
+
const requestedPort = opts.port ?? 0;
|
|
398
|
+
const requestedHost = opts.host ?? '127.0.0.1';
|
|
399
|
+
// Admin bind-policy: refuse non-loopback hosts unless explicitly
|
|
400
|
+
// opted in. Host comes from listen options (not config), so the
|
|
401
|
+
// check belongs here rather than at server construction time.
|
|
402
|
+
if (admin && admin.bind !== 'any' && !LOOPBACK_HOSTS.has(requestedHost)) {
|
|
403
|
+
throw new Error(`@databehave/server: admin is enabled and server.host=${JSON.stringify(requestedHost)} — set admin.bind: "any" to confirm this is intentional, or bind to loopback (127.0.0.1, ::1, localhost). See README "Admin mode".`);
|
|
404
|
+
}
|
|
405
|
+
// Tiny Node `http` ↔ Web Fetch adapter. Node ≥ 18.17 provides
|
|
406
|
+
// `Request`, `Response`, `Headers`, and `Readable.{toWeb,fromWeb}`
|
|
407
|
+
// as built-ins, so no polyfill or extra runtime dependency is needed.
|
|
408
|
+
const server = createNodeHttpServer((req, res) => {
|
|
409
|
+
// Build a Web Request out of the IncomingMessage.
|
|
410
|
+
const host = req.headers.host ?? `${requestedHost}:${requestedPort}`;
|
|
411
|
+
const url = `http://${host}${req.url ?? '/'}`;
|
|
412
|
+
const method = (req.method ?? 'GET').toUpperCase();
|
|
413
|
+
const headers = new Headers();
|
|
414
|
+
for (const [k, v] of Object.entries(req.headers)) {
|
|
415
|
+
if (v === undefined)
|
|
416
|
+
continue;
|
|
417
|
+
if (Array.isArray(v)) {
|
|
418
|
+
for (const value of v)
|
|
419
|
+
headers.append(k, value);
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
headers.set(k, v);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
const init = { method, headers };
|
|
426
|
+
if (method !== 'GET' && method !== 'HEAD') {
|
|
427
|
+
init.body = Readable.toWeb(req);
|
|
428
|
+
// Required when sending a stream body in undici/fetch.
|
|
429
|
+
init.duplex = 'half';
|
|
430
|
+
}
|
|
431
|
+
Promise.resolve()
|
|
432
|
+
.then(() => fetch(new Request(url, init)))
|
|
433
|
+
.then(async (webRes) => {
|
|
434
|
+
res.statusCode = webRes.status;
|
|
435
|
+
webRes.headers.forEach((value, key) => {
|
|
436
|
+
res.setHeader(key, value);
|
|
437
|
+
});
|
|
438
|
+
if (!webRes.body) {
|
|
439
|
+
res.end();
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
const nodeStream = Readable.fromWeb(webRes.body);
|
|
443
|
+
await new Promise((resolveStream, rejectStream) => {
|
|
444
|
+
nodeStream.on('error', rejectStream);
|
|
445
|
+
res.on('error', rejectStream);
|
|
446
|
+
res.on('finish', () => resolveStream());
|
|
447
|
+
nodeStream.pipe(res);
|
|
448
|
+
});
|
|
449
|
+
})
|
|
450
|
+
.catch((err) => {
|
|
451
|
+
// Admin destroy: drop the socket without a response.
|
|
452
|
+
if (err instanceof AdminDestroySocketSignal) {
|
|
453
|
+
try {
|
|
454
|
+
req.socket.destroy();
|
|
455
|
+
}
|
|
456
|
+
catch {
|
|
457
|
+
/* socket may already be gone */
|
|
458
|
+
}
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
if (!res.headersSent) {
|
|
462
|
+
res.statusCode = 500;
|
|
463
|
+
res.setHeader('content-type', 'application/json');
|
|
464
|
+
}
|
|
465
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
466
|
+
res.end(JSON.stringify({ error: 'internal_error', message }));
|
|
467
|
+
});
|
|
468
|
+
});
|
|
469
|
+
return new Promise((resolve, reject) => {
|
|
470
|
+
const onBindError = (err) => {
|
|
471
|
+
reject(err);
|
|
472
|
+
};
|
|
473
|
+
server.once('error', onBindError);
|
|
474
|
+
server.listen(requestedPort, requestedHost, () => {
|
|
475
|
+
// Bind succeeded — detach the bind-time rejector so subsequent
|
|
476
|
+
// runtime errors (EMFILE, accept errors, etc.) don't try to
|
|
477
|
+
// resolve an already-settled promise. Surface them on stderr
|
|
478
|
+
// instead so they're not swallowed silently.
|
|
479
|
+
server.removeListener('error', onBindError);
|
|
480
|
+
server.on('error', (err) => handleRuntimeServerError(err, hooks.onServerError));
|
|
481
|
+
const info = server.address();
|
|
482
|
+
if (admin) {
|
|
483
|
+
emitAdminBanner(info.address, info.port, admin.path);
|
|
484
|
+
}
|
|
485
|
+
resolve({
|
|
486
|
+
port: info.port,
|
|
487
|
+
host: info.address,
|
|
488
|
+
close: () => new Promise((res, rej) => {
|
|
489
|
+
server.close((err) => (err ? rej(err) : res()));
|
|
490
|
+
}),
|
|
491
|
+
});
|
|
492
|
+
});
|
|
493
|
+
});
|
|
494
|
+
};
|
|
495
|
+
return { fetch, listen };
|
|
496
|
+
};
|
|
497
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|