@crvouga/mockingbird-service-dynamodb 1.7.0 → 1.8.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/dist/cli.js CHANGED
@@ -3,8 +3,8 @@ import {
3
3
  runCli,
4
4
  serveCommand,
5
5
  serveTarget
6
- } from "./chunk-3H6JAYFX.js";
7
- import "./chunk-HOHDGG7L.js";
6
+ } from "./chunk-J5TIADMI.js";
7
+ import "./chunk-MKCHND4G.js";
8
8
 
9
9
  // src/cli.ts
10
10
  var code = await runCli(
package/dist/index.d.ts CHANGED
@@ -207,6 +207,15 @@ type FaultCandidate = {
207
207
  namespace: string;
208
208
  };
209
209
  type FaultRegistry = {
210
+ isolateNamespaces(): void;
211
+ snapshot(namespace: string): {
212
+ rules: (FaultRule & {
213
+ remaining: number | null;
214
+ hits: number;
215
+ position: number;
216
+ })[];
217
+ rngState: number;
218
+ };
210
219
  add(rule: FaultRule): FaultRule;
211
220
  list(): (FaultRule & {
212
221
  remaining: number | null;
@@ -214,6 +223,14 @@ type FaultRegistry = {
214
223
  })[];
215
224
  remove(id: string): boolean;
216
225
  clear(): void;
226
+ restore(namespace: string, state: {
227
+ rules: (FaultRule & {
228
+ remaining: number | null;
229
+ hits: number;
230
+ position: number;
231
+ })[];
232
+ rngState: number;
233
+ }): void;
217
234
  /**
218
235
  * Every fault this request should get, in rule order, stopping at the first that answers
219
236
  * or drops (effect-only and delay-only rules let later rules match too). Consumes one of
@@ -391,8 +408,8 @@ type MetricsReport = {
391
408
  };
392
409
  type Metrics = {
393
410
  record(entry: RequestLog): void;
394
- report(): MetricsReport;
395
- reset(): void;
411
+ report(namespace?: string): MetricsReport;
412
+ reset(namespace?: string): void;
396
413
  };
397
414
 
398
415
  /** One journal entry: a request log stamped with when (on the mock clock) it was handled. */
@@ -558,6 +575,9 @@ type PublishInput = {
558
575
  id?: string;
559
576
  };
560
577
  type WebhookHub = {
578
+ pending(namespace: string): number;
579
+ snapshot(namespace: string): unknown;
580
+ restore(namespace: string, snapshot: unknown): void;
561
581
  publish(input: PublishInput): WebhookMessage;
562
582
  /** Replace a namespace's own endpoints (`PUT /__admin/webhook-endpoints`). */
563
583
  setEndpoints(namespace: string, endpoints: WebhookEndpoint[]): WebhookEndpoint[];
@@ -585,6 +605,8 @@ type ServiceTimelineState = Readonly<{
585
605
  }>;
586
606
  type ServiceCheckpoint = Checkpoint<ServiceTimelineState>;
587
607
  type ServiceRuntime<T extends ServiceInstance> = FetchAPI & {
608
+ /** Stop package-owned lifecycle timers when a supervisor closes the runtime. */
609
+ stop?(): void;
588
610
  readonly name: string;
589
611
  readonly sqlite: SqliteClient$1;
590
612
  readonly clock: Clock;
@@ -595,6 +617,13 @@ type ServiceRuntime<T extends ServiceInstance> = FetchAPI & {
595
617
  readonly credentials: CredentialRegistry;
596
618
  /** The webhook hub, when the service has outbound webhooks. */
597
619
  readonly webhooks: WebhookHub | undefined;
620
+ /** Enable independent namespace clocks and PRNGs before serving a fleet. */
621
+ isolateNamespaces(): void;
622
+ namespaceClock(namespace?: string): Clock;
623
+ namespaceOf(request: Request): string;
624
+ /** Opaque in-process checkpoint including records, controls and webhook history. */
625
+ fleetSnapshot(namespace: string): object;
626
+ fleetRestore(snapshot: unknown, namespace: string): void;
598
627
  /** Expand a named preset into fault rules (and webhook faults) for `namespace`. */
599
628
  applyPreset(name: string, namespace?: string, overrides?: Partial<FaultRule>): FaultRule[];
600
629
  /** The instance behind `namespace` (the default one when omitted), created on first use. */
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  document,
8
8
  operationIds,
9
9
  supportedOperationIds
10
- } from "./chunk-HOHDGG7L.js";
10
+ } from "./chunk-MKCHND4G.js";
11
11
  export {
12
12
  DYNAMODB_NAMESPACE,
13
13
  DYNAMODB_PRESETS,
package/dist/server.d.ts CHANGED
@@ -154,6 +154,15 @@ type FaultCandidate$1 = {
154
154
  namespace: string;
155
155
  };
156
156
  type FaultRegistry$1 = {
157
+ isolateNamespaces(): void;
158
+ snapshot(namespace: string): {
159
+ rules: (FaultRule$1 & {
160
+ remaining: number | null;
161
+ hits: number;
162
+ position: number;
163
+ })[];
164
+ rngState: number;
165
+ };
157
166
  add(rule: FaultRule$1): FaultRule$1;
158
167
  list(): (FaultRule$1 & {
159
168
  remaining: number | null;
@@ -161,6 +170,14 @@ type FaultRegistry$1 = {
161
170
  })[];
162
171
  remove(id: string): boolean;
163
172
  clear(): void;
173
+ restore(namespace: string, state: {
174
+ rules: (FaultRule$1 & {
175
+ remaining: number | null;
176
+ hits: number;
177
+ position: number;
178
+ })[];
179
+ rngState: number;
180
+ }): void;
164
181
  /**
165
182
  * Every fault this request should get, in rule order, stopping at the first that answers
166
183
  * or drops (effect-only and delay-only rules let later rules match too). Consumes one of
@@ -325,8 +342,8 @@ type MetricsReport$1 = {
325
342
  };
326
343
  type Metrics$1 = {
327
344
  record(entry: RequestLog$1): void;
328
- report(): MetricsReport$1;
329
- reset(): void;
345
+ report(namespace?: string): MetricsReport$1;
346
+ reset(namespace?: string): void;
330
347
  };
331
348
 
332
349
  /** One journal entry: a request log stamped with when (on the mock clock) it was handled. */
@@ -480,6 +497,9 @@ type PublishInput$1 = {
480
497
  id?: string;
481
498
  };
482
499
  type WebhookHub$1 = {
500
+ pending(namespace: string): number;
501
+ snapshot(namespace: string): unknown;
502
+ restore(namespace: string, snapshot: unknown): void;
483
503
  publish(input: PublishInput$1): WebhookMessage$1;
484
504
  /** Replace a namespace's own endpoints (`PUT /__admin/webhook-endpoints`). */
485
505
  setEndpoints(namespace: string, endpoints: WebhookEndpoint$1[]): WebhookEndpoint$1[];
@@ -507,6 +527,8 @@ type ServiceTimelineState$1 = Readonly<{
507
527
  }>;
508
528
  type ServiceCheckpoint$1 = Checkpoint$1<ServiceTimelineState$1>;
509
529
  type ServiceRuntime$1<T extends ServiceInstance$1> = FetchAPI$1 & {
530
+ /** Stop package-owned lifecycle timers when a supervisor closes the runtime. */
531
+ stop?(): void;
510
532
  readonly name: string;
511
533
  readonly sqlite: SqliteClient$2;
512
534
  readonly clock: Clock$1;
@@ -517,6 +539,13 @@ type ServiceRuntime$1<T extends ServiceInstance$1> = FetchAPI$1 & {
517
539
  readonly credentials: CredentialRegistry$1;
518
540
  /** The webhook hub, when the service has outbound webhooks. */
519
541
  readonly webhooks: WebhookHub$1 | undefined;
542
+ /** Enable independent namespace clocks and PRNGs before serving a fleet. */
543
+ isolateNamespaces(): void;
544
+ namespaceClock(namespace?: string): Clock$1;
545
+ namespaceOf(request: Request): string;
546
+ /** Opaque in-process checkpoint including records, controls and webhook history. */
547
+ fleetSnapshot(namespace: string): object;
548
+ fleetRestore(snapshot: unknown, namespace: string): void;
520
549
  /** Expand a named preset into fault rules (and webhook faults) for `namespace`. */
521
550
  applyPreset(name: string, namespace?: string, overrides?: Partial<FaultRule$1>): FaultRule$1[];
522
551
  /** The instance behind `namespace` (the default one when omitted), created on first use. */
@@ -780,6 +809,15 @@ type FaultCandidate = {
780
809
  namespace: string;
781
810
  };
782
811
  type FaultRegistry = {
812
+ isolateNamespaces(): void;
813
+ snapshot(namespace: string): {
814
+ rules: (FaultRule & {
815
+ remaining: number | null;
816
+ hits: number;
817
+ position: number;
818
+ })[];
819
+ rngState: number;
820
+ };
783
821
  add(rule: FaultRule): FaultRule;
784
822
  list(): (FaultRule & {
785
823
  remaining: number | null;
@@ -787,6 +825,14 @@ type FaultRegistry = {
787
825
  })[];
788
826
  remove(id: string): boolean;
789
827
  clear(): void;
828
+ restore(namespace: string, state: {
829
+ rules: (FaultRule & {
830
+ remaining: number | null;
831
+ hits: number;
832
+ position: number;
833
+ })[];
834
+ rngState: number;
835
+ }): void;
790
836
  /**
791
837
  * Every fault this request should get, in rule order, stopping at the first that answers
792
838
  * or drops (effect-only and delay-only rules let later rules match too). Consumes one of
@@ -964,8 +1010,8 @@ type MetricsReport = {
964
1010
  };
965
1011
  type Metrics = {
966
1012
  record(entry: RequestLog): void;
967
- report(): MetricsReport;
968
- reset(): void;
1013
+ report(namespace?: string): MetricsReport;
1014
+ reset(namespace?: string): void;
969
1015
  };
970
1016
 
971
1017
  /** One journal entry: a request log stamped with when (on the mock clock) it was handled. */
@@ -1131,6 +1177,9 @@ type PublishInput = {
1131
1177
  id?: string;
1132
1178
  };
1133
1179
  type WebhookHub = {
1180
+ pending(namespace: string): number;
1181
+ snapshot(namespace: string): unknown;
1182
+ restore(namespace: string, snapshot: unknown): void;
1134
1183
  publish(input: PublishInput): WebhookMessage;
1135
1184
  /** Replace a namespace's own endpoints (`PUT /__admin/webhook-endpoints`). */
1136
1185
  setEndpoints(namespace: string, endpoints: WebhookEndpoint[]): WebhookEndpoint[];
@@ -1158,6 +1207,8 @@ type ServiceTimelineState = Readonly<{
1158
1207
  }>;
1159
1208
  type ServiceCheckpoint = Checkpoint<ServiceTimelineState>;
1160
1209
  type ServiceRuntime<T extends ServiceInstance> = FetchAPI & {
1210
+ /** Stop package-owned lifecycle timers when a supervisor closes the runtime. */
1211
+ stop?(): void;
1161
1212
  readonly name: string;
1162
1213
  readonly sqlite: SqliteClient$1;
1163
1214
  readonly clock: Clock;
@@ -1168,6 +1219,13 @@ type ServiceRuntime<T extends ServiceInstance> = FetchAPI & {
1168
1219
  readonly credentials: CredentialRegistry;
1169
1220
  /** The webhook hub, when the service has outbound webhooks. */
1170
1221
  readonly webhooks: WebhookHub | undefined;
1222
+ /** Enable independent namespace clocks and PRNGs before serving a fleet. */
1223
+ isolateNamespaces(): void;
1224
+ namespaceClock(namespace?: string): Clock;
1225
+ namespaceOf(request: Request): string;
1226
+ /** Opaque in-process checkpoint including records, controls and webhook history. */
1227
+ fleetSnapshot(namespace: string): object;
1228
+ fleetRestore(snapshot: unknown, namespace: string): void;
1171
1229
  /** Expand a named preset into fault rules (and webhook faults) for `namespace`. */
1172
1230
  applyPreset(name: string, namespace?: string, overrides?: Partial<FaultRule>): FaultRule[];
1173
1231
  /** The instance behind `namespace` (the default one when omitted), created on first use. */
package/dist/server.js CHANGED
@@ -2,8 +2,8 @@ import {
2
2
  DEFAULT_PORT,
3
3
  createServer,
4
4
  serveTarget
5
- } from "./chunk-3H6JAYFX.js";
6
- import "./chunk-HOHDGG7L.js";
5
+ } from "./chunk-J5TIADMI.js";
6
+ import "./chunk-MKCHND4G.js";
7
7
  export {
8
8
  DEFAULT_PORT,
9
9
  createServer,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crvouga/mockingbird-service-dynamodb",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "description": "Stateful Amazon DynamoDB mock with typed items, expressions, indexes, pagination, transactions, and streams.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,334 +0,0 @@
1
- import {
2
- createRuntime
3
- } from "./chunk-HOHDGG7L.js";
4
-
5
- // ../../adapters/node/dist/cli.js
6
- import { readFile } from "node:fs/promises";
7
- import { parseArgs } from "node:util";
8
-
9
- // ../../adapters/node/dist/serve.js
10
- import { createServer } from "node:http";
11
- var serve = async (api, options = {}) => {
12
- const server = createServer(async (req, res) => {
13
- const chunks = [];
14
- for await (const chunk of req) {
15
- chunks.push(Buffer.from(chunk));
16
- }
17
- const body = Buffer.concat(chunks);
18
- const address = server.address();
19
- const port = typeof address === "object" && address !== null ? address.port : void 0;
20
- const base = `http://${req.headers.host ?? `localhost:${port ?? 80}`}`;
21
- const raw = req.url ?? "/";
22
- const url = new URL(raw.replace(/^\/+/, "/"), base);
23
- const method = req.method ?? "GET";
24
- const init = { method, headers: req.headers };
25
- if (method !== "GET" && method !== "HEAD" && body.length > 0) {
26
- init.body = body;
27
- }
28
- const aborted = new AbortController();
29
- res.once("close", () => {
30
- if (!res.writableFinished)
31
- aborted.abort();
32
- });
33
- init.signal = aborted.signal;
34
- const request = new Request(url, init);
35
- let response;
36
- try {
37
- response = await api.fetch(request);
38
- } catch (error) {
39
- if (error.code === "MOCKINGBIRD_DROP") {
40
- req.socket.destroy();
41
- return;
42
- }
43
- res.writeHead(500, { "content-type": "application/json" });
44
- res.end(JSON.stringify({
45
- error: {
46
- type: "mockingbird_internal",
47
- message: error instanceof Error ? error.message : String(error)
48
- }
49
- }));
50
- return;
51
- }
52
- const headers = Object.fromEntries(response.headers);
53
- const cookies = response.headers.getSetCookie();
54
- if (cookies.length > 0)
55
- headers["set-cookie"] = cookies;
56
- if (!response.body) {
57
- res.writeHead(response.status, headers);
58
- res.end();
59
- return;
60
- }
61
- res.writeHead(response.status, headers);
62
- res.flushHeaders();
63
- const reader = response.body.getReader();
64
- try {
65
- for (; ; ) {
66
- const { done, value } = await reader.read();
67
- if (done)
68
- break;
69
- if (!res.write(value))
70
- await new Promise((resolve) => res.once("drain", resolve));
71
- }
72
- res.end();
73
- } catch {
74
- res.destroy();
75
- } finally {
76
- reader.releaseLock();
77
- }
78
- });
79
- await new Promise((resolve, reject) => {
80
- server.once("error", reject);
81
- server.listen(options.port ?? 0, options.host, resolve);
82
- });
83
- return server;
84
- };
85
-
86
- // ../../adapters/node/dist/listen.js
87
- var listen = async (api, options = {}) => {
88
- const host = options.host ?? "127.0.0.1";
89
- const server = await serve(api, { port: options.port ?? 0, host });
90
- const address = server.address();
91
- const port = typeof address === "object" && address !== null ? address.port : options.port ?? 0;
92
- const shown = host.includes(":") ? `[${host}]` : host;
93
- return {
94
- url: `http://${shown}:${port}`,
95
- port,
96
- host,
97
- server,
98
- close: () => new Promise((resolve, reject) => {
99
- server.close((error) => {
100
- if (error && error.code !== "ERR_SERVER_NOT_RUNNING")
101
- reject(error);
102
- else
103
- resolve();
104
- });
105
- server.closeAllConnections?.();
106
- })
107
- };
108
- };
109
-
110
- // ../../adapters/node/dist/cli.js
111
- var optionHelp = (options) => Object.entries(options).map(([name, option]) => {
112
- const flag = `--${name}${option.type === "string" ? ` ${option.value ?? "<value>"}` : ""}`;
113
- const fallback = option.default !== void 0 ? ` (default: ${String(option.default)})` : "";
114
- return ` ${flag.padEnd(30)} ${option.description}${fallback}`;
115
- });
116
- var help = (spec) => [
117
- `${spec.bin} \u2014 ${spec.description}`,
118
- "",
119
- "Usage:",
120
- ` ${spec.bin} <command> [options]`,
121
- "",
122
- "Commands:",
123
- ...Object.entries(spec.commands).map(([name, c]) => ` ${name.padEnd(30)} ${c.summary}`),
124
- "",
125
- `Run \`${spec.bin} <command> --help\` for a command's options.`
126
- ].join("\n");
127
- var commandHelp = (spec, name, command) => [
128
- `${spec.bin} ${name} \u2014 ${command.summary}`,
129
- "",
130
- "Usage:",
131
- ` ${command.usage ?? `${spec.bin} ${name} [options]`}`,
132
- ...command.options ? ["", "Options:", ...optionHelp(command.options)] : []
133
- ].join("\n");
134
- var runCli = async (spec, argv) => {
135
- const pair = argv.length >= 2 ? `${argv[0]} ${argv[1]}` : void 0;
136
- const words = pair !== void 0 && spec.commands[pair] ? 2 : 1;
137
- const name = words === 2 ? pair : argv[0];
138
- const rest = argv.slice(words);
139
- if (name === void 0 || name === "--help" || name === "-h" || name === "help") {
140
- console.log(help(spec));
141
- return 0;
142
- }
143
- const command = spec.commands[name];
144
- if (!command) {
145
- console.error(`${spec.bin}: unknown command ${JSON.stringify(name)}
146
-
147
- ${help(spec)}`);
148
- return 2;
149
- }
150
- if (rest.includes("--help") || rest.includes("-h")) {
151
- console.log(commandHelp(spec, name, command));
152
- return 0;
153
- }
154
- let parsed;
155
- try {
156
- parsed = parseArgs({
157
- args: rest,
158
- allowPositionals: true,
159
- strict: true,
160
- options: Object.fromEntries(Object.entries(command.options ?? {}).map(([key, option]) => [
161
- key,
162
- {
163
- type: option.type,
164
- ...option.default !== void 0 ? { default: option.default } : {}
165
- }
166
- ]))
167
- });
168
- } catch (error) {
169
- console.error(`${spec.bin} ${name}: ${error instanceof Error ? error.message : String(error)}
170
-
171
- ${commandHelp(spec, name, command)}`);
172
- return 2;
173
- }
174
- return command.run(parsed.values, parsed.positionals);
175
- };
176
- var COMMON_SERVE_OPTIONS = {
177
- port: { type: "string", value: "<port>", description: "Port to listen on" },
178
- host: { type: "string", value: "<host>", description: "Interface to bind", default: "127.0.0.1" },
179
- "admin-key": {
180
- type: "string",
181
- value: "<key>",
182
- description: "Require x-mockingbird-admin-key on /__admin/* (env MOCKINGBIRD_ADMIN_KEY)"
183
- },
184
- seed: { type: "string", value: "<seed>", description: "Seed for every random choice" },
185
- log: {
186
- type: "string",
187
- value: "<pretty|json|off>",
188
- description: "Request log format",
189
- default: "pretty"
190
- },
191
- "log-requests": {
192
- type: "boolean",
193
- description: "One JSON line per request: namespace, operationId, status, ids touched (never bodies). Same as --log json"
194
- },
195
- config: {
196
- type: "string",
197
- value: "<file>",
198
- description: "Serve every service in a mockingbird.json config instead"
199
- }
200
- };
201
- var formatLog = (format) => {
202
- if (format === "off")
203
- return void 0;
204
- if (format === "json")
205
- return (entry) => console.log(JSON.stringify(entry));
206
- return (entry) => {
207
- const op = entry.operationId ?? (entry.unmatched ? "UNMATCHED" : "-");
208
- const ns = entry.namespace === "default" ? "" : ` [${entry.namespace}]`;
209
- const fault = entry.faultId ? ` fault=${entry.faultId}` : "";
210
- const adopted = entry.adopted ? " adopted" : "";
211
- const received = entry.request ? ` received=${entry.request.bodyBytes === null ? "?" : `${entry.request.bodyBytes}B`} ct=${entry.request.contentType ?? "-"}${entry.request.transferEncoding ? ` te=${entry.request.transferEncoding}` : ""}` : "";
212
- const issues = entry.issues?.length ? ` issues=${entry.issues.slice(0, 3).map((issue) => `${issue.path || "$"}: ${issue.message}`).join("; ")}${entry.issues.length > 3 ? ` (+${entry.issues.length - 3})` : ""}` : "";
213
- console.log(`${entry.service} ${entry.method} ${entry.path} ${entry.status} ${op} ${entry.durationMs}ms${ns}${fault}${adopted}${received}${issues}`);
214
- };
215
- };
216
- var asString = (value) => typeof value === "string" ? value : void 0;
217
- var loadTarget = async (name, own) => {
218
- if (name === own.name)
219
- return own;
220
- const specifier = `@crvouga/mockingbird-service-${name}/server`;
221
- try {
222
- const mod = await import(specifier);
223
- if (!mod.serveTarget)
224
- throw new Error(`${specifier} exports no serveTarget`);
225
- return mod.serveTarget;
226
- } catch (error) {
227
- const reason = error instanceof Error ? error.message : String(error);
228
- throw new Error(`cannot load service "${name}": ${reason}. Install @crvouga/mockingbird-service-${name}.`);
229
- }
230
- };
231
- var start = async (target, values, config) => {
232
- const runtime = await target.create(values, {
233
- adminKey: config.adminKey,
234
- seed: config.seed,
235
- onLog: formatLog(config.log)
236
- });
237
- const listening = await listen(runtime, { port: config.port, host: config.host });
238
- target.listening?.(listening);
239
- console.log(`${target.name} mock listening on ${listening.url}`);
240
- console.log(`${target.name} health: GET ${listening.url}/health`);
241
- console.log(`${target.name} admin: ${listening.url}/__admin (${config.adminKey ? "x-mockingbird-admin-key required" : "open \u2014 pass --admin-key to lock"})`);
242
- console.log(`${target.name} admin ui: ${listening.url}/__admin/ui`);
243
- for (const line of target.banner?.(runtime) ?? [])
244
- console.log(`${target.name} ${line}`);
245
- return listening;
246
- };
247
- var untilSignal = async (servers) => new Promise((resolve) => {
248
- const stop = async () => {
249
- await Promise.allSettled(servers.map((s) => s.close()));
250
- resolve(0);
251
- };
252
- process.once("SIGINT", stop);
253
- process.once("SIGTERM", stop);
254
- });
255
- var serveCommand = (target) => ({
256
- summary: `Serve the ${target.name} mock over HTTP`,
257
- options: { ...COMMON_SERVE_OPTIONS, ...target.options },
258
- async run(values) {
259
- const log = values["log-requests"] === true ? "json" : asString(values.log) ?? "pretty";
260
- if (!["pretty", "json", "off"].includes(log)) {
261
- console.error(`--log must be pretty, json or off (got ${log})`);
262
- return 2;
263
- }
264
- const configPath = asString(values.config);
265
- if (configPath !== void 0) {
266
- const config = JSON.parse(await readFile(configPath, "utf8"));
267
- const servers = [];
268
- try {
269
- for (const [name, entry] of Object.entries(config.services ?? {})) {
270
- const each = await loadTarget(name, target);
271
- servers.push(await start(each, entry.options ?? {}, {
272
- port: entry.port ?? each.defaultPort,
273
- host: entry.host ?? "127.0.0.1",
274
- ...entry.adminKey !== void 0 ? { adminKey: entry.adminKey } : {},
275
- ...entry.seed !== void 0 ? { seed: entry.seed } : {},
276
- log: config.log ?? log
277
- }));
278
- }
279
- } catch (error) {
280
- await Promise.allSettled(servers.map((s) => s.close()));
281
- console.error(error instanceof Error ? error.message : String(error));
282
- return 1;
283
- }
284
- return untilSignal(servers);
285
- }
286
- const port = asString(values.port);
287
- const adminKey = asString(values["admin-key"]) ?? process.env.MOCKINGBIRD_ADMIN_KEY;
288
- const seed = asString(values.seed);
289
- let listening;
290
- try {
291
- listening = await start(target, values, {
292
- port: port === void 0 ? target.defaultPort : Number.parseInt(port, 10),
293
- host: asString(values.host) ?? "127.0.0.1",
294
- ...adminKey !== void 0 ? { adminKey } : {},
295
- ...seed !== void 0 ? { seed } : {},
296
- log
297
- });
298
- } catch (error) {
299
- console.error(error instanceof Error ? error.message : String(error));
300
- return 1;
301
- }
302
- return untilSignal([listening]);
303
- }
304
- });
305
-
306
- // src/server.ts
307
- var DEFAULT_PORT = 8814;
308
- var createServer2 = async (options = {}) => {
309
- const { port, host, ...rest } = options;
310
- const runtime = createRuntime(rest);
311
- return { ...await listen(runtime, { port: port ?? 0, ...host ? { host } : {} }), runtime };
312
- };
313
- var serveTarget = {
314
- name: "dynamodb",
315
- defaultPort: DEFAULT_PORT,
316
- create: (_values, common) => createRuntime({
317
- ...common.adminKey !== void 0 ? { adminKey: common.adminKey } : {},
318
- ...common.seed !== void 0 ? { seed: common.seed } : {},
319
- ...common.onLog ? { onLog: common.onLog } : {}
320
- }),
321
- banner: () => [
322
- "AWS SDK endpoint: point DynamoDBClient at this URL",
323
- "admin: GET /__admin/tables; GET /__admin/items; GET /__admin/streams"
324
- ]
325
- };
326
-
327
- export {
328
- runCli,
329
- serveCommand,
330
- DEFAULT_PORT,
331
- createServer2 as createServer,
332
- serveTarget
333
- };
334
- //# sourceMappingURL=chunk-3H6JAYFX.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../adapters/node/src/cli.ts", "../../../adapters/node/src/serve.ts", "../../../adapters/node/src/listen.ts", "../src/server.ts"],
4
- "sourcesContent": ["import { readFile } from \"node:fs/promises\"\nimport { type ParseArgsConfig, parseArgs } from \"node:util\"\nimport type { RequestLog, ServiceInstance, ServiceRuntime } from \"@crvouga/mockingbird-service\"\nimport { type Listening, listen } from \"./listen.js\"\n\nexport type CliOption = {\n type: \"string\" | \"boolean\"\n description: string\n /** Shown in help; the value placeholder, e.g. `<port>`. */\n value?: string\n default?: string | boolean\n}\n\nexport type CliValues = Record<string, string | boolean | undefined>\n\nexport type CliCommand = {\n summary: string\n usage?: string\n options?: Record<string, CliOption>\n /** Resolves to an exit code; a server command resolves only when it stops. */\n run(values: CliValues, positionals: string[]): Promise<number>\n}\n\nexport type CliSpec = {\n bin: string\n description: string\n commands: Record<string, CliCommand>\n}\n\nconst optionHelp = (options: Record<string, CliOption>): string[] =>\n Object.entries(options).map(([name, option]) => {\n const flag = `--${name}${option.type === \"string\" ? ` ${option.value ?? \"<value>\"}` : \"\"}`\n const fallback = option.default !== undefined ? ` (default: ${String(option.default)})` : \"\"\n return ` ${flag.padEnd(30)} ${option.description}${fallback}`\n })\n\nconst help = (spec: CliSpec): string =>\n [\n `${spec.bin} \u2014 ${spec.description}`,\n \"\",\n \"Usage:\",\n ` ${spec.bin} <command> [options]`,\n \"\",\n \"Commands:\",\n ...Object.entries(spec.commands).map(([name, c]) => ` ${name.padEnd(30)} ${c.summary}`),\n \"\",\n `Run \\`${spec.bin} <command> --help\\` for a command's options.`,\n ].join(\"\\n\")\n\nconst commandHelp = (spec: CliSpec, name: string, command: CliCommand): string =>\n [\n `${spec.bin} ${name} \u2014 ${command.summary}`,\n \"\",\n \"Usage:\",\n ` ${command.usage ?? `${spec.bin} ${name} [options]`}`,\n ...(command.options ? [\"\", \"Options:\", ...optionHelp(command.options)] : []),\n ].join(\"\\n\")\n\n/** Parse `argv` against `spec` and run the chosen command. Resolves to an exit code. */\nexport const runCli = async (spec: CliSpec, argv: string[]): Promise<number> => {\n // Two-word commands (`corpus pull`) win over one-word ones.\n const pair = argv.length >= 2 ? `${argv[0]} ${argv[1]}` : undefined\n const words = pair !== undefined && spec.commands[pair] ? 2 : 1\n const name = words === 2 ? pair : argv[0]\n const rest = argv.slice(words)\n if (name === undefined || name === \"--help\" || name === \"-h\" || name === \"help\") {\n console.log(help(spec))\n return 0\n }\n const command = spec.commands[name]\n if (!command) {\n console.error(`${spec.bin}: unknown command ${JSON.stringify(name)}\\n\\n${help(spec)}`)\n return 2\n }\n if (rest.includes(\"--help\") || rest.includes(\"-h\")) {\n console.log(commandHelp(spec, name, command))\n return 0\n }\n let parsed: { values: CliValues; positionals: string[] }\n try {\n parsed = parseArgs({\n args: rest,\n allowPositionals: true,\n strict: true,\n options: Object.fromEntries(\n Object.entries(command.options ?? {}).map(([key, option]) => [\n key,\n {\n type: option.type,\n ...(option.default !== undefined ? { default: option.default } : {}),\n },\n ]),\n ) as ParseArgsConfig[\"options\"],\n }) as { values: CliValues; positionals: string[] }\n } catch (error) {\n console.error(\n `${spec.bin} ${name}: ${error instanceof Error ? error.message : String(error)}\\n\\n${commandHelp(spec, name, command)}`,\n )\n return 2\n }\n return command.run(parsed.values, parsed.positionals)\n}\n\n// \u2500\u2500 serve \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type LogFormat = \"pretty\" | \"json\" | \"off\"\n\nexport type CommonServeOptions = {\n adminKey: string | undefined\n seed: string | undefined\n onLog: ((entry: RequestLog) => void) | undefined\n}\n\n/**\n * What a service contributes to `serve`: how to build its runtime from CLI flags,\n * and what to say at startup. Every service's `./server` entry exports one as\n * `serveTarget`, which is also how `serve --config` finds services by name.\n */\nexport type ServeTarget = {\n name: string\n defaultPort: number\n /** Serve flags beyond the common ones. */\n options?: Record<string, CliOption>\n create(\n values: CliValues,\n common: CommonServeOptions,\n ): Promise<ServiceRuntime<ServiceInstance>> | ServiceRuntime<ServiceInstance>\n /** Startup lines after the listen address, e.g. the loaded corpus version. */\n banner?(runtime: ServiceRuntime<ServiceInstance>): string[]\n /** After the HTTP server is bound. A service that speaks more than HTTP attaches it here. */\n listening?(server: Listening): void\n}\n\nconst COMMON_SERVE_OPTIONS: Record<string, CliOption> = {\n port: { type: \"string\", value: \"<port>\", description: \"Port to listen on\" },\n host: { type: \"string\", value: \"<host>\", description: \"Interface to bind\", default: \"127.0.0.1\" },\n \"admin-key\": {\n type: \"string\",\n value: \"<key>\",\n description: \"Require x-mockingbird-admin-key on /__admin/* (env MOCKINGBIRD_ADMIN_KEY)\",\n },\n seed: { type: \"string\", value: \"<seed>\", description: \"Seed for every random choice\" },\n log: {\n type: \"string\",\n value: \"<pretty|json|off>\",\n description: \"Request log format\",\n default: \"pretty\",\n },\n \"log-requests\": {\n type: \"boolean\",\n description:\n \"One JSON line per request: namespace, operationId, status, ids touched (never bodies). Same as --log json\",\n },\n config: {\n type: \"string\",\n value: \"<file>\",\n description: \"Serve every service in a mockingbird.json config instead\",\n },\n}\n\nconst formatLog = (format: LogFormat) => {\n if (format === \"off\") return undefined\n if (format === \"json\") return (entry: RequestLog) => console.log(JSON.stringify(entry))\n return (entry: RequestLog) => {\n const op = entry.operationId ?? (entry.unmatched ? \"UNMATCHED\" : \"-\")\n const ns = entry.namespace === \"default\" ? \"\" : ` [${entry.namespace}]`\n const fault = entry.faultId ? ` fault=${entry.faultId}` : \"\"\n const adopted = entry.adopted ? \" adopted\" : \"\"\n // A rejection says what arrived (never the body) and why the service refused it.\n const received = entry.request\n ? ` received=${entry.request.bodyBytes === null ? \"?\" : `${entry.request.bodyBytes}B`} ct=${entry.request.contentType ?? \"-\"}${\n entry.request.transferEncoding ? ` te=${entry.request.transferEncoding}` : \"\"\n }`\n : \"\"\n const issues = entry.issues?.length\n ? ` issues=${entry.issues\n .slice(0, 3)\n .map((issue) => `${issue.path || \"$\"}: ${issue.message}`)\n .join(\"; \")}${entry.issues.length > 3 ? ` (+${entry.issues.length - 3})` : \"\"}`\n : \"\"\n console.log(\n `${entry.service} ${entry.method} ${entry.path} ${entry.status} ${op} ${entry.durationMs}ms${ns}${fault}${adopted}${received}${issues}`,\n )\n }\n}\n\nconst asString = (value: string | boolean | undefined): string | undefined =>\n typeof value === \"string\" ? value : undefined\n\n/** A service entry in `mockingbird.json`. */\nexport type ConfigService = {\n port?: number\n host?: string\n adminKey?: string\n seed?: string\n /** Service-specific serve flags, by long name: `{ \"webhook-url\": \"\u2026\" }`. */\n options?: Record<string, string | boolean>\n}\n\nexport type MockingbirdConfig = {\n /** Keyed by service name: `junction` loads `@crvouga/mockingbird-service-junction`. */\n services: Record<string, ConfigService>\n log?: LogFormat\n}\n\nconst loadTarget = async (name: string, own: ServeTarget): Promise<ServeTarget> => {\n if (name === own.name) return own\n const specifier = `@crvouga/mockingbird-service-${name}/server`\n try {\n const mod = (await import(specifier)) as { serveTarget?: ServeTarget }\n if (!mod.serveTarget) throw new Error(`${specifier} exports no serveTarget`)\n return mod.serveTarget\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error)\n throw new Error(\n `cannot load service \"${name}\": ${reason}. Install @crvouga/mockingbird-service-${name}.`,\n )\n }\n}\n\nconst start = async (\n target: ServeTarget,\n values: CliValues,\n config: { port: number; host: string; adminKey?: string; seed?: string; log: LogFormat },\n): Promise<Listening> => {\n const runtime = await target.create(values, {\n adminKey: config.adminKey,\n seed: config.seed,\n onLog: formatLog(config.log),\n })\n const listening = await listen(runtime, { port: config.port, host: config.host })\n target.listening?.(listening)\n console.log(`${target.name} mock listening on ${listening.url}`)\n console.log(`${target.name} health: GET ${listening.url}/health`)\n console.log(\n `${target.name} admin: ${listening.url}/__admin (${config.adminKey ? \"x-mockingbird-admin-key required\" : \"open \u2014 pass --admin-key to lock\"})`,\n )\n console.log(`${target.name} admin ui: ${listening.url}/__admin/ui`)\n for (const line of target.banner?.(runtime) ?? []) console.log(`${target.name} ${line}`)\n return listening\n}\n\nconst untilSignal = async (servers: Listening[]): Promise<number> =>\n new Promise((resolve) => {\n const stop = async () => {\n await Promise.allSettled(servers.map((s) => s.close()))\n resolve(0)\n }\n process.once(\"SIGINT\", stop)\n process.once(\"SIGTERM\", stop)\n })\n\n/** The standard `serve` command for a service, including multi-service `--config`. */\nexport const serveCommand = (target: ServeTarget): CliCommand => ({\n summary: `Serve the ${target.name} mock over HTTP`,\n options: { ...COMMON_SERVE_OPTIONS, ...target.options },\n async run(values) {\n const log = (\n values[\"log-requests\"] === true ? \"json\" : (asString(values.log) ?? \"pretty\")\n ) as LogFormat\n if (![\"pretty\", \"json\", \"off\"].includes(log)) {\n console.error(`--log must be pretty, json or off (got ${log})`)\n return 2\n }\n const configPath = asString(values.config)\n if (configPath !== undefined) {\n const config = JSON.parse(await readFile(configPath, \"utf8\")) as MockingbirdConfig\n const servers: Listening[] = []\n try {\n for (const [name, entry] of Object.entries(config.services ?? {})) {\n const each = await loadTarget(name, target)\n servers.push(\n await start(each, entry.options ?? {}, {\n port: entry.port ?? each.defaultPort,\n host: entry.host ?? \"127.0.0.1\",\n ...(entry.adminKey !== undefined ? { adminKey: entry.adminKey } : {}),\n ...(entry.seed !== undefined ? { seed: entry.seed } : {}),\n log: config.log ?? log,\n }),\n )\n }\n } catch (error) {\n await Promise.allSettled(servers.map((s) => s.close()))\n console.error(error instanceof Error ? error.message : String(error))\n return 1\n }\n return untilSignal(servers)\n }\n const port = asString(values.port)\n const adminKey = asString(values[\"admin-key\"]) ?? process.env.MOCKINGBIRD_ADMIN_KEY\n const seed = asString(values.seed)\n let listening: Listening\n try {\n listening = await start(target, values, {\n port: port === undefined ? target.defaultPort : Number.parseInt(port, 10),\n host: asString(values.host) ?? \"127.0.0.1\",\n ...(adminKey !== undefined ? { adminKey } : {}),\n ...(seed !== undefined ? { seed } : {}),\n log,\n })\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error))\n return 1\n }\n return untilSignal([listening])\n },\n})\n", "import { createServer } from \"node:http\"\nimport type { FetchAPI } from \"@crvouga/mockingbird-core\"\n\n/** Options for {@link serve}. */\nexport type NodeServeOptions = {\n port?: number\n host?: string\n}\n\n/**\n * Serve any Mockingbird {@link FetchAPI} over `node:http`.\n * Port defaults to `0`, so the OS assigns an ephemeral port (read from `server.address()`).\n */\nexport const serve = async (api: FetchAPI, options: NodeServeOptions = {}) => {\n const server = createServer(async (req, res) => {\n const chunks: Buffer[] = []\n for await (const chunk of req) {\n chunks.push(Buffer.from(chunk))\n }\n const body = Buffer.concat(chunks)\n const address = server.address()\n const port = typeof address === \"object\" && address !== null ? address.port : undefined\n const base = `http://${req.headers.host ?? `localhost:${port ?? 80}`}`\n const raw = req.url ?? \"/\"\n const url = new URL(raw.replace(/^\\/+/, \"/\"), base)\n const method = req.method ?? \"GET\"\n const init: RequestInit = { method, headers: req.headers as Record<string, string> }\n if (method !== \"GET\" && method !== \"HEAD\" && body.length > 0) {\n init.body = body\n }\n const aborted = new AbortController()\n res.once(\"close\", () => {\n if (!res.writableFinished) aborted.abort()\n })\n init.signal = aborted.signal\n const request = new Request(url, init)\n let response: Response\n try {\n response = await api.fetch(request)\n } catch (error) {\n // A `drop` fault: destroy the socket so the client sees the connection die.\n if ((error as { code?: string }).code === \"MOCKINGBIRD_DROP\") {\n req.socket.destroy()\n return\n }\n res.writeHead(500, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: {\n type: \"mockingbird_internal\",\n message: error instanceof Error ? error.message : String(error),\n },\n }),\n )\n return\n }\n // Headers#entries() joins repeated headers; Set-Cookie must stay one header per cookie.\n const headers: Record<string, string | string[]> = Object.fromEntries(response.headers)\n const cookies = response.headers.getSetCookie()\n if (cookies.length > 0) headers[\"set-cookie\"] = cookies\n if (!response.body) {\n res.writeHead(response.status, headers)\n res.end()\n return\n }\n // Stream the body chunk by chunk: event streams and long-polls must not be buffered.\n res.writeHead(response.status, headers)\n res.flushHeaders()\n const reader = response.body.getReader()\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n if (!res.write(value)) await new Promise<void>((resolve) => res.once(\"drain\", resolve))\n }\n res.end()\n } catch {\n res.destroy()\n } finally {\n reader.releaseLock()\n }\n })\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject)\n server.listen(options.port ?? 0, options.host, resolve)\n })\n return server\n}\n", "import type { Server } from \"node:http\"\nimport type { FetchAPI } from \"@crvouga/mockingbird-core\"\nimport { serve } from \"./serve.js\"\n\nexport type ListenOptions = {\n /** Default `0`: the OS picks a free port. */\n port?: number\n /** Default `127.0.0.1`: a mock should not be reachable off the machine by accident. */\n host?: string\n}\n\n/** A running server, with the address it actually bound. */\nexport type Listening = {\n url: string\n port: number\n host: string\n server: Server\n close(): Promise<void>\n}\n\nexport const listen = async (api: FetchAPI, options: ListenOptions = {}): Promise<Listening> => {\n const host = options.host ?? \"127.0.0.1\"\n const server = await serve(api, { port: options.port ?? 0, host })\n const address = server.address()\n const port = typeof address === \"object\" && address !== null ? address.port : (options.port ?? 0)\n const shown = host.includes(\":\") ? `[${host}]` : host\n return {\n url: `http://${shown}:${port}`,\n port,\n host,\n server,\n close: () =>\n new Promise<void>((resolve, reject) => {\n // Stop accepting first, then drop keep-alive sockets so close() can finish.\n server.close((error) => {\n if (error && (error as { code?: string }).code !== \"ERR_SERVER_NOT_RUNNING\") reject(error)\n else resolve()\n })\n server.closeAllConnections?.()\n }),\n }\n}\n", "/// <reference types=\"node\" />\nimport { type Listening, listen, type ServeTarget } from \"@crvouga/mockingbird-adapter-node\"\nimport { createRuntime, type DynamoRuntime, type DynamoRuntimeOptions } from \"./runtime.js\"\nexport const DEFAULT_PORT = 8814\nexport type DynamoServerOptions = DynamoRuntimeOptions & { port?: number; host?: string }\nexport const createServer = async (\n options: DynamoServerOptions = {},\n): Promise<Listening & { runtime: DynamoRuntime }> => {\n const { port, host, ...rest } = options\n const runtime = createRuntime(rest)\n return { ...(await listen(runtime, { port: port ?? 0, ...(host ? { host } : {}) })), runtime }\n}\nexport const serveTarget: ServeTarget = {\n name: \"dynamodb\",\n defaultPort: DEFAULT_PORT,\n create: (_values, common) =>\n createRuntime({\n ...(common.adminKey !== undefined ? { adminKey: common.adminKey } : {}),\n ...(common.seed !== undefined ? { seed: common.seed } : {}),\n ...(common.onLog ? { onLog: common.onLog } : {}),\n }),\n banner: () => [\n \"AWS SDK endpoint: point DynamoDBClient at this URL\",\n \"admin: GET /__admin/tables; GET /__admin/items; GET /__admin/streams\",\n ],\n}\n"],
5
- "mappings": "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",
6
- "names": ["createServer"]
7
- }