@prisma/composer 0.1.0-dev.18 → 0.1.0-dev.3

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.
Files changed (43) hide show
  1. package/dist/{app-config-DJdU4ubR-BwioNK8j.d.mts → app-config-5mXxjaEl-D2Q6MU5g.d.mts} +19 -105
  2. package/dist/assertions.d.mts +1 -1
  3. package/dist/assertions.mjs.map +1 -1
  4. package/dist/bin.mjs +266 -81
  5. package/dist/bin.mjs.map +1 -1
  6. package/dist/casts-Ci5rYYaR.mjs.map +1 -1
  7. package/dist/casts.d.mts +1 -1
  8. package/dist/config-C23NciC8.d.mts +1 -0
  9. package/dist/config.d.mts +3 -3
  10. package/dist/config.mjs +1 -2
  11. package/dist/config.mjs.map +1 -1
  12. package/dist/deploy-C23NciC8.d.mts +1 -0
  13. package/dist/deploy.d.mts +2 -2
  14. package/dist/deploy.mjs +5 -12
  15. package/dist/deploy.mjs.map +1 -1
  16. package/dist/dist-B0axxnBf.mjs.map +1 -1
  17. package/dist/{graph-B7NcPiOr-aSUOCGTH.d.mts → graph-D383dfW2-Cepin3Om.d.mts} +3 -3
  18. package/dist/{graph-types-BgT9UEdm-Bz-_OcJH.d.mts → graph-types-COu3ss99-CrJcsbDJ.d.mts} +4 -4
  19. package/dist/{index-B2DJ5CN4.d.mts → index-8wU5wpMV.d.mts} +3 -3
  20. package/dist/{nextjs-DLyeRR7M-B9ukbB2L.d.mts → index-DIyo-rxT.d.mts} +5 -5
  21. package/dist/index.d.mts +3 -3
  22. package/dist/nextjs-control.d.mts +5 -5
  23. package/dist/nextjs-control.mjs.map +1 -1
  24. package/dist/nextjs.d.mts +2 -2
  25. package/dist/nextjs.mjs.map +1 -1
  26. package/dist/node-control.d.mts +4 -4
  27. package/dist/node-control.mjs.map +1 -1
  28. package/dist/node.d.mts +4 -4
  29. package/dist/node.mjs.map +1 -1
  30. package/dist/report.d.mts +3 -3
  31. package/dist/report.mjs.map +1 -1
  32. package/dist/{service-rpc.d.mts → rpc.d.mts} +11 -19
  33. package/dist/rpc.mjs +184 -0
  34. package/dist/rpc.mjs.map +1 -0
  35. package/dist/testing.d.mts +2 -2
  36. package/dist/testing.mjs.map +1 -1
  37. package/package.json +14 -14
  38. package/dist/config-ByZICgry.d.mts +0 -1
  39. package/dist/container-transport-DKmKg5JQ-DKWs0ubK.mjs +0 -45
  40. package/dist/container-transport-DKmKg5JQ-DKWs0ubK.mjs.map +0 -1
  41. package/dist/deploy-ByZICgry.d.mts +0 -1
  42. package/dist/service-rpc.mjs +0 -353
  43. package/dist/service-rpc.mjs.map +0 -1
