@crvouga/mockingbird-service-firstpromoter 3.6.0 → 3.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,19 @@
1
1
  # Changelog — @crvouga/mockingbird-service-firstpromoter
2
2
 
3
- ## 3.6.0 (2026-10-17)
3
+ ## 3.8.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
+ - validate block limits, filter nutrients, list block children ([2acb823](https://github.com/crvouga/mockingbird/commit/2acb823ba66b30f3d03221996e015c127b0f72c6))
9
+
10
+ ## 3.7.0 (2026-10-18)
11
+
12
+ ### Features
13
+
14
+ - resolve the agent-reported issue queue in one batch ([25c52b6](https://github.com/crvouga/mockingbird/commit/25c52b668a53ddb80b968419601a20abf33f956b))
15
+
16
+ ## 3.6.0 (2026-10-16)
4
17
 
5
18
  ### Features
6
19
 
package/README.md CHANGED
@@ -74,11 +74,12 @@ await server.close()
74
74
  | --- | --- |
75
75
  | `POST /v2/company/promoters` | `{email, cust_id?, profile?: {first_name, last_name}, drip_emails?, initial_campaign_id?}` → the promoter (`FirstPromoterV2ResponseSchema`), enrolled in the default campaign with a `ref_token` (first name + digits) and `ref_link` `https://acme.example/referrals?fpr=<token>`. A live promoter with the same email or `cust_id` is 422 `{message, errors: {email: ["has already been taken"]}}`. |
76
76
  | `GET /v2/company/promoters?page=&per_page=` | `{data: [promoter], meta: {pending_count}}`; archived promoters are left out. |
77
- | `GET /v2/company/promoters/{value}?find_by=id\|cust_id\|ref_token\|email` | One promoter (archived ones too, with `archived_at`), or 404 `{message: "Promoter not found"}`. |
77
+ | `GET /v2/company/promoters/{value}?find_by=id\|cust_id\|auth_token\|ref_token\|promo_code\|email` | One promoter (archived ones too, with `archived_at`), or 404 `{message: "Promoter not found"}`. `promo_code` resolves codes seeded through `POST /__admin/promo-codes` to the promoter owning that campaign enrolment. `auth_token` is a deterministic per-promoter token that `POST` / `GET /__admin/promoters` report as `auth_token` (the vendor's promoter schema has no such field, so the promoter body does not carry it). Any other `find_by` is 400. |
78
78
  | `PUT /v2/company/promoters/{id}` | `{cust_id?, email?, note?, profile?}` → the promoter; 404 / 422 as above. |
79
79
  | `POST /v2/company/promoters/archive` | `{ids: [..]}` → a completed batch `{id, status, total, selected_total, processed_count, failed_count, action_label, progress, processing_errors, …}`. |
80
80
  | `POST /v2/promoters/iframe_login?promoter_id=` | `{access_token, expires_in}`, or 404. |
81
81
  | `POST /v2/track/signup` | `{email, tid? \| promoter_id? \| ref_id?, uid?, skip_email_notification?}` → the referral. An unknown `tid`, promoter or ref token is 404; none of them is 400; an email already tracked is 422. With `autoConvert` (default on) the referral becomes a customer at once and `lead_becomes_referral` is posted. |
82
+ | `PUT /v2/company/commissions/{id}` | `{internal_note?, external_note?}` (the vendor's `CommissionUpdate`) → the updated commission, reflected in `GET /v2/company/commissions`; other fields are not writable. An unknown id is 404 `{message: "Commission not found", code: "not_found"}`. |
82
83
  | `GET /v2/company/referrals` | A bare array of stored referrals and live promoter/campaign metadata. `q` searches email/uid; `ids[]`, `filters[type]=lead\|customer`, `filters[state]`, `filters[promoter_id]`, and inclusive `filters[created_at\|customer_since][from\|to]` filter before paging. `page` starts at 1; `per_page` defaults to 20 (max 100). Exhausted pages and unmatched searches return `[]`. |
83
84
  | `GET /v2/company/referrals/{id}` | The same referral projection as listing. A numeric ID or `find_by=email\|uid` selects it; missing records are 404. |
84
85
 
@@ -109,7 +110,7 @@ is `user:pass`. Non-2xx answers are retried; `GET /__admin/webhooks`, `…/event
109
110
  | `POST /__admin/referrals/:id/convert` | `{saleAmount?}`: the lead paid; credits the promoter (percent reward × amount) and posts the webhook. |
110
111
  | `POST /__admin/commissions` | Seed a commission against an existing `{promoter_campaign_id, amount, unit?, status?, fulfilled?, is_paid?, referral_id?, sale_amount?, event_id?}`. Defaults: approved, points, unfulfilled/unpaid. A referral must belong to that promoter and campaign. |
111
112
  | `POST /__admin/promo-codes` | Seed `{promo_code, promoter_campaign_id}` against an existing promoter campaign for sale attribution tests. |
112
- | `GET\|PUT /__admin/settings` | `{website?, defaultCampaignId?, autoConvert?, campaigns?}` (campaigns carry `referralRewards` / `promoterRewards` with `coupon`, `amount`, `unit`, `per_of_sale`). The default campaign's referral coupon is `ACME50`. |
113
+ | `GET\|PUT /__admin/settings` | `{website?, defaultCampaignId?, autoConvert?, promoCodeCreatesReferral?, campaigns?}` (campaigns carry `referralRewards` / `promoterRewards` with `coupon`, `amount`, `unit`, `per_of_sale`). The default campaign's referral coupon is `ACME50`. |
113
114
 
114
115
  Fault presets (`POST /__admin/faults {"preset": "<name>", "count"?: n}`; `GET /__admin/faults/presets`):
115
116
  `created_but_500` (stored, then 500: the retry must adopt by `cust_id`), `lookup_unavailable`
@@ -146,6 +147,24 @@ Codes must be seeded through the admin control; tokens must belong to the referr
146
147
  campaign. All validation precedes sale/commission/balance writes; snapshots/reset include event
147
148
  deduplication. A successful sale preserves the existing conversion webhook behavior.
148
149
 
150
+ When no lead matches `email` / `uid`, the vendor's [tracking contract](https://github.com/firstpromoter/docs/blob/d4e9e6f16bf4801c524508d2809a425ea6419d7d/api-reference-v2/api-admin/tracking-api/openapi-v2-tracking.json)
151
+ lets `tid` or `ref_id` "bypass the signup tracking": the lead is created and the sale assigned in
152
+ one request. The emulator does the same when the `tid` (a click from `POST /__admin/clicks`) or
153
+ `ref_id` resolves to a live promoter and the request names the lead by `email`; the new lead counts
154
+ toward the promoter's referrals, becomes a customer and posts `lead_becomes_referral`. This is
155
+ docs-verified (the tracking OpenAPI above), not oracle-verified. `uid` alone cannot name a new lead,
156
+ and an `email` that is already a lead under another `uid` is 422 (as in signup tracking).
157
+
158
+ **`promo_code` alone: best guess, not oracle-verified.** The vendor documents nothing further for
159
+ `promo_code` ("For promo code tracking"), so whether a sale carrying only a promo code creates the
160
+ lead is unobserved. Default (`promoCodeCreatesReferral: false`): a sale for an unknown buyer with
161
+ only `promo_code` is the same 404 as any unattributed sale, and nothing is stored. Opt in with
162
+ `PUT /__admin/settings {"promoCodeCreatesReferral": true}` to have a code seeded through
163
+ `POST /__admin/promo-codes` create the lead (needs `email`), assign the sale to the promoter owning
164
+ that campaign enrolment, and post `lead_becomes_referral`, exactly like `tid` / `ref_id`. An
165
+ unseeded code is 404 in both modes. Treat a test that depends on this setting as depending on an
166
+ emulator assumption until a live response is captured.
167
+
149
168
  ### Namespaces
150
169
 
151
170
  `x-mockingbird-namespace`, a `/__admin/ns/<name>` prefix in `FIRST_PROMOTER_API_URL`, or by API key:
@@ -161,8 +180,8 @@ deduplication. A successful sale preserves the existing conversion webhook behav
161
180
  - Refunds, standalone commission creation/editing/approval, cash payouts and commission filters
162
181
  beyond those listed above; fraud checks;
163
182
  public promo-code provisioning; the hosted affiliate portal behind the iframe token.
164
- - Sale tracking requires an existing referral (the vendor's one-step signup bypass is unmodelled).
165
- Currency is recorded without foreign-exchange conversion; plan-specific rewards, quantity/MRR
183
+ - Creating a lead from `promo_code` alone is off by default (`promoCodeCreatesReferral`): the vendor documents the one-step bypass only for `tid` and `ref_id`, so the opt-in behavior is a best guess, not oracle-verified.
184
+ - Currency is recorded without foreign-exchange conversion; plan-specific rewards, quantity/MRR
166
185
  calculations, multiple reward tiers, split commissions and notification emails are unmodelled.
167
186
  Commission rounding and immediate approval are deterministic emulator policies, not live-verified
168
187
  campaign policy. The default campaign reward remains 10 percent, as before.
package/SUPPORT.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  Generated from `openapi.yaml`; do not edit by hand.
4
4
 
5
- - operations in spec: **16**
6
- - supported by the emulator: **16**
7
- - parity enabled: **16**
5
+ - operations in spec: **17**
6
+ - supported by the emulator: **17**
7
+ - parity enabled: **17**
8
8
 
9
9
  | operationId | route | emulator | parity | notes |
10
10
  | --- | --- | --- | --- | --- |
@@ -20,6 +20,7 @@ Generated from `openapi.yaml`; do not edit by hand.
20
20
  | `ListCommissions` | `GET /v2/company/commissions` | ✅ supported | ✅ | |
21
21
  | `FulfillCommissions` | `POST /v2/company/commissions/mark_fulfilled` | ✅ supported | ⚠️ unsafe (opt-in) | |
22
22
  | `DestroyCommissions` | `DELETE /v2/company/commissions/destroy` | ✅ supported | ⚠️ unsafe (opt-in) | |
23
+ | `UpdateCommission` | `PUT /v2/company/commissions/{id}` | ✅ supported | ⚠️ unsafe (opt-in) | |
23
24
  | `ListBatchProcesses` | `GET /v2/company/batch_processes` | ✅ supported | ✅ | |
24
25
  | `BatchProcessProgress` | `GET /v2/company/batch_processes/progress` | ✅ supported | ✅ | |
25
26
  | `GetBatchProcess` | `GET /v2/company/batch_processes/{id}` | ✅ supported | ✅ | |
@@ -3,17 +3,31 @@ import {
3
3
  createRuntime,
4
4
  normalizeBootControls,
5
5
  normalizeControls,
6
+ normalizeIdBase,
6
7
  ownedTransport,
7
8
  parseDuration,
8
9
  parseFaultHeader,
9
10
  resolveAdminPrefix,
10
11
  restoreClock
11
- } from "./chunk-OHWRVHV3.js";
12
+ } from "./chunk-G6BNGSL2.js";
12
13
 
13
14
  // ../../adapters/node/dist/cli.js
14
15
  import { readFile as readFile5 } from "node:fs/promises";
15
16
  import { parseArgs } from "node:util";
16
17
 
18
+ // ../../adapters/node/dist/boot-settings.js
19
+ var checkSettings = (target, settings, label) => {
20
+ if (!target.parseSettings)
21
+ throw new Error(`${label}: ${target.name} takes no boot settings`);
22
+ try {
23
+ return target.parseSettings(settings);
24
+ } catch (error) {
25
+ throw new Error(`${label}: ${error instanceof Error ? error.message : String(error)}`, {
26
+ cause: error
27
+ });
28
+ }
29
+ };
30
+
17
31
  // ../../adapters/node/dist/fleet.js
18
32
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
19
33
  import { createHash as createHash4, randomUUID as randomUUID4 } from "node:crypto";
@@ -2663,6 +2677,9 @@ var fleet_config_schema_default = {
2663
2677
  adminControls: {
2664
2678
  $ref: "#/$defs/controls"
2665
2679
  },
2680
+ idBase: {
2681
+ $ref: "#/$defs/idBase"
2682
+ },
2666
2683
  namespace: {
2667
2684
  type: "string",
2668
2685
  pattern: "^[A-Za-z0-9_.-]{1,64}$"
@@ -2752,6 +2769,12 @@ var fleet_config_schema_default = {
2752
2769
  adminControls: {
2753
2770
  $ref: "#/$defs/controls"
2754
2771
  },
2772
+ idBase: {
2773
+ $ref: "#/$defs/idBase"
2774
+ },
2775
+ settings: {
2776
+ type: "object"
2777
+ },
2755
2778
  fixtures: {
2756
2779
  type: "object"
2757
2780
  },
@@ -2798,6 +2821,18 @@ var fleet_config_schema_default = {
2798
2821
  }
2799
2822
  }
2800
2823
  },
2824
+ idBase: {
2825
+ anyOf: [
2826
+ {
2827
+ type: "integer",
2828
+ minimum: 0
2829
+ },
2830
+ {
2831
+ type: "string",
2832
+ pattern: "^(boot|[0-9]+)$"
2833
+ }
2834
+ ]
2835
+ },
2801
2836
  controls: {
2802
2837
  type: "object",
2803
2838
  additionalProperties: false,
@@ -2947,6 +2982,8 @@ async function preflightFleet(config, options) {
2947
2982
  throw new Error("protected archive policy requires a protected repository; configure its protector before startup");
2948
2983
  resolveAdminPrefix(config.adminPrefix);
2949
2984
  normalizeBootControls(config.adminControls);
2985
+ if (config.idBase !== void 0)
2986
+ normalizeIdBase(config.idBase, "idBase");
2950
2987
  const targets = /* @__PURE__ */ new Map();
2951
2988
  const ports = /* @__PURE__ */ new Set();
2952
2989
  for (const [name, entry] of Object.entries(config.services)) {
@@ -2978,6 +3015,13 @@ async function preflightFleet(config, options) {
2978
3015
  throw new Error("invalid protocol namespace selector");
2979
3016
  }
2980
3017
  }
3018
+ if (entry.idBase !== void 0)
3019
+ normalizeIdBase(entry.idBase, "idBase");
3020
+ if (entry.settings !== void 0) {
3021
+ if (protocol !== "http" || !("create" in target))
3022
+ throw new Error("settings: only HTTP services take boot settings");
3023
+ checkSettings(target, entry.settings, "settings");
3024
+ }
2981
3025
  const port = entry.port ?? target.defaultPort;
2982
3026
  if (port !== 0) {
2983
3027
  const key = `${entry.host ?? "127.0.0.1"}:${port}`;
@@ -3013,7 +3057,7 @@ async function preflightFleet(config, options) {
3013
3057
  break;
3014
3058
  }
3015
3059
  }
3016
- targets.set(name, { ...target, packageVersion: packageVersion ?? "3.6.0" });
3060
+ targets.set(name, { ...target, packageVersion: packageVersion ?? "3.8.0" });
3017
3061
  } catch (error) {
3018
3062
  throw new Error(`service ${name}: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
3019
3063
  }
@@ -3239,7 +3283,11 @@ var serve = async (api, options = {}) => {
3239
3283
  // ../../adapters/node/dist/listen.js
3240
3284
  var listen = async (api, options = {}) => {
3241
3285
  const host = options.host ?? "127.0.0.1";
3242
- const server = await serve(api, { port: options.port ?? 0, host });
3286
+ const server = await serve(api, {
3287
+ port: options.port ?? 0,
3288
+ host,
3289
+ ...options.maxBodyBytes !== void 0 ? { maxBodyBytes: options.maxBodyBytes } : {}
3290
+ });
3243
3291
  const address = server.address();
3244
3292
  const port = typeof address === "object" && address !== null ? address.port : options.port ?? 0;
3245
3293
  const shown = host.includes(":") ? `[${host}]` : host;
@@ -3333,6 +3381,7 @@ var httpChild = async (target, entry, options, admission, generation, privateAcc
3333
3381
  options.onLog?.(entry2);
3334
3382
  },
3335
3383
  ...entry.adminControls !== void 0 ? { adminControls: entry.adminControls } : {},
3384
+ ...entry.settings !== void 0 ? { settings: checkSettings(target, entry.settings, "settings") } : {},
3336
3385
  ...entry.fixtures !== void 0 ? { fixtures: entry.fixtures } : {},
3337
3386
  ...(advertisedHttpBase(entry) ?? entry.baseUrl) !== void 0 ? { baseUrl: advertisedHttpBase(entry) ?? entry.baseUrl } : {}
3338
3387
  });
@@ -3351,6 +3400,8 @@ var httpChild = async (target, entry, options, admission, generation, privateAcc
3351
3400
  ].some((method) => typeof created[method] !== "function"))
3352
3401
  throw new Error("HTTP target does not implement the fleet runtime protocol; build/install matching supported service versions");
3353
3402
  const runtime = created;
3403
+ if (entry.idBase !== void 0)
3404
+ runtime.setIdBase?.(entry.idBase);
3354
3405
  const unobserve = runtime.webhooks?.observeDeliveries(observer.delivery);
3355
3406
  if (options.outbound && runtime.webhooks)
3356
3407
  runtime.webhooks.setTransportPolicy(ownedTransport(options.outbound));
@@ -3435,7 +3486,8 @@ var httpChild = async (target, entry, options, admission, generation, privateAcc
3435
3486
  try {
3436
3487
  server = await listen(api, {
3437
3488
  port: entry.port ?? target.defaultPort,
3438
- host: entry.host ?? "127.0.0.1"
3489
+ host: entry.host ?? "127.0.0.1",
3490
+ ...target.maxBodyBytes !== void 0 ? { maxBodyBytes: target.maxBodyBytes } : {}
3439
3491
  });
3440
3492
  target.listening?.(server);
3441
3493
  } catch (error) {
@@ -3949,6 +4001,7 @@ async function startFleet(config, options) {
3949
4001
  ...entry,
3950
4002
  adminPrefix: resolveAdminPrefix(entry.adminPrefix ?? adminPrefix),
3951
4003
  ...adminKey !== void 0 ? { adminKey } : {},
4004
+ ...(entry.idBase ?? config.idBase) !== void 0 ? { idBase: entry.idBase ?? config.idBase } : {},
3952
4005
  // Fleet-wide controls, with the service's own keys replacing them.
3953
4006
  ...config.adminControls !== void 0 || entry.adminControls !== void 0 ? { adminControls: { ...config.adminControls, ...entry.adminControls } } : {}
3954
4007
  }, options, (namespace, request) => management?.admit(namespace, request), (namespace) => management?.generation(namespace), (namespace, request) => management?.privateRequest(namespace, request) ?? false, {
@@ -4633,6 +4686,16 @@ var COMMON_SERVE_OPTIONS = {
4633
4686
  value: "<seed>",
4634
4687
  description: "Seed for every random choice (env MOCKINGBIRD_SEED)"
4635
4688
  },
4689
+ "id-base": {
4690
+ type: "string",
4691
+ value: "<n|boot>",
4692
+ 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)"
4693
+ },
4694
+ settings: {
4695
+ type: "string",
4696
+ value: "<json|file>",
4697
+ 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)"
4698
+ },
4636
4699
  "admin-controls": {
4637
4700
  type: "string",
4638
4701
  value: "<json|file>",
@@ -4727,19 +4790,40 @@ var readJsonFile = async (path, label) => {
4727
4790
  }
4728
4791
  };
4729
4792
  var isObject2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
4793
+ var readJsonOption = async (source, label) => {
4794
+ const trimmed = source.trim();
4795
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
4796
+ try {
4797
+ return JSON.parse(trimmed);
4798
+ } catch {
4799
+ throw new Error(`${label}: not valid JSON`);
4800
+ }
4801
+ }
4802
+ return readJsonFile(source, label);
4803
+ };
4804
+ var resolveServeIdBase = (values, env = process.env) => {
4805
+ const source = asString(values["id-base"]) ?? env.MOCKINGBIRD_ID_BASE;
4806
+ if (source === void 0 || source.trim() === "")
4807
+ return void 0;
4808
+ normalizeIdBase(source.trim(), "--id-base");
4809
+ return source.trim();
4810
+ };
4811
+ var resolveServeSettings = async (target, values, env = process.env) => {
4812
+ const flag = asString(values.settings);
4813
+ const source = flag ?? env.MOCKINGBIRD_SETTINGS;
4814
+ if (source === void 0 || source.trim() === "")
4815
+ return void 0;
4816
+ const label = flag !== void 0 ? "--settings" : "MOCKINGBIRD_SETTINGS";
4817
+ const parsed = await readJsonOption(source, label);
4818
+ if (!isObject2(parsed))
4819
+ throw new Error(`${label}: expected a JSON object`);
4820
+ return checkSettings(target, parsed, label);
4821
+ };
4730
4822
  var resolveServeControls = async (values, env = process.env, base) => {
4731
4823
  const source = asString(values["admin-controls"]) ?? env.MOCKINGBIRD_ADMIN_CONTROLS;
4732
4824
  let document = isObject2(base) ? { ...base } : {};
4733
4825
  if (source !== void 0 && source.trim() !== "") {
4734
- let parsed;
4735
- if (source.trim().startsWith("{")) {
4736
- try {
4737
- parsed = JSON.parse(source);
4738
- } catch {
4739
- throw new Error("--admin-controls: not valid JSON");
4740
- }
4741
- } else
4742
- parsed = await readJsonFile(source, "--admin-controls");
4826
+ const parsed = source.trim().startsWith("{") ? await readJsonOption(source, "--admin-controls") : await readJsonFile(source, "--admin-controls");
4743
4827
  if (!isObject2(parsed))
4744
4828
  throw new Error("--admin-controls: expected a JSON object");
4745
4829
  document = { ...document, ...parsed };
@@ -4789,9 +4873,16 @@ var start = async (target, values, config) => {
4789
4873
  adminKey: config.adminKey,
4790
4874
  seed: config.seed,
4791
4875
  onLog: formatLog(config.log),
4876
+ ...config.settings !== void 0 ? { settings: config.settings } : {},
4792
4877
  ...config.adminControls !== void 0 ? { adminControls: config.adminControls } : {}
4793
4878
  });
4794
- const listening = await listen(runtime, { port: config.port, host: config.host });
4879
+ if (config.idBase !== void 0)
4880
+ runtime.setIdBase?.(config.idBase);
4881
+ const listening = await listen(runtime, {
4882
+ port: config.port,
4883
+ host: config.host,
4884
+ ...target.maxBodyBytes !== void 0 ? { maxBodyBytes: target.maxBodyBytes } : {}
4885
+ });
4795
4886
  target.listening?.(listening);
4796
4887
  console.log(`${target.name} emulator listening on ${listening.url}`);
4797
4888
  console.log(`${target.name} health: GET ${listening.url}${adminPrefix}/health`);
@@ -4836,6 +4927,11 @@ var serveCommand = (target) => ({
4836
4927
  const adminControls = await resolveServeControls(values, process.env, config.adminControls);
4837
4928
  if (adminControls !== void 0)
4838
4929
  config.adminControls = adminControls;
4930
+ if (values.settings !== void 0)
4931
+ throw new Error("--settings serves a single service; give each service its own `settings` in the config");
4932
+ const idBase = config.idBase ?? resolveServeIdBase(values);
4933
+ if (idBase !== void 0)
4934
+ config.idBase = idBase;
4839
4935
  const fleet = await startFleet(config, {
4840
4936
  load: (name) => loadTarget(name, target),
4841
4937
  onLog: formatLog(config.log ?? log),
@@ -4865,8 +4961,12 @@ var serveCommand = (target) => ({
4865
4961
  let listening;
4866
4962
  try {
4867
4963
  const adminControls = await resolveServeControls(values);
4964
+ const idBase = resolveServeIdBase(values);
4965
+ const settings = await resolveServeSettings(target, values);
4868
4966
  listening = await start(target, values, {
4869
4967
  ...adminControls !== void 0 ? { adminControls } : {},
4968
+ ...idBase !== void 0 ? { idBase } : {},
4969
+ ...settings !== void 0 ? { settings } : {},
4870
4970
  adminPrefix: resolveAdminPrefix(asString(values["admin-prefix"]) ?? process.env.MOCKINGBIRD_ADMIN_PREFIX),
4871
4971
  port: port === void 0 ? target.defaultPort : Number.parseInt(port, 10),
4872
4972
  host: asString(values.host) ?? "127.0.0.1",
@@ -4934,4 +5034,4 @@ export {
4934
5034
  createServer2 as createServer,
4935
5035
  serveTarget
4936
5036
  };
4937
- //# sourceMappingURL=chunk-QTSDT26U.js.map
5037
+ //# sourceMappingURL=chunk-C6B3TYF4.js.map