@crvouga/mockingbird-service-mailosaur 3.4.0 → 3.6.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 +12 -0
- package/dist/{chunk-RTJ3O3AX.js → chunk-4B6IN77Y.js} +214 -41
- package/dist/chunk-4B6IN77Y.js.map +7 -0
- package/dist/chunk-U3FYDM4L.js +1 -1
- package/dist/cli.js +1 -1
- package/dist/server.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-RTJ3O3AX.js.map +0 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog — @crvouga/mockingbird-service-mailosaur
|
|
2
2
|
|
|
3
|
+
## 3.6.0 (2026-10-17)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- resolve fleet and emulator issue batch ([26d2f8c](https://github.com/crvouga/mockingbird/commit/26d2f8cee99fefed93192204bac44fb1be35c1da))
|
|
8
|
+
|
|
9
|
+
## 3.5.0 (2026-10-15)
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
- resolve SQL, routing and writer gaps ([73f97d0](https://github.com/crvouga/mockingbird/commit/73f97d0d2379f44b9131180498f4fab76648fed9))
|
|
14
|
+
|
|
3
15
|
## 3.4.0 (2026-10-15)
|
|
4
16
|
|
|
5
17
|
### Features
|
|
@@ -21,9 +21,6 @@ import { createServer as createTlsServer } from "node:tls";
|
|
|
21
21
|
|
|
22
22
|
// ../../adapters/node/dist/cli.js
|
|
23
23
|
import { readFile as readFile5 } from "node:fs/promises";
|
|
24
|
-
import { createRequire as createRequire3 } from "node:module";
|
|
25
|
-
import { resolve as resolve3 } from "node:path";
|
|
26
|
-
import { pathToFileURL } from "node:url";
|
|
27
24
|
import { parseArgs } from "node:util";
|
|
28
25
|
|
|
29
26
|
// ../../adapters/node/dist/fleet.js
|
|
@@ -37,6 +34,31 @@ import { createHash as createHash3, randomBytes, randomUUID as randomUUID3 } fro
|
|
|
37
34
|
|
|
38
35
|
// ../../adapters/node/dist/fleet-archive.js
|
|
39
36
|
import { createHash } from "node:crypto";
|
|
37
|
+
function validateCompatibilityTags(tags) {
|
|
38
|
+
if (!tags || typeof tags !== "object" || Array.isArray(tags))
|
|
39
|
+
throw new Error("invalid archive compatibility tags");
|
|
40
|
+
const entries = Object.entries(tags);
|
|
41
|
+
if (entries.length > 32 || entries.some(([key, value]) => !/^[A-Za-z0-9_.-]{1,64}$/.test(key) || typeof value !== "string" || value.length < 1 || value.length > 256 || [...value].some((character) => character.charCodeAt(0) < 32 || character.charCodeAt(0) === 127)))
|
|
42
|
+
throw new Error("invalid archive compatibility tags");
|
|
43
|
+
}
|
|
44
|
+
function assertCompatibilityTags(tags, policy) {
|
|
45
|
+
if (tags !== void 0)
|
|
46
|
+
validateCompatibilityTags(tags);
|
|
47
|
+
if (!policy)
|
|
48
|
+
return;
|
|
49
|
+
validateCompatibilityTags(policy.tags);
|
|
50
|
+
if (policy.missing !== void 0 && !["allow", "reject"].includes(policy.missing))
|
|
51
|
+
throw new Error("invalid missing compatibility policy");
|
|
52
|
+
if (tags === void 0 && policy.missing === "allow")
|
|
53
|
+
return;
|
|
54
|
+
if (canonical(tags) !== canonical(policy.tags))
|
|
55
|
+
throw new Error("application archive compatibility mismatch");
|
|
56
|
+
}
|
|
57
|
+
function assertArchiveCompatibility(input, policy) {
|
|
58
|
+
const archive = validateArchive(input);
|
|
59
|
+
assertCompatibilityTags(archive.compatibility, policy);
|
|
60
|
+
return archive;
|
|
61
|
+
}
|
|
40
62
|
var canonical = (value) => {
|
|
41
63
|
if (Array.isArray(value))
|
|
42
64
|
return `[${value.map(canonical).join(",")}]`;
|
|
@@ -56,6 +78,8 @@ function validateArchive(value) {
|
|
|
56
78
|
const { sha256, ...content } = doc;
|
|
57
79
|
if (doc.format !== "mockingbird.fleet/v1" || typeof doc.sourceId !== "string" || typeof doc.createdAt !== "string" || !doc.namespaces || typeof doc.namespaces !== "object" || Array.isArray(doc.namespaces) || sha256 !== digest(content))
|
|
58
80
|
throw new Error("unsupported or corrupt fleet archive");
|
|
81
|
+
if (doc.compatibility !== void 0)
|
|
82
|
+
validateCompatibilityTags(doc.compatibility);
|
|
59
83
|
for (const [namespace, entry] of Object.entries(doc.namespaces)) {
|
|
60
84
|
if (!/^[A-Za-z0-9_.-]{1,64}$/.test(namespace) || !entry || !Number.isFinite(entry.clock?.now) || typeof entry.clock?.frozen !== "boolean" || !entry.services || !Object.keys(entry.services).length)
|
|
61
85
|
throw new Error("invalid archive namespace");
|
|
@@ -71,6 +95,7 @@ function inspectArchive(input) {
|
|
|
71
95
|
format: archive.format,
|
|
72
96
|
createdAt: archive.createdAt,
|
|
73
97
|
sha256: archive.sha256,
|
|
98
|
+
...archive.compatibility ? { compatibility: archive.compatibility } : {},
|
|
74
99
|
namespaces: Object.fromEntries(Object.entries(archive.namespaces).map(([name2, ns]) => [
|
|
75
100
|
name2,
|
|
76
101
|
{
|
|
@@ -713,11 +738,28 @@ var ingressSupport = {
|
|
|
713
738
|
streaming: true,
|
|
714
739
|
signing: "vendor request signing is not used; webhook signatures remain payload based"
|
|
715
740
|
},
|
|
741
|
+
cognito: {
|
|
742
|
+
publicOrigin: true,
|
|
743
|
+
pathPrefix: true,
|
|
744
|
+
namespaces: "path-or-header",
|
|
745
|
+
streaming: true,
|
|
746
|
+
signing: "JWT issuer and JWKS use the configured public namespace; SigV4 verification is not modelled"
|
|
747
|
+
},
|
|
748
|
+
medplum: {
|
|
749
|
+
publicOrigin: true,
|
|
750
|
+
pathPrefix: true,
|
|
751
|
+
namespaces: "path-or-header",
|
|
752
|
+
streaming: true,
|
|
753
|
+
signing: "FHIR, OAuth and storage URLs use the configured public namespace"
|
|
754
|
+
},
|
|
716
755
|
other: {
|
|
717
756
|
publicOrigin: false,
|
|
718
757
|
reason: "host/path-sensitive signing and hosted URL rewriting are not certified; use a direct endpoint"
|
|
719
758
|
}
|
|
720
759
|
};
|
|
760
|
+
function supportsPublicIngress(service) {
|
|
761
|
+
return service === "stripe" || service === "cognito" || service === "medplum";
|
|
762
|
+
}
|
|
721
763
|
function advertisedHttpBase(entry) {
|
|
722
764
|
if (entry.publicPath !== void 0 && !entry.publicOrigin)
|
|
723
765
|
throw new Error("publicPath requires publicOrigin");
|
|
@@ -1256,7 +1298,7 @@ data: ${JSON.stringify(data)}
|
|
|
1256
1298
|
{
|
|
1257
1299
|
protocol: c.protocol,
|
|
1258
1300
|
coverage: c.coverage,
|
|
1259
|
-
ingress: c.targetName
|
|
1301
|
+
ingress: supportsPublicIngress(c.targetName ?? "") ? ingressSupport[c.targetName] : ingressSupport.other,
|
|
1260
1302
|
target: c.targetName,
|
|
1261
1303
|
outboundPolicy: c.outboundPolicy ?? "unsupported",
|
|
1262
1304
|
version: 1,
|
|
@@ -2340,11 +2382,12 @@ data: ${JSON.stringify(data)}
|
|
|
2340
2382
|
format: "mockingbird.fleet/v1",
|
|
2341
2383
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2342
2384
|
sourceId: this.ctx.id,
|
|
2385
|
+
...this.ctx.options.archiveCompatibility ? { compatibility: structuredClone(this.ctx.options.archiveCompatibility.tags) } : {},
|
|
2343
2386
|
namespaces: contents
|
|
2344
2387
|
});
|
|
2345
2388
|
}
|
|
2346
2389
|
async restoreArchive(input, selectedNamespace) {
|
|
2347
|
-
const archive =
|
|
2390
|
+
const archive = assertArchiveCompatibility(input, this.ctx.options.archiveCompatibility);
|
|
2348
2391
|
const entries = Object.entries(archive.namespaces).filter(([ns]) => selectedNamespace === void 0 || ns === selectedNamespace);
|
|
2349
2392
|
if (!entries.length)
|
|
2350
2393
|
throw new Error("selected namespace absent from archive");
|
|
@@ -2928,7 +2971,7 @@ async function preflightFleet(config, options) {
|
|
|
2928
2971
|
if (entry.target !== void 0 && !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(entry.target))
|
|
2929
2972
|
throw new Error("target must name a supported service suffix");
|
|
2930
2973
|
const service = entry.target ?? name2;
|
|
2931
|
-
if (advertisedHttpBase(entry) && service
|
|
2974
|
+
if (advertisedHttpBase(entry) && !supportsPublicIngress(service))
|
|
2932
2975
|
throw new Error(`public ingress unsupported for ${service}; use a direct endpoint to preserve signed targets`);
|
|
2933
2976
|
const target = await options.load(service);
|
|
2934
2977
|
const protocol = "protocol" in target ? target.protocol : "http";
|
|
@@ -2979,7 +3022,7 @@ async function preflightFleet(config, options) {
|
|
|
2979
3022
|
break;
|
|
2980
3023
|
}
|
|
2981
3024
|
}
|
|
2982
|
-
targets.set(name2, { ...target, packageVersion: packageVersion ?? "3.
|
|
3025
|
+
targets.set(name2, { ...target, packageVersion: packageVersion ?? "3.6.0" });
|
|
2983
3026
|
} catch (error) {
|
|
2984
3027
|
throw new Error(`service ${name2}: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
2985
3028
|
}
|
|
@@ -3023,6 +3066,11 @@ async function preflightFleet(config, options) {
|
|
|
3023
3066
|
return ordered;
|
|
3024
3067
|
}
|
|
3025
3068
|
function validateFleetPolicies(options) {
|
|
3069
|
+
if (options.archiveCompatibility) {
|
|
3070
|
+
validateCompatibilityTags(options.archiveCompatibility.tags);
|
|
3071
|
+
if (options.archiveCompatibility.missing !== void 0 && !["allow", "reject"].includes(options.archiveCompatibility.missing))
|
|
3072
|
+
throw new Error("archiveCompatibility.missing must be allow or reject");
|
|
3073
|
+
}
|
|
3026
3074
|
if (options.journal && !options.repository)
|
|
3027
3075
|
throw new Error("durable operation journal requires an archive repository");
|
|
3028
3076
|
if (options.cors) {
|
|
@@ -4015,10 +4063,44 @@ async function startFleet(config, options) {
|
|
|
4015
4063
|
}
|
|
4016
4064
|
}
|
|
4017
4065
|
|
|
4018
|
-
// ../../adapters/node/dist/fleet-
|
|
4019
|
-
import { readFile as readFile4 } from "node:fs/promises";
|
|
4066
|
+
// ../../adapters/node/dist/fleet-loader.js
|
|
4020
4067
|
import { createRequire as createRequire2 } from "node:module";
|
|
4021
4068
|
import { resolve as resolve2 } from "node:path";
|
|
4069
|
+
import { pathToFileURL } from "node:url";
|
|
4070
|
+
var suffix = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
4071
|
+
function createInstalledServiceLoader(options) {
|
|
4072
|
+
if (!options.projectRoot)
|
|
4073
|
+
throw new Error("consumer projectRoot required");
|
|
4074
|
+
const allowed = new Set(options.services);
|
|
4075
|
+
for (const name2 of allowed)
|
|
4076
|
+
if (!suffix.test(name2))
|
|
4077
|
+
throw new Error("invalid service suffix");
|
|
4078
|
+
const require2 = createRequire2(resolve2(options.projectRoot, "package.json"));
|
|
4079
|
+
const targets = new Map((options.targets ?? []).map((target) => [target.name, target]));
|
|
4080
|
+
return async (name2) => {
|
|
4081
|
+
if (!suffix.test(name2) || !allowed.has(name2))
|
|
4082
|
+
throw new Error("service is not declared in loader allowlist");
|
|
4083
|
+
const own = targets.get(name2);
|
|
4084
|
+
if (own)
|
|
4085
|
+
return own;
|
|
4086
|
+
const specifier = `@crvouga/mockingbird-service-${name2}/server`;
|
|
4087
|
+
let location;
|
|
4088
|
+
try {
|
|
4089
|
+
location = require2.resolve(specifier);
|
|
4090
|
+
} catch {
|
|
4091
|
+
throw new Error(`cannot load service "${name2}": install @crvouga/mockingbird-service-${name2} in the consumer project; its /server export is required`);
|
|
4092
|
+
}
|
|
4093
|
+
const mod = await import(pathToFileURL(location).href);
|
|
4094
|
+
if (!mod.serveTarget || mod.serveTarget.name !== name2 || ("protocol" in mod.serveTarget ? typeof mod.serveTarget.start !== "function" : typeof mod.serveTarget.create !== "function"))
|
|
4095
|
+
throw new Error(`${specifier} exports no matching serveTarget`);
|
|
4096
|
+
return mod.serveTarget;
|
|
4097
|
+
};
|
|
4098
|
+
}
|
|
4099
|
+
|
|
4100
|
+
// ../../adapters/node/dist/fleet-tools.js
|
|
4101
|
+
import { readFile as readFile4 } from "node:fs/promises";
|
|
4102
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
4103
|
+
import { resolve as resolve3 } from "node:path";
|
|
4022
4104
|
|
|
4023
4105
|
// ../../adapters/node/dist/fleet-client.js
|
|
4024
4106
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
@@ -4032,6 +4114,14 @@ var FleetClientError = class extends Error {
|
|
|
4032
4114
|
this.details = details;
|
|
4033
4115
|
}
|
|
4034
4116
|
};
|
|
4117
|
+
var FleetClientResponseError = class extends FleetClientError {
|
|
4118
|
+
code;
|
|
4119
|
+
constructor(code, status, origin) {
|
|
4120
|
+
super(status, { code, body: "omitted", ...origin ? { origin } : {} });
|
|
4121
|
+
this.code = code;
|
|
4122
|
+
this.name = "FleetClientResponseError";
|
|
4123
|
+
}
|
|
4124
|
+
};
|
|
4035
4125
|
var FleetClient = class {
|
|
4036
4126
|
base;
|
|
4037
4127
|
options;
|
|
@@ -4044,7 +4134,14 @@ var FleetClient = class {
|
|
|
4044
4134
|
if (url.username || url.password)
|
|
4045
4135
|
throw new Error("fleet client URL must not contain credentials");
|
|
4046
4136
|
url.searchParams.set("namespace", options.namespace ?? this.options.namespace ?? "default");
|
|
4137
|
+
const limit = options.maxResponseBytes ?? this.options.maxResponseBytes ?? 64 * 1024 * 1024;
|
|
4138
|
+
if (!Number.isSafeInteger(limit) || limit < 1)
|
|
4139
|
+
throw new Error("invalid response byte limit");
|
|
4140
|
+
const deadline = AbortSignal.timeout(this.options.timeoutMs ?? 3e4);
|
|
4141
|
+
const signal = options.signal ? AbortSignal.any([options.signal, deadline]) : deadline;
|
|
4142
|
+
signal.throwIfAborted();
|
|
4047
4143
|
const response = await (this.options.fetch ?? fetch)(url, {
|
|
4144
|
+
redirect: "manual",
|
|
4048
4145
|
method: options.method ?? (options.body === void 0 ? "GET" : "POST"),
|
|
4049
4146
|
headers: {
|
|
4050
4147
|
"content-type": "application/json",
|
|
@@ -4052,11 +4149,71 @@ var FleetClient = class {
|
|
|
4052
4149
|
...options.idempotencyKey ? { "idempotency-key": options.idempotencyKey } : {}
|
|
4053
4150
|
},
|
|
4054
4151
|
...options.body !== void 0 ? { body: JSON.stringify(options.body) } : {},
|
|
4055
|
-
signal
|
|
4152
|
+
signal
|
|
4056
4153
|
});
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
throw new
|
|
4154
|
+
if (response.status >= 300 && response.status < 400) {
|
|
4155
|
+
await response.body?.cancel();
|
|
4156
|
+
throw new FleetClientResponseError("redirect", response.status, url.origin);
|
|
4157
|
+
}
|
|
4158
|
+
if (Number(response.headers.get("content-length")) > limit) {
|
|
4159
|
+
await response.body?.cancel();
|
|
4160
|
+
throw new FleetClientResponseError("response_too_large", response.status);
|
|
4161
|
+
}
|
|
4162
|
+
const reader = response.body?.getReader();
|
|
4163
|
+
const chunks = [];
|
|
4164
|
+
let size = 0;
|
|
4165
|
+
const abort = () => {
|
|
4166
|
+
void reader?.cancel(signal.reason).catch(() => {
|
|
4167
|
+
});
|
|
4168
|
+
};
|
|
4169
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
4170
|
+
try {
|
|
4171
|
+
if (reader)
|
|
4172
|
+
while (true) {
|
|
4173
|
+
signal.throwIfAborted();
|
|
4174
|
+
const { done, value } = await reader.read();
|
|
4175
|
+
signal.throwIfAborted();
|
|
4176
|
+
if (done)
|
|
4177
|
+
break;
|
|
4178
|
+
size += value.byteLength;
|
|
4179
|
+
if (size > limit) {
|
|
4180
|
+
await reader.cancel();
|
|
4181
|
+
throw new FleetClientResponseError("response_too_large", response.status);
|
|
4182
|
+
}
|
|
4183
|
+
chunks.push(value);
|
|
4184
|
+
}
|
|
4185
|
+
} finally {
|
|
4186
|
+
signal.removeEventListener("abort", abort);
|
|
4187
|
+
if (signal.aborted)
|
|
4188
|
+
await reader?.cancel(signal.reason).catch(() => {
|
|
4189
|
+
});
|
|
4190
|
+
reader?.releaseLock();
|
|
4191
|
+
}
|
|
4192
|
+
const bytes2 = new Uint8Array(size);
|
|
4193
|
+
let offset = 0;
|
|
4194
|
+
for (const chunk of chunks) {
|
|
4195
|
+
bytes2.set(chunk, offset);
|
|
4196
|
+
offset += chunk.byteLength;
|
|
4197
|
+
}
|
|
4198
|
+
const text2 = new TextDecoder().decode(bytes2);
|
|
4199
|
+
let data;
|
|
4200
|
+
try {
|
|
4201
|
+
data = text2.length ? JSON.parse(text2) : void 0;
|
|
4202
|
+
} catch {
|
|
4203
|
+
if (response.ok)
|
|
4204
|
+
throw new FleetClientResponseError("invalid_json", response.status);
|
|
4205
|
+
}
|
|
4206
|
+
if (!response.ok) {
|
|
4207
|
+
const error = data && typeof data === "object" ? data.error : void 0;
|
|
4208
|
+
const detail = { body: "omitted" };
|
|
4209
|
+
if (error && typeof error === "object")
|
|
4210
|
+
for (const key of ["type", "code"]) {
|
|
4211
|
+
const value = error[key];
|
|
4212
|
+
if (typeof value === "string" && /^[A-Za-z0-9_.-]{1,128}$/.test(value))
|
|
4213
|
+
detail[key] = value;
|
|
4214
|
+
}
|
|
4215
|
+
throw new FleetClientError(response.status, detail);
|
|
4216
|
+
}
|
|
4060
4217
|
return data;
|
|
4061
4218
|
}
|
|
4062
4219
|
discover() {
|
|
@@ -4122,17 +4279,52 @@ function renderConnections(manifest, privateManifest, namespace, mapping) {
|
|
|
4122
4279
|
const child = manifest.services[entry.service], secret = privateManifest.services[entry.service];
|
|
4123
4280
|
if (!child || !secret)
|
|
4124
4281
|
throw new Error(`missing service mapping ${entry.service}`);
|
|
4282
|
+
let endpoint;
|
|
4125
4283
|
if (child.protocol === "http") {
|
|
4126
4284
|
const template = child.namespaces.path;
|
|
4127
4285
|
if (typeof template !== "string")
|
|
4128
4286
|
throw new Error(`missing HTTP namespace mapping ${entry.service}`);
|
|
4129
|
-
|
|
4287
|
+
endpoint = new URL(template.replace("{name}", encodeURIComponent(namespace)), secret.url).href;
|
|
4130
4288
|
} else {
|
|
4131
|
-
const
|
|
4132
|
-
if (!
|
|
4289
|
+
const selected = secret.namespaces?.[namespace];
|
|
4290
|
+
if (!selected)
|
|
4133
4291
|
throw new Error(`missing namespace mapping ${namespace}/${entry.service}`);
|
|
4134
|
-
|
|
4292
|
+
endpoint = selected;
|
|
4135
4293
|
}
|
|
4294
|
+
const url = new URL(endpoint);
|
|
4295
|
+
const field = entry.field ?? "url";
|
|
4296
|
+
let value;
|
|
4297
|
+
switch (field) {
|
|
4298
|
+
case "url":
|
|
4299
|
+
value = endpoint;
|
|
4300
|
+
break;
|
|
4301
|
+
case "hostname":
|
|
4302
|
+
value = url.hostname.replace(/^\[|\]$/g, "");
|
|
4303
|
+
break;
|
|
4304
|
+
case "port":
|
|
4305
|
+
value = url.port;
|
|
4306
|
+
break;
|
|
4307
|
+
case "username":
|
|
4308
|
+
value = decodeURIComponent(url.username);
|
|
4309
|
+
break;
|
|
4310
|
+
case "password":
|
|
4311
|
+
value = decodeURIComponent(url.password);
|
|
4312
|
+
break;
|
|
4313
|
+
case "pathname":
|
|
4314
|
+
value = decodeURIComponent(url.pathname);
|
|
4315
|
+
break;
|
|
4316
|
+
case "database":
|
|
4317
|
+
value = decodeURIComponent(url.pathname.replace(/^\//, ""));
|
|
4318
|
+
break;
|
|
4319
|
+
default:
|
|
4320
|
+
throw new Error("unsupported connection field");
|
|
4321
|
+
}
|
|
4322
|
+
if (!value) {
|
|
4323
|
+
if (typeof entry.fallback !== "string")
|
|
4324
|
+
throw new Error(`missing connection component ${field}`);
|
|
4325
|
+
value = entry.fallback;
|
|
4326
|
+
}
|
|
4327
|
+
result[variable] = value;
|
|
4136
4328
|
}
|
|
4137
4329
|
return result;
|
|
4138
4330
|
}
|
|
@@ -4156,7 +4348,7 @@ async function doctorFleet(config, options, probes = []) {
|
|
|
4156
4348
|
const plan = [];
|
|
4157
4349
|
try {
|
|
4158
4350
|
const targets = await preflightFleet(config, options);
|
|
4159
|
-
const require2 =
|
|
4351
|
+
const require2 = createRequire3(resolve3(process.cwd(), "package.json"));
|
|
4160
4352
|
for (const [service, target] of targets) {
|
|
4161
4353
|
let version = "development";
|
|
4162
4354
|
try {
|
|
@@ -4211,7 +4403,7 @@ async function doctorFleet(config, options, probes = []) {
|
|
|
4211
4403
|
};
|
|
4212
4404
|
}
|
|
4213
4405
|
async function rehearseFleet(config, options, input, probes = [], timeoutMs = 3e4) {
|
|
4214
|
-
const archive =
|
|
4406
|
+
const archive = assertArchiveCompatibility(input, options.archiveCompatibility);
|
|
4215
4407
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4216
4408
|
const isolated = {
|
|
4217
4409
|
...config,
|
|
@@ -4223,7 +4415,7 @@ async function rehearseFleet(config, options, input, probes = [], timeoutMs = 3e
|
|
|
4223
4415
|
};
|
|
4224
4416
|
let fleet;
|
|
4225
4417
|
try {
|
|
4226
|
-
fleet = await startFleet(isolated,
|
|
4418
|
+
fleet = await startFleet(isolated, options);
|
|
4227
4419
|
const client = new FleetClient(fleet.manifest.adminBase, {
|
|
4228
4420
|
...config.adminKey ? { adminKey: config.adminKey } : {}
|
|
4229
4421
|
});
|
|
@@ -4598,26 +4790,7 @@ var resolveServeControls = async (values, env = process.env, base) => {
|
|
|
4598
4790
|
normalizeBootControls(document, "adminControls");
|
|
4599
4791
|
return document;
|
|
4600
4792
|
};
|
|
4601
|
-
var loadTarget =
|
|
4602
|
-
if (name2 === own.name)
|
|
4603
|
-
return own;
|
|
4604
|
-
const specifier = `@crvouga/mockingbird-service-${name2}/server`;
|
|
4605
|
-
try {
|
|
4606
|
-
let mod;
|
|
4607
|
-
try {
|
|
4608
|
-
mod = await import(specifier);
|
|
4609
|
-
} catch {
|
|
4610
|
-
const fromProject = createRequire3(resolve3(process.cwd(), "package.json"));
|
|
4611
|
-
mod = await import(pathToFileURL(fromProject.resolve(specifier)).href);
|
|
4612
|
-
}
|
|
4613
|
-
if (!mod.serveTarget)
|
|
4614
|
-
throw new Error(`${specifier} exports no serveTarget`);
|
|
4615
|
-
return mod.serveTarget;
|
|
4616
|
-
} catch (error) {
|
|
4617
|
-
const reason = error instanceof Error ? error.message : String(error);
|
|
4618
|
-
throw new Error(`cannot load service "${name2}": ${reason}. Install @crvouga/mockingbird-service-${name2}.`);
|
|
4619
|
-
}
|
|
4620
|
-
};
|
|
4793
|
+
var loadTarget = (name2, own) => createInstalledServiceLoader({ projectRoot: process.cwd(), services: [name2], targets: [own] })(name2);
|
|
4621
4794
|
var start = async (target, values, config) => {
|
|
4622
4795
|
const adminPrefix = resolveAdminPrefix(config.adminPrefix);
|
|
4623
4796
|
const runtime = await target.create(values, {
|
|
@@ -4976,4 +5149,4 @@ export {
|
|
|
4976
5149
|
createServer2 as createServer,
|
|
4977
5150
|
serveTarget
|
|
4978
5151
|
};
|
|
4979
|
-
//# sourceMappingURL=chunk-
|
|
5152
|
+
//# sourceMappingURL=chunk-4B6IN77Y.js.map
|