@databehave/server 0.1.4 → 0.2.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 +17 -0
- package/README.md +85 -83
- package/dist/cors.d.ts +1 -1
- package/dist/cors.js +1 -1
- package/dist/cors.js.map +1 -1
- package/dist/http.d.ts +94 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +23 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +10 -20
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -18
- package/dist/index.js.map +1 -1
- package/dist/log.d.ts +9 -49
- package/dist/log.d.ts.map +1 -1
- package/dist/log.js +16 -92
- package/dist/log.js.map +1 -1
- package/dist/node-authority.d.ts +12 -0
- package/dist/node-authority.d.ts.map +1 -0
- package/dist/node-authority.js +72 -0
- package/dist/node-authority.js.map +1 -0
- package/dist/node-body.d.ts +11 -0
- package/dist/node-body.d.ts.map +1 -0
- package/dist/node-body.js +61 -0
- package/dist/node-body.js.map +1 -0
- package/dist/node-http.d.ts +19 -0
- package/dist/node-http.d.ts.map +1 -0
- package/dist/node-http.js +210 -0
- package/dist/node-http.js.map +1 -0
- package/dist/plugins/access-log.d.ts +11 -0
- package/dist/plugins/access-log.d.ts.map +1 -0
- package/dist/plugins/access-log.js +27 -0
- package/dist/plugins/access-log.js.map +1 -0
- package/dist/plugins/cors.d.ts +5 -0
- package/dist/plugins/cors.d.ts.map +1 -0
- package/dist/plugins/cors.js +35 -0
- package/dist/plugins/cors.js.map +1 -0
- package/dist/plugins/routes.d.ts +5 -0
- package/dist/plugins/routes.d.ts.map +1 -0
- package/dist/plugins/routes.js +10 -0
- package/dist/plugins/routes.js.map +1 -0
- package/dist/request.d.ts +2 -2
- package/dist/request.d.ts.map +1 -1
- package/dist/request.js +6 -4
- package/dist/request.js.map +1 -1
- package/dist/route-key.d.ts +2 -0
- package/dist/route-key.d.ts.map +1 -1
- package/dist/route-key.js +5 -1
- package/dist/route-key.js.map +1 -1
- package/dist/server.d.ts +7 -59
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +289 -466
- package/dist/server.js.map +1 -1
- package/dist/types.d.ts +10 -156
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/package.json +9 -22
- package/dist/admin/admin-routes.d.ts +0 -42
- package/dist/admin/admin-routes.d.ts.map +0 -1
- package/dist/admin/admin-routes.js +0 -472
- package/dist/admin/admin-routes.js.map +0 -1
- package/dist/admin/admin-types.d.ts +0 -170
- package/dist/admin/admin-types.d.ts.map +0 -1
- package/dist/admin/admin-types.js +0 -30
- package/dist/admin/admin-types.js.map +0 -1
- package/dist/admin/banner.d.ts +0 -11
- package/dist/admin/banner.d.ts.map +0 -1
- package/dist/admin/banner.js +0 -5
- package/dist/admin/banner.js.map +0 -1
- package/dist/admin/header-parser.d.ts +0 -14
- package/dist/admin/header-parser.d.ts.map +0 -1
- package/dist/admin/header-parser.js +0 -171
- package/dist/admin/header-parser.js.map +0 -1
- package/dist/admin/inject.d.ts +0 -48
- package/dist/admin/inject.d.ts.map +0 -1
- package/dist/admin/inject.js +0 -167
- package/dist/admin/inject.js.map +0 -1
- package/dist/admin/overrides-store.d.ts +0 -18
- package/dist/admin/overrides-store.d.ts.map +0 -1
- package/dist/admin/overrides-store.js +0 -100
- package/dist/admin/overrides-store.js.map +0 -1
- package/dist/admin/resolve-cors.d.ts +0 -22
- package/dist/admin/resolve-cors.d.ts.map +0 -1
- package/dist/admin/resolve-cors.js +0 -28
- package/dist/admin/resolve-cors.js.map +0 -1
- package/dist/admin/scenarios-store.d.ts +0 -15
- package/dist/admin/scenarios-store.d.ts.map +0 -1
- package/dist/admin/scenarios-store.js +0 -109
- package/dist/admin/scenarios-store.js.map +0 -1
- package/dist/admin/ui.css +0 -1
- package/dist/admin/ui.html +0 -13
- package/dist/admin/ui.js +0 -240
- package/dist/bin-helpers.d.ts +0 -46
- package/dist/bin-helpers.d.ts.map +0 -1
- package/dist/bin-helpers.js +0 -61
- package/dist/bin-helpers.js.map +0 -1
- package/dist/bin.d.ts +0 -3
- package/dist/bin.d.ts.map +0 -1
- package/dist/bin.js +0 -86
- package/dist/bin.js.map +0 -1
- package/dist/define.d.ts +0 -26
- package/dist/define.d.ts.map +0 -1
- package/dist/define.js +0 -55
- package/dist/define.js.map +0 -1
- package/dist/json-config.d.ts +0 -170
- package/dist/json-config.d.ts.map +0 -1
- package/dist/json-config.js +0 -684
- package/dist/json-config.js.map +0 -1
- package/dist/jsonc.d.ts +0 -24
- package/dist/jsonc.d.ts.map +0 -1
- package/dist/jsonc.js +0 -125
- package/dist/jsonc.js.map +0 -1
- package/dist/middleware/request-validation.d.ts +0 -58
- package/dist/middleware/request-validation.d.ts.map +0 -1
- package/dist/middleware/request-validation.js +0 -328
- package/dist/middleware/request-validation.js.map +0 -1
- package/dist/mock-mode.d.ts +0 -95
- package/dist/mock-mode.d.ts.map +0 -1
- package/dist/mock-mode.js +0 -95
- package/dist/mock-mode.js.map +0 -1
- package/dist/openapi/auto-schema.d.ts +0 -83
- package/dist/openapi/auto-schema.d.ts.map +0 -1
- package/dist/openapi/auto-schema.js +0 -232
- package/dist/openapi/auto-schema.js.map +0 -1
- package/dist/openapi/generate.d.ts +0 -20
- package/dist/openapi/generate.d.ts.map +0 -1
- package/dist/openapi/generate.js +0 -121
- package/dist/openapi/generate.js.map +0 -1
- package/dist/openapi/loader.d.ts +0 -18
- package/dist/openapi/loader.d.ts.map +0 -1
- package/dist/openapi/loader.js +0 -25
- package/dist/openapi/loader.js.map +0 -1
- package/dist/openapi/register.d.ts +0 -58
- package/dist/openapi/register.d.ts.map +0 -1
- package/dist/openapi/register.js +0 -166
- package/dist/openapi/register.js.map +0 -1
- package/dist/openapi/seed.d.ts +0 -16
- package/dist/openapi/seed.d.ts.map +0 -1
- package/dist/openapi/seed.js +0 -58
- package/dist/openapi/seed.js.map +0 -1
- package/dist/openapi/translate.d.ts +0 -55
- package/dist/openapi/translate.d.ts.map +0 -1
- package/dist/openapi/translate.js +0 -319
- package/dist/openapi/translate.js.map +0 -1
- package/dist/openapi/walker.d.ts +0 -44
- package/dist/openapi/walker.d.ts.map +0 -1
- package/dist/openapi/walker.js +0 -15
- package/dist/openapi/walker.js.map +0 -1
- package/dist/run.d.ts +0 -27
- package/dist/run.d.ts.map +0 -1
- package/dist/run.js +0 -87
- package/dist/run.js.map +0 -1
- package/dist/validation/validate.d.ts +0 -38
- package/dist/validation/validate.d.ts.map +0 -1
- package/dist/validation/validate.js +0 -372
- package/dist/validation/validate.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"admin-types.d.ts","sourceRoot":"","sources":["../../src/admin/admin-types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,EAAE,OAAO,MAE5C,CAAA;AACD,MAAM,MAAM,qBAAqB,GAAG,OAAO,uBAAuB,CAAA;AAElE;;;;;GAKG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;IACjD,QAAQ,CAAC,IAAI,8BAA6B;;CAI3C;AAED;;;;;;;;;;GAUG;AACH,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACvC;IACE,IAAI,EAAE,kBAAkB,CAAA;IACxB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChC,GACD;IACE,IAAI,EAAE,aAAa,CAAA;IACnB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,OAAO,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GACD;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3C;IACE,IAAI,EAAE,OAAO,CAAA;IACb,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,CAAC,EAAE,OAAO,CACZ,SAAS,EACT;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,SAAS,CAAA;KAAE,CAC3D,CAAA;CACF,GACD;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAA;AAEvB;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAA;AAEnD,uFAAuF;AACvF,MAAM,MAAM,aAAa,GAAG,eAAe,CAAA;AAE3C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAA;IACjC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAC9B;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,KAAK,GACL,aAAa,GACb;IAAE,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAA;CAAE,CAAA;AAE1C,4DAA4D;AAC5D,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,iFAAiF;IACjF,EAAE,CAAC,EAAE,OAAO,CAAA;IACZ,oEAAoE;IACpE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;OAGG;IACH,IAAI,CAAC,EAAE,eAAe,GAAG,KAAK,CAAA;IAC9B,qEAAqE;IACrE,IAAI,CAAC,EAAE,aAAa,CAAA;IACpB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB;;;;;;;;;OASG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,iEAAiE;AACjE,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,SAAS,EAAE,SAAS,cAAc,EAAE,CAAA;IAC7C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,kEAAkE;AAClE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB"}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Admin-mode types & internal sentinel.
|
|
3
|
-
*
|
|
4
|
-
* `admin` is an opt-in extension of `Config` that
|
|
5
|
-
* mounts an in-memory error-injection panel + `x-mock-*` headers
|
|
6
|
-
* under a configurable mount path (default `/databehave`). See
|
|
7
|
-
* {@link AdminModeConfig} on `Config.admin`.
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Internal symbol attached to the response object returned by
|
|
11
|
-
* {@link createInjectHook} when an `x-mock-destroy` is honored. The
|
|
12
|
-
* kit's `server.listen()` http adapter recognizes this property and
|
|
13
|
-
* drops the underlying socket without writing a response. Hidden
|
|
14
|
-
* from {@link MockResponse} on purpose — destroy is not a
|
|
15
|
-
* normal HTTP response shape.
|
|
16
|
-
*/
|
|
17
|
-
export const DESTROY_SOCKET_SENTINEL = Symbol.for('@databehave/server:admin:destroy-socket');
|
|
18
|
-
/**
|
|
19
|
-
* Thrown internally by `server.fetch` when the admin inject hook
|
|
20
|
-
* surfaced a {@link DESTROY_SOCKET_SENTINEL} response. `server.listen()`
|
|
21
|
-
* catches it and destroys the socket; callers of `server.fetch()`
|
|
22
|
-
* outside a listening server will observe the throw.
|
|
23
|
-
*/
|
|
24
|
-
export class AdminDestroySocketSignal extends Error {
|
|
25
|
-
name = 'AdminDestroySocketSignal';
|
|
26
|
-
constructor() {
|
|
27
|
-
super('@databehave/server: admin x-mock-destroy requested');
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
//# sourceMappingURL=admin-types.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"admin-types.js","sourceRoot":"","sources":["../../src/admin/admin-types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAkB,MAAM,CAAC,GAAG,CAC9D,yCAAyC,CAC1C,CAAA;AAGD;;;;;GAKG;AACH,MAAM,OAAO,wBAAyB,SAAQ,KAAK;IACxC,IAAI,GAAG,0BAA0B,CAAA;IAC1C;QACE,KAAK,CAAC,oDAAoD,CAAC,CAAA;IAC7D,CAAC;CACF"}
|
package/dist/admin/banner.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* stdout notice emitted at `server.listen()` start when admin is
|
|
3
|
-
* enabled. Splitting it out keeps the banner format unit-testable
|
|
4
|
-
* (no need to spin up a real http server just to assert a string).
|
|
5
|
-
*/
|
|
6
|
-
export interface AdminBannerLogger {
|
|
7
|
-
info(message: string): void;
|
|
8
|
-
}
|
|
9
|
-
export declare const formatAdminBanner: (host: string, port: number, path: string) => string;
|
|
10
|
-
export declare const emitAdminBanner: (host: string, port: number, path: string, logger?: AdminBannerLogger) => void;
|
|
11
|
-
//# sourceMappingURL=banner.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"banner.d.ts","sourceRoot":"","sources":["../../src/admin/banner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAED,eAAO,MAAM,iBAAiB,GAC5B,MAAM,MAAM,EACZ,MAAM,MAAM,EACZ,MAAM,MAAM,KACX,MAC2G,CAAA;AAE9G,eAAO,MAAM,eAAe,GAC1B,MAAM,MAAM,EACZ,MAAM,MAAM,EACZ,MAAM,MAAM,EACZ,SAAQ,iBAA2B,KAClC,IAEF,CAAA"}
|
package/dist/admin/banner.js
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
export const formatAdminBanner = (host, port, path) => `[@databehave/server] admin panel ready at http://${host}:${port}${path} (dev mock — disable in production)`;
|
|
2
|
-
export const emitAdminBanner = (host, port, path, logger = console) => {
|
|
3
|
-
logger.info(formatAdminBanner(host, port, path));
|
|
4
|
-
};
|
|
5
|
-
//# sourceMappingURL=banner.js.map
|
package/dist/admin/banner.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"banner.js","sourceRoot":"","sources":["../../src/admin/banner.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,IAAY,EACZ,IAAY,EACZ,IAAY,EACJ,EAAE,CACV,oDAAoD,IAAI,IAAI,IAAI,GAAG,IAAI,qCAAqC,CAAA;AAE9G,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,IAAY,EACZ,IAAY,EACZ,IAAY,EACZ,SAA4B,OAAO,EAC7B,EAAE;IACR,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;AAClD,CAAC,CAAA"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { ErrorMode } from './admin-types.js';
|
|
2
|
-
export type HeaderParseResult = {
|
|
3
|
-
kind: 'none';
|
|
4
|
-
} | {
|
|
5
|
-
kind: 'mode';
|
|
6
|
-
mode: ErrorMode;
|
|
7
|
-
} | {
|
|
8
|
-
kind: 'error';
|
|
9
|
-
message: string;
|
|
10
|
-
};
|
|
11
|
-
export declare const parseHeaderMode: (headers: Readonly<Record<string, string>>) => HeaderParseResult;
|
|
12
|
-
/** Public alias of {@link parseHeaderMode}. */
|
|
13
|
-
export declare const parseMockHeaders: (headers: Readonly<Record<string, string>>) => HeaderParseResult;
|
|
14
|
-
//# sourceMappingURL=header-parser.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"header-parser.d.ts","sourceRoot":"","sources":["../../src/admin/header-parser.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAEjD,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAkJtC,eAAO,MAAM,eAAe,GAC1B,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KACxC,iBAqCF,CAAA;AAGD,+CAA+C;AAC/C,eAAO,MAAM,gBAAgB,YA1ClB,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KACxC,iBAyC4C,CAAA"}
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Parse `x-mock-*` request headers into an `ErrorMode` (or surface a
|
|
3
|
-
* conflict error). One header set ↔ one ErrorMode. Multiple terminal
|
|
4
|
-
* modes (e.g. both `x-mock-status` and `x-mock-business-failure`) are
|
|
5
|
-
* rejected with `kind: 'conflict'` so the caller can return 400.
|
|
6
|
-
*
|
|
7
|
-
* Base64 inputs (`x-mock-body`, `x-mock-business-failure-extra`) use
|
|
8
|
-
* standard base64 (NOT url-safe), per the README contract.
|
|
9
|
-
*/
|
|
10
|
-
import { Buffer } from 'node:buffer';
|
|
11
|
-
// Note: `x-mock-business-failure-b64` is an alternative to
|
|
12
|
-
// `x-mock-business-failure` that accepts a base64-UTF8 message so
|
|
13
|
-
// non-ASCII strings can travel through an HTTP header — Node's fetch
|
|
14
|
-
// rejects non-ASCII byte values in header values.
|
|
15
|
-
const TERMINAL_HEADERS = [
|
|
16
|
-
'x-mock-status',
|
|
17
|
-
'x-mock-business-failure',
|
|
18
|
-
'x-mock-business-failure-b64',
|
|
19
|
-
'x-mock-body',
|
|
20
|
-
'x-mock-empty',
|
|
21
|
-
'x-mock-malformed',
|
|
22
|
-
'x-mock-hang',
|
|
23
|
-
'x-mock-destroy',
|
|
24
|
-
];
|
|
25
|
-
const get = (h, name) => h[name];
|
|
26
|
-
const decodeBase64Json = (raw, headerName) => {
|
|
27
|
-
let decoded;
|
|
28
|
-
try {
|
|
29
|
-
decoded = Buffer.from(raw, 'base64').toString('utf8');
|
|
30
|
-
}
|
|
31
|
-
catch (err) {
|
|
32
|
-
throw new Error(`invalid ${headerName} header: base64 decode failed (${err instanceof Error ? err.message : String(err)})`);
|
|
33
|
-
}
|
|
34
|
-
try {
|
|
35
|
-
return JSON.parse(decoded);
|
|
36
|
-
}
|
|
37
|
-
catch (err) {
|
|
38
|
-
throw new Error(`invalid ${headerName} header: JSON parse failed (${err instanceof Error ? err.message : String(err)})`);
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
const parseIntStrict = (raw, headerName) => {
|
|
42
|
-
const n = Number.parseInt(raw, 10);
|
|
43
|
-
if (!Number.isFinite(n)) {
|
|
44
|
-
throw new Error(`invalid ${headerName} header: not an integer (${JSON.stringify(raw)})`);
|
|
45
|
-
}
|
|
46
|
-
return n;
|
|
47
|
-
};
|
|
48
|
-
const parseTerminal = (h) => {
|
|
49
|
-
const present = TERMINAL_HEADERS.filter((name) => get(h, name) !== undefined);
|
|
50
|
-
if (present.length === 0)
|
|
51
|
-
return null;
|
|
52
|
-
if (present.length > 1) {
|
|
53
|
-
throw new Error(`conflicting x-mock-* headers: ${present.join(', ')} — pick exactly one terminal mode`);
|
|
54
|
-
}
|
|
55
|
-
const [only] = present;
|
|
56
|
-
switch (only) {
|
|
57
|
-
case 'x-mock-status': {
|
|
58
|
-
const status = parseIntStrict(get(h, 'x-mock-status'), 'x-mock-status');
|
|
59
|
-
return { kind: 'http-status', status };
|
|
60
|
-
}
|
|
61
|
-
case 'x-mock-business-failure':
|
|
62
|
-
case 'x-mock-business-failure-b64': {
|
|
63
|
-
let message;
|
|
64
|
-
if (only === 'x-mock-business-failure-b64') {
|
|
65
|
-
const raw = get(h, 'x-mock-business-failure-b64');
|
|
66
|
-
try {
|
|
67
|
-
message = Buffer.from(raw, 'base64').toString('utf8');
|
|
68
|
-
}
|
|
69
|
-
catch (err) {
|
|
70
|
-
throw new Error(`invalid x-mock-business-failure-b64 header: base64 decode failed (${err instanceof Error ? err.message : String(err)})`);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
message = get(h, 'x-mock-business-failure');
|
|
75
|
-
}
|
|
76
|
-
const extraRaw = get(h, 'x-mock-business-failure-extra');
|
|
77
|
-
if (extraRaw === undefined)
|
|
78
|
-
return { kind: 'business-failure', message };
|
|
79
|
-
const extra = decodeBase64Json(extraRaw, 'x-mock-business-failure-extra');
|
|
80
|
-
if (extra === null || typeof extra !== 'object' || Array.isArray(extra)) {
|
|
81
|
-
throw new Error('invalid x-mock-business-failure-extra header: decoded value must be a JSON object');
|
|
82
|
-
}
|
|
83
|
-
return {
|
|
84
|
-
kind: 'business-failure',
|
|
85
|
-
message,
|
|
86
|
-
extra: extra,
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
case 'x-mock-body': {
|
|
90
|
-
const body = decodeBase64Json(get(h, 'x-mock-body'), 'x-mock-body');
|
|
91
|
-
const statusRaw = get(h, 'x-mock-body-status');
|
|
92
|
-
const contentType = get(h, 'x-mock-body-content-type');
|
|
93
|
-
const mode = { kind: 'custom-body', body };
|
|
94
|
-
if (statusRaw !== undefined) {
|
|
95
|
-
;
|
|
96
|
-
mode.status = parseIntStrict(statusRaw, 'x-mock-body-status');
|
|
97
|
-
}
|
|
98
|
-
if (contentType !== undefined) {
|
|
99
|
-
;
|
|
100
|
-
mode.contentType = contentType;
|
|
101
|
-
}
|
|
102
|
-
return mode;
|
|
103
|
-
}
|
|
104
|
-
case 'x-mock-empty': {
|
|
105
|
-
const statusRaw = get(h, 'x-mock-empty-status');
|
|
106
|
-
if (statusRaw === undefined)
|
|
107
|
-
return { kind: 'empty-body' };
|
|
108
|
-
return {
|
|
109
|
-
kind: 'empty-body',
|
|
110
|
-
status: parseIntStrict(statusRaw, 'x-mock-empty-status'),
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
case 'x-mock-malformed': {
|
|
114
|
-
const statusRaw = get(h, 'x-mock-malformed-status');
|
|
115
|
-
if (statusRaw === undefined)
|
|
116
|
-
return { kind: 'malformed-json' };
|
|
117
|
-
return {
|
|
118
|
-
kind: 'malformed-json',
|
|
119
|
-
status: parseIntStrict(statusRaw, 'x-mock-malformed-status'),
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
case 'x-mock-hang':
|
|
123
|
-
return { kind: 'hang' };
|
|
124
|
-
case 'x-mock-destroy':
|
|
125
|
-
return { kind: 'destroy' };
|
|
126
|
-
/* v8 ignore next 3 -- exhaustiveness: unreachable */
|
|
127
|
-
default:
|
|
128
|
-
// exhaustiveness — unreachable.
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
export const parseHeaderMode = (headers) => {
|
|
133
|
-
try {
|
|
134
|
-
const terminal = parseTerminal(headers);
|
|
135
|
-
const delayRaw = get(headers, 'x-mock-delay');
|
|
136
|
-
if (terminal === null && delayRaw === undefined) {
|
|
137
|
-
return { kind: 'none' };
|
|
138
|
-
}
|
|
139
|
-
if (delayRaw === undefined) {
|
|
140
|
-
return { kind: 'mode', mode: terminal };
|
|
141
|
-
}
|
|
142
|
-
const ms = parseIntStrict(delayRaw, 'x-mock-delay');
|
|
143
|
-
if (ms < 0) {
|
|
144
|
-
return {
|
|
145
|
-
kind: 'error',
|
|
146
|
-
message: 'invalid x-mock-delay header: must be >= 0',
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
if (terminal === null) {
|
|
150
|
-
return { kind: 'mode', mode: { kind: 'delay', ms } };
|
|
151
|
-
}
|
|
152
|
-
if (terminal.kind === 'delay' ||
|
|
153
|
-
terminal.kind === 'hang' ||
|
|
154
|
-
terminal.kind === 'destroy') {
|
|
155
|
-
return {
|
|
156
|
-
kind: 'error',
|
|
157
|
-
message: `x-mock-delay cannot wrap kind=${terminal.kind}`,
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
return { kind: 'mode', mode: { kind: 'delay', ms, then: terminal } };
|
|
161
|
-
}
|
|
162
|
-
catch (err) {
|
|
163
|
-
return {
|
|
164
|
-
kind: 'error',
|
|
165
|
-
message: err instanceof Error ? err.message : String(err),
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
};
|
|
169
|
-
/** Public alias of {@link parseHeaderMode}. */
|
|
170
|
-
export const parseMockHeaders = parseHeaderMode;
|
|
171
|
-
//# sourceMappingURL=header-parser.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"header-parser.js","sourceRoot":"","sources":["../../src/admin/header-parser.ts"],"names":[],"mappings":"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"}
|
package/dist/admin/inject.d.ts
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* onRequest hook that consults `x-mock-*` headers + sticky overrides
|
|
3
|
-
* and produces a `MockResponse` short-circuit. Header-derived
|
|
4
|
-
* modes always beat sticky modes (per-request scoping > sticky rules).
|
|
5
|
-
*
|
|
6
|
-
* Modes handled directly here:
|
|
7
|
-
* - http-status, business-failure, custom-body, empty-body,
|
|
8
|
-
* malformed-json, delay (recursive), hang
|
|
9
|
-
*
|
|
10
|
-
* `destroy` is signalled via a sentinel response (see
|
|
11
|
-
* {@link DESTROY_SOCKET_SENTINEL}) so the kit's `server.listen()` http
|
|
12
|
-
* adapter can drop the socket without writing a body. When
|
|
13
|
-
* `allowDestroy: false`, destroy resolves to a normal 503 response
|
|
14
|
-
* instead.
|
|
15
|
-
*/
|
|
16
|
-
import type { MockRequest, MockResponse } from '../types.js';
|
|
17
|
-
import type { OverridesStore } from './overrides-store.js';
|
|
18
|
-
import { type ErrorMode } from './admin-types.js';
|
|
19
|
-
export type ResolveResult = {
|
|
20
|
-
kind: 'mode';
|
|
21
|
-
mode: ErrorMode;
|
|
22
|
-
source: 'header' | 'sticky';
|
|
23
|
-
} | {
|
|
24
|
-
kind: 'error';
|
|
25
|
-
message: string;
|
|
26
|
-
} | {
|
|
27
|
-
kind: 'none';
|
|
28
|
-
};
|
|
29
|
-
/**
|
|
30
|
-
* Pure resolver: header overrides beat sticky overrides. Returns
|
|
31
|
-
* `'none'` when nothing applies and `'error'` for malformed headers.
|
|
32
|
-
*/
|
|
33
|
-
export declare const resolveMode: (store: OverridesStore, method: string, path: string, headers: Readonly<Record<string, string>>) => ResolveResult;
|
|
34
|
-
export interface InjectHookOptions {
|
|
35
|
-
readonly store: OverridesStore;
|
|
36
|
-
/** Paths matching any of these prefixes are passed through (no injection). */
|
|
37
|
-
readonly bypassPathPrefixes?: readonly string[];
|
|
38
|
-
/** When false, destroy mode resolves to a 503 instead of dropping the socket. */
|
|
39
|
-
readonly allowDestroy?: boolean;
|
|
40
|
-
readonly logger?: {
|
|
41
|
-
warn(message: string): void;
|
|
42
|
-
info?(message: string): void;
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
export declare const createInjectHook: (opts: InjectHookOptions) => (req: MockRequest) => Promise<MockResponse | void>;
|
|
46
|
-
/** True when the response carries the internal destroy-socket sentinel. */
|
|
47
|
-
export declare const isDestroySocketSentinel: (res: MockResponse | undefined | null) => boolean;
|
|
48
|
-
//# sourceMappingURL=inject.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"inject.d.ts","sourceRoot":"","sources":["../../src/admin/inject.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EACb,MAAM,aAAa,CAAA;AAEpB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAE1D,OAAO,EAA2B,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAI1E,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAAA;CAAE,GAC9D;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAEpB;;;GAGG;AACH,eAAO,MAAM,WAAW,GACtB,OAAO,cAAc,EACrB,QAAQ,MAAM,EACd,MAAM,MAAM,EACZ,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KACxC,aAUF,CAAA;AAuGD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAA;IAC9B,8EAA8E;IAC9E,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC/C,iFAAiF;IACjF,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAA;IAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE;QAChB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;QAC3B,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAC7B,CAAA;CACF;AAED,eAAO,MAAM,gBAAgB,GAAI,MAAM,iBAAiB,MAUpD,KAAK,WAAW,KACf,OAAO,CAAC,YAAY,GAAG,IAAI,CA+C/B,CAAA;AAED,2EAA2E;AAC3E,eAAO,MAAM,uBAAuB,GAClC,KAAK,YAAY,GAAG,SAAS,GAAG,IAAI,KACnC,OAGF,CAAA"}
|
package/dist/admin/inject.js
DELETED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import { parseHeaderMode } from './header-parser.js';
|
|
2
|
-
import { DESTROY_SOCKET_SENTINEL } from './admin-types.js';
|
|
3
|
-
const TAG_HEADER = 'x-mock-injected';
|
|
4
|
-
/**
|
|
5
|
-
* Pure resolver: header overrides beat sticky overrides. Returns
|
|
6
|
-
* `'none'` when nothing applies and `'error'` for malformed headers.
|
|
7
|
-
*/
|
|
8
|
-
export const resolveMode = (store, method, path, headers) => {
|
|
9
|
-
const fromHeader = parseHeaderMode(headers);
|
|
10
|
-
if (fromHeader.kind === 'error')
|
|
11
|
-
return { kind: 'error', message: fromHeader.message };
|
|
12
|
-
if (fromHeader.kind === 'mode') {
|
|
13
|
-
return { kind: 'mode', mode: fromHeader.mode, source: 'header' };
|
|
14
|
-
}
|
|
15
|
-
const sticky = store.resolve(method, path);
|
|
16
|
-
if (sticky)
|
|
17
|
-
return { kind: 'mode', mode: sticky.mode, source: 'sticky' };
|
|
18
|
-
return { kind: 'none' };
|
|
19
|
-
};
|
|
20
|
-
const buildResponse = (mode, source) => {
|
|
21
|
-
const tagHeaders = {
|
|
22
|
-
[TAG_HEADER]: `${mode.kind}:${source}`,
|
|
23
|
-
};
|
|
24
|
-
switch (mode.kind) {
|
|
25
|
-
case 'http-status':
|
|
26
|
-
return {
|
|
27
|
-
status: mode.status,
|
|
28
|
-
json: { error: true, status: mode.status, injected: mode.kind },
|
|
29
|
-
headers: tagHeaders,
|
|
30
|
-
};
|
|
31
|
-
case 'business-failure':
|
|
32
|
-
return {
|
|
33
|
-
status: 200,
|
|
34
|
-
json: {
|
|
35
|
-
success: false,
|
|
36
|
-
message: mode.message,
|
|
37
|
-
...(mode.extra ?? {}),
|
|
38
|
-
},
|
|
39
|
-
headers: { ...tagHeaders, 'content-type': 'application/json' },
|
|
40
|
-
};
|
|
41
|
-
case 'custom-body': {
|
|
42
|
-
const status = mode.status ?? 200;
|
|
43
|
-
const contentType = mode.contentType ?? 'application/json';
|
|
44
|
-
if (typeof mode.body === 'string' && !contentType.includes('json')) {
|
|
45
|
-
return {
|
|
46
|
-
status,
|
|
47
|
-
text: mode.body,
|
|
48
|
-
headers: { ...tagHeaders, 'content-type': contentType },
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
const payload = typeof mode.body === 'string' ? mode.body : JSON.stringify(mode.body);
|
|
52
|
-
return {
|
|
53
|
-
status,
|
|
54
|
-
raw: payload,
|
|
55
|
-
headers: { ...tagHeaders, 'content-type': contentType },
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
case 'empty-body':
|
|
59
|
-
return {
|
|
60
|
-
status: mode.status ?? 204,
|
|
61
|
-
empty: true,
|
|
62
|
-
headers: tagHeaders,
|
|
63
|
-
};
|
|
64
|
-
case 'malformed-json':
|
|
65
|
-
return {
|
|
66
|
-
status: mode.status ?? 200,
|
|
67
|
-
raw: '{',
|
|
68
|
-
headers: { ...tagHeaders, 'content-type': 'application/json' },
|
|
69
|
-
};
|
|
70
|
-
/* v8 ignore start -- defensive: delay/hang/destroy never reach here */
|
|
71
|
-
case 'delay':
|
|
72
|
-
case 'hang':
|
|
73
|
-
case 'destroy':
|
|
74
|
-
// delay/hang are handled before this function; destroy is dispatched
|
|
75
|
-
// through the sentinel branch. Reaching here is a bug.
|
|
76
|
-
return {
|
|
77
|
-
status: 500,
|
|
78
|
-
json: {
|
|
79
|
-
error: true,
|
|
80
|
-
message: `inject: ${mode.kind} should be handled before buildResponse`,
|
|
81
|
-
},
|
|
82
|
-
headers: tagHeaders,
|
|
83
|
-
};
|
|
84
|
-
/* v8 ignore stop */
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
const buildDestroyDisabledResponse = () => ({
|
|
88
|
-
status: 503,
|
|
89
|
-
json: {
|
|
90
|
-
error: 'x-mock-destroy disabled by admin.allowDestroy:false',
|
|
91
|
-
},
|
|
92
|
-
headers: { [TAG_HEADER]: 'destroy-disabled' },
|
|
93
|
-
});
|
|
94
|
-
/**
|
|
95
|
-
* Sentinel response: shaped as a normal empty 204 so anything that
|
|
96
|
-
* inspects the public type sees a valid response, but tagged with
|
|
97
|
-
* {@link DESTROY_SOCKET_SENTINEL} so `server.listen()` can drop the
|
|
98
|
-
* socket instead of writing the body.
|
|
99
|
-
*/
|
|
100
|
-
const buildDestroySentinel = () => {
|
|
101
|
-
const base = {
|
|
102
|
-
status: 204,
|
|
103
|
-
empty: true,
|
|
104
|
-
headers: { [TAG_HEADER]: 'destroy' },
|
|
105
|
-
};
|
|
106
|
-
Object.defineProperty(base, DESTROY_SOCKET_SENTINEL, {
|
|
107
|
-
value: true,
|
|
108
|
-
enumerable: false,
|
|
109
|
-
writable: false,
|
|
110
|
-
configurable: false,
|
|
111
|
-
});
|
|
112
|
-
return base;
|
|
113
|
-
};
|
|
114
|
-
export const createInjectHook = (opts) => {
|
|
115
|
-
const { store } = opts;
|
|
116
|
-
const bypass = opts.bypassPathPrefixes ?? ['/databehave'];
|
|
117
|
-
const allowDestroy = opts.allowDestroy !== false;
|
|
118
|
-
const logger = opts.logger ?? console;
|
|
119
|
-
const shouldBypass = (path) => bypass.some((p) => path.startsWith(p));
|
|
120
|
-
return async (req) => {
|
|
121
|
-
if (shouldBypass(req.path))
|
|
122
|
-
return undefined;
|
|
123
|
-
const resolved = resolveMode(store, req.method, req.path, req.headers);
|
|
124
|
-
if (resolved.kind === 'none')
|
|
125
|
-
return undefined;
|
|
126
|
-
if (resolved.kind === 'error') {
|
|
127
|
-
return {
|
|
128
|
-
status: 400,
|
|
129
|
-
json: { error: 'invalid x-mock-* header', detail: resolved.message },
|
|
130
|
-
headers: { [TAG_HEADER]: 'header-error' },
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
const { mode, source } = resolved;
|
|
134
|
-
if (mode.kind === 'hang') {
|
|
135
|
-
logger.warn(`[@databehave/server/admin] hang triggered on ${req.method} ${req.path} ` +
|
|
136
|
-
`(source=${source}) — request will never resolve; close the client to recover.`);
|
|
137
|
-
/* v8 ignore start -- promise never resolves; return is unreachable */
|
|
138
|
-
await new Promise(() => {
|
|
139
|
-
/* never resolves */
|
|
140
|
-
});
|
|
141
|
-
return undefined;
|
|
142
|
-
/* v8 ignore stop */
|
|
143
|
-
}
|
|
144
|
-
if (mode.kind === 'destroy') {
|
|
145
|
-
if (!allowDestroy) {
|
|
146
|
-
logger.warn(`[@databehave/server/admin] destroy requested on ${req.method} ${req.path} ` +
|
|
147
|
-
`(source=${source}) but admin.allowDestroy:false — responding 503.`);
|
|
148
|
-
return buildDestroyDisabledResponse();
|
|
149
|
-
}
|
|
150
|
-
return buildDestroySentinel();
|
|
151
|
-
}
|
|
152
|
-
if (mode.kind === 'delay') {
|
|
153
|
-
await new Promise((r) => setTimeout(r, mode.ms));
|
|
154
|
-
if (mode.then === undefined)
|
|
155
|
-
return undefined;
|
|
156
|
-
return buildResponse(mode.then, source);
|
|
157
|
-
}
|
|
158
|
-
return buildResponse(mode, source);
|
|
159
|
-
};
|
|
160
|
-
};
|
|
161
|
-
/** True when the response carries the internal destroy-socket sentinel. */
|
|
162
|
-
export const isDestroySocketSentinel = (res) => {
|
|
163
|
-
if (!res)
|
|
164
|
-
return false;
|
|
165
|
-
return res[DESTROY_SOCKET_SENTINEL] === true;
|
|
166
|
-
};
|
|
167
|
-
//# sourceMappingURL=inject.js.map
|
package/dist/admin/inject.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"inject.js","sourceRoot":"","sources":["../../src/admin/inject.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { ErrorMode, StickyMatcher, StickyOverride } from './admin-types.js';
|
|
2
|
-
export interface OverridesStoreLogger {
|
|
3
|
-
warn(message: string): void;
|
|
4
|
-
info?(message: string): void;
|
|
5
|
-
}
|
|
6
|
-
export interface OverridesStore {
|
|
7
|
-
add(input: {
|
|
8
|
-
matcher: StickyMatcher;
|
|
9
|
-
mode: ErrorMode;
|
|
10
|
-
description?: string;
|
|
11
|
-
}): StickyOverride;
|
|
12
|
-
remove(id: string): boolean;
|
|
13
|
-
list(): readonly StickyOverride[];
|
|
14
|
-
clear(): number;
|
|
15
|
-
resolve(method: string, path: string): StickyOverride | undefined;
|
|
16
|
-
}
|
|
17
|
-
export declare const createOverridesStore: (logger?: OverridesStoreLogger) => OverridesStore;
|
|
18
|
-
//# sourceMappingURL=overrides-store.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"overrides-store.d.ts","sourceRoot":"","sources":["../../src/admin/overrides-store.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEhF,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,KAAK,EAAE;QACT,OAAO,EAAE,aAAa,CAAA;QACtB,IAAI,EAAE,SAAS,CAAA;QACf,WAAW,CAAC,EAAE,MAAM,CAAA;KACrB,GAAG,cAAc,CAAA;IAClB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;IAC3B,IAAI,IAAI,SAAS,cAAc,EAAE,CAAA;IACjC,KAAK,IAAI,MAAM,CAAA;IACf,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAAA;CAClE;AAED,eAAO,MAAM,oBAAoB,GAC/B,SAAQ,oBAA8B,KACrC,cAkGF,CAAA"}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* In-memory sticky overrides registry. Lost on process restart by
|
|
3
|
-
* design — this tool is for ad-hoc dev sessions, not persistence.
|
|
4
|
-
*
|
|
5
|
-
* Resolution priority (first hit wins): `exact` > `path` > `global`.
|
|
6
|
-
* When two stickies live at the same priority level, the **last** one
|
|
7
|
-
* added wins (and a warning is logged) so the dev's most-recent click
|
|
8
|
-
* in the UI is always the active rule.
|
|
9
|
-
*/
|
|
10
|
-
import { randomUUID } from 'node:crypto';
|
|
11
|
-
export const createOverridesStore = (logger = console) => {
|
|
12
|
-
// Insertion-ordered. `Map.values()` yields oldest → newest, so
|
|
13
|
-
// when iterating we keep track of the *last* hit per priority bucket.
|
|
14
|
-
const byId = new Map();
|
|
15
|
-
const sameMatcher = (a, b) => {
|
|
16
|
-
if (a.kind !== b.kind)
|
|
17
|
-
return false;
|
|
18
|
-
if (a.kind === 'exact' && b.kind === 'exact') {
|
|
19
|
-
return (a.method.toUpperCase() === b.method.toUpperCase() && a.path === b.path);
|
|
20
|
-
}
|
|
21
|
-
if (a.kind === 'path' && b.kind === 'path')
|
|
22
|
-
return a.path === b.path;
|
|
23
|
-
return a.kind === 'global' && b.kind === 'global';
|
|
24
|
-
};
|
|
25
|
-
const describeMatcher = (m) => {
|
|
26
|
-
if (m.kind === 'exact')
|
|
27
|
-
return `${m.method.toUpperCase()} ${m.path}`;
|
|
28
|
-
if (m.kind === 'path')
|
|
29
|
-
return `* ${m.path}`;
|
|
30
|
-
return '* (global)';
|
|
31
|
-
};
|
|
32
|
-
const add = ({ matcher, mode, description }) => {
|
|
33
|
-
// Detect same-matcher collision so the warning is informative.
|
|
34
|
-
for (const existing of byId.values()) {
|
|
35
|
-
if (sameMatcher(existing.matcher, matcher)) {
|
|
36
|
-
logger.warn(`[mock-server/overrides] duplicate matcher ${describeMatcher(matcher)} ` +
|
|
37
|
-
`— new rule shadows ${existing.id} (last-wins). Remove the old one if unintended.`);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
const override = {
|
|
41
|
-
id: randomUUID(),
|
|
42
|
-
matcher: matcher.kind === 'exact'
|
|
43
|
-
? {
|
|
44
|
-
kind: 'exact',
|
|
45
|
-
method: matcher.method.toUpperCase(),
|
|
46
|
-
path: matcher.path,
|
|
47
|
-
}
|
|
48
|
-
: matcher.kind === 'global' && matcher.methods && matcher.methods.length > 0
|
|
49
|
-
? {
|
|
50
|
-
kind: 'global',
|
|
51
|
-
methods: matcher.methods.map((m) => m.toUpperCase()),
|
|
52
|
-
}
|
|
53
|
-
: matcher.kind === 'global'
|
|
54
|
-
? { kind: 'global' }
|
|
55
|
-
: matcher,
|
|
56
|
-
mode,
|
|
57
|
-
createdAt: new Date().toISOString(),
|
|
58
|
-
...(description !== undefined ? { description } : {}),
|
|
59
|
-
};
|
|
60
|
-
byId.set(override.id, override);
|
|
61
|
-
return override;
|
|
62
|
-
};
|
|
63
|
-
const remove = (id) => byId.delete(id);
|
|
64
|
-
const list = () => [...byId.values()];
|
|
65
|
-
const clear = () => {
|
|
66
|
-
const n = byId.size;
|
|
67
|
-
byId.clear();
|
|
68
|
-
return n;
|
|
69
|
-
};
|
|
70
|
-
const resolve = (method, path) => {
|
|
71
|
-
const m = method.toUpperCase();
|
|
72
|
-
// Walk newest → oldest so the last-added rule wins per bucket.
|
|
73
|
-
const all = [...byId.values()].reverse();
|
|
74
|
-
let exactHit;
|
|
75
|
-
let pathHit;
|
|
76
|
-
let globalHit;
|
|
77
|
-
for (const o of all) {
|
|
78
|
-
if (o.matcher.kind === 'exact') {
|
|
79
|
-
if (!exactHit && o.matcher.method === m && o.matcher.path === path) {
|
|
80
|
-
exactHit = o;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
else if (o.matcher.kind === 'path') {
|
|
84
|
-
if (!pathHit && o.matcher.path === path)
|
|
85
|
-
pathHit = o;
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
if (!globalHit
|
|
89
|
-
&& (!o.matcher.methods
|
|
90
|
-
|| o.matcher.methods.length === 0
|
|
91
|
-
|| o.matcher.methods.includes(m))) {
|
|
92
|
-
globalHit = o;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return exactHit ?? pathHit ?? globalHit;
|
|
97
|
-
};
|
|
98
|
-
return { add, remove, list, clear, resolve };
|
|
99
|
-
};
|
|
100
|
-
//# sourceMappingURL=overrides-store.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"overrides-store.js","sourceRoot":"","sources":["../../src/admin/overrides-store.ts"],"names":[],"mappings":"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"}
|