stitchkit 0.9.0 → 0.10.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/dist/cli.js +1 -1
- package/dist/contract/define.d.ts +23 -7
- package/dist/contract/define.d.ts.map +1 -1
- package/dist/{index-13psnhhe.js → index-f39j6twc.js} +1 -1
- package/dist/{index-zshrc6kx.js → index-s8gtzt8w.js} +36 -37
- package/dist/node.js +1 -1
- package/dist/observability/audit.d.ts.map +1 -1
- package/dist/observability/context.d.ts +6 -1
- package/dist/observability/context.d.ts.map +1 -1
- package/dist/observability/event.d.ts +6 -0
- package/dist/observability/event.d.ts.map +1 -1
- package/dist/observability/index.js +1 -0
- package/dist/retained.d.ts +1 -1
- package/dist/server/context.d.ts +18 -1
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/create.d.ts.map +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/logger.d.ts +3 -2
- package/dist/server/logger.d.ts.map +1 -1
- package/dist/tools.d.ts +0 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +1 -27
- package/llms-full.txt +15 -34
- package/package.json +3 -3
- package/dist/tools/dispatch.d.ts +0 -65
- package/dist/tools/dispatch.d.ts.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -5,9 +5,9 @@ export type Transport = (typeof ALL_TRANSPORTS)[number];
|
|
|
5
5
|
/**
|
|
6
6
|
* The transport tag on `ctx.source`. The four built-ins keep autocomplete, but
|
|
7
7
|
* the union is **open** (`string & {}`) so a bring-your-own transport — e.g. a
|
|
8
|
-
* raw-WebSocket lane
|
|
9
|
-
* tag its own calls (`source: 'local-ws'`). `source` is transport-only and
|
|
10
|
-
* carries no framework behaviour (→ ADR 0002
|
|
8
|
+
* raw-WebSocket lane that runs a contract through the app's own dispatch loop —
|
|
9
|
+
* can tag its own calls (`source: 'local-ws'`). `source` is transport-only and
|
|
10
|
+
* carries no framework behaviour (→ ADR 0002).
|
|
11
11
|
*/
|
|
12
12
|
export type TransportSource = 'http' | 'mcp' | 'agent' | 'cli' | (string & {});
|
|
13
13
|
interface EndpointDefBase {
|
|
@@ -40,10 +40,10 @@ interface EndpointDefBase {
|
|
|
40
40
|
* The core attaches **no** behaviour to it (it stays generic — ADR 0002): it
|
|
41
41
|
* rides through to `MethodDef.idempotent`, where a transport that can retry
|
|
42
42
|
* reads it. A reliable bring-your-own-transport lane (e.g. a raw-WebSocket
|
|
43
|
-
* client
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
43
|
+
* client) replays an `idempotent` call after a reconnect — that is the
|
|
44
|
+
* durability guarantee — while a non-idempotent one is rejected rather than
|
|
45
|
+
* re-sent (a duplicate would be a second side effect). Unset means "unknown" —
|
|
46
|
+
* a careful transport treats it as non-idempotent.
|
|
47
47
|
*/
|
|
48
48
|
idempotent?: boolean;
|
|
49
49
|
/**
|
|
@@ -129,6 +129,17 @@ export interface RuntimeContext {
|
|
|
129
129
|
input: unknown;
|
|
130
130
|
file?: File;
|
|
131
131
|
source: TransportSource;
|
|
132
|
+
/**
|
|
133
|
+
* The raw Web `Request`, its parsed `URL` and `Headers` — set on the HTTP
|
|
134
|
+
* transport (and reachable in every lifecycle hook, including `onError` on a
|
|
135
|
+
* validation failure). Absent on the non-HTTP transports (MCP / agent / CLI /
|
|
136
|
+
* a bring-your-own lane), which carry no `Request`, so they are optional and a
|
|
137
|
+
* reader narrows them. Web Fetch types only — the core stays Fetch-clean
|
|
138
|
+
* (→ ADR 0013).
|
|
139
|
+
*/
|
|
140
|
+
req?: Request;
|
|
141
|
+
url?: URL;
|
|
142
|
+
headers?: Headers;
|
|
132
143
|
traceId?: string;
|
|
133
144
|
spanId?: string;
|
|
134
145
|
ipAddress?: string;
|
|
@@ -140,6 +151,11 @@ export interface HandlerContext<TParams = undefined, TInput = undefined> {
|
|
|
140
151
|
input: TInput;
|
|
141
152
|
file?: File;
|
|
142
153
|
source: TransportSource;
|
|
154
|
+
/** Raw Web `Request` / `URL` / `Headers` — set on the HTTP transport, absent
|
|
155
|
+
* on the tool transports (see {@link RuntimeContext}). */
|
|
156
|
+
req?: Request;
|
|
157
|
+
url?: URL;
|
|
158
|
+
headers?: Headers;
|
|
143
159
|
traceId?: string;
|
|
144
160
|
spanId?: string;
|
|
145
161
|
ipAddress?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../../src/contract/define.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAEtC,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;AAErE,eAAO,MAAM,cAAc,0CAA2C,CAAC;AACvE,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAExD;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,KAAK,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAE/E,UAAU,eAAe;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;;;OAYG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;;;;;;;OAYG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,kEAAkE;IAClE,WAAW,EAAE,MAAM,CAAC;IACpB,qFAAqF;IACrF,UAAU,CAAC,EAAE,SAAS,CAAC,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC;CAC3C;AAED;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,oFAAoF;IACpF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gFAAgF;IAChF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,kFAAkF;IAClF,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,mEAAmE;IACnE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,qEAAqE;IACrE,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,UAAU,mBAAoB,SAAQ,eAAe;IACnD,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED,UAAU,eAAgB,SAAQ,eAAe;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IAC9B,oEAAoE;IACpE,EAAE,CAAC,EAAE,cAAc,CAAC;IACpB,yEAAyE;IACzE,WAAW,CAAC,EAAE,uBAAuB,CAAC;CACvC;AAED,MAAM,MAAM,WAAW,GAAG,mBAAmB,GAAG,eAAe,CAAC;AAEhE,MAAM,WAAW,YAAY,CAAC,MAAM,SAAS,MAAM,GAAG,MAAM;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW,CAC1B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACnE,MAAM,SAAS,MAAM,GAAG,MAAM;IAE9B,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IAC3B,SAAS,EAAE,CAAC,CAAC;CACd;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACxE,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,EACxB,SAAS,EAAE,CAAC,GACX,WAAW,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;AAC5B,wBAAgB,cAAc,CAC5B,MAAM,SAAS,MAAM,EACrB,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EAC3C,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,SAAS,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AAmDjF,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAID,MAAM,WAAW,cAAc,CAAC,OAAO,GAAG,SAAS,EAAE,MAAM,GAAG,SAAS;IACrE,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAID,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;AAYtE,KAAK,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;AAE9D;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,GAAG,EAAE,MAAM,CAAC;IACZ,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,IAAI,GAAG,cAAc,CAAC;AAElD,KAAK,aAAa,CAAC,CAAC,IAAI,CAAC,SAAS;IAAE,SAAS,EAAE,MAAM,CAAC,SAAS,MAAM,CAAA;CAAE,GACnE;KAAG,CAAC,IAAI,CAAC,GAAG,aAAa;CAAE,GAC3B,OAAO,CAAC;AAEZ,KAAK,YAAY,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,GAClD,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,GAC5B,aAAa,CAAC,CAAC,CAAC,CAAC;AAEnB,KAAK,cAAc,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;AAEpF,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,CAAC,MAAM,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAC/D,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAChC,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;AAE1D,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,IAAI;KAC9D,CAAC,IAAI,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CACjC,CAAC;AAEF,KAAK,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS;IAAE,MAAM,EAAE,SAAS,SAAS,EAAE,CAAA;CAAE,GAC5D,MAAM,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAChC,IAAI,GACJ,KAAK,GACP,IAAI,CAAC;AAST,KAAK,QAAQ,CAAC,CAAC,EAAE,KAAK,IAAI,YAAY,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;AAElD,MAAM,MAAM,gBAAgB,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,MAAM,QAAQ,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAC/E,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAChC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;AAE7D,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,KAAK,IAAI;KAC1E,CAAC,IAAI,MAAM,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,CAAC,GAAG,KAAK,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC;CAC5F,CAAC;AAIF,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,IAAI,gBAAgB,CACnF,CAAC,EACD,OAAO,CACR,CAAC"}
|
|
1
|
+
{"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../../src/contract/define.ts"],"names":[],"mappings":"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"}
|
|
@@ -1000,4 +1000,4 @@ function safeInputSchema(tool) {
|
|
|
1000
1000
|
}
|
|
1001
1001
|
}
|
|
1002
1002
|
|
|
1003
|
-
export { coerceJsonArgs, toolResultFromError,
|
|
1003
|
+
export { coerceJsonArgs, toolResultFromError, flattenDiscriminatedUnion, collectTools, createToolRunner, formatToolError, fetchGuarded, readCapped, parseCliArgs, DEFAULT_EXIT_CODES, emitResult, pollUntil, pollUntilDone, createCli };
|
|
@@ -343,38 +343,15 @@ async function readJsonBody(req) {
|
|
|
343
343
|
badRequest("Invalid JSON body");
|
|
344
344
|
}
|
|
345
345
|
}
|
|
346
|
-
|
|
347
|
-
const parsedParams = method.paramsSchema ? method.paramsSchema.parse(pathParams) : undefined;
|
|
348
|
-
let parsedInput;
|
|
349
|
-
let file;
|
|
350
|
-
if (method.multipart) {
|
|
351
|
-
const cap = method.maxUploadBytes ?? maxUploadBytes;
|
|
352
|
-
const multipart = await parseMultipart(req, method.multipart, method.inputSchema, cap);
|
|
353
|
-
parsedInput = multipart.fields;
|
|
354
|
-
file = multipart.file;
|
|
355
|
-
} else if (method.inputSchema) {
|
|
356
|
-
if (req.method === "GET") {
|
|
357
|
-
parsedInput = method.inputSchema.parse(parseQueryParams(url));
|
|
358
|
-
} else if (req.method === "DELETE") {
|
|
359
|
-
const ct = req.headers.get("content-type");
|
|
360
|
-
if (ct?.includes("application/json")) {
|
|
361
|
-
parsedInput = method.inputSchema.parse(await readJsonBody(req));
|
|
362
|
-
} else {
|
|
363
|
-
parsedInput = method.inputSchema.parse(parseQueryParams(url));
|
|
364
|
-
}
|
|
365
|
-
} else {
|
|
366
|
-
parsedInput = method.inputSchema.parse(await readJsonBody(req));
|
|
367
|
-
}
|
|
368
|
-
}
|
|
346
|
+
function buildBaseContext(req, url, pathParams, traceId, clientIp) {
|
|
369
347
|
const safePathParams = {};
|
|
370
348
|
for (const [k, v] of Object.entries(pathParams)) {
|
|
371
349
|
if (!RESERVED_KEYS.has(k) && !isUnsafeKey(k))
|
|
372
350
|
safePathParams[k] = v;
|
|
373
351
|
}
|
|
374
352
|
return {
|
|
375
|
-
params:
|
|
376
|
-
input:
|
|
377
|
-
...file && { file },
|
|
353
|
+
params: pathParams,
|
|
354
|
+
input: undefined,
|
|
378
355
|
source: "http",
|
|
379
356
|
req,
|
|
380
357
|
url,
|
|
@@ -384,6 +361,27 @@ async function buildContext(req, url, method, pathParams, traceId, clientIp, max
|
|
|
384
361
|
...getClientInfo(req, clientIp)
|
|
385
362
|
};
|
|
386
363
|
}
|
|
364
|
+
async function parseRequestInto(ctx, req, url, method, maxUploadBytes) {
|
|
365
|
+
if (method.paramsSchema) {
|
|
366
|
+
ctx.params = method.paramsSchema.parse(ctx.params);
|
|
367
|
+
}
|
|
368
|
+
if (method.multipart) {
|
|
369
|
+
const cap = method.maxUploadBytes ?? maxUploadBytes;
|
|
370
|
+
const multipart = await parseMultipart(req, method.multipart, method.inputSchema, cap);
|
|
371
|
+
ctx.input = multipart.fields;
|
|
372
|
+
if (multipart.file)
|
|
373
|
+
ctx.file = multipart.file;
|
|
374
|
+
} else if (method.inputSchema) {
|
|
375
|
+
if (req.method === "GET") {
|
|
376
|
+
ctx.input = method.inputSchema.parse(parseQueryParams(url));
|
|
377
|
+
} else if (req.method === "DELETE") {
|
|
378
|
+
const ct = req.headers.get("content-type");
|
|
379
|
+
ctx.input = ct?.includes("application/json") ? method.inputSchema.parse(await readJsonBody(req)) : method.inputSchema.parse(parseQueryParams(url));
|
|
380
|
+
} else {
|
|
381
|
+
ctx.input = method.inputSchema.parse(await readJsonBody(req));
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
387
385
|
function buildErrorContext(req, url, traceId, clientIp) {
|
|
388
386
|
return {
|
|
389
387
|
params: undefined,
|
|
@@ -447,8 +445,8 @@ function levelForStatus(status) {
|
|
|
447
445
|
return "warn";
|
|
448
446
|
return "info";
|
|
449
447
|
}
|
|
450
|
-
function buildLogFields(method, path, status, durationMs, traceId) {
|
|
451
|
-
return { traceId, method, path, status, durationMs };
|
|
448
|
+
function buildLogFields(method, path, status, durationMs, traceId, errorCode) {
|
|
449
|
+
return { traceId, method, path, status, durationMs, ...errorCode && { errorCode } };
|
|
452
450
|
}
|
|
453
451
|
function formatMs(ms) {
|
|
454
452
|
if (ms >= 1000)
|
|
@@ -492,20 +490,21 @@ function logIncoming(req, pathname, traceId, ipAddress) {
|
|
|
492
490
|
}
|
|
493
491
|
return log;
|
|
494
492
|
}
|
|
495
|
-
function logOutgoing(req, pathname, status, log, ipAddress) {
|
|
493
|
+
function logOutgoing(req, pathname, status, log, ipAddress, errorCode) {
|
|
496
494
|
const ms = elapsedMs(log.startTime);
|
|
497
495
|
if (isProd) {
|
|
498
496
|
console.log(JSON.stringify({
|
|
499
497
|
ts: new Date().toISOString(),
|
|
500
498
|
level: levelForStatus(status),
|
|
501
499
|
msg: `${req.method} ${pathname} ${status}`,
|
|
502
|
-
...buildLogFields(req.method, pathname, status, Math.round(ms), log.traceId),
|
|
500
|
+
...buildLogFields(req.method, pathname, status, Math.round(ms), log.traceId, errorCode),
|
|
503
501
|
ip: ipAddress
|
|
504
502
|
}));
|
|
505
503
|
return;
|
|
506
504
|
}
|
|
507
505
|
const mc = METHOD_COLOR[req.method] ?? c.dim;
|
|
508
|
-
|
|
506
|
+
const code = errorCode ? ` ${c.red}${errorCode}${c.reset}` : "";
|
|
507
|
+
console.log(`${c.gray}[${timestamp()}]${c.reset} ${mc}${req.method}${c.reset} ${c.dim}${log.traceId}${c.reset} ${c.cyan}←${c.reset} ${safePath(pathname)} ${statusColor(status)}${status}${c.reset}${code} ${durationColor(ms)}${formatMs(ms)}${c.reset} ${ipLabel(ipAddress ?? "")}`);
|
|
509
508
|
}
|
|
510
509
|
|
|
511
510
|
// src/server/create.ts
|
|
@@ -534,15 +533,15 @@ function createHandler(config) {
|
|
|
534
533
|
});
|
|
535
534
|
reqLog = { traceId, startTime: performance.now() };
|
|
536
535
|
}
|
|
537
|
-
const logDone = (status) => {
|
|
536
|
+
const logDone = (status, errorCode) => {
|
|
538
537
|
if (!reqLog)
|
|
539
538
|
return;
|
|
540
539
|
if (useDefaultLog)
|
|
541
|
-
logOutgoing(req, url.pathname, status, reqLog, ipAddress);
|
|
540
|
+
logOutgoing(req, url.pathname, status, reqLog, ipAddress, errorCode);
|
|
542
541
|
if (customLogger) {
|
|
543
542
|
const durationMs = Math.round(elapsedMs(reqLog.startTime));
|
|
544
543
|
const level = levelForStatus(status);
|
|
545
|
-
customLogger[level](`${req.method} ${url.pathname} ${status} ${durationMs}ms`, buildLogFields(req.method, url.pathname, status, durationMs, reqLog.traceId));
|
|
544
|
+
customLogger[level](`${req.method} ${url.pathname} ${status}${errorCode ? ` ${errorCode}` : ""} ${durationMs}ms`, buildLogFields(req.method, url.pathname, status, durationMs, reqLog.traceId, errorCode));
|
|
546
545
|
}
|
|
547
546
|
};
|
|
548
547
|
const respondError = async (err, errCtx, endpoint) => {
|
|
@@ -557,7 +556,7 @@ function createHandler(config) {
|
|
|
557
556
|
} catch {}
|
|
558
557
|
}
|
|
559
558
|
const appErr = normalizeError(err);
|
|
560
|
-
logDone(appErr.status);
|
|
559
|
+
logDone(appErr.status, appErr.code);
|
|
561
560
|
return json(appErr.toJSON(), appErr.status, cors, req);
|
|
562
561
|
};
|
|
563
562
|
if (cors && req.method === "OPTIONS") {
|
|
@@ -600,9 +599,9 @@ function createHandler(config) {
|
|
|
600
599
|
return respondError(new AppError("NOT_FOUND", "Not found", 404));
|
|
601
600
|
}
|
|
602
601
|
const { method, pathParams, groupHooks } = match;
|
|
603
|
-
|
|
602
|
+
const ctx = buildBaseContext(req, url, pathParams, traceId, clientIp);
|
|
604
603
|
try {
|
|
605
|
-
|
|
604
|
+
await parseRequestInto(ctx, req, url, method, config.maxUploadBytes);
|
|
606
605
|
if (hooks?.beforeHandle) {
|
|
607
606
|
await hooks.beforeHandle(ctx, method);
|
|
608
607
|
}
|
package/dist/node.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/observability/audit.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,kBAAkB,CAAC;AAElE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAe,KAAK,eAAe,EAAmB,MAAM,YAAY,CAAC;AAGhF,oCAAoC;AACpC,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,KAAK,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,iFAAiF;IACjF,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC;IAC1C,yEAAyE;IACzE,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED,qEAAqE;AACrE,MAAM,WAAW,SAAS;IACxB;;;;OAIG;IACH,IAAI,EAAE,CAAC,CAAC,EACN,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,KACpD,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpD;;;OAGG;IACH,QAAQ,EAAE,aAAa,CAAC;CACzB;AAmBD,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/observability/audit.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,kBAAkB,CAAC;AAElE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAe,KAAK,eAAe,EAAmB,MAAM,YAAY,CAAC;AAGhF,oCAAoC;AACpC,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,KAAK,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,iFAAiF;IACjF,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC;IAC1C,yEAAyE;IACzE,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED,qEAAqE;AACrE,MAAM,WAAW,SAAS;IACxB;;;;OAIG;IACH,IAAI,EAAE,CAAC,CAAC,EACN,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,KACpD,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpD;;;OAGG;IACH,QAAQ,EAAE,aAAa,CAAC;CACzB;AAmBD,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CAgG9D"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { TransportSource } from '../contract';
|
|
2
|
+
import type { JsonValue } from './sanitize';
|
|
2
3
|
import { type TraceContext } from './trace';
|
|
3
4
|
/** Everything known about the request in flight. */
|
|
4
5
|
export interface RequestContext {
|
|
@@ -22,6 +23,7 @@ export interface RequestContext {
|
|
|
22
23
|
error?: {
|
|
23
24
|
code?: string;
|
|
24
25
|
message?: string;
|
|
26
|
+
details?: JsonValue;
|
|
25
27
|
};
|
|
26
28
|
}
|
|
27
29
|
/** Run `fn` with `ctx` as the active request context. */
|
|
@@ -40,11 +42,14 @@ export declare function getUserId(): string | undefined;
|
|
|
40
42
|
export declare function setRequestUser(userId: string): void;
|
|
41
43
|
/**
|
|
42
44
|
* Record the error outcome on the active context. Call this from the error
|
|
43
|
-
* handler — the audit hook reads it when the request completes.
|
|
45
|
+
* handler — the audit hook reads it when the request completes. Optional
|
|
46
|
+
* `details` carries structure the message string flattens (e.g. the failing
|
|
47
|
+
* Zod issues) onto `RequestEvent.errorDetail`.
|
|
44
48
|
*/
|
|
45
49
|
export declare function setRequestError(error: {
|
|
46
50
|
code?: string;
|
|
47
51
|
message?: string;
|
|
52
|
+
details?: JsonValue;
|
|
48
53
|
}): void;
|
|
49
54
|
/** Options for `wrapInRequestContext`. */
|
|
50
55
|
export interface WrapRequestContextOptions {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/observability/context.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAEjE,oDAAoD;AACpD,MAAM,WAAW,cAAc;IAC7B,sCAAsC;IACtC,KAAK,EAAE,YAAY,CAAC;IACpB,4CAA4C;IAC5C,MAAM,EAAE,eAAe,CAAC;IACxB,iBAAiB;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/observability/context.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAEjE,oDAAoD;AACpD,MAAM,WAAW,cAAc;IAC7B,sCAAsC;IACtC,KAAK,EAAE,YAAY,CAAC;IACpB,4CAA4C;IAC5C,MAAM,EAAE,eAAe,CAAC;IACxB,iBAAiB;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,SAAS,CAAA;KAAE,CAAC;CAClE;AAID,yDAAyD;AACzD,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,GAAG,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAE5E;AAED,sEAAsE;AACtE,wBAAgB,iBAAiB,IAAI,cAAc,GAAG,SAAS,CAE9D;AAED,mEAAmE;AACnE,wBAAgB,UAAU,IAAI,MAAM,GAAG,SAAS,CAE/C;AAED,qDAAqD;AACrD,wBAAgB,SAAS,IAAI,MAAM,GAAG,SAAS,CAE9C;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAGnD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB,GAAG,IAAI,CAGP;AAED,0CAA0C;AAC1C,MAAM,WAAW,yBAAyB;IACxC;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,EACvD,OAAO,GAAE,yBAA8B,GACtC,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAiBhD"}
|
|
@@ -31,6 +31,12 @@ export interface RequestEvent {
|
|
|
31
31
|
errorCode?: string;
|
|
32
32
|
/** Error message — failures only. */
|
|
33
33
|
errorMessage?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Structured error detail — failures only, when the error handler recorded it
|
|
36
|
+
* via `setRequestError({ details })` (e.g. the failing validation issues the
|
|
37
|
+
* `errorMessage` string flattens). HTTP path only.
|
|
38
|
+
*/
|
|
39
|
+
errorDetail?: JsonValue;
|
|
34
40
|
/** Sanitised request payload — the HTTP body or the tool arguments. */
|
|
35
41
|
payload: JsonValue | null;
|
|
36
42
|
/** Item count of the result, when it is a list. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../src/observability/event.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,mCAAmC;IACnC,MAAM,EAAE,eAAe,CAAC;IACxB,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kCAAkC;IAClC,EAAE,EAAE,OAAO,CAAC;IACZ,6EAA6E;IAC7E,UAAU,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uEAAuE;IACvE,OAAO,EAAE,SAAS,GAAG,IAAI,CAAC;IAC1B,mDAAmD;IACnD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,4CAA4C;IAC5C,aAAa,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,SAAS,EAAE,IAAI,CAAC;CACjB"}
|
|
1
|
+
{"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../src/observability/event.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,mCAAmC;IACnC,MAAM,EAAE,eAAe,CAAC;IACxB,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kCAAkC;IAClC,EAAE,EAAE,OAAO,CAAC;IACZ,6EAA6E;IAC7E,UAAU,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,uEAAuE;IACvE,OAAO,EAAE,SAAS,GAAG,IAAI,CAAC;IAC1B,mDAAmD;IACnD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,4CAA4C;IAC5C,aAAa,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,SAAS,EAAE,IAAI,CAAC;CACjB"}
|
|
@@ -148,6 +148,7 @@ function createAuditHook(config) {
|
|
|
148
148
|
durationMs,
|
|
149
149
|
errorCode: ctx.error?.code,
|
|
150
150
|
errorMessage: ctx.error?.message,
|
|
151
|
+
...ctx.error?.details !== undefined && { errorDetail: ctx.error.details },
|
|
151
152
|
payload: sanitizePayload(body, sanitize),
|
|
152
153
|
resultSize: null,
|
|
153
154
|
responseBytes: 0,
|
package/dist/retained.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* Transport-agnostic: wrap it around any pub/sub. `createSocketIOClient`'s
|
|
11
11
|
* `retain` option uses it internally, and a bring-your-own-transport lane (a raw
|
|
12
|
-
* WebSocket driving a contract through
|
|
12
|
+
* WebSocket driving a contract through the app's own dispatch loop) can use it
|
|
13
13
|
* directly for its own event channel. Browser-safe — no Node built-ins.
|
|
14
14
|
*/
|
|
15
15
|
export interface RetainedTopics<Events extends Record<string, unknown>> {
|
package/dist/server/context.d.ts
CHANGED
|
@@ -5,6 +5,23 @@
|
|
|
5
5
|
import { type RuntimeContext } from '../contract';
|
|
6
6
|
import { type ClientIpOptions } from './request';
|
|
7
7
|
import type { MethodDef } from './types';
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Assemble everything knowable from the URL alone — path params, the request,
|
|
10
|
+
* trace id and client info — **before** any schema parsing. Bound first so a
|
|
11
|
+
* later validation failure still hands `onError` the path params and the
|
|
12
|
+
* request (an empty context loses both); `parseRequestInto` then enriches it
|
|
13
|
+
* with the schema-validated `params` / `input`.
|
|
14
|
+
*
|
|
15
|
+
* `params` starts as the raw matched path params (a property of the URL, known
|
|
16
|
+
* the moment the route matched) and is replaced by the validated value when the
|
|
17
|
+
* endpoint declares a `paramsSchema`.
|
|
18
|
+
*/
|
|
19
|
+
export declare function buildBaseContext(req: Request, url: URL, pathParams: Record<string, string>, traceId: string, clientIp: ClientIpOptions): RuntimeContext;
|
|
20
|
+
/**
|
|
21
|
+
* Parse `params` / `input` against the endpoint schemas and write them onto an
|
|
22
|
+
* already-assembled base context. A validation failure throws a `ZodError`
|
|
23
|
+
* here — the base context (path params, request) is preserved for `onError`.
|
|
24
|
+
*/
|
|
25
|
+
export declare function parseRequestInto(ctx: RuntimeContext, req: Request, url: URL, method: MethodDef, maxUploadBytes?: number): Promise<void>;
|
|
9
26
|
export declare function buildErrorContext(req: Request, url: URL, traceId: string, clientIp: ClientIpOptions): RuntimeContext;
|
|
10
27
|
//# sourceMappingURL=context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/server/context.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAG9D,OAAO,EAAE,KAAK,eAAe,EAAmC,MAAM,WAAW,CAAC;AAClF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAmCzC,
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/server/context.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAG9D,OAAO,EAAE,KAAK,eAAe,EAAmC,MAAM,WAAW,CAAC;AAClF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAmCzC;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,GAAG,EACR,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAClC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,eAAe,GACxB,cAAc,CAmBhB;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,SAAS,EACjB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,eAAe,GACxB,cAAc,CAWhB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/server/create.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAEV,eAAe,EACf,aAAa,EAGd,MAAM,SAAS,CAAC;AAEjB,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/server/create.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAEV,eAAe,EACf,aAAa,EAGd,MAAM,SAAS,CAAC;AAEjB,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAkNxF;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,uBAsBnD"}
|
package/dist/server/index.js
CHANGED
package/dist/server/logger.d.ts
CHANGED
|
@@ -3,12 +3,13 @@ export declare function elapsedMs(startTime: number): number;
|
|
|
3
3
|
/** Map an HTTP status to a log level. */
|
|
4
4
|
export declare function levelForStatus(status: number): 'error' | 'warn' | 'info';
|
|
5
5
|
/** The structured fields shared by every completed-request log line. */
|
|
6
|
-
export declare function buildLogFields(method: string, path: string, status: number, durationMs: number, traceId: string): {
|
|
6
|
+
export declare function buildLogFields(method: string, path: string, status: number, durationMs: number, traceId: string, errorCode?: string): {
|
|
7
7
|
traceId: string;
|
|
8
8
|
method: string;
|
|
9
9
|
path: string;
|
|
10
10
|
status: number;
|
|
11
11
|
durationMs: number;
|
|
12
|
+
errorCode?: string;
|
|
12
13
|
};
|
|
13
14
|
export interface RequestLog {
|
|
14
15
|
traceId: string;
|
|
@@ -18,5 +19,5 @@ export declare function shouldLog(pathname: string, method: string): boolean;
|
|
|
18
19
|
/** Open the timing window for a request. Development prints a `→` line. */
|
|
19
20
|
export declare function logIncoming(req: Request, pathname: string, traceId: string, ipAddress?: string): RequestLog;
|
|
20
21
|
/** Close a request. Development: `←` line. Production: one structured JSON line. */
|
|
21
|
-
export declare function logOutgoing(req: Request, pathname: string, status: number, log: RequestLog, ipAddress?: string): void;
|
|
22
|
+
export declare function logOutgoing(req: Request, pathname: string, status: number, log: RequestLog, ipAddress?: string, errorCode?: string): void;
|
|
22
23
|
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/server/logger.ts"],"names":[],"mappings":"AAwCA,6DAA6D;AAC7D,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEnD;AAoBD,yCAAyC;AACzC,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAIxE;AAED,wEAAwE;AACxE,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/server/logger.ts"],"names":[],"mappings":"AAwCA,6DAA6D;AAC7D,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEnD;AAoBD,yCAAyC;AACzC,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAIxE;AAED,wEAAwE;AACxE,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,GACjB;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAEA;AA0BD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAID,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAGnE;AAED,2EAA2E;AAC3E,wBAAgB,WAAW,CACzB,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,GACjB,UAAU,CASZ;AAED,oFAAoF;AACpF,wBAAgB,WAAW,CACzB,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,UAAU,EACf,SAAS,CAAC,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,GACjB,IAAI,CA4BN"}
|
package/dist/tools.d.ts
CHANGED
|
@@ -4,7 +4,6 @@ export { type CliConfig, createCli } from './tools/cli';
|
|
|
4
4
|
export type { ExitCodeMap } from './tools/cli-format';
|
|
5
5
|
export type { CliWaitConfig } from './tools/cli-wait';
|
|
6
6
|
export { coerceJsonArgs } from './tools/coerce';
|
|
7
|
-
export { type ContractDispatcher, type ContractDispatcherConfig, createContractDispatcher, } from './tools/dispatch';
|
|
8
7
|
export type { ToolCallHooks, ToolLifecycle, ToolResult } from './tools/execute';
|
|
9
8
|
export { flattenDiscriminatedUnion } from './tools/flatten';
|
|
10
9
|
export { buildToolManifest, type ToolManifestEntry } from './tools/manifest';
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,gBAAgB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACrF,OAAO,EAAE,KAAK,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,gBAAgB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACrF,OAAO,EAAE,KAAK,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAChF,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EACL,cAAc,EACd,KAAK,wBAAwB,EAC7B,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,QAAQ,EACR,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,2BAA2B,EAC3B,kBAAkB,EAClB,KAAK,SAAS,EACd,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,KAAK,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,KAAK,kBAAkB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EACL,2BAA2B,EAC3B,uBAAuB,EACvB,KAAK,uBAAuB,EAC5B,4BAA4B,EAC5B,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,kBAAkB,EAClB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,gBAAgB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,KAAK,sBAAsB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,KAAK,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAE,KAAK,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/tools.js
CHANGED
|
@@ -8,14 +8,13 @@ import {
|
|
|
8
8
|
collectTools,
|
|
9
9
|
createCli,
|
|
10
10
|
createToolRunner,
|
|
11
|
-
executeToolMethod,
|
|
12
11
|
fetchGuarded,
|
|
13
12
|
flattenDiscriminatedUnion,
|
|
14
13
|
formatToolError,
|
|
15
14
|
pollUntil,
|
|
16
15
|
readCapped,
|
|
17
16
|
toolResultFromError
|
|
18
|
-
} from "./index-
|
|
17
|
+
} from "./index-f39j6twc.js";
|
|
19
18
|
import {
|
|
20
19
|
toJsonSchema
|
|
21
20
|
} from "./index-0ed3bx43.js";
|
|
@@ -69,30 +68,6 @@ function mountAgent(services, config = {}) {
|
|
|
69
68
|
}
|
|
70
69
|
return tools;
|
|
71
70
|
}
|
|
72
|
-
// src/tools/dispatch.ts
|
|
73
|
-
function createContractDispatcher(services, config) {
|
|
74
|
-
const list = Array.isArray(services) ? services : [services];
|
|
75
|
-
const index = new Map;
|
|
76
|
-
for (const service of list) {
|
|
77
|
-
for (const [name, method] of Object.entries(service.methods)) {
|
|
78
|
-
if (index.has(name)) {
|
|
79
|
-
throw new Error(`createContractDispatcher: duplicate method "${name}" across services`);
|
|
80
|
-
}
|
|
81
|
-
index.set(name, method);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return {
|
|
85
|
-
methods: [...index.keys()],
|
|
86
|
-
dispatch(method, args, context) {
|
|
87
|
-
const target = index.get(method);
|
|
88
|
-
if (!target) {
|
|
89
|
-
return Promise.resolve(toolResultFromError(new AppError("NOT_FOUND", `Unknown method: ${method}`, 404)));
|
|
90
|
-
}
|
|
91
|
-
const ctx = { ...config.context, ...context, source: config.source };
|
|
92
|
-
return executeToolMethod(target, method, args, ctx, config.hooks, config.lifecycle, config.coerceJsonArgs ?? false);
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
71
|
// src/tools/manifest.ts
|
|
97
72
|
function buildToolManifest(tools) {
|
|
98
73
|
return tools.map((t) => {
|
|
@@ -1311,7 +1286,6 @@ export {
|
|
|
1311
1286
|
createToolkit,
|
|
1312
1287
|
createStdioMcpServer,
|
|
1313
1288
|
createMcpHandler,
|
|
1314
|
-
createContractDispatcher,
|
|
1315
1289
|
createCli,
|
|
1316
1290
|
collectTools,
|
|
1317
1291
|
coerceJsonArgs,
|
package/llms-full.txt
CHANGED
|
@@ -1876,37 +1876,20 @@ Notes:
|
|
|
1876
1876
|
|
|
1877
1877
|
Sometimes the transport is neither HTTP nor Socket.IO — a desktop app whose UI
|
|
1878
1878
|
webview talks to its own local Bun sidecar over a raw WebSocket, an IPC channel,
|
|
1879
|
-
a queue worker. You still
|
|
1880
|
-
|
|
1881
|
-
|
|
1879
|
+
a queue worker. You can still drive it from one `defineContract`: share the
|
|
1880
|
+
contract's Zod schemas to validate each inbound frame, run your handlers, and
|
|
1881
|
+
reuse the contract metadata below. You own **both** the wire (framing,
|
|
1882
|
+
handshake, reconnect) *and* the per-call validate-run loop — stitchkit ships the
|
|
1883
|
+
contract and its metadata, not a transport engine. A reliable-RPC-over-raw-
|
|
1884
|
+
WebSocket engine would be a competing WebSocket transport
|
|
1885
|
+
([ADR 0008](../decisions/0008-thin-wrappers.md)); the wire stays yours.
|
|
1882
1886
|
|
|
1883
|
-
|
|
1884
|
-
runs a contract method by its key through the *same* core as the MCP / agent
|
|
1885
|
-
mounts — same validation, the same `{ ok, data } | { ok: false, code, … }`
|
|
1886
|
-
envelope, the same hooks and `beforeHandle` scope gate. You own the wire (framing,
|
|
1887
|
-
handshake, reconnect) and call `dispatch` per inbound frame.
|
|
1887
|
+
Two pieces of the contract carry straight over to a bring-your-own lane:
|
|
1888
1888
|
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
const service = implement(runtimeContract, { 'tasks.setDone': (ctx) => doIt(ctx.input), … })
|
|
1894
|
-
|
|
1895
|
-
const dispatcher = createContractDispatcher(service, { source: 'local-ws' })
|
|
1896
|
-
|
|
1897
|
-
// In your raw-WebSocket server, per `{ id, method, params }` frame:
|
|
1898
|
-
ws.onmessage = async (frame) => {
|
|
1899
|
-
const { id, method, params } = JSON.parse(frame.data)
|
|
1900
|
-
const result = await dispatcher.dispatch(method, params) // validates + runs
|
|
1901
|
-
ws.send(JSON.stringify({ id, ...result })) // { ok, data } | { ok:false, code, … }
|
|
1902
|
-
}
|
|
1903
|
-
```
|
|
1904
|
-
|
|
1905
|
-
`dispatch` never throws for a normal call — a handler error becomes a failed
|
|
1906
|
-
result, and an unknown method is a `NOT_FOUND` result. Pass `hooks`
|
|
1907
|
-
(`beforeToolCall` / `afterToolCall`) and `lifecycle.beforeHandle` to audit and
|
|
1908
|
-
scope-guard exactly like the other transports. Tag calls with your own
|
|
1909
|
-
`source` — `TransportSource` is an open union.
|
|
1889
|
+
- **`source` is an open tag.** `TransportSource` is `'http' | 'mcp' | 'agent' |
|
|
1890
|
+
'cli' | (string & {})`, so a handler or hook can tell your transport's calls
|
|
1891
|
+
apart — tag them `source: 'local-ws'` and read `ctx.source`.
|
|
1892
|
+
- **`idempotent` drives replay-on-reconnect** — see below.
|
|
1910
1893
|
|
|
1911
1894
|
### Durability — `idempotent` + replay
|
|
1912
1895
|
|
|
@@ -1932,8 +1915,9 @@ also catches up on the latest pushed state.
|
|
|
1932
1915
|
|
|
1933
1916
|
This is deliberately *not* a reliable-RPC engine — that would be a competing
|
|
1934
1917
|
WebSocket transport ([ADR 0008](../decisions/0008-thin-wrappers.md)). stitchkit
|
|
1935
|
-
gives you the
|
|
1936
|
-
|
|
1918
|
+
gives you the contract and the metadata (`idempotent`, the open `source` tag,
|
|
1919
|
+
`createRetainedTopics`); the wire and the per-call execution stay yours. See
|
|
1920
|
+
[ADR 0028](../decisions/0028-revert-contract-dispatcher.md).
|
|
1937
1921
|
|
|
1938
1922
|
|
|
1939
1923
|
==============================================================================
|
|
@@ -3058,7 +3042,6 @@ Server-only. Turns contracts into MCP and AI-agent tools. Needs the
|
|
|
3058
3042
|
| `mountMcp` | function | add contract tools to an existing `McpServer` — [guide](../guide/mcp-and-agents.md#mountmcp) |
|
|
3059
3043
|
| `implementRemote` | function | bind a contract to a remote HTTP API — [guide](../guide/mcp-and-agents.md#proxying-a-remote-api--implementremote) |
|
|
3060
3044
|
| `mountAgent` | function | a Vercel AI SDK `ToolSet` from a service — [guide](../guide/mcp-and-agents.md#ai-agents--mountagent) |
|
|
3061
|
-
| `createContractDispatcher` | function | run a contract over a bring-your-own transport — [guide](../guide/realtime.md#bring-your-own-transport) |
|
|
3062
3045
|
| `createCli` | function | a command-line program from contracts — [guide](../guide/cli.md) (also on `stitchkit/cli`) |
|
|
3063
3046
|
| `createToolkit` | function | context-typed tool mounts — [guide](../guide/cli.md#typed-context) |
|
|
3064
3047
|
| `mountViewFile` | function | a native multimodal "view file" MCP tool |
|
|
@@ -3070,8 +3053,6 @@ Server-only. Turns contracts into MCP and AI-agent tools. Needs the
|
|
|
3070
3053
|
| `ImplementRemoteOptions` | _type_ | options for `implementRemote` |
|
|
3071
3054
|
| `McpMountConfig` | _type_ | config for `mountMcp` |
|
|
3072
3055
|
| `AgentMountConfig` | _type_ | config for `mountAgent` |
|
|
3073
|
-
| `ContractDispatcher` | _type_ | the `createContractDispatcher` handle |
|
|
3074
|
-
| `ContractDispatcherConfig` | _type_ | config for `createContractDispatcher` |
|
|
3075
3056
|
| `AgentContext` | _type_ | the context merged into agent tool handlers |
|
|
3076
3057
|
| `CliConfig` | _type_ | config for `createCli` |
|
|
3077
3058
|
| `CliWaitConfig` | _type_ | `--wait` polling config |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stitchkit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Contract-first backend framework — one defineContract() into an HTTP API, MCP tools, AI-agent tools and a typed client. Bun and Node.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bun",
|
|
@@ -155,8 +155,8 @@
|
|
|
155
155
|
"@tanstack/react-query": "5.101.0",
|
|
156
156
|
"@types/bun": "^1.3.14",
|
|
157
157
|
"@types/json-schema": "^7.0.15",
|
|
158
|
-
"@types/react": "^19.2.
|
|
159
|
-
"ai": "^6.0.
|
|
158
|
+
"@types/react": "^19.2.17",
|
|
159
|
+
"ai": "^6.0.207",
|
|
160
160
|
"react": "^19.2.7",
|
|
161
161
|
"react-query-kit": "^3.3.4",
|
|
162
162
|
"socket.io": "^4.8.3",
|
package/dist/tools/dispatch.d.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Drive a contract over a **bring-your-own transport**.
|
|
3
|
-
*
|
|
4
|
-
* The HTTP server, the MCP mount and the agent mount all run a contract method
|
|
5
|
-
* the same way: slice the flat args, validate `params` / `input` against the Zod
|
|
6
|
-
* schemas, run the handler, validate the output, and return a typed result
|
|
7
|
-
* envelope. `createContractDispatcher` exposes exactly that core for a transport
|
|
8
|
-
* stitchkit does not own — a raw WebSocket lane (webview ↔ a local sidecar), an
|
|
9
|
-
* IPC channel, a queue worker. The transport owns the wire (framing, handshake,
|
|
10
|
-
* reconnect); the dispatcher owns "given a method name and args, run it safely."
|
|
11
|
-
*
|
|
12
|
-
* This is the same execution path as `mountMcp` / `mountAgent` (it shares
|
|
13
|
-
* `executeToolMethod`), so a bespoke transport gets identical validation and the
|
|
14
|
-
* identical `{ ok, code, details, hint }` error envelope for free, instead of a
|
|
15
|
-
* hand-rolled method registry. → ADR 0027. Upholds ADR 0008 (no competing
|
|
16
|
-
* engine — the transport is the app's) and ADR 0002 (the core stays generic —
|
|
17
|
-
* `source` is a free tag, `idempotent` carries no built-in behaviour).
|
|
18
|
-
*/
|
|
19
|
-
import { type TransportSource } from '../contract';
|
|
20
|
-
import type { ServiceDef } from '../server/types';
|
|
21
|
-
import { type ToolCallHooks, type ToolLifecycle, type ToolResult } from './execute';
|
|
22
|
-
export interface ContractDispatcherConfig {
|
|
23
|
-
/** Transport tag written to every call's `ctx.source` — e.g. `'local-ws'`. */
|
|
24
|
-
source: TransportSource;
|
|
25
|
-
/** Static context merged into every call (overridden by per-call context). */
|
|
26
|
-
context?: Record<string, unknown>;
|
|
27
|
-
/**
|
|
28
|
-
* Observability hooks — the same `beforeToolCall` / `afterToolCall` the MCP and
|
|
29
|
-
* agent mounts fire, so a bespoke transport audits calls the same way.
|
|
30
|
-
*/
|
|
31
|
-
hooks?: ToolCallHooks;
|
|
32
|
-
/**
|
|
33
|
-
* Auth / scope gate and result transform run for every call — pass a
|
|
34
|
-
* `createAuthHook` result as `beforeHandle` to scope-guard the transport like
|
|
35
|
-
* an HTTP route.
|
|
36
|
-
*/
|
|
37
|
-
lifecycle?: ToolLifecycle;
|
|
38
|
-
/**
|
|
39
|
-
* Coerce JSON-stringified array / object arguments before validation. Off by
|
|
40
|
-
* default — a structured transport (WebSocket JSON) sends real types; only an
|
|
41
|
-
* LLM-style flat-string transport needs it.
|
|
42
|
-
*/
|
|
43
|
-
coerceJsonArgs?: boolean;
|
|
44
|
-
}
|
|
45
|
-
export interface ContractDispatcher {
|
|
46
|
-
/**
|
|
47
|
-
* Run one contract method by its endpoint key (e.g. `'transcriptions.list'`)
|
|
48
|
-
* with a flat argument object. Returns the `{ ok: true, data } | { ok: false,
|
|
49
|
-
* code, details?, hint? }` envelope the MCP / agent transports use — it does
|
|
50
|
-
* not throw for a normal call; a handler error becomes a failed result, and an
|
|
51
|
-
* unknown method is a `NOT_FOUND` result. Per-call `context` is merged after
|
|
52
|
-
* the static `config.context` (neither can shadow `source`).
|
|
53
|
-
*/
|
|
54
|
-
dispatch(method: string, args: Record<string, unknown>, context?: Record<string, unknown>): Promise<ToolResult>;
|
|
55
|
-
/** Every method key this dispatcher can run, across the given services. */
|
|
56
|
-
readonly methods: readonly string[];
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Build a {@link ContractDispatcher} from one or more `implement()` services.
|
|
60
|
-
* Every method of every service is dispatchable by its key — exposure is the
|
|
61
|
-
* transport's choice (which services it dispatches), not the contract's `expose`
|
|
62
|
-
* (that gates the built-in HTTP / MCP / agent / CLI transports).
|
|
63
|
-
*/
|
|
64
|
-
export declare function createContractDispatcher(services: ServiceDef | ServiceDef[], config: ContractDispatcherConfig): ContractDispatcher;
|
|
65
|
-
//# sourceMappingURL=dispatch.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../src/tools/dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAY,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,KAAK,EAAa,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,UAAU,EAEhB,MAAM,WAAW,CAAC;AAEnB,MAAM,WAAW,wBAAwB;IACvC,8EAA8E;IAC9E,MAAM,EAAE,eAAe,CAAC;IACxB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC;;;OAGG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB;;;;OAIG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;;;;OAOG;IACH,QAAQ,CACN,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,OAAO,CAAC,UAAU,CAAC,CAAC;IACvB,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,UAAU,GAAG,UAAU,EAAE,EACnC,MAAM,EAAE,wBAAwB,GAC/B,kBAAkB,CAqCpB"}
|