@crvouga/mockingbird-service-emqx 0.1.0 → 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 CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog — @crvouga/mockingbird-service-emqx
2
2
 
3
- ## 0.1.0 (2026-10-11)
3
+ ## 0.2.0 (2026-10-12)
4
+
5
+ ### Features
6
+
7
+ - unify the emulator control plane ([2068547](https://github.com/crvouga/mockingbird/commit/2068547bedde4e2e2331c1657c1a78120e84428b))
8
+
9
+ ### Dependencies
10
+
11
+ - `@crvouga/mockingbird-service-sqlite`
12
+
13
+ ## 0.1.0 (2026-10-10)
4
14
 
5
15
  Initial release.
package/DISCOVERY.md CHANGED
@@ -35,6 +35,7 @@ repository; live parity is an additional oracle check, not a substitute for the
35
35
 
36
36
  - `GET /__admin/health`
37
37
  - `GET /__admin`
38
+ - `GET /__admin/controls`
38
39
  - `GET /__admin/state`
39
40
  - `GET /__admin/requests`
40
41
  - `GET /__admin/metrics`
@@ -45,6 +46,28 @@ For HTTP services, use `x-mockingbird-namespace` (or the documented credential/p
45
46
  parallel tests do not share state. Admin state, journal, metrics and fault-preset endpoints are
46
47
  designed for assertions and diagnosis by consuming test suites.
47
48
 
49
+ ## Admin controls
50
+
51
+ Every HTTP emulator takes the same controls, and each means the same thing at boot
52
+ (`createRuntime({ adminControls })`, `serve --admin-controls`), over `/__admin`, and in a request header:
53
+
54
+ | Control | Admin API | Request header | Interface |
55
+ | --- | --- | --- | --- |
56
+ | Isolate state by key | `GET /__admin/namespaces` | `x-mockingbird-namespace: <key>` | [Namespaces](https://mockingbird.chrisvouga.dev/docs/admin-controls/namespaces) |
57
+ | Reset to boot | `POST /__admin/reset` | `x-mockingbird-reset: true` | [Reset](https://mockingbird.chrisvouga.dev/docs/admin-controls/reset) |
58
+ | Snapshot and restore | `POST /__admin/snapshots`, `POST /__admin/snapshots/<id>/restore` | `x-mockingbird-snapshot: <name>`, `x-mockingbird-restore: <name>` | [Snapshot and restore](https://mockingbird.chrisvouga.dev/docs/admin-controls/snapshot-and-restore) |
59
+ | Move the clock | `POST /__admin/clock` | `x-mockingbird-time: <instant>`, `x-mockingbird-advance: <duration>` | [Clock](https://mockingbird.chrisvouga.dev/docs/admin-controls/clock) |
60
+ | Read or branch from old state | `GET /__admin/timeline` | `x-mockingbird-at: <checkpoint>`, `x-mockingbird-branch: <name>` | [Checkpoints and branches](https://mockingbird.chrisvouga.dev/docs/admin-controls/checkpoints-and-branches) |
61
+ | Inject a fault | `POST /__admin/faults` | `x-mockingbird-fault: <fault>` | [Faults](https://mockingbird.chrisvouga.dev/docs/admin-controls/faults) |
62
+ | Latency and timeouts | `PUT /__admin/latency` | `x-mockingbird-delay: <duration>`, `x-mockingbird-timeout: <duration>` | [Latency and timeouts](https://mockingbird.chrisvouga.dev/docs/admin-controls/latency-and-timeouts) |
63
+ | Replay from a seed | `PUT /__admin/controls` | `x-mockingbird-seed: <seed>` | [Seed and determinism](https://mockingbird.chrisvouga.dev/docs/admin-controls/seed-and-determinism) |
64
+ | See what happened | `GET /__admin/requests`, `GET /__admin/state` | | [Journal, metrics and state](https://mockingbird.chrisvouga.dev/docs/admin-controls/journal-and-state) |
65
+
66
+ `GET /__admin` lists every route and header with a one-line summary, and `GET /__admin/controls`
67
+ is the namespace's current control document. The same seed and the same requests give the same
68
+ bytes. Setting controls as an emulator starts is [Boot](https://mockingbird.chrisvouga.dev/docs/admin-controls/boot); every route and header is in
69
+ the [Reference](https://mockingbird.chrisvouga.dev/docs/admin-controls/reference). The full guide: <https://mockingbird.chrisvouga.dev/docs/admin-controls>.
70
+
48
71
  ## Report a mismatch or missing capability
49
72
 
50
73
  Follow the [agent reporting contract](https://github.com/crvouga/mockingbird/blob/main/docs/REPORTING_ISSUES.md). Include package version,
package/README.md CHANGED
@@ -57,6 +57,7 @@ const client = await mqtt.connectAsync(emqx.mqttUrl, {
57
57
  })
58
58
  await client.subscribeAsync("space:example", { qos: 1 })
59
59
 
60
+ // EMQX publishes no JavaScript SDK for its REST API, so the publisher calls it over HTTP.
60
61
  await fetch(`${emqx.url}/api/v5/publish`, {
61
62
  method: "POST",
62
63
  headers: {
@@ -66,7 +67,7 @@ await fetch(`${emqx.url}/api/v5/publish`, {
66
67
  body: JSON.stringify({ topic: "space:example", payload: "hello", qos: 1, retain: false }),
67
68
  })
68
69
 
69
- // Move time instead of waiting for a session to expire.
70
+ // Test control: move time instead of waiting for a session to expire.
70
71
  await fetch(`${emqx.url}/__admin/clock`, { method: "POST", body: '{"advance": "600s"}' })
71
72
 
72
73
  await client.endAsync()
@@ -2,9 +2,12 @@ import {
2
2
  MQTT_WEBSOCKET_PATH,
3
3
  createClock,
4
4
  createRuntime,
5
+ normalizeBootControls,
5
6
  parseDuration,
6
- resolveAdminPrefix
7
- } from "./chunk-4SYSJ3ZN.js";
7
+ parseFaultHeader,
8
+ resolveAdminPrefix,
9
+ restoreClock
10
+ } from "./chunk-XVKFLVK7.js";
8
11
 
9
12
  // ../../adapters/node/dist/cli.js
10
13
  import { readFile as readFile2 } from "node:fs/promises";
@@ -51,6 +54,8 @@ var serve = async (api, options = {}) => {
51
54
  req.socket.destroy();
52
55
  return;
53
56
  }
57
+ if (aborted.signal.aborted)
58
+ return;
54
59
  res.writeHead(500, { "content-type": "application/json" });
55
60
  res.end(JSON.stringify({
56
61
  error: {
@@ -82,6 +87,7 @@ var serve = async (api, options = {}) => {
82
87
  }
83
88
  res.end();
84
89
  } catch {
90
+ await new Promise((resolve2) => setImmediate(resolve2));
85
91
  res.destroy();
86
92
  } finally {
87
93
  reader.releaseLock();
@@ -165,11 +171,11 @@ var httpChild = async (target, entry, options) => {
165
171
  adminKey: entry.adminKey,
166
172
  seed: entry.seed,
167
173
  onLog: options.onLog,
174
+ ...entry.adminControls !== void 0 ? { adminControls: entry.adminControls } : {},
168
175
  ...entry.fixtures !== void 0 ? { fixtures: entry.fixtures } : {},
169
176
  ...entry.baseUrl !== void 0 ? { baseUrl: entry.baseUrl } : {}
170
177
  });
171
178
  const adminPrefix = resolveAdminPrefix(entry.adminPrefix);
172
- runtime.isolateNamespaces();
173
179
  const locked = /* @__PURE__ */ new Set();
174
180
  const active = /* @__PURE__ */ new Map();
175
181
  const api = {
@@ -431,19 +437,12 @@ async function startFleet(config, options) {
431
437
  return json(400, { error: "freeze must be boolean" });
432
438
  const response2 = await transaction(namespace, selected, async (_name, child) => {
433
439
  const childClock = child.clock(namespace);
434
- childClock.freeze();
435
- childClock.set(target);
436
- if (!frozen)
437
- childClock.unfreeze();
440
+ restoreClock(childClock, { now: target, frozen });
438
441
  await child.settle?.(namespace);
439
442
  return childClock.state();
440
443
  });
441
- if (response2.ok) {
442
- current.freeze();
443
- current.set(target);
444
- if (!frozen)
445
- current.unfreeze();
446
- }
444
+ if (response2.ok)
445
+ restoreClock(current, { now: target, frozen });
447
446
  return response2;
448
447
  }
449
448
  if (!route)
@@ -462,13 +461,8 @@ async function startFleet(config, options) {
462
461
  return json(404, { error: "no snapshot in this namespace" });
463
462
  const restored = new Map([...point.values].map(([name]) => [name, children.get(name)]));
464
463
  const response2 = await transaction(namespace, restored, async (name, child) => child.restore(namespace, point.values.get(name)));
465
- if (response2.ok) {
466
- const current = clock(namespace);
467
- current.freeze();
468
- current.set(point.clock.now);
469
- if (!point.clock.frozen)
470
- current.unfreeze();
471
- }
464
+ if (response2.ok)
465
+ restoreClock(clock(namespace), point.clock);
472
466
  return response2;
473
467
  }
474
468
  const snapshotId = randomUUID();
@@ -494,6 +488,8 @@ async function startFleet(config, options) {
494
488
  for (const [name, entry] of Object.entries(config.services)) {
495
489
  if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name))
496
490
  throw new Error("invalid service name");
491
+ if (config.adminControls !== void 0 || entry.adminControls !== void 0)
492
+ normalizeBootControls({ ...config.adminControls, ...entry.adminControls }, `services.${name}.adminControls`);
497
493
  try {
498
494
  const target = await options.load(name);
499
495
  if (entry.protocol && entry.protocol !== ("protocol" in target ? target.protocol : "http"))
@@ -502,7 +498,9 @@ async function startFleet(config, options) {
502
498
  const child = "start" in target ? await target.start(entry) : await httpChild(target, {
503
499
  ...entry,
504
500
  adminPrefix: resolveAdminPrefix(entry.adminPrefix ?? adminPrefix),
505
- ...adminKey !== void 0 ? { adminKey } : {}
501
+ ...adminKey !== void 0 ? { adminKey } : {},
502
+ // Fleet-wide controls, with the service's own keys replacing them.
503
+ ...config.adminControls !== void 0 || entry.adminControls !== void 0 ? { adminControls: { ...config.adminControls, ...entry.adminControls } } : {}
506
504
  }, options);
507
505
  children.set(name, child);
508
506
  if (!await child.ready())
@@ -635,7 +633,51 @@ var COMMON_SERVE_OPTIONS = {
635
633
  value: "<key>",
636
634
  description: "Require x-mockingbird-admin-key on /__admin/* (env MOCKINGBIRD_ADMIN_KEY)"
637
635
  },
638
- seed: { type: "string", value: "<seed>", description: "Seed for every random choice" },
636
+ seed: {
637
+ type: "string",
638
+ value: "<seed>",
639
+ description: "Seed for every random choice (env MOCKINGBIRD_SEED)"
640
+ },
641
+ "admin-controls": {
642
+ type: "string",
643
+ value: "<json|file>",
644
+ description: "Admin controls to boot with, as JSON or a JSON file: clock, latency, faults, snapshot, namespaces (env MOCKINGBIRD_ADMIN_CONTROLS)"
645
+ },
646
+ clock: {
647
+ type: "string",
648
+ value: "<instant>",
649
+ description: "Start the clock at this instant (epoch ms or ISO-8601)"
650
+ },
651
+ freeze: { type: "boolean", description: "Freeze the clock: it moves only when told to" },
652
+ "auto-advance": {
653
+ type: "string",
654
+ value: "<duration>",
655
+ description: "Step the clock this much before every request (e.g. 1s)"
656
+ },
657
+ latency: {
658
+ type: "string",
659
+ value: "<duration>",
660
+ description: "Baseline response time for every request (e.g. 250ms)"
661
+ },
662
+ jitter: {
663
+ type: "string",
664
+ value: "<duration>",
665
+ description: "Seeded extra latency between 0 and this"
666
+ },
667
+ "virtual-time": {
668
+ type: "boolean",
669
+ description: "Spend latency, delays and timeouts on the mock clock instead of really waiting"
670
+ },
671
+ fault: {
672
+ type: "string",
673
+ value: "<fault>",
674
+ description: 'A fault to boot with, as in x-mockingbird-fault: 503, rate_limited, "status=503; delay=2s"'
675
+ },
676
+ snapshot: {
677
+ type: "string",
678
+ value: "<file>",
679
+ description: "Start from a snapshot document (GET /__admin/snapshots/:id)"
680
+ },
639
681
  log: {
640
682
  type: "string",
641
683
  value: "<pretty|json|off>",
@@ -682,6 +724,68 @@ var formatLog = (format) => {
682
724
  };
683
725
  };
684
726
  var asString = (value) => typeof value === "string" ? value : void 0;
727
+ var readJsonFile = async (path, label) => {
728
+ try {
729
+ return JSON.parse(await readFile2(path, "utf8"));
730
+ } catch (error) {
731
+ throw new Error(`${label}: cannot read ${path}: ${error instanceof Error ? error.message : error}`);
732
+ }
733
+ };
734
+ var isObject2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
735
+ var resolveServeControls = async (values, env = process.env, base) => {
736
+ const source = asString(values["admin-controls"]) ?? env.MOCKINGBIRD_ADMIN_CONTROLS;
737
+ let document = isObject2(base) ? { ...base } : {};
738
+ if (source !== void 0 && source.trim() !== "") {
739
+ let parsed;
740
+ if (source.trim().startsWith("{")) {
741
+ try {
742
+ parsed = JSON.parse(source);
743
+ } catch {
744
+ throw new Error("--admin-controls: not valid JSON");
745
+ }
746
+ } else
747
+ parsed = await readJsonFile(source, "--admin-controls");
748
+ if (!isObject2(parsed))
749
+ throw new Error("--admin-controls: expected a JSON object");
750
+ document = { ...document, ...parsed };
751
+ }
752
+ const clock = isObject2(document.clock) ? { ...document.clock } : {};
753
+ const now = asString(values.clock);
754
+ if (now !== void 0)
755
+ clock.now = now;
756
+ if (values.freeze === true)
757
+ clock.frozen = true;
758
+ const autoAdvance = asString(values["auto-advance"]);
759
+ if (autoAdvance !== void 0)
760
+ clock.autoAdvance = autoAdvance;
761
+ if (Object.keys(clock).length > 0)
762
+ document.clock = clock;
763
+ const delay = asString(values.latency);
764
+ const jitter = asString(values.jitter);
765
+ if (delay !== void 0 || jitter !== void 0) {
766
+ const latency = isObject2(document.latency) ? { ...document.latency } : document.latency !== void 0 ? { delay: document.latency } : {};
767
+ if (delay !== void 0)
768
+ latency.delay = delay;
769
+ if (jitter !== void 0)
770
+ latency.jitter = jitter;
771
+ document.latency = latency;
772
+ }
773
+ if (values["virtual-time"] === true)
774
+ document.virtualTime = true;
775
+ const fault = asString(values.fault);
776
+ if (fault !== void 0)
777
+ document.faults = [
778
+ ...Array.isArray(document.faults) ? document.faults : [],
779
+ parseFaultHeader(fault, "--fault")
780
+ ];
781
+ const snapshot = asString(values.snapshot);
782
+ if (snapshot !== void 0)
783
+ document.snapshot = await readJsonFile(snapshot, "--snapshot");
784
+ if (Object.keys(document).length === 0)
785
+ return void 0;
786
+ normalizeBootControls(document, "adminControls");
787
+ return document;
788
+ };
685
789
  var loadTarget = async (name, own) => {
686
790
  if (name === own.name)
687
791
  return own;
@@ -708,7 +812,8 @@ var start = async (target, values, config) => {
708
812
  adminPrefix,
709
813
  adminKey: config.adminKey,
710
814
  seed: config.seed,
711
- onLog: formatLog(config.log)
815
+ onLog: formatLog(config.log),
816
+ ...config.adminControls !== void 0 ? { adminControls: config.adminControls } : {}
712
817
  });
713
818
  const listening = await listen(runtime, { port: config.port, host: config.host });
714
819
  target.listening?.(listening);
@@ -748,6 +853,9 @@ var serveCommand = (target) => ({
748
853
  const adminKey2 = config.adminKey ?? asString(values["admin-key"]) ?? process.env.MOCKINGBIRD_ADMIN_KEY;
749
854
  if (adminKey2 !== void 0)
750
855
  config.adminKey = adminKey2;
856
+ const adminControls = await resolveServeControls(values, process.env, config.adminControls);
857
+ if (adminControls !== void 0)
858
+ config.adminControls = adminControls;
751
859
  const fleet = await startFleet(config, {
752
860
  load: (name) => loadTarget(name, target),
753
861
  onLog: formatLog(config.log ?? log),
@@ -773,10 +881,12 @@ var serveCommand = (target) => ({
773
881
  }
774
882
  const port = asString(values.port);
775
883
  const adminKey = asString(values["admin-key"]) ?? process.env.MOCKINGBIRD_ADMIN_KEY;
776
- const seed = asString(values.seed);
884
+ const seed = asString(values.seed) ?? process.env.MOCKINGBIRD_SEED;
777
885
  let listening;
778
886
  try {
887
+ const adminControls = await resolveServeControls(values);
779
888
  listening = await start(target, values, {
889
+ ...adminControls !== void 0 ? { adminControls } : {},
780
890
  adminPrefix: resolveAdminPrefix(asString(values["admin-prefix"]) ?? process.env.MOCKINGBIRD_ADMIN_PREFIX),
781
891
  port: port === void 0 ? target.defaultPort : Number.parseInt(port, 10),
782
892
  host: asString(values.host) ?? "127.0.0.1",
@@ -1182,6 +1292,7 @@ var serveTarget = {
1182
1292
  },
1183
1293
  ...common.adminPrefix !== void 0 ? { adminPrefix: common.adminPrefix } : {},
1184
1294
  ...common.adminKey !== void 0 ? { adminKey: common.adminKey } : {},
1295
+ ...common.adminControls !== void 0 ? { adminControls: common.adminControls } : {},
1185
1296
  ...common.seed !== void 0 ? { seed: common.seed } : {},
1186
1297
  ...common.onLog ? { onLog: common.onLog } : {}
1187
1298
  });
@@ -1212,4 +1323,4 @@ export {
1212
1323
  connectStream,
1213
1324
  serveTarget
1214
1325
  };
1215
- //# sourceMappingURL=chunk-XPRMQRYZ.js.map
1326
+ //# sourceMappingURL=chunk-6HMUKZLA.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../adapters/node/src/cli.ts", "../../../adapters/node/src/fleet.ts", "../../../adapters/node/src/serve.ts", "../../../adapters/node/src/listen.ts", "../../../mqtt/broker/src/node.ts", "../src/server.ts"],
4
+ "sourcesContent": ["import type { EventEmitter } from \"node:events\"\nimport { readFile } from \"node:fs/promises\"\nimport { createRequire } from \"node:module\"\nimport { resolve } from \"node:path\"\nimport { pathToFileURL } from \"node:url\"\nimport { type ParseArgsConfig, parseArgs } from \"node:util\"\nimport type {\n MockControls,\n RequestLog,\n ServiceInstance,\n ServiceRuntime,\n} from \"@crvouga/mockingbird-service\"\nimport {\n normalizeBootControls,\n parseFaultHeader,\n resolveAdminPrefix,\n} from \"@crvouga/mockingbird-service\"\nimport { type FleetTarget, startFleet } from \"./fleet.js\"\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 adminPrefix?: string\n adminKey: string | undefined\n seed: string | undefined\n onLog: ((entry: RequestLog) => void) | undefined\n /** Admin controls to boot with: clock, latency, faults, a starting snapshot. */\n adminControls?: MockControls\n /** Synthetic provider fixture objects supplied by a fleet entry. */\n fixtures?: Record<string, unknown>\n baseUrl?: string\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-prefix\": {\n type: \"string\",\n value: \"<path>\",\n description: \"Internal API prefix (default /__admin; env MOCKINGBIRD_ADMIN_PREFIX)\",\n },\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: {\n type: \"string\",\n value: \"<seed>\",\n description: \"Seed for every random choice (env MOCKINGBIRD_SEED)\",\n },\n \"admin-controls\": {\n type: \"string\",\n value: \"<json|file>\",\n description:\n \"Admin controls to boot with, as JSON or a JSON file: clock, latency, faults, snapshot, namespaces (env MOCKINGBIRD_ADMIN_CONTROLS)\",\n },\n clock: {\n type: \"string\",\n value: \"<instant>\",\n description: \"Start the clock at this instant (epoch ms or ISO-8601)\",\n },\n freeze: { type: \"boolean\", description: \"Freeze the clock: it moves only when told to\" },\n \"auto-advance\": {\n type: \"string\",\n value: \"<duration>\",\n description: \"Step the clock this much before every request (e.g. 1s)\",\n },\n latency: {\n type: \"string\",\n value: \"<duration>\",\n description: \"Baseline response time for every request (e.g. 250ms)\",\n },\n jitter: {\n type: \"string\",\n value: \"<duration>\",\n description: \"Seeded extra latency between 0 and this\",\n },\n \"virtual-time\": {\n type: \"boolean\",\n description: \"Spend latency, delays and timeouts on the mock clock instead of really waiting\",\n },\n fault: {\n type: \"string\",\n value: \"<fault>\",\n description:\n 'A fault to boot with, as in x-mockingbird-fault: 503, rate_limited, \"status=503; delay=2s\"',\n },\n snapshot: {\n type: \"string\",\n value: \"<file>\",\n description: \"Start from a snapshot document (GET /__admin/snapshots/:id)\",\n },\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 \"ready-file\": {\n type: \"string\",\n description: \"Atomically publish fleet endpoint JSON\",\n value: \"<file>\",\n },\n \"connections-file\": {\n type: \"string\",\n description: \"Write private connection URLs with mode 0600\",\n value: \"<file>\",\n },\n \"ready-json\": {\n type: \"boolean\",\n description: \"Emit one public JSON record after fleet readiness\",\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\nconst readJsonFile = async (path: string, label: string): Promise<unknown> => {\n try {\n return JSON.parse(await readFile(path, \"utf8\")) as unknown\n } catch (error) {\n throw new Error(\n `${label}: cannot read ${path}: ${error instanceof Error ? error.message : error}`,\n )\n }\n}\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value)\n\n/**\n * The boot controls a `serve` invocation asks for: `--admin-controls` (or `MOCKINGBIRD_ADMIN_CONTROLS`) as\n * the base document, with the single-purpose flags on top. Checked here, so a bad value stops\n * the command before a port is bound. `undefined` when nothing was asked for.\n */\nexport const resolveServeControls = async (\n values: CliValues,\n env: Record<string, string | undefined> = process.env,\n base?: unknown,\n): Promise<MockControls | undefined> => {\n const source = asString(values[\"admin-controls\"]) ?? env.MOCKINGBIRD_ADMIN_CONTROLS\n let document: Record<string, unknown> = isObject(base) ? { ...base } : {}\n if (source !== undefined && source.trim() !== \"\") {\n let parsed: unknown\n if (source.trim().startsWith(\"{\")) {\n try {\n parsed = JSON.parse(source)\n } catch {\n throw new Error(\"--admin-controls: not valid JSON\")\n }\n } else parsed = await readJsonFile(source, \"--admin-controls\")\n if (!isObject(parsed)) throw new Error(\"--admin-controls: expected a JSON object\")\n document = { ...document, ...parsed }\n }\n const clock: Record<string, unknown> = isObject(document.clock) ? { ...document.clock } : {}\n const now = asString(values.clock)\n if (now !== undefined) clock.now = now\n if (values.freeze === true) clock.frozen = true\n const autoAdvance = asString(values[\"auto-advance\"])\n if (autoAdvance !== undefined) clock.autoAdvance = autoAdvance\n if (Object.keys(clock).length > 0) document.clock = clock\n const delay = asString(values.latency)\n const jitter = asString(values.jitter)\n if (delay !== undefined || jitter !== undefined) {\n const latency: Record<string, unknown> = isObject(document.latency)\n ? { ...document.latency }\n : document.latency !== undefined\n ? { delay: document.latency }\n : {}\n if (delay !== undefined) latency.delay = delay\n if (jitter !== undefined) latency.jitter = jitter\n document.latency = latency\n }\n if (values[\"virtual-time\"] === true) document.virtualTime = true\n const fault = asString(values.fault)\n if (fault !== undefined)\n document.faults = [\n ...(Array.isArray(document.faults) ? document.faults : []),\n parseFaultHeader(fault, \"--fault\"),\n ]\n const snapshot = asString(values.snapshot)\n if (snapshot !== undefined) document.snapshot = await readJsonFile(snapshot, \"--snapshot\")\n if (Object.keys(document).length === 0) return undefined\n normalizeBootControls(document, \"adminControls\")\n return document as MockControls\n}\n\n/** A service entry in `mockingbird.json`. */\nexport type ConfigService = {\n protocol?: \"http\" | \"postgres\" | \"redis\"\n port?: number\n host?: string\n adminPrefix?: string\n adminKey?: string\n seed?: string\n /** Admin controls this service boots with. A key given here replaces the fleet-wide one. */\n adminControls?: MockControls\n fixtures?: Record<string, unknown>\n baseUrl?: string\n password?: string\n user?: string\n database?: string\n /** Protocol namespace selectors: database names for Postgres, logical DB indexes for Redis. */\n namespaces?: Record<string, string | number>\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 adminPrefix?: string\n adminKey?: string\n /** Admin controls every HTTP service in the fleet boots with. */\n adminControls?: MockControls\n namespace?: string\n control?: { host?: string; port?: number }\n}\n\nconst loadTarget = async (name: string, own: FleetTarget): Promise<FleetTarget> => {\n if (name === own.name) return own\n const specifier = `@crvouga/mockingbird-service-${name}/server`\n try {\n // A CLI run with npx may live outside the consumer project. Discover its locally\n // installed services as well as siblings of the bundled CLI.\n let mod: { serveTarget?: FleetTarget }\n try {\n mod = (await import(specifier)) as { serveTarget?: FleetTarget }\n } catch {\n const fromProject = createRequire(resolve(process.cwd(), \"package.json\"))\n mod = (await import(pathToFileURL(fromProject.resolve(specifier)).href)) as {\n serveTarget?: FleetTarget\n }\n }\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: {\n port: number\n host: string\n adminPrefix?: string\n adminKey?: string\n seed?: string\n adminControls?: MockControls\n log: LogFormat\n },\n): Promise<Listening> => {\n const adminPrefix = resolveAdminPrefix(config.adminPrefix)\n const runtime = await target.create(values, {\n adminPrefix,\n adminKey: config.adminKey,\n seed: config.seed,\n onLog: formatLog(config.log),\n ...(config.adminControls !== undefined ? { adminControls: config.adminControls } : {}),\n })\n const listening = await listen(runtime, { port: config.port, host: config.host })\n target.listening?.(listening)\n console.log(`${target.name} emulator listening on ${listening.url}`)\n console.log(`${target.name} health: GET ${listening.url}${adminPrefix}/health`)\n console.log(\n `${target.name} admin: ${listening.url}${adminPrefix} (${config.adminKey ? \"x-mockingbird-admin-key required\" : \"open \u2014 pass --admin-key to lock\"})`,\n )\n console.log(`${target.name} admin ui: ${listening.url}${adminPrefix}/ui`)\n for (const line of target.banner?.(runtime) ?? [])\n console.log(`${target.name} ${line.replaceAll(\"/__admin\", adminPrefix)}`)\n return listening\n}\n\nconst untilSignal = async (servers: { close(): Promise<void> }[]): Promise<number> =>\n new Promise((resolve) => {\n const stop = async () => {\n ;(process as EventEmitter).removeListener(\"SIGINT\", stop)\n ;(process as EventEmitter).removeListener(\"SIGTERM\", stop)\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: FleetTarget): CliCommand => ({\n summary: `Serve the ${target.name} emulator or a configured fleet`,\n options: { ...COMMON_SERVE_OPTIONS, ...(\"options\" in target ? 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 try {\n const config = JSON.parse(await readFile(configPath, \"utf8\")) as MockingbirdConfig\n config.adminPrefix = resolveAdminPrefix(\n config.adminPrefix ??\n asString(values[\"admin-prefix\"]) ??\n process.env.MOCKINGBIRD_ADMIN_PREFIX,\n )\n const adminKey =\n config.adminKey ?? asString(values[\"admin-key\"]) ?? process.env.MOCKINGBIRD_ADMIN_KEY\n if (adminKey !== undefined) config.adminKey = adminKey\n // Flags and MOCKINGBIRD_ADMIN_CONTROLS apply on top of the config file's own controls.\n const adminControls = await resolveServeControls(values, process.env, config.adminControls)\n if (adminControls !== undefined) config.adminControls = adminControls\n const fleet = await startFleet(config, {\n load: (name) => loadTarget(name, target),\n onLog: formatLog(config.log ?? log),\n ...(asString(values[\"ready-file\"]) ? { readyFile: asString(values[\"ready-file\"]) } : {}),\n ...(asString(values[\"connections-file\"])\n ? { connectionsFile: asString(values[\"connections-file\"]) }\n : {}),\n onReady: (manifest) => {\n if (values[\"ready-json\"]) console.log(JSON.stringify(manifest))\n else\n for (const [name, endpoint] of Object.entries(manifest.services))\n console.log(`${name} emulator listening on ${endpoint.url}`)\n },\n })\n return untilSignal([fleet])\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error))\n return 1\n }\n }\n if (\"start\" in target) {\n console.error(\"Use --config to supervise protocol services with this command\")\n return 2\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) ?? process.env.MOCKINGBIRD_SEED\n let listening: Listening\n try {\n const adminControls = await resolveServeControls(values)\n listening = await start(target, values, {\n ...(adminControls !== undefined ? { adminControls } : {}),\n adminPrefix: resolveAdminPrefix(\n asString(values[\"admin-prefix\"]) ?? process.env.MOCKINGBIRD_ADMIN_PREFIX,\n ),\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 { randomUUID } from \"node:crypto\"\nimport { chmod, readFile, rename, rm, writeFile } from \"node:fs/promises\"\nimport type { FetchAPI } from \"@crvouga/mockingbird-core\"\nimport type { Clock, ServiceInstance, ServiceRuntime } from \"@crvouga/mockingbird-service\"\nimport {\n createClock,\n normalizeBootControls,\n parseDuration,\n resolveAdminPrefix,\n restoreClock,\n} from \"@crvouga/mockingbird-service\"\nimport type { CommonServeOptions, ConfigService, MockingbirdConfig, ServeTarget } from \"./cli.js\"\nimport type { EndpointManifest } from \"./fleet-manifest.js\"\nimport { type Listening, listen } from \"./listen.js\"\n\nexport type { EndpointManifest } from \"./fleet-manifest.js\"\n\nexport type FleetDiagnostics = {\n activeRequests: number\n activeConnections: number\n blockedCommands: number\n pendingJobs: number\n activeJobs?: number\n pendingWebhooks: number\n unmatchedRequests: number\n}\n\n/** Protocol packages own their state, listeners, credentials and namespace selection. */\nexport type FleetChild = {\n protocol: \"http\" | \"postgres\" | \"redis\"\n url: string\n connection?: string\n connections?: Record<string, string>\n healthUrl?: string\n adminUrl?: string\n namespaces: Record<string, unknown>\n ready(): Promise<boolean>\n close(): Promise<void>\n /** Fence new work synchronously; diagnostics must also account for work already in flight. */\n lock(namespace: string): () => void\n diagnostics(namespace: string): FleetDiagnostics\n checkpoint(namespace: string): Promise<unknown>\n restore(namespace: string, checkpoint: unknown): Promise<void>\n reset(namespace: string): Promise<void>\n clock(namespace: string): Clock\n settle?(namespace: string): Promise<void>\n}\n\nexport type ProtocolTarget = {\n name: string\n protocol: \"postgres\" | \"redis\"\n defaultPort: number\n start(entry: ConfigService): Promise<FleetChild>\n}\nexport type FleetTarget = ServeTarget | ProtocolTarget\n\nexport type FleetOptions = {\n load(name: string): Promise<FleetTarget>\n onLog?: CommonServeOptions[\"onLog\"]\n readyFile?: string | undefined\n connectionsFile?: string | undefined\n onReady?(manifest: EndpointManifest): void\n}\n\nconst EMPTY: FleetDiagnostics = {\n activeRequests: 0,\n activeConnections: 0,\n blockedCommands: 0,\n pendingJobs: 0,\n pendingWebhooks: 0,\n unmatchedRequests: 0,\n}\nconst NS = /^[A-Za-z0-9_.-]{1,64}$/\nconst json = (status: number, value: unknown) => Response.json(value, { status })\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value)\nconst pending = (d: FleetDiagnostics) =>\n d.activeRequests + d.blockedCommands + d.pendingJobs + d.pendingWebhooks\n\nconst publicUrl = (raw: string): string => {\n const url = new URL(raw)\n url.password = \"\"\n return url.href\n}\n\n/** Atomic publication; credentials only go in an explicitly requested 0600 file. */\nconst atomicWrite = async (path: string, value: unknown) => {\n const temp = `${path}.${randomUUID()}.tmp`\n try {\n await writeFile(temp, `${JSON.stringify(value, null, 2)}\\n`, { mode: 0o600, flag: \"wx\" })\n await chmod(temp, 0o600)\n await rename(temp, path)\n } finally {\n await rm(temp, { force: true })\n }\n}\n\nconst removeOwned = async (path: string | undefined, id: string) => {\n if (!path) return\n try {\n const value: unknown = JSON.parse(await readFile(path, \"utf8\"))\n if (isObject(value) && value.id === id) await rm(path, { force: true })\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error\n }\n}\n\nconst httpChild = async (\n target: ServeTarget,\n entry: ConfigService,\n options: FleetOptions,\n): Promise<FleetChild> => {\n const runtime: ServiceRuntime<ServiceInstance> = await target.create(entry.options ?? {}, {\n adminPrefix: resolveAdminPrefix(entry.adminPrefix),\n adminKey: entry.adminKey,\n seed: entry.seed,\n onLog: options.onLog,\n ...(entry.adminControls !== undefined ? { adminControls: entry.adminControls } : {}),\n ...(entry.fixtures !== undefined ? { fixtures: entry.fixtures } : {}),\n ...(entry.baseUrl !== undefined ? { baseUrl: entry.baseUrl } : {}),\n })\n const adminPrefix = resolveAdminPrefix(entry.adminPrefix)\n const locked = new Set<string>()\n const active = new Map<string, number>()\n const api: FetchAPI = {\n async fetch(request) {\n const namespace = runtime.namespaceOf(request)\n if (locked.has(namespace)) return json(409, { error: \"fleet control in progress\", namespace })\n active.set(namespace, (active.get(namespace) ?? 0) + 1)\n try {\n return await runtime.fetch(request)\n } finally {\n active.set(namespace, (active.get(namespace) ?? 1) - 1)\n }\n },\n }\n let server: Listening | undefined\n try {\n server = await listen(api, {\n port: entry.port ?? target.defaultPort,\n host: entry.host ?? \"127.0.0.1\",\n })\n target.listening?.(server)\n } catch (error) {\n runtime.stop?.()\n await server?.close()\n runtime.webhooks?.clear()\n await runtime.webhooks?.idle()\n throw error\n }\n return {\n protocol: \"http\",\n url: server.url,\n healthUrl: `${server.url}${adminPrefix}/health`,\n adminUrl: `${server.url}${adminPrefix}`,\n namespaces: { header: \"x-mockingbird-namespace\", path: `${adminPrefix}/ns/{name}` },\n ready: async () => {\n try {\n return (\n await fetch(`${server.url}${adminPrefix}/health`, { signal: AbortSignal.timeout(2000) })\n ).ok\n } catch {\n return false\n }\n },\n async close() {\n runtime.stop?.()\n runtime.webhooks?.clear()\n await server.close()\n await runtime.webhooks?.idle()\n },\n lock(namespace) {\n if (locked.has(namespace)) throw new Error(\"namespace already locked\")\n locked.add(namespace)\n return () => locked.delete(namespace)\n },\n diagnostics(namespace) {\n return {\n ...EMPTY,\n activeRequests: active.get(namespace) ?? 0,\n pendingWebhooks: runtime.webhooks?.pending(namespace) ?? 0,\n unmatchedRequests: runtime.metrics\n .report(namespace)\n .unmatched.reduce((n, r) => n + r.count, 0),\n }\n },\n async checkpoint(namespace) {\n return runtime.fleetSnapshot(namespace)\n },\n async restore(namespace, checkpoint) {\n runtime.fleetRestore(checkpoint, namespace)\n },\n reset: (namespace) => runtime.reset(namespace),\n clock: (namespace) => runtime.namespaceClock(namespace),\n async settle(namespace) {\n const instance = runtime.instance(namespace) as ServiceInstance & { tick?(): unknown }\n instance.tick?.()\n await runtime.webhooks?.idle()\n },\n }\n}\n\nexport type Fleet = {\n readonly manifest: EndpointManifest\n readonly children: ReadonlyMap<string, FleetChild>\n fetch(request: Request): Promise<Response>\n close(): Promise<void>\n}\n\n/** Resolves only after every child and the aggregate control listener are healthy. */\nexport async function startFleet(config: MockingbirdConfig, options: FleetOptions): Promise<Fleet> {\n const id = randomUUID()\n const startedAt = new Date().toISOString()\n const children = new Map<string, FleetChild>()\n const clocks = new Map<string, Clock>()\n const checkpoints = new Map<\n string,\n { namespace: string; values: Map<string, unknown>; clock: ReturnType<Clock[\"state\"]> }\n >()\n let supervisor: Listening | undefined\n let stopped = false\n let controlling = false\n const close = async () => {\n if (stopped) return\n stopped = true\n await Promise.allSettled([...children.values()].map((child) => child.close()))\n await supervisor?.close()\n await removeOwned(options.readyFile, id)\n await removeOwned(options.connectionsFile, id)\n }\n // Invalidate a previous process's artifacts before attempting startup.\n if (options.readyFile) await rm(options.readyFile, { force: true })\n if (options.connectionsFile) await rm(options.connectionsFile, { force: true })\n\n const clock = (namespace: string) => {\n let value = clocks.get(namespace)\n if (!value) {\n value = createClock()\n clocks.set(namespace, value)\n }\n return value\n }\n const select = (body: Record<string, unknown>): Map<string, FleetChild> => {\n if (body.services === undefined) return children\n if (!Array.isArray(body.services) || body.services.length === 0)\n throw new Error(\"services must be a nonempty list\")\n const selected = new Map<string, FleetChild>()\n for (const name of body.services) {\n if (typeof name !== \"string\" || !children.has(name))\n throw new Error(\"unknown service in selection\")\n selected.set(name, children.get(name) as FleetChild)\n }\n return selected\n }\n const diagnostics = (namespace: string) =>\n Object.fromEntries([...children].map(([name, child]) => [name, child.diagnostics(namespace)]))\n const transaction = async (\n namespace: string,\n selected: Map<string, FleetChild>,\n run: (name: string, child: FleetChild) => Promise<unknown>,\n ): Promise<Response> => {\n if (controlling) return json(409, { error: \"another fleet operation is in progress\" })\n controlling = true\n const release: (() => void)[] = []\n const before = new Map<string, unknown>()\n const results: Record<string, unknown> = {}\n let failure: string | undefined\n try {\n for (const [name, child] of selected) {\n failure = name\n release.push(child.lock(namespace))\n }\n const busy = Object.fromEntries(\n [...selected]\n .filter(([, child]) => {\n const state = child.diagnostics(namespace)\n return (\n state.activeRequests +\n state.blockedCommands +\n state.pendingWebhooks +\n (state.activeJobs ?? 0) >\n 0\n )\n })\n .map(([name, child]) => [name, child.diagnostics(namespace)]),\n )\n if (Object.keys(busy).length)\n return json(409, { error: \"namespace is not quiescent\", services: busy })\n for (const [name, child] of selected) {\n failure = name\n before.set(name, await child.checkpoint(namespace))\n }\n for (const [name, child] of selected) {\n failure = name\n results[name] = { status: \"ok\", result: await run(name, child) }\n }\n return json(200, { status: \"ok\", namespace, services: results })\n } catch {\n const rollback: Record<string, string> = {}\n // Roll back even the child whose mutation failed; it may have partially changed state.\n for (const [name, point] of before) {\n try {\n await selected.get(name)?.restore(namespace, point)\n rollback[name] = \"restored\"\n } catch {\n rollback[name] = \"failed\"\n }\n }\n return json(500, {\n status: \"failed\",\n namespace,\n failedService: failure,\n services: results,\n rollback,\n rolledBack:\n before.size > 0 && Object.values(rollback).every((value) => value === \"restored\"),\n })\n } finally {\n for (const unlock of release.reverse()) unlock()\n controlling = false\n }\n }\n\n const api: FetchAPI = {\n async fetch(request) {\n const url = new URL(request.url)\n const adminPrefix = resolveAdminPrefix(config.adminPrefix)\n const path = url.pathname.startsWith(`${adminPrefix}/`)\n ? url.pathname.slice(adminPrefix.length)\n : \"\"\n if (path === \"/health\" && request.method === \"GET\") {\n const states = await Promise.all(\n [...children].map(async ([name, child]) => {\n let protocolReady = false\n try {\n protocolReady = await child.ready()\n } catch {\n /* reported as failed */\n }\n return [\n name,\n {\n processReady: !stopped,\n protocolReady,\n status: protocolReady ? \"ready\" : \"failed\",\n url: publicUrl(child.url),\n },\n ]\n }),\n )\n const ready =\n !stopped &&\n states.every(([, state]) => (state as { protocolReady: boolean }).protocolReady)\n return json(ready ? 200 : 503, {\n status: ready ? \"ready\" : \"failed\",\n id,\n services: Object.fromEntries(states),\n })\n }\n if (!path.startsWith(\"/fleet/\")) return json(404, { error: \"not found\" })\n const adminKey = config.adminKey ?? process.env.MOCKINGBIRD_ADMIN_KEY\n if (adminKey !== undefined && request.headers.get(\"x-mockingbird-admin-key\") !== adminKey)\n return json(401, { error: \"admin key required\" })\n const route = /^\\/fleet\\/namespaces\\/([^/]+)\\/(reset|snapshots)(?:\\/([^/]+)\\/restore)?$/.exec(\n path,\n )\n const namespace = route\n ? decodeURIComponent(route[1] as string)\n : (url.searchParams.get(\"namespace\") ??\n request.headers.get(\"x-mockingbird-namespace\") ??\n config.namespace ??\n \"default\")\n if (!NS.test(namespace)) return json(400, { error: \"invalid namespace\" })\n if (request.method === \"GET\" && path === \"/fleet/metrics\")\n return json(200, { namespace, services: diagnostics(namespace) })\n if (request.method === \"GET\" && path === \"/fleet/clock\")\n return json(200, {\n namespace,\n ...clock(namespace).state(),\n services: Object.fromEntries(\n [...children].map(([name, child]) => [name, child.clock(namespace).state()]),\n ),\n })\n if (request.method !== \"POST\") return json(405, { error: \"method not allowed\" })\n let body: Record<string, unknown>\n try {\n const text = await request.text()\n const value: unknown = text ? JSON.parse(text) : {}\n if (!isObject(value)) throw new Error(\"expected object\")\n body = value\n } catch {\n return json(400, { error: \"expected JSON object\" })\n }\n let selected: Map<string, FleetChild>\n try {\n selected = select(body)\n } catch (error) {\n return json(400, { error: error instanceof Error ? error.message : \"bad selection\" })\n }\n if (path === \"/fleet/wait-until-idle\") {\n const services = diagnostics(namespace)\n const idle = Object.values(services).every((d) => pending(d) === 0)\n return json(idle ? 200 : 409, { status: idle ? \"idle\" : \"busy\", namespace, services })\n }\n if (path === \"/fleet/clock\") {\n const current = clock(namespace)\n let target = current.now()\n if (body.set !== undefined) {\n target =\n typeof body.set === \"number\"\n ? body.set\n : typeof body.set === \"string\"\n ? Date.parse(body.set)\n : NaN\n if (!Number.isFinite(target))\n return json(400, { error: \"set must be epoch ms or ISO-8601\" })\n }\n if (body.advance !== undefined) {\n const delta = parseDuration(body.advance)\n if (delta === undefined) return json(400, { error: \"invalid advance\" })\n target += delta\n }\n const frozen = body.freeze === undefined ? current.state().frozen : body.freeze\n if (typeof frozen !== \"boolean\") return json(400, { error: \"freeze must be boolean\" })\n const response = await transaction(namespace, selected, async (_name, child) => {\n const childClock = child.clock(namespace)\n restoreClock(childClock, { now: target, frozen })\n await child.settle?.(namespace)\n return childClock.state()\n })\n if (response.ok) restoreClock(current, { now: target, frozen })\n return response\n }\n if (!route) return json(404, { error: \"not found\" })\n if (route[2] === \"reset\") {\n if (route[3]) return json(404, { error: \"not found\" })\n const response = await transaction(namespace, selected, async (_name, child) =>\n child.reset(namespace),\n )\n if (response.ok && selected.size === children.size) clock(namespace).reset()\n return response\n }\n if (route[3]) {\n const point = checkpoints.get(route[3])\n if (!point || point.namespace !== namespace)\n return json(404, { error: \"no snapshot in this namespace\" })\n const restored = new Map(\n [...point.values].map(([name]) => [name, children.get(name) as FleetChild]),\n )\n const response = await transaction(namespace, restored, async (name, child) =>\n child.restore(namespace, point.values.get(name)),\n )\n if (response.ok) restoreClock(clock(namespace), point.clock)\n return response\n }\n const snapshotId = randomUUID()\n const values = new Map<string, unknown>()\n const response = await transaction(namespace, selected, async (name, child) => {\n values.set(name, await child.checkpoint(namespace))\n return { checkpoint: `${snapshotId}:${name}` }\n })\n if (!response.ok) return response\n checkpoints.set(snapshotId, { namespace, values, clock: clock(namespace).state() })\n return json(201, {\n ...((await response.json()) as Record<string, unknown>),\n id: snapshotId,\n label: body.label,\n })\n },\n }\n try {\n const adminPrefix = resolveAdminPrefix(config.adminPrefix)\n if (!isObject(config.services) || Object.keys(config.services).length === 0)\n throw new Error(\"config must contain at least one service\")\n for (const [name, entry] of Object.entries(config.services)) {\n if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name)) throw new Error(\"invalid service name\")\n // Checked before the child starts, so a bad document is reported by name.\n if (config.adminControls !== undefined || entry.adminControls !== undefined)\n normalizeBootControls(\n { ...config.adminControls, ...entry.adminControls },\n `services.${name}.adminControls`,\n )\n try {\n const target = await options.load(name)\n if (entry.protocol && entry.protocol !== (\"protocol\" in target ? target.protocol : \"http\"))\n throw new Error(\"configured protocol does not match target\")\n const adminKey = entry.adminKey ?? config.adminKey ?? process.env.MOCKINGBIRD_ADMIN_KEY\n const child =\n \"start\" in target\n ? await target.start(entry)\n : await httpChild(\n target,\n {\n ...entry,\n adminPrefix: resolveAdminPrefix(entry.adminPrefix ?? adminPrefix),\n ...(adminKey !== undefined ? { adminKey } : {}),\n // Fleet-wide controls, with the service's own keys replacing them.\n ...(config.adminControls !== undefined || entry.adminControls !== undefined\n ? { adminControls: { ...config.adminControls, ...entry.adminControls } }\n : {}),\n },\n options,\n )\n children.set(name, child)\n if (!(await child.ready())) throw new Error(\"protocol readiness failed\")\n } catch {\n throw new Error(`service ${name} failed to start; all started listeners were closed`)\n }\n }\n supervisor = await listen(api, {\n port: config.control?.port ?? 0,\n host: config.control?.host ?? \"127.0.0.1\",\n })\n const manifest: EndpointManifest = {\n version: 1,\n state: \"ready\",\n pid: process.pid,\n id,\n startedAt,\n adminBase: `${supervisor.url}${adminPrefix}/fleet`,\n healthUrl: `${supervisor.url}${adminPrefix}/health`,\n services: Object.fromEntries(\n [...children].map(([name, child]) => [\n name,\n {\n protocol: child.protocol,\n url: publicUrl(child.url),\n healthUrl: child.healthUrl ?? `${supervisor?.url}${adminPrefix}/health`,\n adminUrl: child.adminUrl ?? `${supervisor?.url}${adminPrefix}/fleet`,\n namespaces: child.namespaces,\n processReady: true,\n protocolReady: true,\n },\n ]),\n ),\n }\n if (options.connectionsFile)\n await atomicWrite(options.connectionsFile, {\n version: 1,\n id,\n pid: process.pid,\n services: Object.fromEntries(\n [...children].map(([name, child]) => [\n name,\n { url: child.connection ?? child.url, namespaces: child.connections },\n ]),\n ),\n })\n if (options.readyFile) await atomicWrite(options.readyFile, manifest)\n options.onReady?.(manifest)\n return { manifest, children, fetch: api.fetch, close }\n } catch (error) {\n await close()\n throw error\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` or `timeout` 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 // The client hung up while its request was being held: there is nobody to answer.\n if (aborted.signal.aborted) return\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 // The body failed partway (a `truncate` fault, or the service's own stream). Let what\n // was already written leave first, so the client sees a response that dies mid-body.\n await new Promise<void>((resolve) => setImmediate(resolve))\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\" />\n/**\n * Node and Bun transports for the broker: a TCP listener, MQTT over WebSocket on an existing\n * `node:http` server, and an in-process stream. The engine itself (`./index.js`) needs none of\n * this and stays portable.\n */\nimport { createHash } from \"node:crypto\"\nimport type { Server as HttpServer, IncomingMessage } from \"node:http\"\nimport { createServer, type Socket } from \"node:net\"\nimport { Duplex } from \"node:stream\"\nimport type { Broker, Connection, Transport, TransportInfo } from \"./broker.js\"\nimport { MQTT_WEBSOCKET_PATH } from \"./runtime.js\"\n\n/** Hand a new transport to a broker (`broker.connect`, or `routeConnection` for tenants). */\nexport type Attach = (transport: Transport, info: TransportInfo) => Connection\n\nexport type TcpListenOptions = {\n /** Default `0`: the OS picks a free port. */\n port?: number\n /** Default `127.0.0.1`. */\n host?: string\n}\n\nexport type TcpListening = {\n host: string\n port: number\n /** `mqtt://host:port`. */\n url: string\n /** Stop listening and drop every connection. */\n close(): Promise<void>\n}\n\nconst socketTransport = (socket: Socket, encode: (bytes: Uint8Array) => Uint8Array): Transport => ({\n send: (bytes) => {\n if (!socket.destroyed && socket.writable) socket.write(encode(bytes))\n },\n // Once the kernel has what was written, the socket can go: the peer reads it, then the end.\n close: () => {\n if (!socket.destroyed) socket.end(() => socket.destroy())\n },\n destroy: () => socket.destroy(),\n})\n\n/** Serve MQTT over TCP. */\nexport const listenTcp = (\n attach: Attach,\n options: TcpListenOptions = {},\n): Promise<TcpListening> => {\n const host = options.host ?? \"127.0.0.1\"\n const sockets = new Set<Socket>()\n const server = createServer((socket) => {\n socket.setNoDelay(true)\n sockets.add(socket)\n const connection = attach(\n socketTransport(socket, (bytes) => bytes),\n { kind: \"tcp\" },\n )\n socket.on(\"data\", (chunk: Uint8Array) => connection.receive(chunk))\n socket.on(\"error\", () => socket.destroy())\n socket.on(\"close\", () => {\n sockets.delete(socket)\n connection.closed()\n })\n })\n return new Promise((resolve, reject) => {\n server.once(\"error\", reject)\n server.listen(options.port ?? 0, host, () => {\n server.removeListener(\"error\", reject)\n const address = server.address()\n const port = typeof address === \"object\" && address !== null ? address.port : 0\n const shown = host.includes(\":\") ? `[${host}]` : host\n resolve({\n host,\n port,\n url: `mqtt://${shown}:${port}`,\n close: () =>\n new Promise<void>((done) => {\n for (const socket of sockets) socket.destroy()\n server.close(() => done())\n }),\n })\n })\n })\n}\n\n// \u2500\u2500 WebSocket (RFC 6455) \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\nconst WEBSOCKET_GUID = \"258EAFA5-E914-47DA-95CA-C5AB0DC85B11\"\n/** Above any MQTT packet (the Remaining Length caps one at 256 MB); bounds a hostile frame. */\nconst MAX_FRAME_BYTES = 268_435_460\n\nconst OPCODE = { continuation: 0x0, text: 0x1, binary: 0x2, close: 0x8, ping: 0x9, pong: 0xa }\n\nconst encodeFrame = (opcode: number, payload: Uint8Array): Uint8Array => {\n const length = payload.length\n let header: Buffer\n if (length < 126) {\n header = Buffer.alloc(2)\n header[1] = length\n } else if (length < 65_536) {\n header = Buffer.alloc(4)\n header[1] = 126\n header.writeUInt16BE(length, 2)\n } else {\n header = Buffer.alloc(10)\n header[1] = 127\n header.writeBigUInt64BE(BigInt(length), 2)\n }\n header[0] = 0x80 | opcode\n return Buffer.concat([header, payload])\n}\n\n/** Splits a byte stream into WebSocket messages; control frames are reported as they come. */\nconst frameParser = (onFrame: (opcode: number, data: Buffer) => void, onError: () => void) => {\n let buffer: Buffer = Buffer.alloc(0)\n let fragments: Buffer[] = []\n let fragmentOpcode = 0\n return (chunk: Buffer): void => {\n buffer = buffer.length === 0 ? chunk : Buffer.concat([buffer, chunk])\n for (;;) {\n if (buffer.length < 2) return\n const first = buffer[0] ?? 0\n const second = buffer[1] ?? 0\n // No extension is negotiated, so the reserved bits must be clear; a client must mask.\n if ((first & 0x70) !== 0 || (second & 0x80) === 0) {\n onError()\n return\n }\n const fin = (first & 0x80) !== 0\n const opcode = first & 0x0f\n let length = second & 0x7f\n let offset = 2\n if (length === 126) {\n if (buffer.length < 4) return\n length = buffer.readUInt16BE(2)\n offset = 4\n } else if (length === 127) {\n if (buffer.length < 10) return\n const wide = buffer.readBigUInt64BE(2)\n if (wide > BigInt(MAX_FRAME_BYTES)) {\n onError()\n return\n }\n length = Number(wide)\n offset = 10\n }\n if (buffer.length < offset + 4 + length) return\n const mask = buffer.subarray(offset, offset + 4)\n const payload = Buffer.alloc(length)\n for (let index = 0; index < length; index++) {\n payload[index] = (buffer[offset + 4 + index] ?? 0) ^ (mask[index % 4] ?? 0)\n }\n buffer = buffer.subarray(offset + 4 + length)\n if (opcode >= 0x8) {\n onFrame(opcode, payload)\n continue\n }\n if (opcode === OPCODE.continuation) {\n if (fragmentOpcode === 0) {\n onError()\n return\n }\n fragments.push(payload)\n if (fin) {\n const message = Buffer.concat(fragments)\n const type = fragmentOpcode\n fragments = []\n fragmentOpcode = 0\n onFrame(type, message)\n }\n continue\n }\n if (fin) onFrame(opcode, payload)\n else {\n fragmentOpcode = opcode\n fragments = [payload]\n }\n }\n }\n}\n\nconst refuse = (socket: Socket, status: number, reason: string): void => {\n socket.end(`HTTP/1.1 ${status} ${reason}\\r\\nConnection: close\\r\\nContent-Length: 0\\r\\n\\r\\n`, () =>\n socket.destroy(),\n )\n}\n\nexport type WebSocketOptions = {\n /**\n * The broker side for an upgrade request to `pathname`, or `undefined` when that path does\n * not speak MQTT (the upgrade is answered 404).\n */\n route(pathname: string): Attach | undefined\n /** Subprotocols accepted. Default `[\"mqtt\"]` (MQTT 5.0 section 6). */\n subprotocols?: readonly string[]\n /** Answer 400 to an upgrade offering none of them. Default `true`. */\n requireSubprotocol?: boolean\n}\n\nexport type WebSocketListening = {\n /** Stop accepting upgrades and drop every WebSocket connection. */\n close(): void\n}\n\n/** Serve MQTT over WebSocket on a `node:http` server's `upgrade` event. */\nexport const attachWebSocket = (\n server: HttpServer,\n options: WebSocketOptions,\n): WebSocketListening => {\n const supported = options.subprotocols ?? [\"mqtt\"]\n const sockets = new Set<Socket>()\n const onUpgrade = (request: IncomingMessage, socket: Socket, head: Buffer) => {\n const pathname = new URL(request.url ?? \"/\", \"http://localhost\").pathname\n const attach = options.route(pathname)\n if (!attach) {\n refuse(socket, 404, \"Not Found\")\n return\n }\n const key = request.headers[\"sec-websocket-key\"]\n if (typeof key !== \"string\" || key === \"\") {\n refuse(socket, 400, \"Bad Request\")\n return\n }\n const offered = String(request.headers[\"sec-websocket-protocol\"] ?? \"\")\n .split(\",\")\n .map((each) => each.trim())\n .filter(Boolean)\n const subprotocol = offered.find((each) => supported.includes(each))\n if (subprotocol === undefined && options.requireSubprotocol !== false) {\n refuse(socket, 400, \"Bad Request\")\n return\n }\n socket.setNoDelay(true)\n socket.write(\n [\n \"HTTP/1.1 101 Switching Protocols\",\n \"Upgrade: websocket\",\n \"Connection: Upgrade\",\n `Sec-WebSocket-Accept: ${createHash(\"sha1\")\n .update(key + WEBSOCKET_GUID)\n .digest(\"base64\")}`,\n ...(subprotocol !== undefined ? [`Sec-WebSocket-Protocol: ${subprotocol}`] : []),\n \"\",\n \"\",\n ].join(\"\\r\\n\"),\n )\n sockets.add(socket)\n const transport = socketTransport(socket, (bytes) => encodeFrame(OPCODE.binary, bytes))\n const connection = attach(\n {\n send: transport.send,\n close: () => {\n if (!socket.destroyed && socket.writable) {\n socket.write(encodeFrame(OPCODE.close, Uint8Array.of(0x03, 0xe8)))\n }\n transport.close()\n },\n destroy: transport.destroy,\n },\n { kind: \"websocket\", path: pathname },\n )\n const parse = frameParser(\n (opcode, data) => {\n if (opcode === OPCODE.binary) connection.receive(data)\n else if (opcode === OPCODE.ping) socket.write(encodeFrame(OPCODE.pong, data))\n else if (opcode === OPCODE.close) {\n if (socket.writable) socket.write(encodeFrame(OPCODE.close, data.subarray(0, 2)))\n socket.end(() => socket.destroy())\n }\n // MQTT 5.0 6.0: control packets travel in binary frames; a text frame ends the connection.\n else if (opcode === OPCODE.text) socket.destroy()\n },\n () => socket.destroy(),\n )\n socket.on(\"data\", (chunk: Buffer) => parse(chunk))\n socket.on(\"error\", () => socket.destroy())\n socket.on(\"close\", () => {\n sockets.delete(socket)\n connection.closed()\n })\n if (head.length > 0) parse(head)\n }\n const listener = (request: IncomingMessage, socket: unknown, head: Buffer) =>\n onUpgrade(request, socket as Socket, head)\n server.on(\"upgrade\", listener)\n return {\n close: () => {\n server.removeListener(\"upgrade\", listener)\n for (const socket of sockets) socket.destroy()\n sockets.clear()\n },\n }\n}\n\n/**\n * An in-process connection as a Node stream, for a client library that takes one instead of a\n * URL (`new MqttClient(() => memoryStream(attach), options)` with `mqtt`). No socket is opened.\n */\nexport const memoryStream = (attach: Attach): Duplex => {\n let connection: Connection | undefined\n const stream = new Duplex({\n read() {},\n write(chunk: Uint8Array, _encoding, callback) {\n connection?.receive(chunk)\n callback()\n },\n final(callback) {\n connection?.closed()\n callback()\n },\n destroy(error, callback) {\n connection?.closed()\n callback(error)\n },\n })\n connection = attach(\n {\n send: (bytes) => {\n if (!stream.destroyed) stream.push(Buffer.from(bytes))\n },\n close: () => {\n if (!stream.destroyed) stream.push(null)\n },\n destroy: () => stream.destroy(),\n },\n { kind: \"memory\" },\n )\n return stream\n}\n\n/** What a service runtime exposes for its MQTT side; `serveMqtt` binds listeners to it. */\nexport type MqttRuntime = {\n attach(transport: Transport, info?: TransportInfo, namespace?: string): Connection\n webSocketPath(pathname: string): { namespace: string | undefined } | undefined\n /** Listener URLs, reported by the runtime's health route. */\n readonly endpoints: { mqtt?: string; websocket?: string }\n namespaces(): string[]\n instance(namespace?: string): { broker: Broker }\n /** Replaced by `serveMqtt` with one that also closes what it bound. */\n stop(): void\n}\n\nexport type ServeMqttOptions = TcpListenOptions & {\n /**\n * How often (real ms) expiries are settled when nothing else touches the brokers. A suite\n * that moves the runtime clock needs none of it. Default 1000.\n */\n sweepMs?: number\n /** WebSocket subprotocols accepted. Default `[\"mqtt\"]`. */\n subprotocols?: readonly string[]\n}\n\nexport type MqttListening = {\n tcp: TcpListening\n /** Serve MQTT over WebSocket on a bound HTTP server; returns its `ws://\u2026/mqtt` URL. */\n attachWebSocket(http: { server: HttpServer; url: string }): string\n}\n\n/**\n * Bind a runtime's MQTT listeners: TCP now, WebSocket once its HTTP server is up, and a timer\n * that settles expiries in real time. `runtime.stop()` then closes all of it and drops every\n * client, and so does closing the HTTP server.\n */\nexport const serveMqtt = async (\n runtime: MqttRuntime,\n options: ServeMqttOptions = {},\n): Promise<MqttListening> => {\n const tcp = await listenTcp((transport, info) => runtime.attach(transport, info), options)\n runtime.endpoints.mqtt = tcp.url\n const timer = setInterval(() => {\n for (const name of runtime.namespaces()) runtime.instance(name).broker.sweep()\n }, options.sweepMs ?? 1000)\n timer.unref()\n const dropConnections = runtime.stop\n let webSocket: WebSocketListening | undefined\n runtime.stop = () => {\n clearInterval(timer)\n webSocket?.close()\n void tcp.close()\n dropConnections()\n }\n return {\n tcp,\n attachWebSocket: (http) => {\n // The HTTP server is what a supervisor closes (`serve` on SIGINT): MQTT goes with it.\n http.server.once(\"close\", () => runtime.stop())\n webSocket = attachWebSocket(http.server, {\n ...(options.subprotocols ? { subprotocols: options.subprotocols } : {}),\n route: (pathname) => {\n const match = runtime.webSocketPath(pathname)\n if (!match) return undefined\n return (transport, info) => runtime.attach(transport, info, match.namespace)\n },\n })\n const url = `${http.url.replace(/^http/, \"ws\")}${MQTT_WEBSOCKET_PATH}`\n runtime.endpoints.websocket = url\n return url\n },\n }\n}\n", "/// <reference types=\"node\" />\nimport type { Duplex } from \"node:stream\"\nimport { type Listening, listen, type ServeTarget } from \"@crvouga/mockingbird-adapter-node\"\nimport { memoryStream, serveMqtt } from \"@crvouga/mockingbird-mqtt-broker/node\"\nimport { createRuntime, type EmqxRuntime, type EmqxRuntimeOptions } from \"./runtime.js\"\n\n/** HTTP port `mockingbird-emqx serve` listens on when none is given. */\nexport const DEFAULT_PORT = 8850\n/** MQTT over TCP port `mockingbird-emqx serve` listens on when none is given. */\nexport const DEFAULT_MQTT_PORT = 1883\n\n/** `supported_subprotocols` of EMQX's WebSocket listener. */\nconst SUBPROTOCOLS = [\"mqtt\", \"mqtt-v3\", \"mqtt-v3.1.1\", \"mqtt-v5\"]\n\nexport type EmqxServerOptions = EmqxRuntimeOptions & {\n /** HTTP port: the REST API, `/__admin`, and MQTT over WebSocket at `/mqtt`. Default `0`. */\n port?: number\n /** MQTT over TCP port. Default `0`: the OS picks a free port. */\n mqttPort?: number\n /** Default `127.0.0.1`. */\n host?: string\n /**\n * How often (real ms) expiries are settled when nothing else touches the broker. The served\n * emulator uses 1000; a suite that moves the clock through `/__admin/clock` needs none.\n */\n sweepMs?: number\n}\n\nexport type EmqxServer = Listening & {\n runtime: EmqxRuntime\n /** `mqtt://host:port`, MQTT over TCP. */\n mqttUrl: string\n mqttPort: number\n /** `ws://host:port/mqtt`, MQTT over WebSocket on the HTTP port. */\n wsUrl: string\n}\n\n/**\n * Serve the EMQX emulator in this process: the REST API and admin routes over `node:http`,\n * MQTT over WebSocket on the same port, and MQTT over TCP on its own. Every port defaults to\n * an OS-assigned one, and `close()` stops every listener and drops every client.\n */\nexport const createServer = async (options: EmqxServerOptions = {}): Promise<EmqxServer> => {\n const { port, mqttPort, host, sweepMs, ...rest } = options\n const runtime = createRuntime(rest)\n const mqtt = await serveMqtt(runtime, {\n port: mqttPort ?? 0,\n ...(host !== undefined ? { host } : {}),\n ...(sweepMs !== undefined ? { sweepMs } : {}),\n subprotocols: SUBPROTOCOLS,\n })\n let listening: Listening\n try {\n listening = await listen(runtime, {\n port: port ?? 0,\n ...(host !== undefined ? { host } : {}),\n })\n } catch (error) {\n runtime.stop()\n throw error\n }\n const wsUrl = mqtt.attachWebSocket(listening)\n return {\n ...listening,\n runtime,\n mqttUrl: mqtt.tcp.url,\n mqttPort: mqtt.tcp.port,\n wsUrl,\n close: async () => {\n runtime.stop()\n await mqtt.tcp.close()\n await listening.close()\n },\n }\n}\n\n/**\n * An in-process MQTT connection as a Node stream, with no socket:\n * `new MqttClient(() => connectStream(runtime), { protocolVersion: 5, \u2026 })` with `mqtt`.\n */\nexport const connectStream = (runtime: EmqxRuntime, namespace?: string): Duplex =>\n memoryStream((transport, info) => runtime.attach(transport, info, namespace))\n\nconst text = (value: string | boolean | undefined) =>\n typeof value === \"string\" ? value : undefined\n\nconst pair = (flag: string, value: string | undefined): [string, string] | undefined => {\n if (value === undefined) return undefined\n const colon = value.indexOf(\":\")\n if (colon <= 0) throw new Error(`--${flag} must look like \"<name>:<secret>\"`)\n return [value.slice(0, colon), value.slice(colon + 1)]\n}\n\n/**\n * Runtimes `serve` has built whose HTTP server is not bound yet. `serve` creates a runtime,\n * binds HTTP, then calls `listening` with the server only; a process serves one EMQX target at\n * a time, so the oldest entry is that server's runtime.\n */\nconst awaitingHttp: ((http: Listening) => string)[] = []\n\n/** How `serve` (and `serve --config`) builds the EMQX emulator from flags. */\nexport const serveTarget: ServeTarget = {\n name: \"emqx\",\n defaultPort: DEFAULT_PORT,\n options: {\n \"mqtt-port\": {\n type: \"string\",\n value: \"<port>\",\n description: \"MQTT over TCP port (0 picks a free one)\",\n default: String(DEFAULT_MQTT_PORT),\n },\n \"api-key\": {\n type: \"string\",\n value: \"<key:secret>\",\n description: \"Only accept this REST API key and secret (default: any pair)\",\n },\n \"mqtt-user\": {\n type: \"string\",\n value: \"<username:password>\",\n description: \"Add this user to the built-in database authenticator\",\n },\n \"jwt-secret\": {\n type: \"string\",\n value: \"<secret>\",\n description: \"Enable the JWT authenticator (HS256/384/512, token in the password)\",\n },\n \"no-match\": {\n type: \"string\",\n value: \"<allow|deny>\",\n description: \"authorization.no_match: what applies when no ACL rule decides\",\n default: \"allow\",\n },\n },\n create: async (values, common) => {\n const apiKey = pair(\"api-key\", text(values[\"api-key\"]))\n const user = pair(\"mqtt-user\", text(values[\"mqtt-user\"]))\n const secret = text(values[\"jwt-secret\"])\n const noMatch = text(values[\"no-match\"]) ?? \"allow\"\n if (noMatch !== \"allow\" && noMatch !== \"deny\") {\n throw new Error('--no-match must be \"allow\" or \"deny\"')\n }\n const mqttPort = Number.parseInt(text(values[\"mqtt-port\"]) ?? String(DEFAULT_MQTT_PORT), 10)\n if (!Number.isInteger(mqttPort) || mqttPort < 0 || mqttPort > 65_535) {\n throw new Error(\"--mqtt-port must be a port number\")\n }\n const runtime = createRuntime({\n settings: {\n ...(apiKey ? { apiKeys: [{ key: apiKey[0], secret: apiKey[1] }] } : {}),\n ...(user ? { users: [{ username: user[0], password: user[1] }] } : {}),\n ...(secret ? { jwt: { secret } } : {}),\n authorization: { noMatch },\n },\n ...(common.adminPrefix !== undefined ? { adminPrefix: common.adminPrefix } : {}),\n ...(common.adminKey !== undefined ? { adminKey: common.adminKey } : {}),\n ...(common.adminControls !== undefined ? { adminControls: common.adminControls } : {}),\n ...(common.seed !== undefined ? { seed: common.seed } : {}),\n ...(common.onLog ? { onLog: common.onLog } : {}),\n })\n const mqtt = await serveMqtt(runtime, { port: mqttPort, subprotocols: SUBPROTOCOLS })\n awaitingHttp.push(mqtt.attachWebSocket)\n return runtime\n },\n listening: (http) => {\n awaitingHttp.shift()?.(http)\n },\n banner: (runtime) => {\n const { endpoints } = runtime as EmqxRuntime\n return [\n `mqtt: ${endpoints.mqtt ?? \"(not bound)\"} (MQTT 5 over TCP)`,\n `websocket: ${endpoints.websocket ?? \"(not bound)\"} (subprotocol mqtt)`,\n \"rest: Authorization: Basic <api key>:<secret> on POST /api/v5/publish and DELETE /api/v5/clients/{clientid}\",\n \"namespaces: x-mockingbird-namespace, /__admin/ns/<name>/\u2026, or PUT /__admin/credentials {<api key | mqtt username | client id>: <ns>}\",\n ]\n },\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["readFile", "resolve", "resolve", "text", "response", "pair", "readFile", "isObject", "resolve", "adminKey", "createServer", "createServer", "resolve", "createServer"]
7
+ }