@hediet/linkrpc 0.0.1 → 0.0.2
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/README.md +59 -0
- package/dist/chunks/{boundedTrafficSubscription-1L592xc7.js → boundedTrafficSubscription-XZ1KwXZC.js} +267 -6
- package/dist/chunks/boundedTrafficSubscription-XZ1KwXZC.js.map +1 -0
- package/dist/chunks/{hub.interfaces-BzWfsVT2.js → hub.interfaces-Bf4VfWNX.js} +2 -2
- package/dist/chunks/{hub.interfaces-BzWfsVT2.js.map → hub.interfaces-Bf4VfWNX.js.map} +1 -1
- package/dist/chunks/{hubAccess-DwTZPiI8.d.ts → hubAccess-C06qAKao.d.ts} +2 -2
- package/dist/chunks/{hubAccess-DwTZPiI8.d.ts.map → hubAccess-C06qAKao.d.ts.map} +1 -1
- package/dist/chunks/{hubFacade-CQflVkVC.js → hubFacade-BIB9CoAv.js} +2 -2
- package/dist/chunks/{hubFacade-CQflVkVC.js.map → hubFacade-BIB9CoAv.js.map} +1 -1
- package/dist/chunks/{hubFacade-Dkgw2pTi.d.ts → hubFacade-DtQpGpUy.d.ts} +2 -2
- package/dist/chunks/{hubFacade-Dkgw2pTi.d.ts.map → hubFacade-DtQpGpUy.d.ts.map} +1 -1
- package/dist/chunks/{linkRpcConnection-CtlQmetO.d.ts → linkRpcConnection-BadD37ok.d.ts} +125 -37
- package/dist/chunks/linkRpcConnection-BadD37ok.d.ts.map +1 -0
- package/dist/chunks/{src-D3NUIwyo.js → src-CAhXne71.js} +160 -198
- package/dist/chunks/src-CAhXne71.js.map +1 -0
- package/dist/hub/client/index.d.ts +3 -3
- package/dist/hub/client/index.js +3 -3
- package/dist/hub/common/index.d.ts +14 -14
- package/dist/hub/common/index.js +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/inspection/index.d.ts +1 -1
- package/dist/inspection/index.js +1 -1
- package/dist/node.d.ts +3 -3
- package/dist/node.js +4 -4
- package/dist/web.d.ts +2 -2
- package/dist/web.js +3 -3
- package/package.json +1 -1
- package/dist/chunks/boundedTrafficSubscription-1L592xc7.js.map +0 -1
- package/dist/chunks/linkRpcConnection-CtlQmetO.d.ts.map +0 -1
- package/dist/chunks/src-D3NUIwyo.js.map +0 -1
|
@@ -3,10 +3,9 @@
|
|
|
3
3
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
import { t as __exportAll } from "./rolldown-runtime-4LSo1kEK.js";
|
|
6
|
-
import {
|
|
6
|
+
import { B as requestType, C as defineInterface, F as NotificationType, I as RequestType, M as sha256$1, N as jcsCanonicalize, P as jcsCanonicalizeBytes, R as isApplicationErrorValue, V as zodToSvcJsonSchema, a as topologyInterface, i as nodeInterface, o as trafficInterface, r as TrafficWatchFlowTracker, t as BoundedTrafficSubscription, z as notificationType } from "./boundedTrafficSubscription-XZ1KwXZC.js";
|
|
7
7
|
import { array, boolean, enum as enum$1, int, nonnegative, number, object, optional, positive, string, union, unknown } from "zod/mini";
|
|
8
8
|
import { safeParse } from "zod/v4/core";
|
|
9
|
-
import { z } from "zod";
|
|
10
9
|
//#region src/schema/assignability.ts
|
|
11
10
|
/**
|
|
12
11
|
* Structural subtype check: returns `true` iff every JSON value matching
|
|
@@ -19,6 +18,10 @@ import { z } from "zod";
|
|
|
19
18
|
function isAssignable(sub, sup, components = {}) {
|
|
20
19
|
return _check(sub, sup, components, /* @__PURE__ */ new Set());
|
|
21
20
|
}
|
|
21
|
+
/** Match one JSON value against the structural LinkRPC subset without transforming it. */
|
|
22
|
+
function matchesJsonSchema(value, schema, components = {}) {
|
|
23
|
+
return _matches(value, schema, components, /* @__PURE__ */ new Set());
|
|
24
|
+
}
|
|
22
25
|
function _check(sub, sup, c, seen) {
|
|
23
26
|
if (sup === true) return true;
|
|
24
27
|
if (sub === false) return true;
|
|
@@ -119,8 +122,9 @@ function _matches(v, sup, c, seen) {
|
|
|
119
122
|
if (sup === true) return true;
|
|
120
123
|
if (sup === false) return false;
|
|
121
124
|
if (_isRef(sup)) {
|
|
125
|
+
if (seen.has(sup.$ref)) return false;
|
|
122
126
|
const r = _resolveRef(sup, c);
|
|
123
|
-
return r ? _matches(v, r, c, seen) : false;
|
|
127
|
+
return r ? _matches(v, r, c, new Set(seen).add(sup.$ref)) : false;
|
|
124
128
|
}
|
|
125
129
|
if (_isUnion(sup)) return _branches(sup).some((b) => _matches(v, b, c, seen));
|
|
126
130
|
if (_isConst(sup)) return _jsonEq(v, sup.const);
|
|
@@ -131,12 +135,12 @@ function _matches(v, sup, c, seen) {
|
|
|
131
135
|
case "number": return typeof v === "number";
|
|
132
136
|
case "integer": return typeof v === "number" && Number.isInteger(v);
|
|
133
137
|
case "string": return typeof v === "string";
|
|
134
|
-
case "array": return Array.isArray(v) && _matchesArray(v, sup, c
|
|
135
|
-
case "object": return v !== null && typeof v === "object" && !Array.isArray(v) && _matchesObject(v, sup, c
|
|
138
|
+
case "array": return Array.isArray(v) && _matchesArray(v, sup, c);
|
|
139
|
+
case "object": return v !== null && typeof v === "object" && !Array.isArray(v) && _matchesObject(v, sup, c);
|
|
136
140
|
default: return false;
|
|
137
141
|
}
|
|
138
142
|
}
|
|
139
|
-
function _matchesArray(v, sup, c
|
|
143
|
+
function _matchesArray(v, sup, c) {
|
|
140
144
|
const prefix = sup.prefixItems ?? [];
|
|
141
145
|
const rest = _restOf(sup);
|
|
142
146
|
if (rest === false && v.length !== prefix.length) {
|
|
@@ -145,16 +149,16 @@ function _matchesArray(v, sup, c, seen) {
|
|
|
145
149
|
for (let i = 0; i < v.length; i++) {
|
|
146
150
|
const s = prefix[i] ?? (rest === false ? false : rest);
|
|
147
151
|
if (s === false) return false;
|
|
148
|
-
if (!_matches(v[i], s, c,
|
|
152
|
+
if (!_matches(v[i], s, c, /* @__PURE__ */ new Set())) return false;
|
|
149
153
|
}
|
|
150
154
|
return true;
|
|
151
155
|
}
|
|
152
|
-
function _matchesObject(v, sup, c
|
|
153
|
-
for (const k of sup.required ?? []) if (!(k
|
|
156
|
+
function _matchesObject(v, sup, c) {
|
|
157
|
+
for (const k of sup.required ?? []) if (!Object.hasOwn(v, k)) return false;
|
|
154
158
|
for (const [k, val] of Object.entries(v)) {
|
|
155
|
-
const s = sup.properties[k]
|
|
159
|
+
const s = Object.hasOwn(sup.properties, k) ? sup.properties[k] : sup.additionalProperties;
|
|
156
160
|
if (s === false) return false;
|
|
157
|
-
if (!_matches(val, s, c,
|
|
161
|
+
if (!_matches(val, s, c, /* @__PURE__ */ new Set())) return false;
|
|
158
162
|
}
|
|
159
163
|
return true;
|
|
160
164
|
}
|
|
@@ -218,59 +222,6 @@ function _jsonEq(a, b) {
|
|
|
218
222
|
return false;
|
|
219
223
|
}
|
|
220
224
|
//#endregion
|
|
221
|
-
//#region src/schema/assertSchemaReferences.ts
|
|
222
|
-
const componentPrefix = "#/components/schemas/";
|
|
223
|
-
function componentSchemaRef(name) {
|
|
224
|
-
return componentPrefix + name.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
225
|
-
}
|
|
226
|
-
function componentSchemaName(ref) {
|
|
227
|
-
if (!ref.startsWith(componentPrefix)) throw new Error(`Invalid component reference: ${ref}`);
|
|
228
|
-
const token = ref.slice(21);
|
|
229
|
-
if (token.includes("/") || /~(?:[^01]|$)/.test(token)) throw new Error(`Invalid component reference token: ${ref}`);
|
|
230
|
-
return token.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
231
|
-
}
|
|
232
|
-
/**
|
|
233
|
-
* Check the finite schema graph without interpreting JSON literal payloads.
|
|
234
|
-
* A reference/union-only cycle is invalid; descending into an object member
|
|
235
|
-
* or an array item guards a cycle, but does not imply the schema is nonempty.
|
|
236
|
-
*/
|
|
237
|
-
function assertSchemaReferences(roots, components = {}) {
|
|
238
|
-
const nodes = /* @__PURE__ */ new Set();
|
|
239
|
-
const pending = [...roots, ...Object.values(components)];
|
|
240
|
-
const unguarded = /* @__PURE__ */ new Map();
|
|
241
|
-
while (pending.length > 0) {
|
|
242
|
-
const node = pending.pop();
|
|
243
|
-
if (typeof node === "boolean" || nodes.has(node)) continue;
|
|
244
|
-
nodes.add(node);
|
|
245
|
-
const edges = [];
|
|
246
|
-
if ("$ref" in node) {
|
|
247
|
-
const name = componentSchemaName(node.$ref);
|
|
248
|
-
if (!Object.hasOwn(components, name)) throw new Error(`Unresolved component reference: ${node.$ref}`);
|
|
249
|
-
edges.push(components[name]);
|
|
250
|
-
}
|
|
251
|
-
if ("anyOf" in node) edges.push(...node.anyOf);
|
|
252
|
-
if ("oneOf" in node) edges.push(...node.oneOf);
|
|
253
|
-
unguarded.set(node, edges);
|
|
254
|
-
pending.push(...edges);
|
|
255
|
-
if ("type" in node && node.type === "object") pending.push(...Object.values(node.properties ?? {}), node.additionalProperties);
|
|
256
|
-
if ("type" in node && node.type === "array") {
|
|
257
|
-
if ("prefixItems" in node) pending.push(...node.prefixItems);
|
|
258
|
-
if (node.items !== void 0) pending.push(node.items);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
const visiting = /* @__PURE__ */ new Set();
|
|
262
|
-
const checked = /* @__PURE__ */ new Set();
|
|
263
|
-
const visit = (node) => {
|
|
264
|
-
if (typeof node === "boolean" || checked.has(node)) return;
|
|
265
|
-
if (visiting.has(node)) throw new Error("Unguarded recursive schema: cycle does not descend into a child value");
|
|
266
|
-
visiting.add(node);
|
|
267
|
-
for (const child of unguarded.get(node) ?? []) visit(child);
|
|
268
|
-
visiting.delete(node);
|
|
269
|
-
checked.add(node);
|
|
270
|
-
};
|
|
271
|
-
for (const node of nodes) visit(node);
|
|
272
|
-
}
|
|
273
|
-
//#endregion
|
|
274
225
|
//#region src/schema/materializeJsonSchema.ts
|
|
275
226
|
/**
|
|
276
227
|
* Export a LinkRPC schema and its components as standalone JSON Schema
|
|
@@ -357,128 +308,6 @@ function isRecord(value) {
|
|
|
357
308
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
358
309
|
}
|
|
359
310
|
//#endregion
|
|
360
|
-
//#region src/schema/schemaToZod.ts
|
|
361
|
-
/**
|
|
362
|
-
* Create a recursive LinkRPC-schema validator materializer. Component
|
|
363
|
-
* references are lazy, so self and mutual recursion remain guarded.
|
|
364
|
-
*/
|
|
365
|
-
function createSchemaToZod(components = {}) {
|
|
366
|
-
assertSchemaReferences([], components);
|
|
367
|
-
const refs = /* @__PURE__ */ new Map();
|
|
368
|
-
const component = (name) => {
|
|
369
|
-
const existing = refs.get(name);
|
|
370
|
-
if (existing !== void 0) return existing;
|
|
371
|
-
const source = components[name];
|
|
372
|
-
if (source === void 0) throw new Error(`schemaToZod: dangling component reference "${name}"`);
|
|
373
|
-
const lazy = z.lazy(() => compile(source));
|
|
374
|
-
refs.set(name, lazy);
|
|
375
|
-
return lazy;
|
|
376
|
-
};
|
|
377
|
-
const compile = (schema) => {
|
|
378
|
-
if (schema === true) return z.unknown();
|
|
379
|
-
if (schema === false) return z.never();
|
|
380
|
-
const raw = schema;
|
|
381
|
-
if (Array.isArray(raw.type)) return union$1(raw.type.map((type) => compile({
|
|
382
|
-
...raw,
|
|
383
|
-
type
|
|
384
|
-
})));
|
|
385
|
-
let base;
|
|
386
|
-
if ("$ref" in schema) base = component(componentSchemaName(schema.$ref));
|
|
387
|
-
else if ("const" in schema) base = valueSchema(schema.const);
|
|
388
|
-
else if ("enum" in schema) base = union$1(schema.enum.map(valueSchema));
|
|
389
|
-
else if ("anyOf" in schema) base = union$1(schema.anyOf.map(compile));
|
|
390
|
-
else if ("oneOf" in schema) base = union$1(schema.oneOf.map(compile));
|
|
391
|
-
else if (isAnnotationOnlySchema(raw)) base = z.unknown();
|
|
392
|
-
else switch (schema.type) {
|
|
393
|
-
case "null":
|
|
394
|
-
base = z.null();
|
|
395
|
-
break;
|
|
396
|
-
case "boolean":
|
|
397
|
-
base = z.boolean();
|
|
398
|
-
break;
|
|
399
|
-
case "string":
|
|
400
|
-
base = stringSchema(schema.format);
|
|
401
|
-
break;
|
|
402
|
-
case "integer":
|
|
403
|
-
base = z.number().int();
|
|
404
|
-
break;
|
|
405
|
-
case "number":
|
|
406
|
-
base = z.number();
|
|
407
|
-
break;
|
|
408
|
-
case "array":
|
|
409
|
-
if ("prefixItems" in schema) {
|
|
410
|
-
const tuple = z.tuple(schema.prefixItems.map(compile));
|
|
411
|
-
base = schema.items !== void 0 && schema.items !== false ? tuple.rest(compile(schema.items)) : tuple;
|
|
412
|
-
} else base = z.array(compile(schema.items));
|
|
413
|
-
break;
|
|
414
|
-
case "object": {
|
|
415
|
-
const required = new Set(schema.required ?? []);
|
|
416
|
-
const shape = {};
|
|
417
|
-
for (const [name, property] of Object.entries(schema.properties)) {
|
|
418
|
-
const validator = compile(property);
|
|
419
|
-
shape[name] = required.has(name) ? validator : validator.optional();
|
|
420
|
-
}
|
|
421
|
-
const object = z.object(shape);
|
|
422
|
-
if (schema.additionalProperties === false) base = object.strict();
|
|
423
|
-
else if (schema.additionalProperties === true) base = object.loose();
|
|
424
|
-
else base = object.catchall(compile(schema.additionalProperties));
|
|
425
|
-
break;
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
return base;
|
|
429
|
-
};
|
|
430
|
-
return { toZod(schema) {
|
|
431
|
-
assertSchemaReferences([schema], components);
|
|
432
|
-
return compile(schema);
|
|
433
|
-
} };
|
|
434
|
-
}
|
|
435
|
-
function isAnnotationOnlySchema(schema) {
|
|
436
|
-
return ![
|
|
437
|
-
"$ref",
|
|
438
|
-
"const",
|
|
439
|
-
"enum",
|
|
440
|
-
"anyOf",
|
|
441
|
-
"oneOf",
|
|
442
|
-
"type",
|
|
443
|
-
"properties",
|
|
444
|
-
"items",
|
|
445
|
-
"prefixItems",
|
|
446
|
-
"additionalProperties"
|
|
447
|
-
].some((key) => Object.hasOwn(schema, key));
|
|
448
|
-
}
|
|
449
|
-
function schemaToZod(schema, components = {}) {
|
|
450
|
-
return createSchemaToZod(components).toZod(schema);
|
|
451
|
-
}
|
|
452
|
-
function union$1(items) {
|
|
453
|
-
if (items.length === 0) return z.never();
|
|
454
|
-
if (items.length === 1) return items[0];
|
|
455
|
-
return z.union(items);
|
|
456
|
-
}
|
|
457
|
-
function valueSchema(expected) {
|
|
458
|
-
return z.unknown().refine((actual) => jsonValueEqual(actual, expected), { message: `Expected ${JSON.stringify(expected)}` });
|
|
459
|
-
}
|
|
460
|
-
function jsonValueEqual(actual, expected) {
|
|
461
|
-
if (Object.is(actual, expected)) return true;
|
|
462
|
-
if (Array.isArray(actual) && Array.isArray(expected)) return actual.length === expected.length && actual.every((value, index) => jsonValueEqual(value, expected[index]));
|
|
463
|
-
if (actual !== null && expected !== null && typeof actual === "object" && typeof expected === "object" && !Array.isArray(actual) && !Array.isArray(expected)) {
|
|
464
|
-
const actualRecord = actual;
|
|
465
|
-
const expectedRecord = expected;
|
|
466
|
-
const keys = Object.keys(actualRecord);
|
|
467
|
-
return keys.length === Object.keys(expectedRecord).length && keys.every((key) => Object.hasOwn(expectedRecord, key) && jsonValueEqual(actualRecord[key], expectedRecord[key]));
|
|
468
|
-
}
|
|
469
|
-
return false;
|
|
470
|
-
}
|
|
471
|
-
function stringSchema(format) {
|
|
472
|
-
switch (format) {
|
|
473
|
-
case "email": return z.email();
|
|
474
|
-
case "uri":
|
|
475
|
-
case "url": return z.url();
|
|
476
|
-
case "uuid": return z.uuid();
|
|
477
|
-
case "date-time": return z.iso.datetime();
|
|
478
|
-
default: return z.string();
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
//#endregion
|
|
482
311
|
//#region src/connection/bareInterfaceTarget.ts
|
|
483
312
|
/**
|
|
484
313
|
* Bundle an interface definition with metadata-free foreign-protocol
|
|
@@ -566,13 +395,15 @@ var CodeWriter = class {
|
|
|
566
395
|
* components receive explicit payload types; other types remain Zod-inferred.
|
|
567
396
|
*/
|
|
568
397
|
function generateTsInterface(schema, options = {}) {
|
|
398
|
+
_validateErrors(schema.methods);
|
|
569
399
|
const linkRpcImport = options.linkRpcImport ?? "@hediet/linkrpc";
|
|
570
400
|
const exportName = options.exportName ?? _deriveExportName(schema.id);
|
|
571
401
|
const preserveWireSchema = options.preserveWireSchema ?? false;
|
|
572
402
|
if (options.bareTarget !== void 0) validateBarePrefix(options.bareTarget.prefix, "bareInterfaceTarget");
|
|
573
403
|
const w = new CodeWriter();
|
|
574
404
|
const bareTargetImport = options.bareTarget === void 0 ? "" : "bareInterfaceTarget, ";
|
|
575
|
-
const
|
|
405
|
+
const errorImport = Object.values(schema.methods).some((method) => (method.errors?.length ?? 0) > 0) ? "applicationError, " : "";
|
|
406
|
+
const definitionImport = preserveWireSchema ? `${errorImport}${bareTargetImport}InterfaceDefinition, notificationType, requestType, type LinkRpcInterfaceSchema` : `${errorImport}${bareTargetImport}defineInterface, notificationType, requestType`;
|
|
576
407
|
w.writeLine(`import { ${definitionImport} } from "${linkRpcImport}";`);
|
|
577
408
|
w.writeLine(`import { z } from "zod";`);
|
|
578
409
|
w.writeLine();
|
|
@@ -715,6 +546,20 @@ function _writeMethod(w, method, components, preserveWireSchema) {
|
|
|
715
546
|
}
|
|
716
547
|
w.dedent();
|
|
717
548
|
w.append(")");
|
|
549
|
+
if ((method.errors?.length ?? 0) > 0) {
|
|
550
|
+
w.append(".withErrors([").newline();
|
|
551
|
+
w.indent();
|
|
552
|
+
for (const error of method.errors) {
|
|
553
|
+
w.append(`applicationError(${error.code}, ${JSON.stringify(error.message)}`);
|
|
554
|
+
if (error.data !== void 0) {
|
|
555
|
+
w.append(", ");
|
|
556
|
+
_writeSchema(w, error.data, components, preserveWireSchema);
|
|
557
|
+
}
|
|
558
|
+
w.append("),").newline();
|
|
559
|
+
}
|
|
560
|
+
w.dedent();
|
|
561
|
+
w.append("] as const)");
|
|
562
|
+
}
|
|
718
563
|
if (method.clientStream !== void 0 || method.serverStream !== void 0) {
|
|
719
564
|
w.append(".withStream({").newline();
|
|
720
565
|
w.indent();
|
|
@@ -732,6 +577,19 @@ function _writeMethod(w, method, components, preserveWireSchema) {
|
|
|
732
577
|
w.append("})");
|
|
733
578
|
}
|
|
734
579
|
}
|
|
580
|
+
function _validateErrors(methods) {
|
|
581
|
+
for (const [name, method] of Object.entries(methods)) {
|
|
582
|
+
if (method.result === void 0 && method.errors !== void 0) throw new Error(`generateInterface: notification "${name}" cannot declare errors`);
|
|
583
|
+
const seen = /* @__PURE__ */ new Set();
|
|
584
|
+
for (const error of method.errors ?? []) {
|
|
585
|
+
if (typeof error.message !== "string") throw new Error(`generateInterface: error message on "${name}" is not a string`);
|
|
586
|
+
if (!Number.isInteger(error.code) || error.code < -2147483648 || error.code > 2147483647) throw new Error(`generateInterface: error code ${error.code} on "${name}" is not a signed i32`);
|
|
587
|
+
if (error.code >= -32768 && error.code <= -32e3 || error.code === -32800) throw new Error(`generateInterface: error code ${error.code} on "${name}" is reserved`);
|
|
588
|
+
if (seen.has(error.code)) throw new Error(`generateInterface: duplicate error code ${error.code} on "${name}"`);
|
|
589
|
+
seen.add(error.code);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
735
593
|
function _collectMemberDocs(method) {
|
|
736
594
|
const docs = {};
|
|
737
595
|
if (method.description !== void 0) docs.description = method.description;
|
|
@@ -2178,12 +2036,16 @@ var Channel = class Channel {
|
|
|
2178
2036
|
};
|
|
2179
2037
|
var RpcError = class extends Error {
|
|
2180
2038
|
code;
|
|
2039
|
+
origin;
|
|
2181
2040
|
data;
|
|
2182
|
-
|
|
2041
|
+
hasData;
|
|
2042
|
+
constructor(message, code, data, origin = "local", hasData = data !== void 0) {
|
|
2183
2043
|
super(message);
|
|
2184
2044
|
this.code = code;
|
|
2185
|
-
this.
|
|
2045
|
+
this.origin = origin;
|
|
2186
2046
|
this.name = "RpcError";
|
|
2047
|
+
this.hasData = hasData;
|
|
2048
|
+
if (hasData) this.data = data;
|
|
2187
2049
|
}
|
|
2188
2050
|
};
|
|
2189
2051
|
//#endregion
|
|
@@ -3350,7 +3212,7 @@ var JsonRpcChannel = class JsonRpcChannel {
|
|
|
3350
3212
|
this._streamListeners.delete(key);
|
|
3351
3213
|
if ("error" in m) {
|
|
3352
3214
|
const e = m.error;
|
|
3353
|
-
const err = new RpcError(e.message, e.code, e.data);
|
|
3215
|
+
const err = new RpcError(e.message, e.code, e.data, "remote", Object.hasOwn(e, "data"));
|
|
3354
3216
|
pending.reject(err);
|
|
3355
3217
|
} else pending.resolve(m.result);
|
|
3356
3218
|
return;
|
|
@@ -4043,18 +3905,20 @@ var LinkRpcConnection = class LinkRpcConnection {
|
|
|
4043
3905
|
} : sendOpts;
|
|
4044
3906
|
this._validateOutboundParamsFor(member, wireMethod, params);
|
|
4045
3907
|
const call = this.channel.sendRequestWithStream(wireMethod, params, channelOpts);
|
|
4046
|
-
const
|
|
4047
|
-
return Object.assign(
|
|
3908
|
+
const checked = addCheckedResult(call.result.then((raw) => validateWireResult(member.resultSchema, raw, wireMethod)), member);
|
|
3909
|
+
return Object.assign(checked, {
|
|
4048
3910
|
send: async (payload) => call.send(payload),
|
|
4049
3911
|
cancel: async (reason) => call.cancel(reason),
|
|
4050
3912
|
dispose: (reason) => call.dispose?.(reason),
|
|
4051
3913
|
ping: () => call.ping()
|
|
4052
3914
|
});
|
|
4053
3915
|
};
|
|
4054
|
-
} else proxy[name] =
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
3916
|
+
} else proxy[name] = (params) => {
|
|
3917
|
+
return addCheckedResult((async () => {
|
|
3918
|
+
this._validateOutboundParamsFor(member, wireMethod, params);
|
|
3919
|
+
const raw = await this.channel.sendRequest(wireMethod, params, sendOpts);
|
|
3920
|
+
return validateWireResult(member.resultSchema, raw, wireMethod);
|
|
3921
|
+
})(), member);
|
|
4058
3922
|
};
|
|
4059
3923
|
} else {
|
|
4060
3924
|
const notify = (params) => {
|
|
@@ -4089,6 +3953,8 @@ var LinkRpcConnection = class LinkRpcConnection {
|
|
|
4089
3953
|
const stream = this._buildStreamApi(call.stream, call.signal, member);
|
|
4090
3954
|
try {
|
|
4091
3955
|
const result = await handler(parsedParams.data, call.context, stream);
|
|
3956
|
+
const encodedError = encodeApplicationError(member, result);
|
|
3957
|
+
if (encodedError !== void 0) return { error: encodedError };
|
|
4092
3958
|
validateValue(member.resultSchema, result, `Invalid result for ${call.method}`, ErrorCode.internalError);
|
|
4093
3959
|
return { result: result === void 0 ? null : result };
|
|
4094
3960
|
} catch (e) {
|
|
@@ -4273,6 +4139,102 @@ function directoryWatcherMatchesEntry(watcher, entry) {
|
|
|
4273
4139
|
const serviceId = entry.serviceId ?? "";
|
|
4274
4140
|
return (watcher.interfaceId === void 0 || watcher.interfaceId === entry.iface.info.id) && (watcher.interfaceIdPrefix === void 0 || entry.iface.info.id.startsWith(watcher.interfaceIdPrefix)) && (watcher.serviceId === void 0 || watcher.serviceId === serviceId) && serviceIdMatchesScopes(serviceId, watcher.serviceIdScopes);
|
|
4275
4141
|
}
|
|
4142
|
+
function addCheckedResult(promise, member) {
|
|
4143
|
+
return Object.assign(promise, { result: async () => {
|
|
4144
|
+
try {
|
|
4145
|
+
return {
|
|
4146
|
+
ok: true,
|
|
4147
|
+
value: await promise
|
|
4148
|
+
};
|
|
4149
|
+
} catch (cause) {
|
|
4150
|
+
return {
|
|
4151
|
+
ok: false,
|
|
4152
|
+
error: decodeCheckedError(cause, member.applicationErrors)
|
|
4153
|
+
};
|
|
4154
|
+
}
|
|
4155
|
+
} });
|
|
4156
|
+
}
|
|
4157
|
+
function decodeCheckedError(cause, descriptors) {
|
|
4158
|
+
if (!(cause instanceof RpcError) || cause.origin !== "remote") return {
|
|
4159
|
+
kind: "local",
|
|
4160
|
+
cause
|
|
4161
|
+
};
|
|
4162
|
+
const descriptor = descriptors.find((candidate) => candidate.code === cause.code && candidate.message === cause.message);
|
|
4163
|
+
if (descriptor !== void 0) {
|
|
4164
|
+
if (descriptor.dataSchema === void 0 && !cause.hasData) return {
|
|
4165
|
+
kind: "application",
|
|
4166
|
+
code: descriptor.code,
|
|
4167
|
+
message: descriptor.message
|
|
4168
|
+
};
|
|
4169
|
+
if (descriptor.dataSchema !== void 0 && cause.hasData && matchesApplicationData(descriptor.dataSchema, cause.data)) {
|
|
4170
|
+
if (safeParse(descriptor.dataSchema, cause.data).success) return {
|
|
4171
|
+
kind: "application",
|
|
4172
|
+
code: descriptor.code,
|
|
4173
|
+
message: descriptor.message,
|
|
4174
|
+
data: cause.data
|
|
4175
|
+
};
|
|
4176
|
+
}
|
|
4177
|
+
}
|
|
4178
|
+
return {
|
|
4179
|
+
kind: "remote",
|
|
4180
|
+
code: cause.code,
|
|
4181
|
+
message: cause.message,
|
|
4182
|
+
...cause.hasData ? { data: cause.data } : {}
|
|
4183
|
+
};
|
|
4184
|
+
}
|
|
4185
|
+
function encodeApplicationError(member, value) {
|
|
4186
|
+
if (!isApplicationErrorValue(value)) return void 0;
|
|
4187
|
+
const candidate = value;
|
|
4188
|
+
const descriptor = member.applicationErrors.find((error) => error.code === candidate.code && error.message === candidate.message);
|
|
4189
|
+
if (descriptor === void 0) throw new RpcError(`Undeclared application error ${String(candidate.code)}`, ErrorCode.internalError);
|
|
4190
|
+
const hasData = Object.hasOwn(candidate, "data");
|
|
4191
|
+
if (descriptor.dataSchema === void 0) {
|
|
4192
|
+
if (hasData) throw new RpcError(`Application error ${descriptor.code} must not contain data`, ErrorCode.internalError);
|
|
4193
|
+
return {
|
|
4194
|
+
code: descriptor.code,
|
|
4195
|
+
message: descriptor.message
|
|
4196
|
+
};
|
|
4197
|
+
}
|
|
4198
|
+
if (!hasData) throw new RpcError(`Application error ${descriptor.code} requires data`, ErrorCode.internalError);
|
|
4199
|
+
if (!matchesApplicationData(descriptor.dataSchema, candidate.data)) throw new RpcError(`Invalid data for application error ${descriptor.code}`, ErrorCode.internalError, { issues: [{ message: "Data must be JSON matching the declared wire schema" }] });
|
|
4200
|
+
const parsed = safeParse(descriptor.dataSchema, candidate.data);
|
|
4201
|
+
if (!parsed.success) throw new RpcError(`Invalid data for application error ${descriptor.code}`, ErrorCode.internalError, { issues: parsed.error.issues });
|
|
4202
|
+
return {
|
|
4203
|
+
code: descriptor.code,
|
|
4204
|
+
message: descriptor.message,
|
|
4205
|
+
data: candidate.data
|
|
4206
|
+
};
|
|
4207
|
+
}
|
|
4208
|
+
/** Reject values JSON serialization would silently omit, coerce, or replace via toJSON. */
|
|
4209
|
+
function isWireJsonValue(value, ancestors = /* @__PURE__ */ new Set()) {
|
|
4210
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return true;
|
|
4211
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
4212
|
+
if (typeof value !== "object" || ancestors.has(value)) return false;
|
|
4213
|
+
if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) return false;
|
|
4214
|
+
ancestors.add(value);
|
|
4215
|
+
const children = Array.isArray(value) ? value.values() : Object.values(value);
|
|
4216
|
+
for (const child of children) if (!isWireJsonValue(child, ancestors)) return false;
|
|
4217
|
+
ancestors.delete(value);
|
|
4218
|
+
return true;
|
|
4219
|
+
}
|
|
4220
|
+
const applicationDataSchemas = /* @__PURE__ */ new WeakMap();
|
|
4221
|
+
function matchesApplicationData(schema, value) {
|
|
4222
|
+
if (!isWireJsonValue(value)) return false;
|
|
4223
|
+
let wire = applicationDataSchemas.get(schema);
|
|
4224
|
+
if (wire === void 0) {
|
|
4225
|
+
const components = {};
|
|
4226
|
+
wire = {
|
|
4227
|
+
schema: zodToSvcJsonSchema(schema, {
|
|
4228
|
+
methodName: "applicationError",
|
|
4229
|
+
schemaPosition: "data",
|
|
4230
|
+
components
|
|
4231
|
+
}),
|
|
4232
|
+
components
|
|
4233
|
+
};
|
|
4234
|
+
applicationDataSchemas.set(schema, wire);
|
|
4235
|
+
}
|
|
4236
|
+
return matchesJsonSchema(value, wire.schema, { schemas: wire.components });
|
|
4237
|
+
}
|
|
4276
4238
|
function validateWireResult(schema, raw, wireMethod) {
|
|
4277
4239
|
const value = normalizeWireResult(schema, raw);
|
|
4278
4240
|
validateValue(schema, value, `Invalid result for ${wireMethod}`, ErrorCode.internalError);
|
|
@@ -7790,6 +7752,6 @@ async function createSeededSigningIdentity(opts) {
|
|
|
7790
7752
|
return KeypairSigningIdentity.fromKeypair(ed);
|
|
7791
7753
|
}
|
|
7792
7754
|
//#endregion
|
|
7793
|
-
export { walkHubDetailed as $, bareInterfaceTarget as $t, attachCapabilities as A, PRINCIPAL_PREFIX as At, LinkRpcConnection as B, isRequest as Bt, identityStorageInterface as C, getKeyId as Ct, PublicWrappingIdentity as D, signingInput as Dt, PublicSigningIdentity as E, signingDomainValue as Et, generateX25519Keypair as F, principalForPublicKey as Ft, fetchDirectory as G, StreamDir as Gt, JsonRpcChannel as H, STREAM_METHOD as Ht, formatEndpointUri as I, publicKeyForKeyId as It, intersectServiceIdScopes as J, directoryInterface as Jt, fetchSchema as K, streamInterface as Kt, isHubEndpoint as L, resolveSigningKey as Lt, verifyRpcCall as M, bytesToBase64Url as Mt, crypto_exports as N, keyIdForPrincipal as Nt, Principal as O, withSignature as Ot, generateKeypair as P, keyIdForPublicKey as Pt, walkHub as Q, generateTsInterface as Qt, parseEndpointUri as R, ErrorCode as Rt, identityInterface as S, LINKRPC_UNSIGNED_KEY as St, KeypairSigningIdentity as T, signedHash as Tt, DEFAULT_WALK_DEPTH as U, StreamControlReason as Ut, ServiceHandle as V, isResponse as Vt, HubDirectoryExplorer as W, StreamControlType as Wt, serviceIdMatchesPattern as X, schemasInterface as Xt, normalizeServiceIdScopes as Y, directoryWatchNever as Yt, serviceIdMatchesScopes as Z, zServiceIdPattern as Zt, InMemoryManagedIdentity as _, HUBRPC_META_KEY as _t, verifyCall as a,
|
|
7755
|
+
export { walkHubDetailed as $, bareInterfaceTarget as $t, attachCapabilities as A, PRINCIPAL_PREFIX as At, LinkRpcConnection as B, isRequest as Bt, identityStorageInterface as C, getKeyId as Ct, PublicWrappingIdentity as D, signingInput as Dt, PublicSigningIdentity as E, signingDomainValue as Et, generateX25519Keypair as F, principalForPublicKey as Ft, fetchDirectory as G, StreamDir as Gt, JsonRpcChannel as H, STREAM_METHOD as Ht, formatEndpointUri as I, publicKeyForKeyId as It, intersectServiceIdScopes as J, directoryInterface as Jt, fetchSchema as K, streamInterface as Kt, isHubEndpoint as L, resolveSigningKey as Lt, verifyRpcCall as M, bytesToBase64Url as Mt, crypto_exports as N, keyIdForPrincipal as Nt, Principal as O, withSignature as Ot, generateKeypair as P, keyIdForPublicKey as Pt, walkHub as Q, generateTsInterface as Qt, parseEndpointUri as R, ErrorCode as Rt, identityInterface as S, LINKRPC_UNSIGNED_KEY as St, KeypairSigningIdentity as T, signedHash as Tt, DEFAULT_WALK_DEPTH as U, StreamControlReason as Ut, ServiceHandle as V, isResponse as Vt, HubDirectoryExplorer as W, StreamControlType as Wt, serviceIdMatchesPattern as X, schemasInterface as Xt, normalizeServiceIdScopes as Y, directoryWatchNever as Yt, serviceIdMatchesScopes as Z, zServiceIdPattern as Zt, InMemoryManagedIdentity as _, HUBRPC_META_KEY as _t, verifyCall as a, TransportPair as at, registerIdentityOnOverlay as b, LINKRPC_META_KEY as bt, invoke as c, requireObjectParams as ct, prefix as d, parseMethodName as dt, materializeJsonSchema as en, DEFAULT_RPC_TIMEOUT_MS as et, signCapability as f, capabilityPermits as ft, createManagedPrincipal as g, permissionPermits as gt, PrincipalWithStore as h, permissionMatchesTarget as ht, signParams as i, MultiplexedTransport as it, signRpcCall as j, base64UrlToBytes$1 as jt, CapBag as k, KEY_ID_PREFIX as kt, issueCapability as l, stripLinkRpcWireMeta as lt, SigningSender as m, matchParams as mt, createSeededMemoryPrincipal as n, matchesJsonSchema as nn, Channel as nt, capBagFreshAt as o, connectTransports as ot, OneShotCapStaging as p, hasSignedCapabilityShape as pt, findMethodInSchema as q, defaultsInterface as qt, createSeededSigningIdentity as r, RpcError as rt, capabilityFreshAt as s, traceMessageTransport as st, createMemoryPrincipal as t, isAssignable as tn, withRpcTimeout as tt, permits as u, methodNameToTarget as ut, InMemoryManagedIdentityStorage as v, HUBRPC_SIGNATURE_KEY as vt, KeypairIdentity as w, readSignature as wt, registerLazyIdentityOnOverlay as x, LINKRPC_SIGNATURE_KEY as xt, createManagedIdentity as y, HUBRPC_UNSIGNED_KEY as yt, ChannelConnector as z, isNotification as zt };
|
|
7794
7756
|
|
|
7795
|
-
//# sourceMappingURL=src-
|
|
7757
|
+
//# sourceMappingURL=src-CAhXne71.js.map
|