@crvouga/mockingbird-service-oauth 3.7.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 +7 -1
- package/README.md +15 -2
- package/dist/{chunk-4GFNDUAY.js → chunk-AAKIJOPV.js} +103 -12
- package/dist/chunk-AAKIJOPV.js.map +7 -0
- package/dist/{chunk-ANDSQ2HK.js → chunk-VAXKCT3L.js} +143 -26
- package/dist/chunk-VAXKCT3L.js.map +7 -0
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +59 -1
- package/dist/index.js +1 -1
- package/dist/server.d.ts +99 -0
- package/dist/server.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-4GFNDUAY.js.map +0 -7
- package/dist/chunk-ANDSQ2HK.js.map +0 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
# Changelog — @crvouga/mockingbird-service-oauth
|
|
2
2
|
|
|
3
|
-
## 3.
|
|
3
|
+
## 3.8.0 (2026-10-19)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- resolve the agent-reported issue queue in one batch ([25c52b6](https://github.com/crvouga/mockingbird/commit/25c52b668a53ddb80b968419601a20abf33f956b))
|
|
8
|
+
|
|
9
|
+
## 3.7.0 (2026-10-16)
|
|
4
10
|
|
|
5
11
|
### Features
|
|
6
12
|
|
package/README.md
CHANGED
|
@@ -172,7 +172,7 @@ tapping `oauth-mock-form-post-continue`; with scripts, the page submits the form
|
|
|
172
172
|
|
|
173
173
|
### Fidelity and lifecycle
|
|
174
174
|
|
|
175
|
-
- Authorization-code flow with exact redirect matching, including explicitly registered private-use URI schemes for native apps, state and nonce; duplicate parameters rejected. Invalid clients/callbacks never redirect. Public native clients require S256 PKCE
|
|
175
|
+
- Authorization-code flow with exact redirect matching, including explicitly registered private-use URI schemes for native apps, state and nonce; duplicate parameters rejected. Invalid clients/callbacks never redirect. Public native clients require S256 PKCE unless the client opts in with `pkceOptional`.
|
|
176
176
|
- Real RSA-2048 / RS256 ID tokens and independent public JWKS; correct issuer, audience, expiry, auth time and scope-filtered claims. Keys remain stable until explicitly rotated.
|
|
177
177
|
- Codes expire after 5 minutes and are consumed atomically, including concurrent PKCE redemption. Access/ID tokens last 1 hour. Generic OIDC refresh tokens default to 30 days; Microsoft defaults to 90 days. Apple/Google refresh tokens have no fixed deadline by default; Google inactivity, testing mode and issuance limits still apply. GitHub OAuth app access tokens have no fixed deadline in the emulator. The injected emulator clock controls expiry.
|
|
178
178
|
- Google `access_type=offline` issues refresh tokens on first consent or `prompt=consent`; generic/Microsoft `offline_access` and Apple issue refresh tokens. Refresh cannot expand scopes. Revocation invalidates related access and refresh tokens; unknown tokens succeed idempotently. Refresh tokens are reusable by default; Microsoft returns a replacement without invalidating the old token. Opt-in strict rotation detects reuse and revokes the token family.
|
|
@@ -306,13 +306,26 @@ no grants or account changes. Interactive vendor flows cannot be run unattended
|
|
|
306
306
|
provider applications, so the focused contract tests use the official behavior documented in the
|
|
307
307
|
references below.
|
|
308
308
|
|
|
309
|
+
## Per-client opt-ins
|
|
310
|
+
|
|
311
|
+
Defaults stay strict; these `Client` fields (also accepted by `POST /__admin/clients`) relax one rule each, for one client.
|
|
312
|
+
|
|
313
|
+
| Field | Effect |
|
|
314
|
+
| --- | --- |
|
|
315
|
+
| `pkceOptional: true` | A public client (no `secret`, no `apple`) may omit PKCE, as a [Cognito public app client](https://docs.aws.amazon.com/cognito/latest/developerguide/authorization-endpoint.html) can. A challenge that is sent must still be S256 and is verified at the token endpoint. Conflicts with `requirePkce: true` and with `secret`/`apple`. |
|
|
316
|
+
| `alwaysIssueRefreshToken: true` | Every authorization-code exchange returns a `refresh_token` without `offline_access`, as [Cognito's token endpoint](https://docs.aws.amazon.com/cognito/latest/developerguide/token-endpoint.html) does. `oidc` and `microsoft` profiles only; Google, Apple and GitHub keep their own rules. |
|
|
317
|
+
| `redirectPolicy: { loopbackAnyPort: true }` | RFC 8252 section 7.3: an `http://` loopback redirect (`127.0.0.1`, `[::1]`, `localhost`) may use any port. It must match a registered loopback URI on the same host, path and query. |
|
|
318
|
+
| `redirectPolicy: { schemes: ["exp:"] }` | For the listed custom schemes the host and port may vary (a dev client's LAN address). The request must still match a registered URI with the same scheme, path and query. `http:`, `https:` and executable schemes are rejected. |
|
|
319
|
+
|
|
320
|
+
A Cognito-shaped public client is `{ id, name, redirectUris, pkceOptional: true, alwaysIssueRefreshToken: true }` on an `oidc` mount (for example `/oauth2`). Extra authorize parameters such as `identity_provider` are ignored. The token exchange still requires the exact `redirect_uri` that authorized the code. These are matching rules for registered URIs, not wildcards: a URI that is not a variant of a registered one is still refused without a redirect.
|
|
321
|
+
|
|
309
322
|
## Deliberately not modelled
|
|
310
323
|
|
|
311
324
|
This is a ready-to-use local/test identity provider, **not a production authentication server or a claim that every proprietary provider feature is implemented**. Its ready tier covers the documented OAuth/OIDC login, identity, consent, token, provider-edge-case, and UI surface. Applications should still run a small final check against each real provider before release.
|
|
312
325
|
|
|
313
326
|
Vendor-hosted Google Identity Services/One Tap, native Apple AuthenticationServices, passkeys, MFA, CAPTCHA, password recovery, email delivery/relay forwarding (only Apple's notification of a forwarding change is sent), app-transfer migration, vendor risk engines, tokeninfo/introspection, logout, GitHub Apps installation/device flows, and Microsoft Graph/tenant administration are not implemented. Other configurable OIDC providers can use the generic profile, but their proprietary scopes and claims are not emulated. Scopes are limited to each profile plus explicitly configured additional scopes. Microsoft uses the configured emulator issuer, not real Entra tenant routing. GitHub is the OAuth app login surface, not the full REST API.
|
|
314
327
|
|
|
315
|
-
No implicit flow, dynamic client registration, wildcard redirect matching, persistent signing-key storage (keys are held in memory; supply them through `signingKeys` or derive them from a seed), or distributed-session coordination is provided. Private-use redirect schemes work only when their complete URI is explicitly registered; executable/local schemes such as `javascript:`, `data:` and `file:` are rejected. Sign-in and consent pages extend CSP `form-action` with the transaction's redirect origin (or custom scheme). Browser navigation responses use a provider-owned handoff document so the callback can relay through another origin without inheriting the consent form's policy; direct programmatic interaction requests retain their HTTP redirect response. The `form_post` hand-off page sends no `form-action` at all: browsers apply that directive to every redirect after the submit, and the callback that receives the POST may redirect to an application origin the provider never sees, so no allow-list can cover it. The rest of that page's policy (`default-src 'none'`, nonce-only scripts and styles, `base-uri 'none'`, `frame-ancestors 'none'`) is unchanged. Discovery, JWKS, token, userinfo and revoke answer `OPTIONS` preflights and reflect the request `Origin`, so browser (SPA + PKCE) clients can redeem codes directly; the interaction pages send no CORS headers. Snapshot restore is for the same runtime/instance; signing keys are not serialized. The default backing store is in-memory and state disappears when the process exits. A secure browser context and Web Crypto, Fetch and standard Web APIs are required; Node 22+, Bun and modern browsers provide them.
|
|
328
|
+
No implicit flow, dynamic client registration, wildcard redirect matching (beyond the opt-in `redirectPolicy`), persistent signing-key storage (keys are held in memory; supply them through `signingKeys` or derive them from a seed), or distributed-session coordination is provided. Private-use redirect schemes work only when their complete URI is explicitly registered; executable/local schemes such as `javascript:`, `data:` and `file:` are rejected. Sign-in and consent pages extend CSP `form-action` with the transaction's redirect origin (or custom scheme). Browser navigation responses use a provider-owned handoff document so the callback can relay through another origin without inheriting the consent form's policy; direct programmatic interaction requests retain their HTTP redirect response. The `form_post` hand-off page sends no `form-action` at all: browsers apply that directive to every redirect after the submit, and the callback that receives the POST may redirect to an application origin the provider never sees, so no allow-list can cover it. The rest of that page's policy (`default-src 'none'`, nonce-only scripts and styles, `base-uri 'none'`, `frame-ancestors 'none'`) is unchanged. Discovery, JWKS, token, userinfo and revoke answer `OPTIONS` preflights and reflect the request `Origin`, so browser (SPA + PKCE) clients can redeem codes directly; the interaction pages send no CORS headers. Snapshot restore is for the same runtime/instance; signing keys are not serialized. The default backing store is in-memory and state disappears when the process exits. A secure browser context and Web Crypto, Fetch and standard Web APIs are required; Node 22+, Bun and modern browsers provide them.
|
|
316
329
|
|
|
317
330
|
References: [Google OpenID Connect](https://developers.google.com/identity/openid-connect/openid-connect), [Apple authorization request](https://developer.apple.com/documentation/signinwithapplerestapi/request-an-authorization-to-the-sign-in-with-apple-server.), and [OpenID Connect Core](https://openid.net/specs/openid-connect-core-1_0.html).
|
|
318
331
|
|
|
@@ -5,12 +5,13 @@ import {
|
|
|
5
5
|
createRuntime,
|
|
6
6
|
normalizeBootControls,
|
|
7
7
|
normalizeControls,
|
|
8
|
+
normalizeIdBase,
|
|
8
9
|
ownedTransport,
|
|
9
10
|
parseDuration,
|
|
10
11
|
parseFaultHeader,
|
|
11
12
|
resolveAdminPrefix,
|
|
12
13
|
restoreClock
|
|
13
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-VAXKCT3L.js";
|
|
14
15
|
|
|
15
16
|
// src/server.ts
|
|
16
17
|
import { readFile as readFile6 } from "node:fs/promises";
|
|
@@ -19,6 +20,19 @@ import { readFile as readFile6 } from "node:fs/promises";
|
|
|
19
20
|
import { readFile as readFile5 } from "node:fs/promises";
|
|
20
21
|
import { parseArgs } from "node:util";
|
|
21
22
|
|
|
23
|
+
// ../../adapters/node/dist/boot-settings.js
|
|
24
|
+
var checkSettings = (target, settings, label) => {
|
|
25
|
+
if (!target.parseSettings)
|
|
26
|
+
throw new Error(`${label}: ${target.name} takes no boot settings`);
|
|
27
|
+
try {
|
|
28
|
+
return target.parseSettings(settings);
|
|
29
|
+
} catch (error) {
|
|
30
|
+
throw new Error(`${label}: ${error instanceof Error ? error.message : String(error)}`, {
|
|
31
|
+
cause: error
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
22
36
|
// ../../adapters/node/dist/fleet.js
|
|
23
37
|
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
24
38
|
import { createHash as createHash4, randomUUID as randomUUID4 } from "node:crypto";
|
|
@@ -2668,6 +2682,9 @@ var fleet_config_schema_default = {
|
|
|
2668
2682
|
adminControls: {
|
|
2669
2683
|
$ref: "#/$defs/controls"
|
|
2670
2684
|
},
|
|
2685
|
+
idBase: {
|
|
2686
|
+
$ref: "#/$defs/idBase"
|
|
2687
|
+
},
|
|
2671
2688
|
namespace: {
|
|
2672
2689
|
type: "string",
|
|
2673
2690
|
pattern: "^[A-Za-z0-9_.-]{1,64}$"
|
|
@@ -2757,6 +2774,12 @@ var fleet_config_schema_default = {
|
|
|
2757
2774
|
adminControls: {
|
|
2758
2775
|
$ref: "#/$defs/controls"
|
|
2759
2776
|
},
|
|
2777
|
+
idBase: {
|
|
2778
|
+
$ref: "#/$defs/idBase"
|
|
2779
|
+
},
|
|
2780
|
+
settings: {
|
|
2781
|
+
type: "object"
|
|
2782
|
+
},
|
|
2760
2783
|
fixtures: {
|
|
2761
2784
|
type: "object"
|
|
2762
2785
|
},
|
|
@@ -2803,6 +2826,18 @@ var fleet_config_schema_default = {
|
|
|
2803
2826
|
}
|
|
2804
2827
|
}
|
|
2805
2828
|
},
|
|
2829
|
+
idBase: {
|
|
2830
|
+
anyOf: [
|
|
2831
|
+
{
|
|
2832
|
+
type: "integer",
|
|
2833
|
+
minimum: 0
|
|
2834
|
+
},
|
|
2835
|
+
{
|
|
2836
|
+
type: "string",
|
|
2837
|
+
pattern: "^(boot|[0-9]+)$"
|
|
2838
|
+
}
|
|
2839
|
+
]
|
|
2840
|
+
},
|
|
2806
2841
|
controls: {
|
|
2807
2842
|
type: "object",
|
|
2808
2843
|
additionalProperties: false,
|
|
@@ -2952,6 +2987,8 @@ async function preflightFleet(config, options) {
|
|
|
2952
2987
|
throw new Error("protected archive policy requires a protected repository; configure its protector before startup");
|
|
2953
2988
|
resolveAdminPrefix(config.adminPrefix);
|
|
2954
2989
|
normalizeBootControls(config.adminControls);
|
|
2990
|
+
if (config.idBase !== void 0)
|
|
2991
|
+
normalizeIdBase(config.idBase, "idBase");
|
|
2955
2992
|
const targets = /* @__PURE__ */ new Map();
|
|
2956
2993
|
const ports = /* @__PURE__ */ new Set();
|
|
2957
2994
|
for (const [name, entry] of Object.entries(config.services)) {
|
|
@@ -2983,6 +3020,13 @@ async function preflightFleet(config, options) {
|
|
|
2983
3020
|
throw new Error("invalid protocol namespace selector");
|
|
2984
3021
|
}
|
|
2985
3022
|
}
|
|
3023
|
+
if (entry.idBase !== void 0)
|
|
3024
|
+
normalizeIdBase(entry.idBase, "idBase");
|
|
3025
|
+
if (entry.settings !== void 0) {
|
|
3026
|
+
if (protocol !== "http" || !("create" in target))
|
|
3027
|
+
throw new Error("settings: only HTTP services take boot settings");
|
|
3028
|
+
checkSettings(target, entry.settings, "settings");
|
|
3029
|
+
}
|
|
2986
3030
|
const port = entry.port ?? target.defaultPort;
|
|
2987
3031
|
if (port !== 0) {
|
|
2988
3032
|
const key = `${entry.host ?? "127.0.0.1"}:${port}`;
|
|
@@ -3018,7 +3062,7 @@ async function preflightFleet(config, options) {
|
|
|
3018
3062
|
break;
|
|
3019
3063
|
}
|
|
3020
3064
|
}
|
|
3021
|
-
targets.set(name, { ...target, packageVersion: packageVersion ?? "3.
|
|
3065
|
+
targets.set(name, { ...target, packageVersion: packageVersion ?? "3.8.0" });
|
|
3022
3066
|
} catch (error) {
|
|
3023
3067
|
throw new Error(`service ${name}: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
3024
3068
|
}
|
|
@@ -3338,6 +3382,7 @@ var httpChild = async (target, entry, options, admission, generation, privateAcc
|
|
|
3338
3382
|
options.onLog?.(entry2);
|
|
3339
3383
|
},
|
|
3340
3384
|
...entry.adminControls !== void 0 ? { adminControls: entry.adminControls } : {},
|
|
3385
|
+
...entry.settings !== void 0 ? { settings: checkSettings(target, entry.settings, "settings") } : {},
|
|
3341
3386
|
...entry.fixtures !== void 0 ? { fixtures: entry.fixtures } : {},
|
|
3342
3387
|
...(advertisedHttpBase(entry) ?? entry.baseUrl) !== void 0 ? { baseUrl: advertisedHttpBase(entry) ?? entry.baseUrl } : {}
|
|
3343
3388
|
});
|
|
@@ -3356,6 +3401,8 @@ var httpChild = async (target, entry, options, admission, generation, privateAcc
|
|
|
3356
3401
|
].some((method) => typeof created[method] !== "function"))
|
|
3357
3402
|
throw new Error("HTTP target does not implement the fleet runtime protocol; build/install matching supported service versions");
|
|
3358
3403
|
const runtime = created;
|
|
3404
|
+
if (entry.idBase !== void 0)
|
|
3405
|
+
runtime.setIdBase?.(entry.idBase);
|
|
3359
3406
|
const unobserve = runtime.webhooks?.observeDeliveries(observer.delivery);
|
|
3360
3407
|
if (options.outbound && runtime.webhooks)
|
|
3361
3408
|
runtime.webhooks.setTransportPolicy(ownedTransport(options.outbound));
|
|
@@ -3954,6 +4001,7 @@ async function startFleet(config, options) {
|
|
|
3954
4001
|
...entry,
|
|
3955
4002
|
adminPrefix: resolveAdminPrefix(entry.adminPrefix ?? adminPrefix),
|
|
3956
4003
|
...adminKey !== void 0 ? { adminKey } : {},
|
|
4004
|
+
...(entry.idBase ?? config.idBase) !== void 0 ? { idBase: entry.idBase ?? config.idBase } : {},
|
|
3957
4005
|
// Fleet-wide controls, with the service's own keys replacing them.
|
|
3958
4006
|
...config.adminControls !== void 0 || entry.adminControls !== void 0 ? { adminControls: { ...config.adminControls, ...entry.adminControls } } : {}
|
|
3959
4007
|
}, options, (namespace, request) => management?.admit(namespace, request), (namespace) => management?.generation(namespace), (namespace, request) => management?.privateRequest(namespace, request) ?? false, {
|
|
@@ -4638,6 +4686,16 @@ var COMMON_SERVE_OPTIONS = {
|
|
|
4638
4686
|
value: "<seed>",
|
|
4639
4687
|
description: "Seed for every random choice (env MOCKINGBIRD_SEED)"
|
|
4640
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
|
+
},
|
|
4641
4699
|
"admin-controls": {
|
|
4642
4700
|
type: "string",
|
|
4643
4701
|
value: "<json|file>",
|
|
@@ -4732,19 +4790,40 @@ var readJsonFile = async (path, label) => {
|
|
|
4732
4790
|
}
|
|
4733
4791
|
};
|
|
4734
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
|
+
};
|
|
4735
4822
|
var resolveServeControls = async (values, env = process.env, base) => {
|
|
4736
4823
|
const source = asString(values["admin-controls"]) ?? env.MOCKINGBIRD_ADMIN_CONTROLS;
|
|
4737
4824
|
let document = isObject2(base) ? { ...base } : {};
|
|
4738
4825
|
if (source !== void 0 && source.trim() !== "") {
|
|
4739
|
-
|
|
4740
|
-
if (source.trim().startsWith("{")) {
|
|
4741
|
-
try {
|
|
4742
|
-
parsed = JSON.parse(source);
|
|
4743
|
-
} catch {
|
|
4744
|
-
throw new Error("--admin-controls: not valid JSON");
|
|
4745
|
-
}
|
|
4746
|
-
} else
|
|
4747
|
-
parsed = await readJsonFile(source, "--admin-controls");
|
|
4826
|
+
const parsed = source.trim().startsWith("{") ? await readJsonOption(source, "--admin-controls") : await readJsonFile(source, "--admin-controls");
|
|
4748
4827
|
if (!isObject2(parsed))
|
|
4749
4828
|
throw new Error("--admin-controls: expected a JSON object");
|
|
4750
4829
|
document = { ...document, ...parsed };
|
|
@@ -4794,8 +4873,11 @@ var start = async (target, values, config) => {
|
|
|
4794
4873
|
adminKey: config.adminKey,
|
|
4795
4874
|
seed: config.seed,
|
|
4796
4875
|
onLog: formatLog(config.log),
|
|
4876
|
+
...config.settings !== void 0 ? { settings: config.settings } : {},
|
|
4797
4877
|
...config.adminControls !== void 0 ? { adminControls: config.adminControls } : {}
|
|
4798
4878
|
});
|
|
4879
|
+
if (config.idBase !== void 0)
|
|
4880
|
+
runtime.setIdBase?.(config.idBase);
|
|
4799
4881
|
const listening = await listen(runtime, { port: config.port, host: config.host });
|
|
4800
4882
|
target.listening?.(listening);
|
|
4801
4883
|
console.log(`${target.name} emulator listening on ${listening.url}`);
|
|
@@ -4841,6 +4923,11 @@ var serveCommand = (target) => ({
|
|
|
4841
4923
|
const adminControls = await resolveServeControls(values, process.env, config.adminControls);
|
|
4842
4924
|
if (adminControls !== void 0)
|
|
4843
4925
|
config.adminControls = adminControls;
|
|
4926
|
+
if (values.settings !== void 0)
|
|
4927
|
+
throw new Error("--settings serves a single service; give each service its own `settings` in the config");
|
|
4928
|
+
const idBase = config.idBase ?? resolveServeIdBase(values);
|
|
4929
|
+
if (idBase !== void 0)
|
|
4930
|
+
config.idBase = idBase;
|
|
4844
4931
|
const fleet = await startFleet(config, {
|
|
4845
4932
|
load: (name) => loadTarget(name, target),
|
|
4846
4933
|
onLog: formatLog(config.log ?? log),
|
|
@@ -4870,8 +4957,12 @@ var serveCommand = (target) => ({
|
|
|
4870
4957
|
let listening;
|
|
4871
4958
|
try {
|
|
4872
4959
|
const adminControls = await resolveServeControls(values);
|
|
4960
|
+
const idBase = resolveServeIdBase(values);
|
|
4961
|
+
const settings = await resolveServeSettings(target, values);
|
|
4873
4962
|
listening = await start(target, values, {
|
|
4874
4963
|
...adminControls !== void 0 ? { adminControls } : {},
|
|
4964
|
+
...idBase !== void 0 ? { idBase } : {},
|
|
4965
|
+
...settings !== void 0 ? { settings } : {},
|
|
4875
4966
|
adminPrefix: resolveAdminPrefix(asString(values["admin-prefix"]) ?? process.env.MOCKINGBIRD_ADMIN_PREFIX),
|
|
4876
4967
|
port: port === void 0 ? target.defaultPort : Number.parseInt(port, 10),
|
|
4877
4968
|
host: asString(values.host) ?? "127.0.0.1",
|
|
@@ -4962,4 +5053,4 @@ export {
|
|
|
4962
5053
|
createMultiServer,
|
|
4963
5054
|
serveTarget
|
|
4964
5055
|
};
|
|
4965
|
-
//# sourceMappingURL=chunk-
|
|
5056
|
+
//# sourceMappingURL=chunk-AAKIJOPV.js.map
|