stitchkit 0.25.0 → 0.27.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/browser/client-multipart.d.ts +22 -0
- package/dist/browser/client-multipart.d.ts.map +1 -0
- package/dist/browser/client.d.ts.map +1 -1
- package/dist/browser/http.d.ts +7 -1
- package/dist/browser/http.d.ts.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/contract/define.d.ts +79 -2
- package/dist/contract/define.d.ts.map +1 -1
- package/dist/contract/factory.d.ts +1 -0
- package/dist/contract/factory.d.ts.map +1 -1
- package/dist/contract/index.js +1 -1
- package/dist/{index-h9d1fm0p.js → index-4whcb3c3.js} +64 -22
- package/dist/{index-a9n8m4ec.js → index-jvescqgr.js} +1 -1
- package/dist/{index-x62gnfsk.js → index-pmftwk2a.js} +19 -1
- package/dist/{index-g8kyab85.js → index-y4132gqh.js} +81 -12
- package/dist/{index-tje0q6gp.js → index-zfscdskj.js} +6 -1
- package/dist/{index-4gawbm74.js → index-zza375qp.js} +41 -3
- package/dist/index.js +39 -25
- package/dist/internal/errors.d.ts +6 -1
- package/dist/internal/errors.d.ts.map +1 -1
- package/dist/internal/write-download.d.ts +17 -0
- package/dist/internal/write-download.d.ts.map +1 -0
- package/dist/node.js +3 -3
- package/dist/server/create.d.ts.map +1 -1
- package/dist/server/error-hook.d.ts +14 -3
- package/dist/server/error-hook.d.ts.map +1 -1
- package/dist/server/implement.d.ts.map +1 -1
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +21 -8
- package/dist/server/middleware/cors.d.ts +19 -0
- package/dist/server/middleware/cors.d.ts.map +1 -1
- package/dist/server/openapi.d.ts.map +1 -1
- package/dist/server/router.d.ts +27 -0
- package/dist/server/router.d.ts.map +1 -1
- package/dist/server/types.d.ts +44 -1
- package/dist/server/types.d.ts.map +1 -1
- package/dist/tools/agent.d.ts +2 -0
- package/dist/tools/agent.d.ts.map +1 -1
- package/dist/tools/cli.d.ts.map +1 -1
- package/dist/tools/execute.d.ts +1 -1
- package/dist/tools/execute.d.ts.map +1 -1
- package/dist/tools/list-names.d.ts +2 -1
- package/dist/tools/list-names.d.ts.map +1 -1
- package/dist/tools/mcp.d.ts +10 -3
- package/dist/tools/mcp.d.ts.map +1 -1
- package/dist/tools/mount-download.d.ts.map +1 -1
- package/dist/tools/mount-upload.d.ts.map +1 -1
- package/dist/tools/mount-wait.d.ts.map +1 -1
- package/dist/tools/mount.d.ts +13 -0
- package/dist/tools/mount.d.ts.map +1 -1
- package/dist/tools/names.d.ts +34 -0
- package/dist/tools/names.d.ts.map +1 -1
- package/dist/tools/remote.d.ts.map +1 -1
- package/dist/tools/transports.d.ts.map +1 -1
- package/dist/tools.js +69 -49
- package/llms-full.txt +223 -12
- package/llms.txt +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multipart field encoding for the client — the platform-sensitive corner of
|
|
3
|
+
* `client.ts`, split out so the request-building logic there reads without it.
|
|
4
|
+
*
|
|
5
|
+
* Internal: none of this is public surface. The React Native descriptor path is
|
|
6
|
+
* the only genuinely subtle part, and keeping it together with its two guards
|
|
7
|
+
* makes that subtlety readable in one screen.
|
|
8
|
+
*/
|
|
9
|
+
import type { MultipartFile } from '../contract';
|
|
10
|
+
/** A multipart file field — a `Blob` (web / Bun) or a platform descriptor (RN). */
|
|
11
|
+
export declare function isMultipartFile(value: unknown): value is MultipartFile;
|
|
12
|
+
/**
|
|
13
|
+
* Append the file part. `FormData.append` is typed `(name, value: string | Blob)`
|
|
14
|
+
* by the DOM lib, but on React Native attaching a `{ uri, name, type }`
|
|
15
|
+
* descriptor is the native way to send a file (RN streams it from disk). Route
|
|
16
|
+
* through a structural type whose `append` also accepts a `FileDescriptor` —
|
|
17
|
+
* method-parameter bivariance lets the real `FormData` satisfy it, so the
|
|
18
|
+
* descriptor path stays cast-free. Web / Bun still pass a `Blob`.
|
|
19
|
+
*/
|
|
20
|
+
export declare function appendMultipartFile(form: FormData, field: string, file: MultipartFile): void;
|
|
21
|
+
export declare function appendFormFields(formData: FormData, values: Record<string, unknown>, skipKeys: Set<string>): void;
|
|
22
|
+
//# sourceMappingURL=client-multipart.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-multipart.d.ts","sourceRoot":"","sources":["../../src/browser/client-multipart.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAkB,aAAa,EAAE,MAAM,aAAa,CAAC;AAqBjE,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAEtE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI,CAG5F;AAED,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,GACpB,IAAI,CAKN"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/browser/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/browser/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAI/F,OAAO,EAEL,KAAK,UAAU,IAAI,WAAW,EAG/B,MAAM,QAAQ,CAAC;AAsFhB,kFAAkF;AAClF,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAClE,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACnD;AAED;;;GAGG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAC1D,OAAO,GACP;KAAG,CAAC,IAAI,CAAC,GAAG,MAAM;CAAE,CAAC;AAEzB;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB,CAAC,CAAC,SAAS,MAAM,GAAG,KAAK;IAC5D,UAAU,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC,CAAC;IAClE,eAAe,CAAC,EAAE,SAAS,CAAC,EAAE,CAAC;CAChC;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACrC,KAAK,CAAC,CAAC,SAAS,MAAM,GAAG,KAAK,EAE9B,QAAQ,EAAE,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,EAChC,cAAc,EAAE,YAAY,GAAG,WAAW,EAC1C,cAAc,CAAC,EAAE,oBAAoB,CAAC,CAAC,CAAC,GACvC,gBAAgB,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAepC;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC,EAC1E,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,WAAW,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;CAAE,CAKzF"}
|
package/dist/browser/http.d.ts
CHANGED
|
@@ -65,7 +65,13 @@ type ParamArrayValue = Array<string | number>;
|
|
|
65
65
|
export interface RequestOptions {
|
|
66
66
|
params?: Record<string, ParamValue | ParamArrayValue>;
|
|
67
67
|
timeout?: number;
|
|
68
|
-
|
|
68
|
+
/**
|
|
69
|
+
* How to read the body. `'response'` hands back the untouched `Response` —
|
|
70
|
+
* what a `raw` endpoint answers with, and strictly more than `'blob'`: the
|
|
71
|
+
* caller still gets `.blob()` / `.body`, plus the headers where
|
|
72
|
+
* `Content-Disposition` (the download filename) lives.
|
|
73
|
+
*/
|
|
74
|
+
responseType?: 'json' | 'blob' | 'response';
|
|
69
75
|
}
|
|
70
76
|
/** The HTTP transport adapter `createClient` builds typed methods on. */
|
|
71
77
|
export interface HttpClient {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/browser/http.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD,MAAM,MAAM,QAAQ,GAChB;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,GACzB;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEvB,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC;AAEzD,qBAAa,QAAS,SAAQ,KAAK;aAEf,IAAI,EAAE,MAAM;aACZ,MAAM,EAAE,MAAM;aACd,OAAO,CAAC,EAAE,OAAO;aAEjB,IAAI,CAAC,EAAE,MAAM;gBAJb,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,MAAU,EAClB,OAAO,CAAC,EAAE,OAAO,YAAA,EACjC,OAAO,CAAC,EAAE,MAAM,EACA,IAAI,CAAC,EAAE,MAAM,YAAA;IAM/B,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ;CAG7C;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,GAAG,IAAI,CAU9E;AAED,MAAM,MAAM,cAAc,GACtB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtB,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;AAEtD,4CAA4C;AAC5C,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC;;;;;OAKG;IACH,KAAK,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACvE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,aAAa,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9D;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB;;;OAGG;IACH,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,KAAK,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;AACxD,KAAK,eAAe,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;AAE9C,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,eAAe,CAAC,CAAC;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/browser/http.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
emitResult,
|
|
5
5
|
parseCliArgs,
|
|
6
6
|
pollUntilDone
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-4whcb3c3.js";
|
|
8
8
|
import"./index-0ed3bx43.js";
|
|
9
|
-
import"./index-
|
|
9
|
+
import"./index-zza375qp.js";
|
|
10
10
|
import"./index-c7nyw0yt.js";
|
|
11
11
|
export {
|
|
12
12
|
pollUntilDone,
|
|
@@ -93,6 +93,7 @@ export interface EndpointToolAnnotations {
|
|
|
93
93
|
interface HttpOnlyEndpointDef extends EndpointDefBase {
|
|
94
94
|
expose: readonly ['HTTP'];
|
|
95
95
|
toolName?: never;
|
|
96
|
+
rawResponse?: never;
|
|
96
97
|
}
|
|
97
98
|
interface ToolEndpointDef extends EndpointDefBase {
|
|
98
99
|
toolName?: string;
|
|
@@ -101,11 +102,70 @@ interface ToolEndpointDef extends EndpointDefBase {
|
|
|
101
102
|
ui?: EndpointUiMeta;
|
|
102
103
|
/** MCP behavioural hints (read-only / destructive / title) for hosts. */
|
|
103
104
|
annotations?: EndpointToolAnnotations;
|
|
105
|
+
rawResponse?: never;
|
|
104
106
|
}
|
|
105
|
-
|
|
107
|
+
/**
|
|
108
|
+
* An endpoint whose handler returns the **`Response` itself** instead of data —
|
|
109
|
+
* a file download, a PDF, an SSE stream, a redirect. → ADR 0038.
|
|
110
|
+
*
|
|
111
|
+
* ```ts
|
|
112
|
+
* pdf: {
|
|
113
|
+
* method: 'GET', path: '/:id/pdf', desc: 'Download the offer as a PDF',
|
|
114
|
+
* params: z.object({ id: z.uuid() }),
|
|
115
|
+
* rawResponse: true, contentType: 'application/pdf',
|
|
116
|
+
* }
|
|
117
|
+
* ```
|
|
118
|
+
*
|
|
119
|
+
* Only the **response** is raw — hence the name, and the difference from
|
|
120
|
+
* `rawRoutes`, which sit outside the contract entirely. Here the request half is
|
|
121
|
+
* unchanged: `params` / `input` / `multipart` parse and validate exactly as
|
|
122
|
+
* elsewhere, and `beforeHandle` runs, so the auth gate applies with no guard in
|
|
123
|
+
* the handler. What is handed over is the response, so there is no `output` to
|
|
124
|
+
* validate, nothing to serialize into a tool result, and the endpoint is
|
|
125
|
+
* **HTTP-only**: never an MCP tool, an agent tool or a CLI command.
|
|
126
|
+
* `afterHandle` is skipped (it transforms data; there is none).
|
|
127
|
+
*/
|
|
128
|
+
interface RawResponseEndpointDef extends EndpointDefBase {
|
|
129
|
+
/**
|
|
130
|
+
* Marks the response as raw. Must be the literal `true` — it is the
|
|
131
|
+
* discriminant of the union, so `rawResponse: false` is not a way to say
|
|
132
|
+
* "normal".
|
|
133
|
+
*/
|
|
134
|
+
rawResponse: true;
|
|
135
|
+
/**
|
|
136
|
+
* The `Content-Type` this endpoint answers with, for documentation only —
|
|
137
|
+
* the handler still sets the real header (`serveFile` detects it from the
|
|
138
|
+
* path). Drives the OpenAPI response media type; without it the endpoint
|
|
139
|
+
* documents as `application/octet-stream`.
|
|
140
|
+
*/
|
|
141
|
+
contentType?: string;
|
|
142
|
+
/** There is no output schema — the handler owns the whole response. */
|
|
143
|
+
output?: never;
|
|
144
|
+
/** Never a tool, so a tool name would be dead metadata. */
|
|
145
|
+
toolName?: never;
|
|
146
|
+
/** MCP-only decoration; a raw endpoint never reaches MCP. */
|
|
147
|
+
ui?: never;
|
|
148
|
+
/** MCP-only decoration; a raw endpoint never reaches MCP. */
|
|
149
|
+
annotations?: never;
|
|
150
|
+
/** Redundant but allowed, so `expose: ['HTTP']` survives a migration. */
|
|
151
|
+
expose?: readonly ['HTTP'];
|
|
152
|
+
}
|
|
153
|
+
export type EndpointDef = HttpOnlyEndpointDef | ToolEndpointDef | RawResponseEndpointDef;
|
|
106
154
|
export interface ContractMeta<TScope extends string = string> {
|
|
107
155
|
prefix: string;
|
|
108
156
|
scope?: TScope;
|
|
157
|
+
/**
|
|
158
|
+
* Contract-wide default for every endpoint's opaque `meta` (→ ADR 0021).
|
|
159
|
+
* Endpoints **shallow-merge** over it, key by key — so a contract-wide
|
|
160
|
+
* `{ public: true }` survives an endpoint that adds `{ rateTier: 2 }`. One
|
|
161
|
+
* level only, no deep merge. An explicit `key: undefined` on the endpoint is
|
|
162
|
+
* the opt-out: it shadows the contract's value, so `meta?.key` readers see
|
|
163
|
+
* nothing — test values, not key membership. → ADR 0036.
|
|
164
|
+
*
|
|
165
|
+
* `expose` deliberately has no equivalent — see ADR 0036 for why, and pin
|
|
166
|
+
* `listToolNames` in a snapshot to catch an endpoint that forgot it.
|
|
167
|
+
*/
|
|
168
|
+
meta?: Record<string, unknown>;
|
|
109
169
|
}
|
|
110
170
|
export interface ContractDef<T extends Record<string, EndpointDef> = Record<string, EndpointDef>, TScope extends string = string> {
|
|
111
171
|
meta: ContractMeta<TScope>;
|
|
@@ -119,11 +179,21 @@ export interface ContractDef<T extends Record<string, EndpointDef> = Record<stri
|
|
|
119
179
|
*/
|
|
120
180
|
export declare function defineContract<const T extends Record<string, EndpointDef>>(meta: {
|
|
121
181
|
prefix: string;
|
|
182
|
+
meta?: Record<string, unknown>;
|
|
122
183
|
}, endpoints: T): ContractDef<T, 'public'>;
|
|
123
184
|
export declare function defineContract<TScope extends string, const T extends Record<string, EndpointDef>>(meta: {
|
|
124
185
|
prefix: string;
|
|
125
186
|
scope: TScope;
|
|
187
|
+
meta?: Record<string, unknown>;
|
|
126
188
|
}, endpoints: T): ContractDef<T, TScope>;
|
|
189
|
+
/**
|
|
190
|
+
* Shallow-merge a contract-wide `meta` default with an endpoint's own — endpoint
|
|
191
|
+
* keys win. Returns `undefined` when neither side declares anything, because
|
|
192
|
+
* readers test `method.meta?.x` and an empty object would read as "declared".
|
|
193
|
+
* One level deep by design: a deep merge invites "how do I unset an inherited
|
|
194
|
+
* key", which has no answer without a sentinel. → ADR 0036.
|
|
195
|
+
*/
|
|
196
|
+
export declare function mergeMeta(contractMeta: Record<string, unknown> | undefined, endpointMeta: Record<string, unknown> | undefined): Record<string, unknown> | undefined;
|
|
127
197
|
export interface RuntimeContext {
|
|
128
198
|
params: unknown;
|
|
129
199
|
input: unknown;
|
|
@@ -191,7 +261,14 @@ type MultipartArgs<E> = E extends {
|
|
|
191
261
|
[P in K]: MultipartFile;
|
|
192
262
|
} : unknown;
|
|
193
263
|
type EndpointArgs<E> = InferInput<Prop<E, 'params'>> & InferInput<Prop<E, 'input'>> & MultipartArgs<E>;
|
|
194
|
-
|
|
264
|
+
/**
|
|
265
|
+
* What the typed client resolves to. A `raw` endpoint hands back the untouched
|
|
266
|
+
* `Response` — its body is bytes, and the headers carry what the caller needs
|
|
267
|
+
* (`Content-Disposition`, `Content-Range`, `ETag`). → ADR 0038.
|
|
268
|
+
*/
|
|
269
|
+
type EndpointOutput<E> = E extends {
|
|
270
|
+
rawResponse: true;
|
|
271
|
+
} ? Response : Prop<E, 'output'> extends ZodType<infer O> ? O : undefined;
|
|
195
272
|
export type EndpointFn<E> = [keyof EndpointArgs<E>] extends [never] ? () => Promise<EndpointOutput<E>> : (args: EndpointArgs<E>) => Promise<EndpointOutput<E>>;
|
|
196
273
|
export type TypedClient<C extends Record<string, EndpointDef>> = {
|
|
197
274
|
[K in keyof C]: EndpointFn<C[K]>;
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../../src/contract/define.ts"],"names":[],"mappings":"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"}
|
|
@@ -25,6 +25,7 @@ import type { ContractDef, EndpointDef } from './define';
|
|
|
25
25
|
export type ScopedDefineContract<TScope extends string> = <const T extends Record<string, EndpointDef>>(meta: {
|
|
26
26
|
prefix: string;
|
|
27
27
|
scope: TScope;
|
|
28
|
+
meta?: Record<string, unknown>;
|
|
28
29
|
}, endpoints: T) => ContractDef<T, TScope>;
|
|
29
30
|
/**
|
|
30
31
|
* Build a `defineContract` that requires a `scope` from the application's own
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/contract/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAGzD,0EAA0E;AAC1E,MAAM,MAAM,oBAAoB,CAAC,MAAM,SAAS,MAAM,IAAI,CACxD,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EAE3C,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/contract/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAGzD,0EAA0E;AAC1E,MAAM,MAAM,oBAAoB,CAAC,MAAM,SAAS,MAAM,IAAI,CACxD,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EAE3C,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,EACvE,SAAS,EAAE,CAAC,KACT,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AAE5B;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,SAAS,MAAM,KAAK;IAC9D,cAAc,EAAE,oBAAoB,CAAC,MAAM,CAAC,CAAC;CAC9C,CAiBA"}
|
package/dist/contract/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
isWithinDir,
|
|
8
8
|
normalizeError,
|
|
9
9
|
validateHandlerOutput
|
|
10
|
-
} from "./index-
|
|
10
|
+
} from "./index-zza375qp.js";
|
|
11
11
|
import {
|
|
12
12
|
isRecord,
|
|
13
13
|
isUnsafeKey,
|
|
@@ -346,7 +346,7 @@ function toolResultFromError(err) {
|
|
|
346
346
|
...appErr.hint && { hint: appErr.hint }
|
|
347
347
|
};
|
|
348
348
|
}
|
|
349
|
-
async function executeToolMethod(method, toolName, rawArgs, context, hooks, lifecycle, coerceJson = false) {
|
|
349
|
+
async function executeToolMethod(method, toolName, rawArgs, context, hooks, lifecycle, coerceJson = false, onOutputStrip) {
|
|
350
350
|
const startedAt = Date.now();
|
|
351
351
|
const finish = async (result) => {
|
|
352
352
|
await hooks?.afterToolCall?.(toolName, rawArgs, result, Date.now() - startedAt, context, method);
|
|
@@ -410,7 +410,7 @@ async function executeToolMethod(method, toolName, rawArgs, context, hooks, life
|
|
|
410
410
|
data = transformed;
|
|
411
411
|
}
|
|
412
412
|
if (method.outputSchema) {
|
|
413
|
-
const checked = validateHandlerOutput(method.outputSchema, data);
|
|
413
|
+
const checked = validateHandlerOutput(method.outputSchema, data, onOutputStrip);
|
|
414
414
|
if (!checked.ok) {
|
|
415
415
|
return finish({
|
|
416
416
|
ok: false,
|
|
@@ -437,6 +437,13 @@ var SINGULAR_EXCEPTIONS = new Set([
|
|
|
437
437
|
"progress",
|
|
438
438
|
"news"
|
|
439
439
|
]);
|
|
440
|
+
var TOOL_NAME_RE = /^[a-zA-Z0-9_-]{1,64}$/;
|
|
441
|
+
function normalizeService(value) {
|
|
442
|
+
return value.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
443
|
+
}
|
|
444
|
+
function normalizeMethod(value) {
|
|
445
|
+
return value.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
446
|
+
}
|
|
440
447
|
function singularize(name) {
|
|
441
448
|
if (SINGULAR_EXCEPTIONS.has(name))
|
|
442
449
|
return name;
|
|
@@ -446,22 +453,44 @@ function singularize(name) {
|
|
|
446
453
|
return name.slice(0, -1);
|
|
447
454
|
return name;
|
|
448
455
|
}
|
|
456
|
+
function singularizeTail(name) {
|
|
457
|
+
const cut = name.lastIndexOf("_");
|
|
458
|
+
if (cut === -1)
|
|
459
|
+
return singularize(name);
|
|
460
|
+
return `${name.slice(0, cut + 1)}${singularize(name.slice(cut + 1))}`;
|
|
461
|
+
}
|
|
462
|
+
function hasUsableChars(value) {
|
|
463
|
+
return /[a-zA-Z0-9]/.test(value);
|
|
464
|
+
}
|
|
465
|
+
function assertToolName(name, serviceName, key) {
|
|
466
|
+
const where = `service "${serviceName}", method "${key}"`;
|
|
467
|
+
if (!TOOL_NAME_RE.test(name)) {
|
|
468
|
+
const why = name.length > 64 ? `is ${name.length} characters (max 64) — set an explicit \`toolName\`` : "must match [a-zA-Z0-9_-]";
|
|
469
|
+
throw new Error(`Tool name "${name}" (${where}) ${why}`);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
449
472
|
function toToolName(serviceName, methodName) {
|
|
450
|
-
const normalized = serviceName
|
|
451
|
-
const singular =
|
|
452
|
-
|
|
473
|
+
const normalized = normalizeService(serviceName);
|
|
474
|
+
const singular = singularizeTail(normalized);
|
|
475
|
+
const method = normalizeMethod(methodName);
|
|
476
|
+
if (method === "list")
|
|
453
477
|
return `list_${normalized}`;
|
|
454
|
-
if (
|
|
478
|
+
if (method === "get")
|
|
455
479
|
return `get_${singular}`;
|
|
456
|
-
if (
|
|
480
|
+
if (method === "create")
|
|
457
481
|
return `create_${singular}`;
|
|
458
|
-
if (
|
|
482
|
+
if (method === "update")
|
|
459
483
|
return `update_${singular}`;
|
|
460
|
-
if (
|
|
484
|
+
if (method === "delete")
|
|
461
485
|
return `delete_${singular}`;
|
|
462
|
-
const snake =
|
|
486
|
+
const snake = method.replace(/([A-Z])/g, "_$1").toLowerCase();
|
|
463
487
|
return `${snake}_${singular}`.replace(/^_/, "");
|
|
464
488
|
}
|
|
489
|
+
function assertUniqueToolName(name, taken, surface) {
|
|
490
|
+
if (taken) {
|
|
491
|
+
throw new Error(`Duplicate ${surface} "${name}" across mounted services`);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
465
494
|
|
|
466
495
|
// src/tools/mount.ts
|
|
467
496
|
function applyExtend(base, extra) {
|
|
@@ -475,7 +504,7 @@ function applyExtend(base, extra) {
|
|
|
475
504
|
return z4.intersection(z4.object(extra), base);
|
|
476
505
|
}
|
|
477
506
|
function collectTools(service, transport, config = {}) {
|
|
478
|
-
const { extend, flattenUnionInput = false } = config;
|
|
507
|
+
const { extend, flattenUnionInput = false, assertNames = true } = config;
|
|
479
508
|
const tools = [];
|
|
480
509
|
for (const [methodName, method] of Object.entries(service.methods)) {
|
|
481
510
|
if (transport === "CLI") {
|
|
@@ -486,7 +515,15 @@ function collectTools(service, transport, config = {}) {
|
|
|
486
515
|
}
|
|
487
516
|
if (method.multipart)
|
|
488
517
|
continue;
|
|
518
|
+
if (method.rawResponse)
|
|
519
|
+
continue;
|
|
489
520
|
const name = method.toolName ?? toToolName(service.name, methodName);
|
|
521
|
+
if (assertNames && transport !== "CLI") {
|
|
522
|
+
if (!method.toolName && !hasUsableChars(service.name)) {
|
|
523
|
+
throw new Error(`Service prefix "${service.name}" (method "${methodName}") has no characters usable in a tool name — set an explicit \`toolName\` or rename the prefix`);
|
|
524
|
+
}
|
|
525
|
+
assertToolName(name, service.name, methodName);
|
|
526
|
+
}
|
|
490
527
|
const baseSchema = flattenUnionInput ? mergeSchemas(method.paramsSchema ? flattenUnionsDeep(method.paramsSchema) : undefined, method.inputSchema ? flattenUnionsDeep(method.inputSchema) : undefined) : mergeSchemas(method.paramsSchema, method.inputSchema);
|
|
491
528
|
const shouldExtend = !!extend && (!extend.filter || extend.filter(service, method));
|
|
492
529
|
const schema = shouldExtend && extend ? applyExtend(baseSchema, extend.schema) : baseSchema;
|
|
@@ -502,7 +539,7 @@ function createToolRunner(config) {
|
|
|
502
539
|
extraContext = await config.extend.resolve(rawArgs);
|
|
503
540
|
}
|
|
504
541
|
const cleanArgs = tool.shouldExtend && extendKeys ? Object.fromEntries(Object.entries(rawArgs).filter(([key]) => !extendKeys.has(key))) : rawArgs;
|
|
505
|
-
return executeToolMethod(tool.method, tool.name, cleanArgs, { ...config.context, ...extraContext, source: config.source }, config.hooks, config.lifecycle, config.coerceJsonArgs ?? true);
|
|
542
|
+
return executeToolMethod(tool.method, tool.name, cleanArgs, { ...config.context, ...extraContext, source: config.source }, config.hooks, config.lifecycle, config.coerceJsonArgs ?? true, config.onOutputStrip ? (paths) => config.onOutputStrip?.(tool.name, paths) : undefined);
|
|
506
543
|
};
|
|
507
544
|
}
|
|
508
545
|
function formatToolError(result, toolName, errorHint) {
|
|
@@ -845,7 +882,6 @@ async function pollUntilDone(params) {
|
|
|
845
882
|
}
|
|
846
883
|
|
|
847
884
|
// src/tools/cli.ts
|
|
848
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
849
885
|
import { basename, resolve } from "node:path";
|
|
850
886
|
import process from "node:process";
|
|
851
887
|
|
|
@@ -962,6 +998,17 @@ async function readCapped(res, max) {
|
|
|
962
998
|
return Buffer.concat(chunks);
|
|
963
999
|
}
|
|
964
1000
|
|
|
1001
|
+
// src/internal/write-download.ts
|
|
1002
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
1003
|
+
import { dirname } from "node:path";
|
|
1004
|
+
async function writeDownload(root, target, data) {
|
|
1005
|
+
if (!isWithinDir(root, target)) {
|
|
1006
|
+
throw new Error("download name escapes the output dir");
|
|
1007
|
+
}
|
|
1008
|
+
await mkdir(dirname(target), { recursive: true });
|
|
1009
|
+
await writeFile(target, data);
|
|
1010
|
+
}
|
|
1011
|
+
|
|
965
1012
|
// src/tools/cli.ts
|
|
966
1013
|
var GLOBAL_OPTIONS = [
|
|
967
1014
|
["--json", "Emit raw JSON on stdout (for piping / scripts)"],
|
|
@@ -1085,7 +1132,6 @@ function renderCommandHelp(name, command, tool) {
|
|
|
1085
1132
|
var DEFAULT_DOWNLOAD_MAX_BYTES = 100 * 1024 * 1024;
|
|
1086
1133
|
async function downloadResults(files, dir, stderr, quiet, allowPrivate, maxBytes) {
|
|
1087
1134
|
const root = resolve(dir);
|
|
1088
|
-
await mkdir(root, { recursive: true });
|
|
1089
1135
|
for (const file of files) {
|
|
1090
1136
|
try {
|
|
1091
1137
|
const res = await fetchGuarded(new URL(file.url), allowPrivate);
|
|
@@ -1095,9 +1141,7 @@ async function downloadResults(files, dir, stderr, quiet, allowPrivate, maxBytes
|
|
|
1095
1141
|
if (!buffer)
|
|
1096
1142
|
throw new Error(`file exceeds the ${maxBytes}-byte cap`);
|
|
1097
1143
|
const target = resolve(root, basename(file.name));
|
|
1098
|
-
|
|
1099
|
-
throw new Error("download name escapes the output dir");
|
|
1100
|
-
await writeFile(target, buffer);
|
|
1144
|
+
await writeDownload(root, target, buffer);
|
|
1101
1145
|
if (!quiet)
|
|
1102
1146
|
stderr(`saved ${target} (${(buffer.length / 1024).toFixed(0)}KB)
|
|
1103
1147
|
`);
|
|
@@ -1119,9 +1163,7 @@ async function createCli(config) {
|
|
|
1119
1163
|
const tools = new Map;
|
|
1120
1164
|
for (const service of services) {
|
|
1121
1165
|
for (const mountable of collectTools(service, "CLI")) {
|
|
1122
|
-
|
|
1123
|
-
throw new Error(`Duplicate CLI command "${mountable.name}" across mounted services`);
|
|
1124
|
-
}
|
|
1166
|
+
assertUniqueToolName(mountable.name, tools.has(mountable.name), "CLI command");
|
|
1125
1167
|
tools.set(mountable.name, mountable);
|
|
1126
1168
|
}
|
|
1127
1169
|
}
|
|
@@ -1216,4 +1258,4 @@ function safeInputSchema(tool) {
|
|
|
1216
1258
|
}
|
|
1217
1259
|
}
|
|
1218
1260
|
|
|
1219
|
-
export { coerceJsonArgs, toolResultFromError, flattenDiscriminatedUnion, flattenUnionsDeep, collectTools, createToolRunner, formatToolError, fetchGuarded, readCapped, parseCliArgs, DEFAULT_EXIT_CODES, emitResult, pollUntil, pollUntilDone, createCli };
|
|
1261
|
+
export { coerceJsonArgs, toolResultFromError, flattenDiscriminatedUnion, flattenUnionsDeep, assertToolName, assertUniqueToolName, collectTools, createToolRunner, formatToolError, fetchGuarded, readCapped, writeDownload, parseCliArgs, DEFAULT_EXIT_CODES, emitResult, pollUntil, pollUntilDone, createCli };
|
|
@@ -10,6 +10,8 @@ function defineContract(meta, endpoints) {
|
|
|
10
10
|
if (ep.desc.trim() === "") {
|
|
11
11
|
throw new Error(`Contract "${meta.prefix}": endpoint "${key}" has an empty desc`);
|
|
12
12
|
}
|
|
13
|
+
if (ep.rawResponse)
|
|
14
|
+
assertRawEndpoint(meta.prefix, key, ep);
|
|
13
15
|
if (!("toolName" in ep) || !ep.toolName)
|
|
14
16
|
continue;
|
|
15
17
|
const transports = new Set(ep.expose ? ep.expose.filter((t) => t !== "HTTP") : ["MCP", "AGENT"]);
|
|
@@ -30,6 +32,22 @@ function defineContract(meta, endpoints) {
|
|
|
30
32
|
}
|
|
31
33
|
return { meta, endpoints };
|
|
32
34
|
}
|
|
35
|
+
function assertRawEndpoint(prefix, key, ep) {
|
|
36
|
+
const where = `Contract "${prefix}": raw endpoint "${key}"`;
|
|
37
|
+
if (ep.output)
|
|
38
|
+
throw new Error(`${where} cannot declare an output schema`);
|
|
39
|
+
if ("toolName" in ep && ep.toolName)
|
|
40
|
+
throw new Error(`${where} cannot set a toolName`);
|
|
41
|
+
if ("ui" in ep && ep.ui)
|
|
42
|
+
throw new Error(`${where} cannot set MCP ui metadata`);
|
|
43
|
+
if ("annotations" in ep && ep.annotations) {
|
|
44
|
+
throw new Error(`${where} cannot set MCP annotations`);
|
|
45
|
+
}
|
|
46
|
+
const nonHttp = (ep.expose ?? []).filter((t) => t !== "HTTP");
|
|
47
|
+
if (nonHttp.length > 0) {
|
|
48
|
+
throw new Error(`${where} is HTTP-only — remove ${nonHttp.join(", ")} from expose`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
33
51
|
// src/contract/errors.ts
|
|
34
52
|
var APP_ERROR_BRAND = Symbol.for("stitchkit.AppError");
|
|
35
53
|
|
|
@@ -116,7 +134,7 @@ function createContractFactory() {
|
|
|
116
134
|
const validated = defineContract({ prefix: meta.prefix }, endpoints);
|
|
117
135
|
return {
|
|
118
136
|
endpoints: validated.endpoints,
|
|
119
|
-
meta: { prefix: meta.prefix, scope: meta.scope }
|
|
137
|
+
meta: { ...meta, prefix: meta.prefix, scope: meta.scope }
|
|
120
138
|
};
|
|
121
139
|
}
|
|
122
140
|
};
|
|
@@ -2,15 +2,16 @@ import {
|
|
|
2
2
|
assertCorsConfig,
|
|
3
3
|
corsHeaders,
|
|
4
4
|
corsPreflightResponse
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-zfscdskj.js";
|
|
6
6
|
import {
|
|
7
7
|
AppError,
|
|
8
8
|
badRequest,
|
|
9
9
|
errorCode,
|
|
10
10
|
isWithinDir,
|
|
11
|
+
mergeMeta,
|
|
11
12
|
normalizeError,
|
|
12
13
|
validateHandlerOutput
|
|
13
|
-
} from "./index-
|
|
14
|
+
} from "./index-zza375qp.js";
|
|
14
15
|
import {
|
|
15
16
|
extractIp,
|
|
16
17
|
getClientInfo,
|
|
@@ -212,6 +213,26 @@ function validateRoutes(routeMap) {
|
|
|
212
213
|
}
|
|
213
214
|
}
|
|
214
215
|
}
|
|
216
|
+
function findShadowedRoutes(routeMap, rawRoutes) {
|
|
217
|
+
if (!rawRoutes || rawRoutes.length === 0)
|
|
218
|
+
return [];
|
|
219
|
+
const shadowed = [];
|
|
220
|
+
for (const [httpMethod, entries] of routeMap) {
|
|
221
|
+
for (const entry of entries) {
|
|
222
|
+
const probe = `/${entry.segments.map((s) => s.startsWith(":") ? "__param__" : s).join("/")}`;
|
|
223
|
+
const match = matchRawRoute(rawRoutes, httpMethod, probe);
|
|
224
|
+
if (!match)
|
|
225
|
+
continue;
|
|
226
|
+
shadowed.push({
|
|
227
|
+
pattern: `${httpMethod} ${entry.pattern}`,
|
|
228
|
+
endpoint: `${entry.method.serviceName}.${entry.method.key}`,
|
|
229
|
+
rawRoute: `${match.route.method} ${match.route.path}`,
|
|
230
|
+
scope: entry.method.scope
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return shadowed;
|
|
235
|
+
}
|
|
215
236
|
function matchRawRoute(rawRoutes, httpMethod, pathname) {
|
|
216
237
|
for (const route of rawRoutes) {
|
|
217
238
|
if (route.method !== "ALL" && route.method !== httpMethod)
|
|
@@ -476,6 +497,14 @@ function createHandler(config) {
|
|
|
476
497
|
const resolveId = config.traceId ?? resolveTraceId;
|
|
477
498
|
const routeMap = buildRouteMap(normalizeGroups(config));
|
|
478
499
|
validateRoutes(routeMap);
|
|
500
|
+
for (const shadow of findShadowedRoutes(routeMap, config.rawRoutes)) {
|
|
501
|
+
const gate = shadow.scope && shadow.scope !== "public" ? ` (scope "${shadow.scope}")` : "";
|
|
502
|
+
const line = `[stitchkit] raw route ${shadow.rawRoute} shadows contract route ${shadow.pattern}` + ` → ${shadow.endpoint}${gate} will never run, and its hooks never apply`;
|
|
503
|
+
if (customLogger)
|
|
504
|
+
customLogger.warn(line);
|
|
505
|
+
else
|
|
506
|
+
console.warn(line);
|
|
507
|
+
}
|
|
479
508
|
async function dispatch(req, url, traceId, server, clientIp) {
|
|
480
509
|
const shouldLogRequest = logging && shouldLog(url.pathname, req.method);
|
|
481
510
|
const ipAddress = extractIp(req, clientIp) || undefined;
|
|
@@ -570,6 +599,14 @@ function createHandler(config) {
|
|
|
570
599
|
await groupHooks.beforeHandle(ctx, method);
|
|
571
600
|
}
|
|
572
601
|
let result = await method.handler(ctx);
|
|
602
|
+
if (method.rawResponse) {
|
|
603
|
+
if (!(result instanceof Response)) {
|
|
604
|
+
throw new AppError("INTERNAL_SERVER_ERROR", `Raw endpoint ${method.serviceName}.${method.key} must return a Response`, 500);
|
|
605
|
+
}
|
|
606
|
+
const rawRes = applyCors(result, cors, req);
|
|
607
|
+
logDone(rawRes.status);
|
|
608
|
+
return rawRes;
|
|
609
|
+
}
|
|
573
610
|
if (groupHooks?.afterHandle) {
|
|
574
611
|
const transformed = await groupHooks.afterHandle(ctx, result, method);
|
|
575
612
|
if (transformed !== undefined)
|
|
@@ -580,8 +617,17 @@ function createHandler(config) {
|
|
|
580
617
|
if (transformed !== undefined)
|
|
581
618
|
result = transformed;
|
|
582
619
|
}
|
|
620
|
+
if (result instanceof Response) {
|
|
621
|
+
throw new AppError("INTERNAL_SERVER_ERROR", `${method.serviceName}.${method.key} produced a Response on the data path — only a \`rawResponse: true\` endpoint may return one (an afterHandle hook must return data)`, 500);
|
|
622
|
+
}
|
|
583
623
|
if (method.outputSchema) {
|
|
584
|
-
const checked = validateHandlerOutput(method.outputSchema, result)
|
|
624
|
+
const checked = validateHandlerOutput(method.outputSchema, result, config.warnOnOutputStrip ? (paths) => {
|
|
625
|
+
const line = `[stitchkit] output strip ${method.serviceName}.${method.key}: ${paths.join(", ")}`;
|
|
626
|
+
if (customLogger)
|
|
627
|
+
customLogger.warn(line);
|
|
628
|
+
else
|
|
629
|
+
console.warn(line);
|
|
630
|
+
} : undefined);
|
|
585
631
|
if (!checked.ok) {
|
|
586
632
|
throw new AppError("INTERNAL_SERVER_ERROR", checked.message, 500);
|
|
587
633
|
}
|
|
@@ -656,20 +702,41 @@ function applyCors(res, cors, req) {
|
|
|
656
702
|
const extra = corsHeaders2(cors, req);
|
|
657
703
|
if (Object.keys(extra).length === 0)
|
|
658
704
|
return res;
|
|
659
|
-
|
|
660
|
-
|
|
705
|
+
try {
|
|
706
|
+
for (const [key, value] of Object.entries(extra))
|
|
707
|
+
setCorsHeader(res.headers, key, value);
|
|
708
|
+
return res;
|
|
709
|
+
} catch {
|
|
710
|
+
const headers = new Headers(res.headers);
|
|
711
|
+
for (const [key, value] of Object.entries(extra))
|
|
712
|
+
setCorsHeader(headers, key, value);
|
|
713
|
+
return new Response(res.body, {
|
|
714
|
+
status: res.status,
|
|
715
|
+
statusText: res.statusText,
|
|
716
|
+
headers
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
function setCorsHeader(headers, key, value) {
|
|
721
|
+
if (key !== "Vary") {
|
|
661
722
|
headers.set(key, value);
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
const existing = headers.get("Vary");
|
|
726
|
+
if (existing === null || existing.trim() === "") {
|
|
727
|
+
headers.set("Vary", value);
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
const present = existing.split(",").some((field) => field.trim().toLowerCase() === "origin");
|
|
731
|
+
if (!present)
|
|
732
|
+
headers.set("Vary", `${existing}, ${value}`);
|
|
667
733
|
}
|
|
668
734
|
function json(data, status, cors, req) {
|
|
669
735
|
return Response.json(data, { status, headers: corsHeaders2(cors, req) });
|
|
670
736
|
}
|
|
671
737
|
|
|
672
738
|
// src/server/implement.ts
|
|
739
|
+
var HTTP_ONLY = Object.freeze(["HTTP"]);
|
|
673
740
|
function implement(contract, handlers) {
|
|
674
741
|
const methods = {};
|
|
675
742
|
const groupScope = contract.meta.scope ?? "public";
|
|
@@ -682,7 +749,7 @@ function implement(contract, handlers) {
|
|
|
682
749
|
serviceName: contract.meta.prefix,
|
|
683
750
|
key: String(key),
|
|
684
751
|
toolName: "toolName" in endpoint ? endpoint.toolName : undefined,
|
|
685
|
-
expose: endpoint.expose,
|
|
752
|
+
expose: endpoint.rawResponse ? HTTP_ONLY : endpoint.expose,
|
|
686
753
|
scope: endpoint.scope ?? groupScope,
|
|
687
754
|
paramsSchema: endpoint.params,
|
|
688
755
|
inputSchema: endpoint.input,
|
|
@@ -692,7 +759,9 @@ function implement(contract, handlers) {
|
|
|
692
759
|
idempotent: endpoint.idempotent,
|
|
693
760
|
ui: "ui" in endpoint ? endpoint.ui : undefined,
|
|
694
761
|
annotations: "annotations" in endpoint ? endpoint.annotations : undefined,
|
|
695
|
-
meta: endpoint.meta,
|
|
762
|
+
meta: mergeMeta(contract.meta.meta, endpoint.meta),
|
|
763
|
+
rawResponse: endpoint.rawResponse,
|
|
764
|
+
contentType: "contentType" in endpoint ? endpoint.contentType : undefined,
|
|
696
765
|
handler: (ctx) => typedHandler(ctx)
|
|
697
766
|
};
|
|
698
767
|
}
|