@crvouga/mockingbird-service-mailosaur 3.0.0 → 3.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.
@@ -3,7 +3,7 @@ import {
3
3
  createRuntime,
4
4
  parseDuration,
5
5
  resolveAdminPrefix
6
- } from "./chunk-3QF4WQTT.js";
6
+ } from "./chunk-UW6DSYMU.js";
7
7
 
8
8
  // src/server.ts
9
9
  import { writeFileSync } from "node:fs";
@@ -172,7 +172,9 @@ var httpChild = async (target, entry, options) => {
172
172
  adminPrefix: resolveAdminPrefix(entry.adminPrefix),
173
173
  adminKey: entry.adminKey,
174
174
  seed: entry.seed,
175
- onLog: options.onLog
175
+ onLog: options.onLog,
176
+ ...entry.fixtures !== void 0 ? { fixtures: entry.fixtures } : {},
177
+ ...entry.baseUrl !== void 0 ? { baseUrl: entry.baseUrl } : {}
176
178
  });
177
179
  const adminPrefix = resolveAdminPrefix(entry.adminPrefix);
178
180
  runtime.isolateNamespaces();
@@ -718,7 +720,7 @@ var start = async (target, values, config) => {
718
720
  });
719
721
  const listening = await listen(runtime, { port: config.port, host: config.host });
720
722
  target.listening?.(listening);
721
- console.log(`${target.name} mock listening on ${listening.url}`);
723
+ console.log(`${target.name} emulator listening on ${listening.url}`);
722
724
  console.log(`${target.name} health: GET ${listening.url}${adminPrefix}/health`);
723
725
  console.log(`${target.name} admin: ${listening.url}${adminPrefix} (${config.adminKey ? "x-mockingbird-admin-key required" : "open \u2014 pass --admin-key to lock"})`);
724
726
  console.log(`${target.name} admin ui: ${listening.url}${adminPrefix}/ui`);
@@ -738,7 +740,7 @@ var untilSignal = async (servers) => new Promise((resolve2) => {
738
740
  process.once("SIGTERM", stop);
739
741
  });
