@crvouga/mockingbird-service-emqx 0.5.0 → 0.7.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,6 +1,18 @@
1
1
  # Changelog — @crvouga/mockingbird-service-emqx
2
2
 
3
- ## 0.5.0 (2026-10-17)
3
+ ## 0.7.0 (2026-10-21)
4
+
5
+ ### Features
6
+
7
+ - raise the serve and fleet body limit to the S3 maximum ([86b9e2b](https://github.com/crvouga/mockingbird/commit/86b9e2b80bcaaaef57f52edbac50b27da0b42f33))
8
+
9
+ ## 0.6.0 (2026-10-18)
10
+
11
+ ### Features
12
+
13
+ - resolve the agent-reported issue queue in one batch ([25c52b6](https://github.com/crvouga/mockingbird/commit/25c52b668a53ddb80b968419601a20abf33f956b))
14
+
15
+ ## 0.5.0 (2026-10-16)
4
16
 
5
17
  ### Features
6
18
 
@@ -4,17 +4,31 @@ import {
4
4
  createRuntime,
5
5
  normalizeBootControls,
6
6
  normalizeControls,
7
+ normalizeIdBase,
7
8
  ownedTransport,
8
9
  parseDuration,
9
10
  parseFaultHeader,
10
11
  resolveAdminPrefix,
11
12
  restoreClock
12
- } from "./chunk-X2C4CFIC.js";
13
+ } from "./chunk-YXGEJYVV.js";
13
14
 
14
15
  // ../../adapters/node/dist/cli.js
15
16
  import { readFile as readFile5 } from "node:fs/promises";
16
17
  import { parseArgs } from "node:util";
17
18
 
19
+ // ../../adapters/node/dist/boot-settings.js
20
+ var checkSettings = (target, settings, label) => {
21
+ if (!target.parseSettings)
22
+ throw new Error(`${label}: ${target.name} takes no boot settings`);
23
+ try {
24
+ return target.parseSettings(settings);
25
+ } catch (error) {
26
+ throw new Error(`${label}: ${error instanceof Error ? error.message : String(error)}`, {
27
+ cause: error
28
+ });
29
+ }
30
+ };
31
+
18
32
  // ../../adapters/node/dist/fleet.js
19
33
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
20
34
  import { createHash as createHash4, randomUUID as randomUUID4 } from "node:crypto";
@@ -2664,6 +2678,9 @@ var fleet_config_schema_default = {
2664
2678
  adminControls: {
2665
2679
  $ref: "#/$defs/controls"
2666
2680
  },
2681
+ idBase: {
2682
+ $ref: "#/$defs/idBase"
2683
+ },
2667
2684
  namespace: {
2668
2685
  type: "string",
2669
2686
  pattern: "^[A-Za-z0-9_.-]{1,64}$"
@@ -2753,6 +2770,12 @@ var fleet_config_schema_default = {
2753
2770
  adminControls: {
2754
2771
  $ref: "#/$defs/controls"
2755
2772
  },
2773
+ idBase: {
2774
+ $ref: "#/$defs/idBase"
2775
+ },
2776
+ settings: {
2777
+ type: "object"
2778
+ },
2756
2779
  fixtures: {
2757
2780
  type: "object"
2758
2781
  },
@@ -2799,6 +2822,18 @@ var fleet_config_schema_default = {
2799
2822
  }
2800
2823
  }
2801
2824
  },
2825
+ idBase: {
2826
+ anyOf: [
2827
+ {
2828
+ type: "integer",
2829
+ minimum: 0
2830
+ },
2831
+ {
2832
+ type: "string",
2833
+ pattern: "^(boot|[0-9]+)$"
2834
+ }
2835
+ ]
2836
+ },
2802
2837
  controls: {
2803
2838
  type: "object",
2804
2839
  additionalProperties: false,
@@ -2948,6 +2983,8 @@ async function preflightFleet(config, options) {
2948
2983
  throw new Error("protected archive policy requires a protected repository; configure its protector before startup");
2949
2984
  resolveAdminPrefix(config.adminPrefix);
2950
2985
  normalizeBootControls(config.adminControls);
2986
+ if (config.idBase !== void 0)
2987
+ normalizeIdBase(config.idBase, "idBase");
2951
2988
  const targets = /* @__PURE__ */ new Map();
2952
2989
  const ports = /* @__PURE__ */ new Set();
2953
2990
  for (const [name, entry] of Object.entries(config.services)) {
@@ -2979,6 +3016,13 @@ async function preflightFleet(config, options) {
2979
3016
  throw new Error("invalid protocol namespace selector");
2980
3017
  }
2981
3018
  }
3019
+ if (entry.idBase !== void 0)
3020
+ normalizeIdBase(entry.idBase, "idBase");
3021
+ if (entry.settings !== void 0) {
3022
+ if (protocol !== "http" || !("create" in target))
3023
+ throw new Error("settings: only HTTP services take boot settings");
3024
+ checkSettings(target, entry.settings, "settings");
3025
+ }
2982
3026
  const port = entry.port ?? target.defaultPort;
2983
3027
  if (port !== 0) {
2984
3028
  const key = `${entry.host ?? "127.0.0.1"}:${port}`;
@@ -3014,7 +3058,7 @@ async function preflightFleet(config, options) {
3014
3058
  break;
3015
3059
  }
3016
3060
  }
3017
- targets.set(name, { ...target, packageVersion: packageVersion ?? "0.5.0" });
3061
+ targets.set(name, { ...target, packageVersion: packageVersion ?? "0.7.0" });
3018
3062
  } catch (error) {
3019
3063
  throw new Error(`service ${name}: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
3020
3064
  }
@@ -3240,7 +3284,11 @@ var serve = async (api, options = {}) => {
3240
3284
  // ../../adapters/node/dist/listen.js
3241
3285
  var listen = async (api, options = {}) => {
3242
3286
  const host = options.host ?? "127.0.0.1";
3243
- const server = await serve(api, { port: options.port ?? 0, host });
3287
+ const server = await serve(api, {
3288
+ port: options.port ?? 0,
3289
+ host,
3290
+ ...options.maxBodyBytes !== void 0 ? { maxBodyBytes: options.maxBodyBytes } : {}
3291
+ });
3244
3292
  const address = server.address();
3245
3293
  const port = typeof address === "object" && address !== null ? address.port : options.port ?? 0;
3246
3294
  const shown = host.includes(":") ? `[${host}]` : host;
@@ -3334,6 +3382,7 @@ var httpChild = async (target, entry, options, admission, generation, privateAcc
3334
3382
  options.onLog?.(entry2);
3335
3383
  },
3336
3384
  ...entry.adminControls !== void 0 ? { adminControls: entry.adminControls } : {},
3385
+ ...entry.settings !== void 0 ? { settings: checkSettings(target, entry.settings, "settings") } : {},
3337
3386
  ...entry.fixtures !== void 0 ? { fixtures: entry.fixtures } : {},
3338
3387
  ...(advertisedHttpBase(entry) ?? entry.baseUrl) !== void 0 ? { baseUrl: advertisedHttpBase(entry) ?? entry.baseUrl } : {}
3339
3388
  });
@@ -3352,6 +3401,8 @@ var httpChild = async (target, entry, options, admission, generation, privateAcc
3352
3401
  ].some((method) => typeof created[method] !== "function"))
3353
3402
  throw new Error("HTTP target does not implement the fleet runtime protocol; build/install matching supported service versions");
3354
3403
  const runtime = created;
3404
+ if (entry.idBase !== void 0)
3405
+ runtime.setIdBase?.(entry.idBase);
3355
3406
  const unobserve = runtime.webhooks?.observeDeliveries(observer.delivery);
3356
3407
  if (options.outbound && runtime.webhooks)
3357
3408
  runtime.webhooks.setTransportPolicy(ownedTransport(options.outbound));
@@ -3436,7 +3487,8 @@ var httpChild = async (target, entry, options, admission, generation, privateAcc
3436
3487
  try {
3437
3488
  server = await listen(api, {
3438
3489
  port: entry.port ?? target.defaultPort,
3439
- host: entry.host ?? "127.0.0.1"
3490
+ host: entry.host ?? "127.0.0.1",
3491
+ ...target.maxBodyBytes !== void 0 ? { maxBodyBytes: target.maxBodyBytes } : {}
3440
3492
  });
3441
3493
  target.listening?.(server);
3442
3494
  } catch (error) {
@@ -3950,6 +4002,7 @@ async function startFleet(config, options) {
3950
4002
  ...entry,
3951
4003
  adminPrefix: resolveAdminPrefix(entry.adminPrefix ?? adminPrefix),
3952
4004
  ...adminKey !== void 0 ? { adminKey } : {},
4005
+ ...(entry.idBase ?? config.idBase) !== void 0 ? { idBase: entry.idBase ?? config.idBase } : {},
3953
4006
  // Fleet-wide controls, with the service's own keys replacing them.
3954
4007
  ...config.adminControls !== void 0 || entry.adminControls !== void 0 ? { adminControls: { ...config.adminControls, ...entry.adminControls } } : {}
3955
4008
  }, options, (namespace, request) => management?.admit(namespace, request), (namespace) => management?.generation(namespace), (namespace, request) => management?.privateRequest(namespace, request) ?? false, {
@@ -4634,6 +4687,16 @@ var COMMON_SERVE_OPTIONS = {
4634
4687
  value: "<seed>",
4635
4688
  description: "Seed for every random choice (env MOCKINGBIRD_SEED)"
4636
4689
  },
4690
+ "id-base": {
4691
+ type: "string",
4692
+ value: "<n|boot>",
4693
+ description: "Start generated ids at this base so a restart does not reissue the last boot's ids; boot derives one from the clock (env MOCKINGBIRD_ID_BASE; default 0, the same ids every boot)"
4694
+ },
4695
+ settings: {
4696
+ type: "string",
4697
+ value: "<json|file>",
4698
+ description: "Service settings to boot with, as JSON or a JSON file; every namespace starts from them (env MOCKINGBIRD_SETTINGS; only for services that declare settings)"
4699
+ },
4637
4700
  "admin-controls": {
4638
4701
  type: "string",
4639
4702
  value: "<json|file>",
@@ -4728,19 +4791,40 @@ var readJsonFile = async (path, label) => {
4728
4791
  }
4729
4792
  };
4730
4793
  var isObject2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
4794
+ var readJsonOption = async (source, label) => {
4795
+ const trimmed = source.trim();
4796
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
4797
+ try {
4798
+ return JSON.parse(trimmed);
4799
+ } catch {
4800
+ throw new Error(`${label}: not valid JSON`);
4801
+ }
4802
+ }
4803
+ return readJsonFile(source, label);
4804
+ };
4805
+ var resolveServeIdBase = (values, env = process.env) => {
4806
+ const source = asString(values["id-base"]) ?? env.MOCKINGBIRD_ID_BASE;
4807
+ if (source === void 0 || source.trim() === "")
4808
+ return void 0;
4809
+ normalizeIdBase(source.trim(), "--id-base");
4810
+ return source.trim();
4811
+ };
4812
+ var resolveServeSettings = async (target, values, env = process.env) => {
4813
+ const flag = asString(values.settings);
4814
+ const source = flag ?? env.MOCKINGBIRD_SETTINGS;
4815
+ if (source === void 0 || source.trim() === "")
4816
+ return void 0;
4817
+ const label = flag !== void 0 ? "--settings" : "MOCKINGBIRD_SETTINGS";
4818
+ const parsed = await readJsonOption(source, label);
4819
+ if (!isObject2(parsed))
4820
+ throw new Error(`${label}: expected a JSON object`);
4821
+ return checkSettings(target, parsed, label);
4822
+ };
4731
4823
  var resolveServeControls = async (values, env = process.env, base) => {
4732
4824
  const source = asString(values["admin-controls"]) ?? env.MOCKINGBIRD_ADMIN_CONTROLS;
4733
4825
  let document = isObject2(base) ? { ...base } : {};
4734
4826
  if (source !== void 0 && source.trim() !== "") {
4735
- let parsed;
4736
- if (source.trim().startsWith("{")) {
4737
- try {
4738
- parsed = JSON.parse(source);
4739
- } catch {
4740
- throw new Error("--admin-controls: not valid JSON");
4741
- }
4742
- } else
4743
- parsed = await readJsonFile(source, "--admin-controls");
4827
+ const parsed = source.trim().startsWith("{") ? await readJsonOption(source, "--admin-controls") : await readJsonFile(source, "--admin-controls");
4744
4828
  if (!isObject2(parsed))
4745
4829
  throw new Error("--admin-controls: expected a JSON object");
4746
4830
  document = { ...document, ...parsed };
@@ -4790,9 +4874,16 @@ var start = async (target, values, config) => {
4790
4874
  adminKey: config.adminKey,
4791
4875
  seed: config.seed,
4792
4876
  onLog: formatLog(config.log),
4877
+ ...config.settings !== void 0 ? { settings: config.settings } : {},
4793
4878
  ...config.adminControls !== void 0 ? { adminControls: config.adminControls } : {}
4794
4879
  });
4795
- const listening = await listen(runtime, { port: config.port, host: config.host });
4880
+ if (config.idBase !== void 0)
4881
+ runtime.setIdBase?.(config.idBase);
4882
+ const listening = await listen(runtime, {
4883
+ port: config.port,
4884
+ host: config.host,
4885
+ ...target.maxBodyBytes !== void 0 ? { maxBodyBytes: target.maxBodyBytes } : {}
4886
+ });
4796
4887
  target.listening?.(listening);
4797
4888
  console.log(`${target.name} emulator listening on ${listening.url}`);
4798
4889
  console.log(`${target.name} health: GET ${listening.url}${adminPrefix}/health`);
@@ -4837,6 +4928,11 @@ var serveCommand = (target) => ({
4837
4928
  const adminControls = await resolveServeControls(values, process.env, config.adminControls);
4838
4929
  if (adminControls !== void 0)
4839
4930
  config.adminControls = adminControls;
4931
+ if (values.settings !== void 0)
4932
+ throw new Error("--settings serves a single service; give each service its own `settings` in the config");
4933
+ const idBase = config.idBase ?? resolveServeIdBase(values);
4934
+ if (idBase !== void 0)
4935
+ config.idBase = idBase;
4840
4936
  const fleet = await startFleet(config, {
4841
4937
  load: (name) => loadTarget(name, target),
4842
4938
  onLog: formatLog(config.log ?? log),
@@ -4866,8 +4962,12 @@ var serveCommand = (target) => ({
4866
4962
  let listening;
4867
4963
  try {
4868
4964
  const adminControls = await resolveServeControls(values);
4965
+ const idBase = resolveServeIdBase(values);
4966
+ const settings = await resolveServeSettings(target, values);
4869
4967
  listening = await start(target, values, {
4870
4968
  ...adminControls !== void 0 ? { adminControls } : {},
4969
+ ...idBase !== void 0 ? { idBase } : {},
4970
+ ...settings !== void 0 ? { settings } : {},
4871
4971
  adminPrefix: resolveAdminPrefix(asString(values["admin-prefix"]) ?? process.env.MOCKINGBIRD_ADMIN_PREFIX),
4872
4972
  port: port === void 0 ? target.defaultPort : Number.parseInt(port, 10),
4873
4973
  host: asString(values.host) ?? "127.0.0.1",
@@ -5304,4 +5404,4 @@ export {
5304
5404
  connectStream,
5305
5405
  serveTarget
5306
5406
  };
5307
- //# sourceMappingURL=chunk-PDRKZKB7.js.map
5407
+ //# sourceMappingURL=chunk-SIKX3OSS.js.map