@@ -1,353 +0,0 @@
1
- import { t as blindCast } from "./casts-Ci5rYYaR.mjs";
2
- import { i as dependency, p as provisionNeed } from "./graph-BmrUEdo9-6Oq1hSmS.mjs";
3
- import { l as string } from "./dist-B0axxnBf.mjs";
4
- //#region ../../0-framework/2-authoring/service-rpc/dist/index.mjs
5
- /** Bounded jittered backoff for retrying a dropped call. `maxRetries` is retries after the first attempt. */
6
- const RETRY = {
7
- initialDelayMs: 250,
8
- multiplier: 2,
9
- maxDelayMs: 5e3,
10
- maxRetries: 5
11
- };
12
- const IDEMPOTENCY_KEY_HEADER$1 = "Idempotency-Key";
13
- function sleep(ms) {
14
- return new Promise((resolve) => setTimeout(resolve, ms));
15
- }
16
- /** Whether a non-OK response is safe to retry: 429 or any 5xx, never another 4xx. */
17
- function isRetryableStatus(status) {
18
- return status === 429 || status >= 500;
19
- }
20
- /** The server's `{ error }` body, if the response has one — undefined otherwise. */
21
- async function errorDetail(res) {
22
- try {
23
- const body = await res.json();
24
- return typeof body === "object" && body !== null && "error" in body ? String(body.error) : void 0;
25
- } catch {
26
- return;
27
- }
28
- }
29
- /** `<base>/rpc/<method>`, preserving a base URL's own path (e.g. a mount point). */
30
- function methodUrl(base, method) {
31
- const normalizedBase = base.endsWith("/") ? base : `${base}/`;
32
- return new URL(`rpc/${method}`, normalizedBase).toString();
33
- }
34
- /**
35
- * Sends one call over `send`, retrying a thrown error, 429, or 5xx with
36
- * full-jitter backoff. `buildRequest` runs per attempt but carries the same
37
- * idempotency key each time — only the transport call repeats, not the key.
38
- */
39
- async function callWithRetry(send, buildRequest, method) {
40
- let delay = RETRY.initialDelayMs;
41
- let retries = 0;
42
- for (;;) {
43
- let res;
44
- try {
45
- res = await send(buildRequest());
46
- } catch (err) {
47
- if (retries >= RETRY.maxRetries) throw err;
48
- retries += 1;
49
- await sleep(Math.random() * delay);
50
- delay = Math.min(delay * RETRY.multiplier, RETRY.maxDelayMs);
51
- continue;
52
- }
53
- if (res.ok) return res.json();
54
- if (!isRetryableStatus(res.status) || retries >= RETRY.maxRetries) {
55
- const detail = await errorDetail(res);
56
- throw new Error(`RPC call "${method}" failed: ${res.status} ${res.statusText}` + (detail !== void 0 ? ` — ${detail}` : ""));
57
- }
58
- retries += 1;
59
- await sleep(Math.random() * delay);
60
- delay = Math.min(delay * RETRY.multiplier, RETRY.maxDelayMs);
61
- }
62
- }
63
- function makeClient(contract, url, opts) {
64
- const send = opts?.fetch ?? fetch;
65
- const baseHeaders = { "content-type": "application/json" };
66
- if (opts?.serviceKey !== void 0) baseHeaders["Authorization"] = `Bearer ${opts.serviceKey}`;
67
- const client = {};
68
- for (const method of Object.keys(contract.__cmp)) client[method] = async (input) => {
69
- const idempotencyKey = crypto.randomUUID();
70
- const body = JSON.stringify(input);
71
- return callWithRetry(send, () => new Request(methodUrl(url, method), {
72
- method: "POST",
73
- headers: {
74
- ...baseHeaders,
75
- [IDEMPOTENCY_KEY_HEADER$1]: idempotencyKey
76
- },
77
- body
78
- }), method);
79
- };
80
- return blindCast(client);
81
- }
82
- function contract(fns) {
83
- const value = {
84
- kind: "rpc",
85
- __cmp: fns,
86
- satisfies: (required) => value === required
87
- };
88
- return Object.freeze(value);
89
- }
90
- /** ADR-0031's need brand for RPC's per-binding service key — the target registers a provisioner under this. */
91
- const RPC_PEER_KEY = Symbol.for("prisma:rpc/per-binding-key");
92
- /** The provisioning need `rpc()`'s `serviceKey` param declares (ADR-0030): a shared, unguessable value the target mints per consumer edge. */
93
- const perBindingToken = () => provisionNeed(RPC_PEER_KEY);
94
- function rpc(arg) {
95
- if (!isRpcContract(arg)) return arg;
96
- return dependency({
97
- type: "rpc",
98
- connection: {
99
- params: {
100
- url: string(),
101
- serviceKey: string({
102
- optional: true,
103
- provision: perBindingToken()
104
- })
105
- },
106
- hydrate: ({ url, serviceKey }) => makeClient(arg, url, { serviceKey })
107
- },
108
- required: arg
109
- });
110
- }
111
- function isRpcContract(value) {
112
- return typeof value === "object" && value !== null && "kind" in value && value.kind === "rpc" && "__cmp" in value && "satisfies" in value;
113
- }
114
- async function standardValidate(schema, value) {
115
- const result = await schema["~standard"].validate(value);
116
- if (result.issues !== void 0) throw new Error(`Schema validation failed: ${result.issues.map((issue) => issue.message).join("; ")}`);
117
- return result.value;
118
- }
119
- /** The reserved env var the target (slice 2) writes the accepted key set to. */
120
- const RPC_ACCEPTED_KEYS_ENV = "COMPOSER_RPC_ACCEPTED_KEYS";
121
- function outcome(body, status = 200) {
122
- return {
123
- status,
124
- bodyText: JSON.stringify(body)
125
- };
126
- }
127
- function toResponse(o) {
128
- return new Response(o.bodyText, {
129
- status: o.status,
130
- headers: { "content-type": "application/json" }
131
- });
132
- }
133
- /** The generic message every caller-facing 500 carries — the real error goes to `console.error` instead. */
134
- const INTERNAL_ERROR_MESSAGE = "Internal server error";
135
- /** Request body cap. Internal RPC payloads are small records, not uploads; 1 MiB bounds a slow request's memory. */
136
- const MAX_BODY_BYTES = 1048576;
137
- var RequestBodyTooLargeError = class extends Error {};
138
- /** Reads the body as text, aborting past `maxBytes` of bytes actually read — `content-length` is caller-supplied, so untrusted. */
139
- async function readBoundedBody(req, maxBytes) {
140
- const reader = req.body?.getReader();
141
- if (reader === void 0) return "";
142
- const decoder = new TextDecoder();
143
- let text = "";
144
- let total = 0;
145
- for (;;) {
146
- const { done, value } = await reader.read();
147
- if (done) break;
148
- total += value.byteLength;
149
- if (total > maxBytes) {
150
- await reader.cancel();
151
- throw new RequestBodyTooLargeError();
152
- }
153
- text += decoder.decode(value, { stream: true });
154
- }
155
- text += decoder.decode();
156
- return text;
157
- }
158
- /** How long a completed 2xx/4xx answer stays replayable for a repeated key. */
159
- const REPLAY_TTL_MS = 6e4;
160
- /**
161
- * Per-method, per-key deduplication. A duplicate arriving mid-execution
162
- * single-flights onto the same promise; a completed 2xx/4xx replays for
163
- * REPLAY_TTL_MS; a 5xx is never kept, since that is what a retry re-executes.
164
- * Keyed by method first, so a replay can never answer a different method.
165
- */
166
- var IdempotencyStore = class {
167
- byMethod = /* @__PURE__ */ new Map();
168
- lru = /* @__PURE__ */ new Set();
169
- async dispatch(method, key, run) {
170
- const bucket = this.bucketFor(method);
171
- const existing = bucket.get(key);
172
- if (existing?.kind === "pending") return existing.promise;
173
- if (existing?.kind === "completed") {
174
- if (Date.now() - existing.completedAt < REPLAY_TTL_MS) {
175
- this.lru.delete(existing);
176
- this.lru.add(existing);
177
- return existing.outcome;
178
- }
179
- bucket.delete(key);
180
- this.lru.delete(existing);
181
- }
182
- const promise = run();
183
- bucket.set(key, {
184
- kind: "pending",
185
- promise
186
- });
187
- let result;
188
- try {
189
- result = await promise;
190
- } catch (err) {
191
- bucket.delete(key);
192
- throw err;
193
- }
194
- if (result.status >= 500) bucket.delete(key);
195
- else {
196
- const entry = {
197
- kind: "completed",
198
- outcome: result,
199
- completedAt: Date.now(),
200
- method,
201
- key
202
- };
203
- bucket.set(key, entry);
204
- this.lru.add(entry);
205
- this.evictOverflow();
206
- }
207
- return result;
208
- }
209
- bucketFor(method) {
210
- let bucket = this.byMethod.get(method);
211
- if (bucket === void 0) {
212
- bucket = /* @__PURE__ */ new Map();
213
- this.byMethod.set(method, bucket);
214
- }
215
- return bucket;
216
- }
217
- evictOverflow() {
218
- if (this.lru.size <= 1e3) return;
219
- const oldest = this.lru.values().next().value;
220
- if (oldest !== void 0) {
221
- this.lru.delete(oldest);
222
- this.byMethod.get(oldest.method)?.delete(oldest.key);
223
- }
224
- }
225
- };
226
- /** The provisioned accepted key set, or undefined when the deploy never provisioned one (local/test — enforcement off). */
227
- function acceptedKeys() {
228
- const raw = process.env[RPC_ACCEPTED_KEYS_ENV];
229
- if (raw === void 0 || raw === "") return void 0;
230
- let parsed;
231
- try {
232
- parsed = JSON.parse(raw);
233
- } catch {
234
- return [];
235
- }
236
- return Array.isArray(parsed) && parsed.every((key) => typeof key === "string") ? parsed : [];
237
- }
238
- /**
239
- * Length-independent constant-time string equality — no early exit on the
240
- * first mismatched character or on a length difference, so a caller cannot
241
- * time its way toward a valid key. No `node:crypto`, to keep this module
242
- * runtime-agnostic.
243
- */
244
- function constantTimeEquals(a, b) {
245
- const length = Math.max(a.length, b.length);
246
- let diff = a.length ^ b.length;
247
- for (let i = 0; i < length; i++) diff |= (i < a.length ? a.charCodeAt(i) : 0) ^ (i < b.length ? b.charCodeAt(i) : 0);
248
- return diff === 0;
249
- }
250
- /** Whether `presented` is a member of `accepted` — always compares against every key. */
251
- function isAcceptedKey(presented, accepted) {
252
- let matched = false;
253
- for (const key of accepted) matched = constantTimeEquals(presented, key) || matched;
254
- return matched;
255
- }
256
- const BEARER_PREFIX = "Bearer ";
257
- /** The bearer token on `Authorization`, or `''` if the header is missing or malformed. */
258
- function bearerToken(req) {
259
- const header = req.headers.get("authorization");
260
- return header?.startsWith(BEARER_PREFIX) ? header.slice(7) : "";
261
- }
262
- const IDEMPOTENCY_KEY_HEADER = "Idempotency-Key";
263
- /**
264
- * Flattens every exposed port's methods into one method → {schemas, handler}
265
- * table. RPC dispatch is flat (`/rpc/<method>`), so a method name exposed by
266
- * more than one port is a construction-time error, as is a missing handler.
267
- */
268
- function methodTable(expose, handlers) {
269
- const table = /* @__PURE__ */ new Map();
270
- for (const [port, contract] of Object.entries(expose)) {
271
- const portHandlers = handlers[port] ?? {};
272
- for (const [method, fn] of Object.entries(contract.__cmp)) {
273
- if (table.has(method)) throw new Error(`serve(): method "${method}" is exposed by more than one port — RPC dispatch is flat (POST /rpc/<method>), so method names must be unique across a service's exposed ports.`);
274
- const handler = portHandlers[method];
275
- if (handler === void 0) throw new Error(`serve(): no handler supplied for exposed method "${port}.${method}".`);
276
- const { input, output } = blindCast(fn);
277
- table.set(method, {
278
- input,
279
- output,
280
- handler
281
- });
282
- }
283
- }
284
- return table;
285
- }
286
- /**
287
- * Routes `POST /rpc/<method>`: checks the service key, requires an
288
- * Idempotency-Key, single-flights/replays through `IdempotencyStore`, and —
289
- * per call — parses JSON within the body cap, validates input, calls the
290
- * handler with `service.load()`'s deps plus `{ idempotencyKey }`, validates
291
- * the output, and responds JSON. A handler or output-validation failure
292
- * masks its message behind a generic 500 and logs the real error; an
293
- * unknown method or invalid input is a 4xx. `load()` is called exactly
294
- * once, here, before the handler ever runs.
295
- */
296
- function serve(service, handlers) {
297
- const table = methodTable(service.expose ?? {}, blindCast(handlers));
298
- const deps = service.load();
299
- const idempotency = new IdempotencyStore();
300
- return async (req) => {
301
- const accepted = acceptedKeys();
302
- if (accepted !== void 0 && !isAcceptedKey(bearerToken(req), accepted)) return toResponse(outcome({ error: "Unauthorized: missing or invalid service key" }, 401));
303
- const { pathname } = new URL(req.url);
304
- const methodName = /^\/rpc\/([^/]+)$/.exec(pathname)?.[1];
305
- if (methodName === void 0) return toResponse(outcome({ error: `Not found: ${pathname}` }, 404));
306
- const method = table.get(methodName);
307
- if (method === void 0) return toResponse(outcome({ error: `Unknown RPC method "${methodName}"` }, 404));
308
- if (req.method !== "POST") return toResponse(outcome({ error: `Method "${methodName}" requires POST` }, 405));
309
- const idempotencyKey = req.headers.get(IDEMPOTENCY_KEY_HEADER.toLowerCase()) || void 0;
310
- const ctx = { idempotencyKey };
311
- const run = async () => {
312
- let bodyText;
313
- try {
314
- bodyText = await readBoundedBody(req, MAX_BODY_BYTES);
315
- } catch (err) {
316
- if (err instanceof RequestBodyTooLargeError) return outcome({ error: `Request body exceeds the ${MAX_BODY_BYTES}-byte limit` }, 413);
317
- console.error(`serve(): reading the request body for "${methodName}" failed:`, err);
318
- return outcome({ error: INTERNAL_ERROR_MESSAGE }, 500);
319
- }
320
- let body;
321
- try {
322
- body = JSON.parse(bodyText);
323
- } catch {
324
- return outcome({ error: "Request body must be JSON" }, 400);
325
- }
326
- let input;
327
- try {
328
- input = await standardValidate(method.input, body);
329
- } catch (err) {
330
- return outcome({ error: err instanceof Error ? err.message : String(err) }, 400);
331
- }
332
- try {
333
- const result = await method.handler(input, deps, ctx);
334
- let output;
335
- try {
336
- output = await standardValidate(method.output, result);
337
- } catch (err) {
338
- console.error(`serve(): handler for "${methodName}" returned output that failed schema validation — this is a provider bug:`, err);
339
- return outcome({ error: INTERNAL_ERROR_MESSAGE }, 500);
340
- }
341
- return outcome(output);
342
- } catch (err) {
343
- console.error(`serve(): handler for "${methodName}" threw:`, err);
344
- return outcome({ error: INTERNAL_ERROR_MESSAGE }, 500);
345
- }
346
- };
347
- return toResponse(idempotencyKey === void 0 ? await run() : await idempotency.dispatch(methodName, idempotencyKey, run));
348
- };
349
- }
350
- //#endregion
351
- export { RPC_ACCEPTED_KEYS_ENV, RPC_PEER_KEY, contract, makeClient, perBindingToken, rpc, serve };
352
-
353
- //# sourceMappingURL=service-rpc.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"service-rpc.mjs","names":[],"sources":["../../../0-framework/2-authoring/service-rpc/dist/index.mjs"],"sourcesContent":["import { blindCast } from \"@internal/foundation/casts\";\nimport { dependency, provisionNeed, string } from \"@internal/core\";\n//#region src/client.ts\n/** Bounded jittered backoff for retrying a dropped call. `maxRetries` is retries after the first attempt. */\nconst RETRY = {\n\tinitialDelayMs: 250,\n\tmultiplier: 2,\n\tmaxDelayMs: 5e3,\n\tmaxRetries: 5\n};\nconst IDEMPOTENCY_KEY_HEADER$1 = \"Idempotency-Key\";\nfunction sleep(ms) {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n/** Whether a non-OK response is safe to retry: 429 or any 5xx, never another 4xx. */\nfunction isRetryableStatus(status) {\n\treturn status === 429 || status >= 500;\n}\n/** The server's `{ error }` body, if the response has one — undefined otherwise. */\nasync function errorDetail(res) {\n\ttry {\n\t\tconst body = await res.json();\n\t\treturn typeof body === \"object\" && body !== null && \"error\" in body ? String(body.error) : void 0;\n\t} catch {\n\t\treturn;\n\t}\n}\n/** `<base>/rpc/<method>`, preserving a base URL's own path (e.g. a mount point). */\nfunction methodUrl(base, method) {\n\tconst normalizedBase = base.endsWith(\"/\") ? base : `${base}/`;\n\treturn new URL(`rpc/${method}`, normalizedBase).toString();\n}\n/**\n* Sends one call over `send`, retrying a thrown error, 429, or 5xx with\n* full-jitter backoff. `buildRequest` runs per attempt but carries the same\n* idempotency key each time — only the transport call repeats, not the key.\n*/\nasync function callWithRetry(send, buildRequest, method) {\n\tlet delay = RETRY.initialDelayMs;\n\tlet retries = 0;\n\tfor (;;) {\n\t\tlet res;\n\t\ttry {\n\t\t\tres = await send(buildRequest());\n\t\t} catch (err) {\n\t\t\tif (retries >= RETRY.maxRetries) throw err;\n\t\t\tretries += 1;\n\t\t\tawait sleep(Math.random() * delay);\n\t\t\tdelay = Math.min(delay * RETRY.multiplier, RETRY.maxDelayMs);\n\t\t\tcontinue;\n\t\t}\n\t\tif (res.ok) return res.json();\n\t\tif (!isRetryableStatus(res.status) || retries >= RETRY.maxRetries) {\n\t\t\tconst detail = await errorDetail(res);\n\t\t\tthrow new Error(`RPC call \"${method}\" failed: ${res.status} ${res.statusText}` + (detail !== void 0 ? ` — ${detail}` : \"\"));\n\t\t}\n\t\tretries += 1;\n\t\tawait sleep(Math.random() * delay);\n\t\tdelay = Math.min(delay * RETRY.multiplier, RETRY.maxDelayMs);\n\t}\n}\nfunction makeClient(contract, url, opts) {\n\tconst send = opts?.fetch ?? fetch;\n\tconst baseHeaders = { \"content-type\": \"application/json\" };\n\tif (opts?.serviceKey !== void 0) baseHeaders[\"Authorization\"] = `Bearer ${opts.serviceKey}`;\n\tconst client = {};\n\tfor (const method of Object.keys(contract.__cmp)) client[method] = async (input) => {\n\t\tconst idempotencyKey = crypto.randomUUID();\n\t\tconst body = JSON.stringify(input);\n\t\treturn callWithRetry(send, () => new Request(methodUrl(url, method), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t...baseHeaders,\n\t\t\t\t[IDEMPOTENCY_KEY_HEADER$1]: idempotencyKey\n\t\t\t},\n\t\t\tbody\n\t\t}), method);\n\t};\n\treturn blindCast(client);\n}\n//#endregion\n//#region src/contract.ts\nfunction contract(fns) {\n\tconst value = {\n\t\tkind: \"rpc\",\n\t\t__cmp: fns,\n\t\tsatisfies: (required) => value === required\n\t};\n\treturn Object.freeze(value);\n}\n//#endregion\n//#region src/rpc.ts\n/** ADR-0031's need brand for RPC's per-binding service key — the target registers a provisioner under this. */\nconst RPC_PEER_KEY = Symbol.for(\"prisma:rpc/per-binding-key\");\n/** The provisioning need `rpc()`'s `serviceKey` param declares (ADR-0030): a shared, unguessable value the target mints per consumer edge. */\nconst perBindingToken = () => provisionNeed(RPC_PEER_KEY);\nfunction rpc(arg) {\n\tif (!isRpcContract(arg)) return arg;\n\treturn dependency({\n\t\ttype: \"rpc\",\n\t\tconnection: {\n\t\t\tparams: {\n\t\t\t\turl: string(),\n\t\t\t\tserviceKey: string({\n\t\t\t\t\toptional: true,\n\t\t\t\t\tprovision: perBindingToken()\n\t\t\t\t})\n\t\t\t},\n\t\t\thydrate: ({ url, serviceKey }) => makeClient(arg, url, { serviceKey })\n\t\t},\n\t\trequired: arg\n\t});\n}\nfunction isRpcContract(value) {\n\treturn typeof value === \"object\" && value !== null && \"kind\" in value && value.kind === \"rpc\" && \"__cmp\" in value && \"satisfies\" in value;\n}\n//#endregion\n//#region src/standard-schema.ts\nasync function standardValidate(schema, value) {\n\tconst result = await schema[\"~standard\"].validate(value);\n\tif (result.issues !== void 0) throw new Error(`Schema validation failed: ${result.issues.map((issue) => issue.message).join(\"; \")}`);\n\treturn result.value;\n}\n//#endregion\n//#region src/serve.ts\n/** The reserved env var the target (slice 2) writes the accepted key set to. */\nconst RPC_ACCEPTED_KEYS_ENV = \"COMPOSER_RPC_ACCEPTED_KEYS\";\nfunction outcome(body, status = 200) {\n\treturn {\n\t\tstatus,\n\t\tbodyText: JSON.stringify(body)\n\t};\n}\nfunction toResponse(o) {\n\treturn new Response(o.bodyText, {\n\t\tstatus: o.status,\n\t\theaders: { \"content-type\": \"application/json\" }\n\t});\n}\n/** The generic message every caller-facing 500 carries — the real error goes to `console.error` instead. */\nconst INTERNAL_ERROR_MESSAGE = \"Internal server error\";\n/** Request body cap. Internal RPC payloads are small records, not uploads; 1 MiB bounds a slow request's memory. */\nconst MAX_BODY_BYTES = 1048576;\nvar RequestBodyTooLargeError = class extends Error {};\n/** Reads the body as text, aborting past `maxBytes` of bytes actually read — `content-length` is caller-supplied, so untrusted. */\nasync function readBoundedBody(req, maxBytes) {\n\tconst reader = req.body?.getReader();\n\tif (reader === void 0) return \"\";\n\tconst decoder = new TextDecoder();\n\tlet text = \"\";\n\tlet total = 0;\n\tfor (;;) {\n\t\tconst { done, value } = await reader.read();\n\t\tif (done) break;\n\t\ttotal += value.byteLength;\n\t\tif (total > maxBytes) {\n\t\t\tawait reader.cancel();\n\t\t\tthrow new RequestBodyTooLargeError();\n\t\t}\n\t\ttext += decoder.decode(value, { stream: true });\n\t}\n\ttext += decoder.decode();\n\treturn text;\n}\n/** How long a completed 2xx/4xx answer stays replayable for a repeated key. */\nconst REPLAY_TTL_MS = 6e4;\n/**\n* Per-method, per-key deduplication. A duplicate arriving mid-execution\n* single-flights onto the same promise; a completed 2xx/4xx replays for\n* REPLAY_TTL_MS; a 5xx is never kept, since that is what a retry re-executes.\n* Keyed by method first, so a replay can never answer a different method.\n*/\nvar IdempotencyStore = class {\n\tbyMethod = /* @__PURE__ */ new Map();\n\tlru = /* @__PURE__ */ new Set();\n\tasync dispatch(method, key, run) {\n\t\tconst bucket = this.bucketFor(method);\n\t\tconst existing = bucket.get(key);\n\t\tif (existing?.kind === \"pending\") return existing.promise;\n\t\tif (existing?.kind === \"completed\") {\n\t\t\tif (Date.now() - existing.completedAt < REPLAY_TTL_MS) {\n\t\t\t\tthis.lru.delete(existing);\n\t\t\t\tthis.lru.add(existing);\n\t\t\t\treturn existing.outcome;\n\t\t\t}\n\t\t\tbucket.delete(key);\n\t\t\tthis.lru.delete(existing);\n\t\t}\n\t\tconst promise = run();\n\t\tbucket.set(key, {\n\t\t\tkind: \"pending\",\n\t\t\tpromise\n\t\t});\n\t\tlet result;\n\t\ttry {\n\t\t\tresult = await promise;\n\t\t} catch (err) {\n\t\t\tbucket.delete(key);\n\t\t\tthrow err;\n\t\t}\n\t\tif (result.status >= 500) bucket.delete(key);\n\t\telse {\n\t\t\tconst entry = {\n\t\t\t\tkind: \"completed\",\n\t\t\t\toutcome: result,\n\t\t\t\tcompletedAt: Date.now(),\n\t\t\t\tmethod,\n\t\t\t\tkey\n\t\t\t};\n\t\t\tbucket.set(key, entry);\n\t\t\tthis.lru.add(entry);\n\t\t\tthis.evictOverflow();\n\t\t}\n\t\treturn result;\n\t}\n\tbucketFor(method) {\n\t\tlet bucket = this.byMethod.get(method);\n\t\tif (bucket === void 0) {\n\t\t\tbucket = /* @__PURE__ */ new Map();\n\t\t\tthis.byMethod.set(method, bucket);\n\t\t}\n\t\treturn bucket;\n\t}\n\tevictOverflow() {\n\t\tif (this.lru.size <= 1e3) return;\n\t\tconst oldest = this.lru.values().next().value;\n\t\tif (oldest !== void 0) {\n\t\t\tthis.lru.delete(oldest);\n\t\t\tthis.byMethod.get(oldest.method)?.delete(oldest.key);\n\t\t}\n\t}\n};\n/** The provisioned accepted key set, or undefined when the deploy never provisioned one (local/test — enforcement off). */\nfunction acceptedKeys() {\n\tconst raw = process.env[RPC_ACCEPTED_KEYS_ENV];\n\tif (raw === void 0 || raw === \"\") return void 0;\n\tlet parsed;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch {\n\t\treturn [];\n\t}\n\treturn Array.isArray(parsed) && parsed.every((key) => typeof key === \"string\") ? parsed : [];\n}\n/**\n* Length-independent constant-time string equality — no early exit on the\n* first mismatched character or on a length difference, so a caller cannot\n* time its way toward a valid key. No `node:crypto`, to keep this module\n* runtime-agnostic.\n*/\nfunction constantTimeEquals(a, b) {\n\tconst length = Math.max(a.length, b.length);\n\tlet diff = a.length ^ b.length;\n\tfor (let i = 0; i < length; i++) diff |= (i < a.length ? a.charCodeAt(i) : 0) ^ (i < b.length ? b.charCodeAt(i) : 0);\n\treturn diff === 0;\n}\n/** Whether `presented` is a member of `accepted` — always compares against every key. */\nfunction isAcceptedKey(presented, accepted) {\n\tlet matched = false;\n\tfor (const key of accepted) matched = constantTimeEquals(presented, key) || matched;\n\treturn matched;\n}\nconst BEARER_PREFIX = \"Bearer \";\n/** The bearer token on `Authorization`, or `''` if the header is missing or malformed. */\nfunction bearerToken(req) {\n\tconst header = req.headers.get(\"authorization\");\n\treturn header?.startsWith(BEARER_PREFIX) ? header.slice(7) : \"\";\n}\nconst IDEMPOTENCY_KEY_HEADER = \"Idempotency-Key\";\n/**\n* Flattens every exposed port's methods into one method → {schemas, handler}\n* table. RPC dispatch is flat (`/rpc/<method>`), so a method name exposed by\n* more than one port is a construction-time error, as is a missing handler.\n*/\nfunction methodTable(expose, handlers) {\n\tconst table = /* @__PURE__ */ new Map();\n\tfor (const [port, contract] of Object.entries(expose)) {\n\t\tconst portHandlers = handlers[port] ?? {};\n\t\tfor (const [method, fn] of Object.entries(contract.__cmp)) {\n\t\t\tif (table.has(method)) throw new Error(`serve(): method \"${method}\" is exposed by more than one port — RPC dispatch is flat (POST /rpc/<method>), so method names must be unique across a service's exposed ports.`);\n\t\t\tconst handler = portHandlers[method];\n\t\t\tif (handler === void 0) throw new Error(`serve(): no handler supplied for exposed method \"${port}.${method}\".`);\n\t\t\tconst { input, output } = blindCast(fn);\n\t\t\ttable.set(method, {\n\t\t\t\tinput,\n\t\t\t\toutput,\n\t\t\t\thandler\n\t\t\t});\n\t\t}\n\t}\n\treturn table;\n}\n/**\n* Routes `POST /rpc/<method>`: checks the service key, requires an\n* Idempotency-Key, single-flights/replays through `IdempotencyStore`, and —\n* per call — parses JSON within the body cap, validates input, calls the\n* handler with `service.load()`'s deps plus `{ idempotencyKey }`, validates\n* the output, and responds JSON. A handler or output-validation failure\n* masks its message behind a generic 500 and logs the real error; an\n* unknown method or invalid input is a 4xx. `load()` is called exactly\n* once, here, before the handler ever runs.\n*/\nfunction serve(service, handlers) {\n\tconst table = methodTable(service.expose ?? {}, blindCast(handlers));\n\tconst deps = service.load();\n\tconst idempotency = new IdempotencyStore();\n\treturn async (req) => {\n\t\tconst accepted = acceptedKeys();\n\t\tif (accepted !== void 0 && !isAcceptedKey(bearerToken(req), accepted)) return toResponse(outcome({ error: \"Unauthorized: missing or invalid service key\" }, 401));\n\t\tconst { pathname } = new URL(req.url);\n\t\tconst methodName = /^\\/rpc\\/([^/]+)$/.exec(pathname)?.[1];\n\t\tif (methodName === void 0) return toResponse(outcome({ error: `Not found: ${pathname}` }, 404));\n\t\tconst method = table.get(methodName);\n\t\tif (method === void 0) return toResponse(outcome({ error: `Unknown RPC method \"${methodName}\"` }, 404));\n\t\tif (req.method !== \"POST\") return toResponse(outcome({ error: `Method \"${methodName}\" requires POST` }, 405));\n\t\tconst idempotencyKey = req.headers.get(IDEMPOTENCY_KEY_HEADER.toLowerCase()) || void 0;\n\t\tconst ctx = { idempotencyKey };\n\t\tconst run = async () => {\n\t\t\tlet bodyText;\n\t\t\ttry {\n\t\t\t\tbodyText = await readBoundedBody(req, MAX_BODY_BYTES);\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof RequestBodyTooLargeError) return outcome({ error: `Request body exceeds the ${MAX_BODY_BYTES}-byte limit` }, 413);\n\t\t\t\tconsole.error(`serve(): reading the request body for \"${methodName}\" failed:`, err);\n\t\t\t\treturn outcome({ error: INTERNAL_ERROR_MESSAGE }, 500);\n\t\t\t}\n\t\t\tlet body;\n\t\t\ttry {\n\t\t\t\tbody = JSON.parse(bodyText);\n\t\t\t} catch {\n\t\t\t\treturn outcome({ error: \"Request body must be JSON\" }, 400);\n\t\t\t}\n\t\t\tlet input;\n\t\t\ttry {\n\t\t\t\tinput = await standardValidate(method.input, body);\n\t\t\t} catch (err) {\n\t\t\t\treturn outcome({ error: err instanceof Error ? err.message : String(err) }, 400);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst result = await method.handler(input, deps, ctx);\n\t\t\t\tlet output;\n\t\t\t\ttry {\n\t\t\t\t\toutput = await standardValidate(method.output, result);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(`serve(): handler for \"${methodName}\" returned output that failed schema validation — this is a provider bug:`, err);\n\t\t\t\t\treturn outcome({ error: INTERNAL_ERROR_MESSAGE }, 500);\n\t\t\t\t}\n\t\t\t\treturn outcome(output);\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(`serve(): handler for \"${methodName}\" threw:`, err);\n\t\t\t\treturn outcome({ error: INTERNAL_ERROR_MESSAGE }, 500);\n\t\t\t}\n\t\t};\n\t\treturn toResponse(idempotencyKey === void 0 ? await run() : await idempotency.dispatch(methodName, idempotencyKey, run));\n\t};\n}\n//#endregion\nexport { RPC_ACCEPTED_KEYS_ENV, RPC_PEER_KEY, contract, makeClient, perBindingToken, rpc, serve };\n\n//# sourceMappingURL=index.mjs.map"],"mappings":"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"}