740
742
  var serveCommand = (target) => ({
741
- summary: `Serve the ${target.name} mock or a configured fleet`,
743
+ summary: `Serve the ${target.name} emulator or a configured fleet`,
742
744
  options: { ...COMMON_SERVE_OPTIONS, ..."options" in target ? target.options : {} },
743
745
  async run(values) {
744
746
  const log = values["log-requests"] === true ? "json" : asString(values.log) ?? "pretty";
@@ -764,7 +766,7 @@ var serveCommand = (target) => ({
764
766
  console.log(JSON.stringify(manifest));
765
767
  else
766
768
  for (const [name2, endpoint] of Object.entries(manifest.services))
767
- console.log(`${name2} mock listening on ${endpoint.url}`);
769
+ console.log(`${name2} emulator listening on ${endpoint.url}`);
768
770
  }
769
771
  });
770
772
  return untilSignal([fleet]);
@@ -1055,4 +1057,4 @@ export {
1055
1057
  createServer2 as createServer,
1056
1058
  serveTarget
1057
1059
  };
1058
- //# sourceMappingURL=chunk-NWHF63LJ.js.map
1060
+ //# sourceMappingURL=chunk-X6FOBGVH.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/server.ts", "../../../adapters/node/src/cli.ts", "../../../adapters/node/src/fleet.ts", "../../../adapters/node/src/serve.ts", "../../../adapters/node/src/listen.ts", "../src/tls.ts"],
4
+ "sourcesContent": ["/// <reference types=\"node\" />\nimport { writeFileSync } from \"node:fs\"\nimport { readFile } from \"node:fs/promises\"\nimport {\n connect,\n createServer as createNetServer,\n type Server as NetServer,\n type Socket,\n} from \"node:net\"\nimport { createServer as createTlsServer, type Server as TlsServer } from \"node:tls\"\nimport { type Listening, listen, type ServeTarget } from \"@crvouga/mockingbird-adapter-node\"\nimport { createRuntime, type MailosaurRuntime, type MailosaurRuntimeOptions } from \"./runtime.js\"\nimport { type SelfSignedCertificate, selfSignedCertificate } from \"./tls.js\"\n\nexport type { SelfSignedCertificate } from \"./tls.js\"\nexport { selfSignedCertificate } from \"./tls.js\"\n\n/** Port `mockingbird-mailosaur serve` listens on when none is given. */\nexport const DEFAULT_PORT = 8793\n\nexport type TlsOptions = {\n /** Default `0`: the OS picks a free port. */\n port?: number\n /** PEM certificate and key; default: a fresh self-signed one for localhost, 127.0.0.1 and mailosaur.com. */\n cert?: string\n key?: string\n}\n\nexport type MailosaurServerOptions = MailosaurRuntimeOptions & {\n /** Default `0`: the OS picks a free port. */\n port?: number\n /** Default `127.0.0.1`. */\n host?: string\n /**\n * Also answer over HTTPS. The `mailosaur` SDK only speaks HTTPS (it calls `https.request`\n * whatever its base URL says), so pass `tls: true` whenever the SDK is the client.\n */\n tls?: boolean | TlsOptions\n}\n\nexport type MailosaurServer = Listening & {\n runtime: MailosaurRuntime\n /** `https://127.0.0.1:<port>` when `tls` was asked for. */\n tlsUrl?: string\n /** The same port as an HTTP proxy (`HTTPS_PROXY`), how the unmodified SDK reaches the mock. */\n proxyUrl?: string\n /** The PEM certificate the HTTPS listener presents (trust it with `ca` / `NODE_EXTRA_CA_CERTS`). */\n cert?: string\n}\n\ntype Endpoint = { host: string; port: number }\ntype Door = { port: number; close(): Promise<void> }\n\nconst listenOn = async (server: NetServer | TlsServer, bind: Endpoint): Promise<number> => {\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject)\n server.listen(bind.port, bind.host, resolve)\n })\n const address = server.address()\n return typeof address === \"object\" && address !== null ? address.port : bind.port\n}\n\n/** Pipe `socket` (after replaying `head`) to `target`, tearing both down together. */\nconst tunnel = (socket: Socket, target: Endpoint, head: Uint8Array, sockets: Set<Socket>) => {\n const inner = connect(target.port, target.host)\n sockets.add(socket)\n sockets.add(inner)\n const close = () => {\n socket.destroy()\n inner.destroy()\n sockets.delete(socket)\n sockets.delete(inner)\n }\n socket.on(\"error\", close).on(\"close\", close)\n inner.on(\"error\", close).on(\"close\", close)\n if (head.length > 0) inner.write(head)\n socket.pipe(inner)\n inner.pipe(socket)\n socket.resume()\n}\n\n/**\n * One port that speaks HTTPS, plain HTTP and the HTTP `CONNECT` proxy method, all onto the\n * runtime's plain HTTP listener `upstream`:\n *\n * - a TLS ClientHello is terminated with `certificate` (the SDK's direct HTTPS);\n * - `CONNECT <any host>:<port>` is answered `200` and the tunnel is terminated the same way.\n * The `mailosaur` SDK drops the port of its base URL (it always connects to 443), so this\n * is how an unmodified SDK reaches the mock: `HTTPS_PROXY=http://127.0.0.1:<port>` when the\n * client is constructed, and the certificate trusted (`NODE_EXTRA_CA_CERTS`). Every CONNECT\n * target is tunnelled into the mock, never to the network;\n * - anything else is plain HTTP.\n */\nconst secureDoor = async (\n certificate: SelfSignedCertificate,\n upstream: Endpoint,\n bind: Endpoint,\n): Promise<Door> => {\n const sockets = new Set<Socket>()\n const terminator = createTlsServer({ cert: certificate.cert, key: certificate.key }, (socket) =>\n tunnel(socket, upstream, new Uint8Array(), sockets),\n )\n const tlsPort = await listenOn(terminator, { host: \"127.0.0.1\", port: 0 })\n const decrypted = { host: \"127.0.0.1\", port: tlsPort }\n const door = createNetServer((socket) => {\n let buffered = Buffer.alloc(0)\n const onData = (chunk: Buffer) => {\n buffered = Buffer.concat([buffered, chunk])\n if (buffered[0] === 0x16) {\n socket.off(\"data\", onData)\n socket.pause()\n tunnel(socket, decrypted, buffered, sockets)\n return\n }\n const end = buffered.indexOf(\"\\r\\n\\r\\n\")\n if (end < 0 && buffered.length < 16_384) return\n socket.off(\"data\", onData)\n socket.pause()\n if (/^CONNECT /i.test(buffered.subarray(0, 8).toString(\"latin1\"))) {\n socket.write(\"HTTP/1.1 200 Connection Established\\r\\n\\r\\n\")\n tunnel(socket, decrypted, buffered.subarray(end + 4), sockets)\n } else {\n tunnel(socket, upstream, buffered, sockets)\n }\n }\n socket.on(\"data\", onData)\n socket.on(\"error\", () => socket.destroy())\n })\n const port = await listenOn(door, bind)\n return {\n port,\n close: () =>\n new Promise<void>((resolve) => {\n for (const socket of sockets) socket.destroy()\n terminator.close()\n door.close(() => resolve())\n }),\n }\n}\n\n/** The hosts the generated certificate names: loopback, and the SDK's default host. */\nexport const CERTIFICATE_HOSTS = [\"localhost\", \"127.0.0.1\", \"mailosaur.com\"] as const\n\nconst certificateFor = (tls: TlsOptions): SelfSignedCertificate =>\n tls.cert && tls.key ? { cert: tls.cert, key: tls.key } : selfSignedCertificate(CERTIFICATE_HOSTS)\n\n/** Serve the Mailosaur mock over `node:http`, and over HTTPS too when `tls` is set. */\nexport const createServer = async (\n options: MailosaurServerOptions = {},\n): Promise<MailosaurServer> => {\n const { port, host, tls, ...rest } = options\n const runtime = createRuntime(rest)\n const listening = await listen(runtime, {\n port: port ?? 0,\n ...(host !== undefined ? { host } : {}),\n })\n if (!tls) return { ...listening, runtime }\n const options_ = tls === true ? {} : tls\n const certificate = certificateFor(options_)\n const door = await secureDoor(\n certificate,\n { host: listening.host, port: listening.port },\n { host: listening.host, port: options_.port ?? 0 },\n )\n const shown = listening.host.includes(\":\") ? `[${listening.host}]` : listening.host\n return {\n ...listening,\n runtime,\n tlsUrl: `https://${shown}:${door.port}`,\n proxyUrl: `http://${shown}:${door.port}`,\n cert: certificate.cert,\n close: async () => {\n await door.close()\n await listening.close()\n },\n }\n}\n\nconst text = (value: string | boolean | undefined) =>\n typeof value === \"string\" ? value : undefined\n\n/** How `serve` (and `serve --config`) builds the Mailosaur mock from flags. */\nexport const serveTarget: ServeTarget = {\n name: \"mailosaur\",\n defaultPort: DEFAULT_PORT,\n options: {\n \"tls-port\": {\n type: \"string\",\n value: \"<port>\",\n description:\n \"Also serve HTTPS and an HTTP CONNECT proxy on this port (the mailosaur SDK only speaks HTTPS, always to port 443): construct the SDK with HTTPS_PROXY=http://127.0.0.1:<port>\",\n },\n \"tls-cert\": { type: \"string\", value: \"<pem file>\", description: \"Certificate for --tls-port\" },\n \"tls-key\": { type: \"string\", value: \"<pem file>\", description: \"Private key for --tls-port\" },\n \"tls-cert-out\": {\n type: \"string\",\n value: \"<file>\",\n description:\n \"Write the generated self-signed certificate here (use it as NODE_EXTRA_CA_CERTS for the app)\",\n },\n \"poll-delay\": {\n type: \"string\",\n value: \"<ms[,ms\u2026]>\",\n description: \"x-ms-delay the SDK waits between empty polls (default 20)\",\n },\n },\n create: async (values, common) => {\n const delays = text(values[\"poll-delay\"])\n if (delays && !/^\\d+(,\\d+)*$/.test(delays)) {\n throw new Error(\"--poll-delay must look like 20 or 20,50,100\")\n }\n const runtime = createRuntime({\n ...(delays ? { settings: { pollDelaysMs: delays.split(\",\").map(Number) } } : {}),\n ...(common.adminPrefix !== undefined ? { adminPrefix: common.adminPrefix } : {}),\n ...(common.adminKey !== undefined ? { adminKey: common.adminKey } : {}),\n ...(common.seed !== undefined ? { seed: common.seed } : {}),\n ...(common.onLog ? { onLog: common.onLog } : {}),\n })\n const tlsPort = text(values[\"tls-port\"])\n if (tlsPort !== undefined) {\n const certFile = text(values[\"tls-cert\"])\n const keyFile = text(values[\"tls-key\"])\n if ((certFile === undefined) !== (keyFile === undefined)) {\n throw new Error(\"--tls-cert and --tls-key go together\")\n }\n const certificate = certificateFor(\n certFile && keyFile\n ? { cert: await readFile(certFile, \"utf8\"), key: await readFile(keyFile, \"utf8\") }\n : {},\n )\n const out = text(values[\"tls-cert-out\"])\n if (out) writeFileSync(out, certificate.cert)\n // The secure door fronts its own loopback HTTP listener over the same runtime.\n const inner = await listen(runtime, { port: 0 })\n const door = await secureDoor(\n certificate,\n { host: inner.host, port: inner.port },\n { host: \"127.0.0.1\", port: Number(tlsPort) },\n )\n console.log(\n `mailosaur HTTPS + CONNECT proxy on 127.0.0.1:${door.port} (HTTPS_PROXY=http://127.0.0.1:${door.port})`,\n )\n }\n return runtime\n },\n banner: () => [\n \"auth: Authorization: Basic base64(<api key>:) \u2014 any key; the SDK needs HTTPS (--tls-port)\",\n \"ingest: POST /__admin/ingest {to, from?, subject?, html?, text?, server?, type?}\",\n \"namespaces: x-mockingbird-namespace, /__admin/ns/<name>/\u2026, or PUT /__admin/credentials {<api key>: <ns>}\",\n ],\n}\n", "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 { RequestLog, ServiceInstance, ServiceRuntime } from \"@crvouga/mockingbird-service\"\nimport { resolveAdminPrefix } 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 /** 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: { 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 \"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\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 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 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 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 })\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 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)\n let listening: Listening\n try {\n listening = await start(target, values, {\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 { createClock, parseDuration, resolveAdminPrefix } 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.fixtures !== undefined ? { fixtures: entry.fixtures } : {}),\n ...(entry.baseUrl !== undefined ? { baseUrl: entry.baseUrl } : {}),\n })\n const adminPrefix = resolveAdminPrefix(entry.adminPrefix)\n runtime.isolateNamespaces()\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 childClock.freeze()\n childClock.set(target)\n if (!frozen) childClock.unfreeze()\n await child.settle?.(namespace)\n return childClock.state()\n })\n if (response.ok) {\n current.freeze()\n current.set(target)\n if (!frozen) current.unfreeze()\n }\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) {\n const current = clock(namespace)\n current.freeze()\n current.set(point.clock.now)\n if (!point.clock.frozen) current.unfreeze()\n }\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 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 },\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` 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 { generateKeyPairSync, randomBytes, sign } from \"node:crypto\"\n\n/**\n * A throwaway self-signed certificate for `localhost` / `127.0.0.1`, generated in memory at\n * startup. The Mailosaur SDK always speaks HTTPS (it calls `https.request` whatever the base\n * URL says), so the mock has to answer over TLS; generating the certificate here means no\n * private key ships in the package and no `openssl` is needed.\n *\n * Minimal DER encoding of an X.509 v3 certificate (ECDSA P-256 / SHA-256) with a\n * subjectAltName for every host given.\n */\nexport type SelfSignedCertificate = { cert: string; key: string }\n\nconst tlv = (tag: number, ...parts: Uint8Array[]): Uint8Array => {\n const length = parts.reduce((sum, part) => sum + part.length, 0)\n const header =\n length < 0x80\n ? [tag, length]\n : length < 0x100\n ? [tag, 0x81, length]\n : [tag, 0x82, length >> 8, length & 0xff]\n const out = new Uint8Array(header.length + length)\n out.set(header, 0)\n let offset = header.length\n for (const part of parts) {\n out.set(part, offset)\n offset += part.length\n }\n return out\n}\n\nconst sequence = (...parts: Uint8Array[]) => tlv(0x30, ...parts)\nconst bytes = (value: string) => new TextEncoder().encode(value)\n\nconst oid = (dotted: string): Uint8Array => {\n const [first = 0, second = 0, ...rest] = dotted.split(\".\").map(Number)\n const out = [first * 40 + second]\n for (const arc of rest) {\n const base128 = [arc & 0x7f]\n for (let value = arc >> 7; value > 0; value >>= 7) base128.unshift((value & 0x7f) | 0x80)\n out.push(...base128)\n }\n return tlv(0x06, Uint8Array.from(out))\n}\n\n/** A non-negative DER INTEGER: minimal bytes (no redundant leading zeros), 0x00-padded if the high bit is set. */\nconst integer = (value: Uint8Array) => {\n let start = 0\n while (start < value.length - 1 && value[start] === 0) start++\n const bytes = value.subarray(start)\n return tlv(0x02, (bytes[0] ?? 0) & 0x80 ? Uint8Array.from([0, ...bytes]) : bytes)\n}\n\nconst utcTime = (date: Date) => {\n const two = (n: number) => String(n).padStart(2, \"0\")\n return tlv(\n 0x17,\n bytes(\n `${two(date.getUTCFullYear() % 100)}${two(date.getUTCMonth() + 1)}${two(date.getUTCDate())}` +\n `${two(date.getUTCHours())}${two(date.getUTCMinutes())}${two(date.getUTCSeconds())}Z`,\n ),\n )\n}\n\nconst name = (commonName: string) =>\n sequence(tlv(0x31, sequence(oid(\"2.5.4.3\"), tlv(0x0c, bytes(commonName)))))\n\nconst ipBytes = (ip: string) => Uint8Array.from(ip.split(\".\").map(Number))\n\nconst pem = (label: string, der: Uint8Array) =>\n `-----BEGIN ${label}-----\\n${(\n Buffer.from(der)\n .toString(\"base64\")\n .match(/.{1,64}/g) ?? []\n ).join(\"\\n\")}\\n-----END ${label}-----\\n`\n\n/** A fresh certificate valid from a day ago for ten years, for `hosts` (names or IPv4). */\nexport const selfSignedCertificate = (\n hosts: readonly string[] = [\"localhost\", \"127.0.0.1\"],\n): SelfSignedCertificate => {\n const { privateKey, publicKey } = generateKeyPairSync(\"ec\", { namedCurve: \"prime256v1\" })\n const algorithm = sequence(oid(\"1.2.840.10045.4.3.2\"))\n const now = Date.now()\n const altNames = sequence(\n ...hosts.map((host) =>\n /^\\d+\\.\\d+\\.\\d+\\.\\d+$/.test(host) ? tlv(0x87, ipBytes(host)) : tlv(0x82, bytes(host)),\n ),\n )\n const extensions = tlv(\n 0xa3,\n sequence(\n sequence(oid(\"2.5.29.19\"), tlv(0x04, sequence(tlv(0x01, Uint8Array.from([0xff]))))),\n sequence(oid(\"2.5.29.17\"), tlv(0x04, altNames)),\n ),\n )\n const serial = randomBytes(16)\n serial[0] = (serial[0] ?? 0) & 0x7f\n const tbs = sequence(\n tlv(0xa0, integer(Uint8Array.from([2]))),\n integer(serial),\n algorithm,\n name(hosts[0] ?? \"localhost\"),\n sequence(utcTime(new Date(now - 86_400_000)), utcTime(new Date(now + 3_650 * 86_400_000))),\n name(hosts[0] ?? \"localhost\"),\n new Uint8Array(publicKey.export({ type: \"spki\", format: \"der\" })),\n extensions,\n )\n const signature = sign(\"sha256\", tbs, privateKey)\n const certificate = sequence(tbs, algorithm, tlv(0x03, Uint8Array.from([0]), signature))\n return {\n cert: pem(\"CERTIFICATE\", certificate),\n key: privateKey.export({ type: \"pkcs8\", format: \"pem\" }).toString(),\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["readFile", "readFile", "resolve", "resolve", "name", "text", "response", "name", "resolve", "readFile", "adminKey", "start", "bytes", "resolve", "createServer", "readFile"]
7
+ }
package/dist/cli.js CHANGED
@@ -3,8 +3,8 @@ import {
3
3
  runCli,
4
4
  serveCommand,
5
5
  serveTarget
6
- } from "./chunk-NWHF63LJ.js";
7
- import "./chunk-3QF4WQTT.js";
6
+ } from "./chunk-X6FOBGVH.js";
7
+ import "./chunk-UW6DSYMU.js";
8
8
 
9
9
  // src/cli.ts
10
10
  var code = await runCli(
package/dist/index.d.ts CHANGED
@@ -10,88 +10,16 @@ interface FetchAPI$1 {
10
10
  fetch(request: Request): Promise<Response>;
11
11
  }
12
12
 
13
- /** Bind values accepted by Mockingbird's SQLite port (matches sqlite-mem / better-sqlite3). */
14
- type SqliteValue$1 = null | number | bigint | string | Uint8Array | boolean;
15
- /** Mutation counters returned by {@link SqliteStatement.run}. */
16
- type SqliteRunResult$1 = {
17
- changes: number;
18
- lastInsertRowid: number | bigint;
13
+ type MountedAPI = FetchAPI & {
14
+ readonly prefix: string;
15
+ GET: FetchHandler;
16
+ POST: FetchHandler;
17
+ PUT: FetchHandler;
18
+ PATCH: FetchHandler;
19
+ DELETE: FetchHandler;
20
+ HEAD: FetchHandler;
21
+ OPTIONS: FetchHandler;
19
22
  };
20
- /**
21
- * Prepared statement bound to a {@link SqliteClient}.
22
- *
23
- * Pass bind values as rest arguments on each call (no sticky `bind()`).
24
- */
25
- interface SqliteStatement$1 {
26
- run(...params: SqliteValue$1[]): SqliteRunResult$1;
27
- all<T = Record<string, unknown>>(...params: SqliteValue$1[]): T[];
28
- get<T = Record<string, unknown>>(...params: SqliteValue$1[]): T | undefined;
29
- }
30
- /**
31
- * Sync SQLite client port owned by Mockingbird.
32
- *
33
- * Duck-typed so `@crvouga/mockingbird-service-sqlite` `Database`, better-sqlite3, and wrapped
34
- * `bun:sqlite` instances all work when they expose this surface.
35
- */
36
- interface SqliteClient$1 {
37
- exec(sql: string): void;
38
- prepare(sql: string): SqliteStatement$1;
39
- transaction<T>(fn: () => T): T;
40
- }
41
-
42
- /** Every stored record carries a monotonically increasing sequence for stable ordering. */
43
- type Stored<T> = {
44
- seq: number;
45
- value: T;
46
- };
47
- type ListRecordsOptions<T> = {
48
- /** Keep only records passing the predicate. */
49
- where?: (value: T, seq: number) => boolean;
50
- /** Sort order; default newest first. */
51
- order?: "newest" | "oldest";
52
- };
53
- /**
54
- * A SQLite-backed table of JSON records addressed by id. Ordering is by insertion
55
- * sequence, never by id lexicographic order, so list semantics stay stable.
56
- */
57
- declare class Collection<T> {
58
- private readonly sqlite;
59
- /** Storage namespace. Admin introspection uses this to ignore another namespace's tables. */
60
- readonly namespace: string;
61
- /** Table name inside the namespace. Stable across resets of the rows themselves. */
62
- readonly collectionName: string;
63
- constructor(sqlite: SqliteClient$1,
64
- /** Storage namespace. Admin introspection uses this to ignore another namespace's tables. */
65
- namespace: string,
66
- /** Table name inside the namespace. Stable across resets of the rows themselves. */
67
- collectionName: string);
68
- private bumpCollectionSeq;
69
- nextSequence(): number;
70
- get(id: string): T | undefined;
71
- has(id: string): boolean;
72
- /** Insert a new record, assigning it the next sequence number. */
73
- insert(id: string, value: T): Stored<T>;
74
- /** Replace an existing record's value, keeping its position. */
75
- update(id: string, value: T): Stored<T> | undefined;
76
- delete(id: string): boolean;
77
- /** How many records the collection holds, without reading them. */
78
- count(): number;
79
- list(options?: ListRecordsOptions<T>): Array<Stored<T> & {
80
- id: string;
81
- }>;
82
- }
83
-
84
- /**
85
- * Sequential id source persisted in SQLite. Ids are deterministic for a given
86
- * sequence history (`cus_` + 14 opaque chars), so reproductions stay stable.
87
- */
88
- declare class IdSequence {
89
- private readonly sqlite;
90
- private readonly namespace;
91
- private readonly salt;
92
- constructor(sqlite: SqliteClient$1, namespace: string, salt?: string);
93
- next(prefix: string, length?: number): string;
94
- }
95
23
 
96
24
  /** A stable identifier for a point in a {@link Timeline}. */
97
25
  type CheckpointId = string;
@@ -182,6 +110,91 @@ declare class Timeline<T> {
182
110
  interface FetchAPI {
183
111
  fetch(request: Request): Promise<Response>;
184
112
  }
113
+ /** A bare function form of {@link FetchAPI}, compatible with `Bun.serve`, workerd, and Deno. */
114
+ type FetchHandler = (request: Request) => Promise<Response>;
115
+
116
+ /** Bind values accepted by Mockingbird's SQLite port (matches sqlite-mem / better-sqlite3). */
117
+ type SqliteValue$1 = null | number | bigint | string | Uint8Array | boolean;
118
+ /** Mutation counters returned by {@link SqliteStatement.run}. */
119
+ type SqliteRunResult$1 = {
120
+ changes: number;
121
+ lastInsertRowid: number | bigint;
122
+ };
123
+ /**
124
+ * Prepared statement bound to a {@link SqliteClient}.
125
+ *
126
+ * Pass bind values as rest arguments on each call (no sticky `bind()`).
127
+ */
128
+ interface SqliteStatement$1 {
129
+ run(...params: SqliteValue$1[]): SqliteRunResult$1;
130
+ all<T = Record<string, unknown>>(...params: SqliteValue$1[]): T[];
131
+ get<T = Record<string, unknown>>(...params: SqliteValue$1[]): T | undefined;
132
+ }
133
+ /**
134
+ * Sync SQLite client port owned by Mockingbird.
135
+ *
136
+ * Duck-typed so `@crvouga/mockingbird-service-sqlite` `Database`, better-sqlite3, and wrapped
137
+ * `bun:sqlite` instances all work when they expose this surface.
138
+ */
139
+ interface SqliteClient$1 {
140
+ exec(sql: string): void;
141
+ prepare(sql: string): SqliteStatement$1;
142
+ transaction<T>(fn: () => T): T;
143
+ }
144
+
145
+ /** Every stored record carries a monotonically increasing sequence for stable ordering. */
146
+ type Stored<T> = {
147
+ seq: number;
148
+ value: T;
149
+ };
150
+ type ListRecordsOptions<T> = {
151
+ /** Keep only records passing the predicate. */
152
+ where?: (value: T, seq: number) => boolean;
153
+ /** Sort order; default newest first. */
154
+ order?: "newest" | "oldest";
155
+ };
156
+ /**
157
+ * A SQLite-backed table of JSON records addressed by id. Ordering is by insertion
158
+ * sequence, never by id lexicographic order, so list semantics stay stable.
159
+ */
160
+ declare class Collection<T> {
161
+ private readonly sqlite;
162
+ /** Storage namespace. Admin introspection uses this to ignore another namespace's tables. */
163
+ readonly namespace: string;
164
+ /** Table name inside the namespace. Stable across resets of the rows themselves. */
165
+ readonly collectionName: string;
166
+ constructor(sqlite: SqliteClient$1,
167
+ /** Storage namespace. Admin introspection uses this to ignore another namespace's tables. */
168
+ namespace: string,
169
+ /** Table name inside the namespace. Stable across resets of the rows themselves. */
170
+ collectionName: string);
171
+ private bumpCollectionSeq;
172
+ nextSequence(): number;
173
+ get(id: string): T | undefined;
174
+ has(id: string): boolean;
175
+ /** Insert a new record, assigning it the next sequence number. */
176
+ insert(id: string, value: T): Stored<T>;
177
+ /** Replace an existing record's value, keeping its position. */
178
+ update(id: string, value: T): Stored<T> | undefined;
179
+ delete(id: string): boolean;
180
+ /** How many records the collection holds, without reading them. */
181
+ count(): number;
182
+ list(options?: ListRecordsOptions<T>): Array<Stored<T> & {
183
+ id: string;
184
+ }>;
185
+ }
186
+
187
+ /**
188
+ * Sequential id source persisted in SQLite. Ids are deterministic for a given
189
+ * sequence history (`cus_` + 14 opaque chars), so reproductions stay stable.
190
+ */
191
+ declare class IdSequence {
192
+ private readonly sqlite;
193
+ private readonly namespace;
194
+ private readonly salt;
195
+ constructor(sqlite: SqliteClient$1, namespace: string, salt?: string);
196
+ next(prefix: string, length?: number): string;
197
+ }
185
198
 
186
199
  /** Options every provider constructor accepts. */
187
200
  type APIOptions = {
@@ -624,6 +637,8 @@ type ServiceRuntime<T extends ServiceInstance> = FetchAPI & {
624
637
  /** Stop package-owned lifecycle timers when a supervisor closes the runtime. */
625
638
  stop?(): void;
626
639
  readonly name: string;
640
+ /** Same-origin Fetch handler and App Router method exports, sharing this runtime. */
641
+ mount(prefix: string): MountedAPI;
627
642
  readonly sqlite: SqliteClient$1;
628
643
  readonly clock: Clock;
629
644
  readonly faults: FaultRegistry;
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  parseAddresses,
16
16
  supportedOperationIds,
17
17
  textContent
18
- } from "./chunk-3QF4WQTT.js";
18
+ } from "./chunk-UW6DSYMU.js";
19
19
  export {
20
20
  ANY_SERVER,
21
21
  DEFAULT_AWAIT_TIMEOUT_MS,