stitchkit 0.26.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.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 +60 -3
- package/dist/contract/define.d.ts.map +1 -1
- package/dist/contract/index.js +1 -1
- package/dist/{index-q5w3cvvp.js → index-4whcb3c3.js} +3 -1
- package/dist/{index-p6fge9a5.js → index-jvescqgr.js} +1 -1
- package/dist/{index-h4y2wg3n.js → index-pmftwk2a.js} +18 -0
- package/dist/{index-bkccbx64.js → index-y4132gqh.js} +72 -10
- package/dist/{index-tje0q6gp.js → index-zfscdskj.js} +6 -1
- package/dist/index.js +20 -8
- package/dist/node.js +3 -3
- package/dist/server/create.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 +18 -5
- 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 +31 -1
- package/dist/server/types.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/mount.d.ts.map +1 -1
- package/dist/tools/remote.d.ts.map +1 -1
- package/dist/tools.js +24 -12
- package/llms-full.txt +129 -8
- package/llms.txt +1 -1
- package/package.json +1 -1
- /package/dist/{index-0d0rb85d.js → index-zza375qp.js} +0 -0
|
@@ -1 +1 @@
|
|
|
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;
|
|
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,8 +102,55 @@ 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;
|
|
@@ -110,7 +158,9 @@ export interface ContractMeta<TScope extends string = string> {
|
|
|
110
158
|
* Contract-wide default for every endpoint's opaque `meta` (→ ADR 0021).
|
|
111
159
|
* Endpoints **shallow-merge** over it, key by key — so a contract-wide
|
|
112
160
|
* `{ public: true }` survives an endpoint that adds `{ rateTier: 2 }`. One
|
|
113
|
-
* level only
|
|
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.
|
|
114
164
|
*
|
|
115
165
|
* `expose` deliberately has no equivalent — see ADR 0036 for why, and pin
|
|
116
166
|
* `listToolNames` in a snapshot to catch an endpoint that forgot it.
|
|
@@ -211,7 +261,14 @@ type MultipartArgs<E> = E extends {
|
|
|
211
261
|
[P in K]: MultipartFile;
|
|
212
262
|
} : unknown;
|
|
213
263
|
type EndpointArgs<E> = InferInput<Prop<E, 'params'>> & InferInput<Prop<E, 'input'>> & MultipartArgs<E>;
|
|
214
|
-
|
|
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;
|
|
215
272
|
export type EndpointFn<E> = [keyof EndpointArgs<E>] extends [never] ? () => Promise<EndpointOutput<E>> : (args: EndpointArgs<E>) => Promise<EndpointOutput<E>>;
|
|
216
273
|
export type TypedClient<C extends Record<string, EndpointDef>> = {
|
|
217
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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"}
|
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,
|
|
@@ -515,6 +515,8 @@ function collectTools(service, transport, config = {}) {
|
|
|
515
515
|
}
|
|
516
516
|
if (method.multipart)
|
|
517
517
|
continue;
|
|
518
|
+
if (method.rawResponse)
|
|
519
|
+
continue;
|
|
518
520
|
const name = method.toolName ?? toToolName(service.name, methodName);
|
|
519
521
|
if (assertNames && transport !== "CLI") {
|
|
520
522
|
if (!method.toolName && !hasUsableChars(service.name)) {
|
|
@@ -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
|
|
|
@@ -2,7 +2,7 @@ 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,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
mergeMeta,
|
|
12
12
|
normalizeError,
|
|
13
13
|
validateHandlerOutput
|
|
14
|
-
} from "./index-
|
|
14
|
+
} from "./index-zza375qp.js";
|
|
15
15
|
import {
|
|
16
16
|
extractIp,
|
|
17
17
|
getClientInfo,
|
|
@@ -213,6 +213,26 @@ function validateRoutes(routeMap) {
|
|
|
213
213
|
}
|
|
214
214
|
}
|
|
215
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
|
+
}
|
|
216
236
|
function matchRawRoute(rawRoutes, httpMethod, pathname) {
|
|
217
237
|
for (const route of rawRoutes) {
|
|
218
238
|
if (route.method !== "ALL" && route.method !== httpMethod)
|
|
@@ -477,6 +497,14 @@ function createHandler(config) {
|
|
|
477
497
|
const resolveId = config.traceId ?? resolveTraceId;
|
|
478
498
|
const routeMap = buildRouteMap(normalizeGroups(config));
|
|
479
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
|
+
}
|
|
480
508
|
async function dispatch(req, url, traceId, server, clientIp) {
|
|
481
509
|
const shouldLogRequest = logging && shouldLog(url.pathname, req.method);
|
|
482
510
|
const ipAddress = extractIp(req, clientIp) || undefined;
|
|
@@ -571,6 +599,14 @@ function createHandler(config) {
|
|
|
571
599
|
await groupHooks.beforeHandle(ctx, method);
|
|
572
600
|
}
|
|
573
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
|
+
}
|
|
574
610
|
if (groupHooks?.afterHandle) {
|
|
575
611
|
const transformed = await groupHooks.afterHandle(ctx, result, method);
|
|
576
612
|
if (transformed !== undefined)
|
|
@@ -581,6 +617,9 @@ function createHandler(config) {
|
|
|
581
617
|
if (transformed !== undefined)
|
|
582
618
|
result = transformed;
|
|
583
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
|
+
}
|
|
584
623
|
if (method.outputSchema) {
|
|
585
624
|
const checked = validateHandlerOutput(method.outputSchema, result, config.warnOnOutputStrip ? (paths) => {
|
|
586
625
|
const line = `[stitchkit] output strip ${method.serviceName}.${method.key}: ${paths.join(", ")}`;
|
|
@@ -663,20 +702,41 @@ function applyCors(res, cors, req) {
|
|
|
663
702
|
const extra = corsHeaders2(cors, req);
|
|
664
703
|
if (Object.keys(extra).length === 0)
|
|
665
704
|
return res;
|
|
666
|
-
|
|
667
|
-
|
|
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") {
|
|
668
722
|
headers.set(key, value);
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
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}`);
|
|
674
733
|
}
|
|
675
734
|
function json(data, status, cors, req) {
|
|
676
735
|
return Response.json(data, { status, headers: corsHeaders2(cors, req) });
|
|
677
736
|
}
|
|
678
737
|
|
|
679
738
|
// src/server/implement.ts
|
|
739
|
+
var HTTP_ONLY = Object.freeze(["HTTP"]);
|
|
680
740
|
function implement(contract, handlers) {
|
|
681
741
|
const methods = {};
|
|
682
742
|
const groupScope = contract.meta.scope ?? "public";
|
|
@@ -689,7 +749,7 @@ function implement(contract, handlers) {
|
|
|
689
749
|
serviceName: contract.meta.prefix,
|
|
690
750
|
key: String(key),
|
|
691
751
|
toolName: "toolName" in endpoint ? endpoint.toolName : undefined,
|
|
692
|
-
expose: endpoint.expose,
|
|
752
|
+
expose: endpoint.rawResponse ? HTTP_ONLY : endpoint.expose,
|
|
693
753
|
scope: endpoint.scope ?? groupScope,
|
|
694
754
|
paramsSchema: endpoint.params,
|
|
695
755
|
inputSchema: endpoint.input,
|
|
@@ -700,6 +760,8 @@ function implement(contract, handlers) {
|
|
|
700
760
|
ui: "ui" in endpoint ? endpoint.ui : undefined,
|
|
701
761
|
annotations: "annotations" in endpoint ? endpoint.annotations : undefined,
|
|
702
762
|
meta: mergeMeta(contract.meta.meta, endpoint.meta),
|
|
763
|
+
rawResponse: endpoint.rawResponse,
|
|
764
|
+
contentType: "contentType" in endpoint ? endpoint.contentType : undefined,
|
|
703
765
|
handler: (ctx) => typedHandler(ctx)
|
|
704
766
|
};
|
|
705
767
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// src/server/middleware/cors.ts
|
|
2
2
|
var DEFAULT_CORS_ALLOW_HEADERS = "Content-Type, Authorization, X-Trace-Id, traceparent, tracestate";
|
|
3
|
+
var DEFAULT_CORS_EXPOSE_HEADERS = "Content-Disposition, Content-Length, Content-Range, Accept-Ranges, ETag, Last-Modified, X-Trace-Id";
|
|
3
4
|
function assertCorsConfig(config) {
|
|
4
5
|
if (config.credentials && (config.origin === undefined || config.origin === "*")) {
|
|
5
6
|
throw new Error("[stitchkit] cors: `credentials: true` cannot be combined with a wildcard origin. " + "Set `origin` to an explicit string or list.");
|
|
@@ -23,6 +24,10 @@ function corsHeaders(config, requestOrigin) {
|
|
|
23
24
|
"Access-Control-Allow-Methods": config.methods ?? "GET, POST, PUT, PATCH, DELETE, OPTIONS",
|
|
24
25
|
"Access-Control-Allow-Headers": config.headers ?? DEFAULT_CORS_ALLOW_HEADERS
|
|
25
26
|
};
|
|
27
|
+
const expose = Array.isArray(config.exposeHeaders) ? config.exposeHeaders.join(", ") : config.exposeHeaders ?? DEFAULT_CORS_EXPOSE_HEADERS;
|
|
28
|
+
if (expose !== "") {
|
|
29
|
+
headers["Access-Control-Expose-Headers"] = expose;
|
|
30
|
+
}
|
|
26
31
|
if (allowOrigin !== undefined) {
|
|
27
32
|
headers["Access-Control-Allow-Origin"] = allowOrigin;
|
|
28
33
|
if (config.credentials) {
|
|
@@ -41,4 +46,4 @@ function corsPreflightResponse(config, req) {
|
|
|
41
46
|
});
|
|
42
47
|
}
|
|
43
48
|
|
|
44
|
-
export { DEFAULT_CORS_ALLOW_HEADERS, assertCorsConfig, corsHeaders, corsPreflightResponse };
|
|
49
|
+
export { DEFAULT_CORS_ALLOW_HEADERS, DEFAULT_CORS_EXPOSE_HEADERS, assertCorsConfig, corsHeaders, corsPreflightResponse };
|
package/dist/index.js
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
paginatedSchema,
|
|
17
17
|
rateLimited,
|
|
18
18
|
unauthorized
|
|
19
|
-
} from "./index-
|
|
19
|
+
} from "./index-pmftwk2a.js";
|
|
20
20
|
import {
|
|
21
21
|
isRecord,
|
|
22
22
|
mapObject,
|
|
@@ -207,6 +207,9 @@ function createHttpClient(config) {
|
|
|
207
207
|
if (options.responseType === "blob") {
|
|
208
208
|
return client[method](url, kyOptions).blob();
|
|
209
209
|
}
|
|
210
|
+
if (options.responseType === "response") {
|
|
211
|
+
return await client[method](url, kyOptions);
|
|
212
|
+
}
|
|
210
213
|
const response = await client[method](url, kyOptions);
|
|
211
214
|
if (response.status === 204 || response.headers.get("content-length") === "0") {
|
|
212
215
|
return;
|
|
@@ -248,10 +251,15 @@ function createHttpClient(config) {
|
|
|
248
251
|
}
|
|
249
252
|
|
|
250
253
|
// src/browser/client.ts
|
|
251
|
-
function withTimeout(options,
|
|
252
|
-
|
|
254
|
+
function withTimeout(options, endpoint) {
|
|
255
|
+
const responseType = endpoint.rawResponse ? "response" : undefined;
|
|
256
|
+
if (endpoint.timeout === undefined && responseType === undefined)
|
|
253
257
|
return options;
|
|
254
|
-
return {
|
|
258
|
+
return {
|
|
259
|
+
...options,
|
|
260
|
+
...endpoint.timeout !== undefined && { timeout: endpoint.timeout },
|
|
261
|
+
...responseType && { responseType }
|
|
262
|
+
};
|
|
255
263
|
}
|
|
256
264
|
function withOutput(endpoint, result) {
|
|
257
265
|
const schema = endpoint.output;
|
|
@@ -331,15 +339,15 @@ function createHttpMethod(endpoint, prefix, client, config) {
|
|
|
331
339
|
const formData = new FormData;
|
|
332
340
|
appendMultipartFile(formData, endpoint.multipart, file);
|
|
333
341
|
appendFormFields(formData, firstArg, new Set([...prefixKeys, endpoint.multipart]));
|
|
334
|
-
return withOutput(endpoint, client[httpMethod](url, formData, withTimeout(undefined, endpoint
|
|
342
|
+
return withOutput(endpoint, client[httpMethod](url, formData, withTimeout(undefined, endpoint)));
|
|
335
343
|
}
|
|
336
344
|
if (isGet) {
|
|
337
345
|
const params = collectQueryParams(firstArg, prefixKeys, endpoint);
|
|
338
|
-
return withOutput(endpoint, client.get(url, withTimeout(params ? { params } : undefined, endpoint
|
|
346
|
+
return withOutput(endpoint, client.get(url, withTimeout(params ? { params } : undefined, endpoint)));
|
|
339
347
|
}
|
|
340
348
|
if (httpMethod === "delete") {
|
|
341
349
|
const params = collectQueryParams(firstArg, prefixKeys, endpoint);
|
|
342
|
-
return withOutput(endpoint, client.delete(url, withTimeout(params ? { params } : undefined, endpoint
|
|
350
|
+
return withOutput(endpoint, client.delete(url, withTimeout(params ? { params } : undefined, endpoint)));
|
|
343
351
|
}
|
|
344
352
|
const payload = {};
|
|
345
353
|
for (const [key, value] of Object.entries(firstArg)) {
|
|
@@ -347,7 +355,7 @@ function createHttpMethod(endpoint, prefix, client, config) {
|
|
|
347
355
|
payload[key] = value;
|
|
348
356
|
}
|
|
349
357
|
}
|
|
350
|
-
return withOutput(endpoint, client[httpMethod](url, Object.keys(payload).length > 0 ? payload : undefined, withTimeout(undefined, endpoint
|
|
358
|
+
return withOutput(endpoint, client[httpMethod](url, Object.keys(payload).length > 0 ? payload : undefined, withTimeout(undefined, endpoint)));
|
|
351
359
|
};
|
|
352
360
|
}
|
|
353
361
|
function createFetchMethod(endpoint, prefix, config, contractConfig) {
|
|
@@ -403,6 +411,8 @@ function createFetchMethod(endpoint, prefix, config, contractConfig) {
|
|
|
403
411
|
if (!res2.ok) {
|
|
404
412
|
await throwForErrorResponse(res2, config, null);
|
|
405
413
|
}
|
|
414
|
+
if (endpoint.rawResponse)
|
|
415
|
+
return res2;
|
|
406
416
|
if (res2.status === 204)
|
|
407
417
|
return;
|
|
408
418
|
const json2 = await res2.json();
|
|
@@ -420,6 +430,8 @@ function createFetchMethod(endpoint, prefix, config, contractConfig) {
|
|
|
420
430
|
if (!res.ok) {
|
|
421
431
|
await throwForErrorResponse(res, config, { error: res.statusText });
|
|
422
432
|
}
|
|
433
|
+
if (endpoint.rawResponse)
|
|
434
|
+
return res;
|
|
423
435
|
if (res.status === 204)
|
|
424
436
|
return;
|
|
425
437
|
const json = await res.json();
|
package/dist/node.js
CHANGED
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
createImplement,
|
|
4
4
|
createSocketIOServer,
|
|
5
5
|
implement
|
|
6
|
-
} from "./index-
|
|
7
|
-
import"./index-
|
|
6
|
+
} from "./index-y4132gqh.js";
|
|
7
|
+
import"./index-zfscdskj.js";
|
|
8
8
|
import {
|
|
9
9
|
AppError,
|
|
10
10
|
appError,
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
notFound,
|
|
15
15
|
rateLimited,
|
|
16
16
|
unauthorized
|
|
17
|
-
} from "./index-
|
|
17
|
+
} from "./index-zza375qp.js";
|
|
18
18
|
import"./index-dzx781tm.js";
|
|
19
19
|
import"./index-khwedj16.js";
|
|
20
20
|
import"./index-c7nyw0yt.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/server/create.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/server/create.ts"],"names":[],"mappings":"AAgCA,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,CAyRxF;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,uBAsBnD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"implement.d.ts","sourceRoot":"","sources":["../../src/server/implement.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG5E,OAAO,KAAK,EAAE,QAAQ,EAAa,UAAU,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"implement.d.ts","sourceRoot":"","sources":["../../src/server/implement.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG5E,OAAO,KAAK,EAAE,QAAQ,EAAa,UAAU,EAAE,MAAM,SAAS,CAAC;AAK/D;;;;;GAKG;AACH,wBAAgB,SAAS,CACvB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACrC,IAAI,SAAS,cAAc,GAAG,cAAc,EAC5C,QAAQ,EAAE,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,UAAU,CAyD3E;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,SAAS,cAAc,MACjD,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EAC3C,UAAU,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,EAChC,UAAU,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,KAC1B,UAAU,CACd"}
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { AppError, appError, badRequest, conflict, forbidden, isStitchErrorCode, notFound, rateLimited, STITCH_ERROR_STATUS, type StitchErrorCode, unauthorized, } from '../contract';
|
|
2
2
|
export { errorCode, formatZodError, normalizeError, type ZodIssueSummary, zodIssues, } from '../internal/errors';
|
|
3
|
+
export { isWithinDir } from '../internal/within-dir';
|
|
3
4
|
export { cacheHeaders, createCache } from './cache';
|
|
4
5
|
export { createHandler, createServer } from './create';
|
|
5
6
|
export { createErrorHook, type ErrorHookConfig, type ResolvedError, } from './error-hook';
|
|
@@ -8,7 +9,7 @@ export { type ByteRange, parseByteRange, type ServeFileOptions, serveFile, weakE
|
|
|
8
9
|
export { createImplement, implement } from './implement';
|
|
9
10
|
export { type AuthHook, type AuthHookConfig, type AuthRule, type BearerResolverConfig, createAuthHook, createBearerResolver, extractToken, type JwtPayload, type SignJwtOptions, signJwt, verifyJwt, } from './middleware/auth';
|
|
10
11
|
export { type CookieDef, type CookieOptions, defineCookie, parseCookies, serializeCookie, } from './middleware/cookies';
|
|
11
|
-
export { type CorsConfig, corsHeaders, corsPreflightResponse, DEFAULT_CORS_ALLOW_HEADERS, } from './middleware/cors';
|
|
12
|
+
export { type CorsConfig, corsHeaders, corsPreflightResponse, DEFAULT_CORS_ALLOW_HEADERS, DEFAULT_CORS_EXPOSE_HEADERS, } from './middleware/cors';
|
|
12
13
|
export { deriveCodeChallenge, type PkceMethod, verifyPkce } from './middleware/pkce';
|
|
13
14
|
export { parseMultipart } from './multipart';
|
|
14
15
|
export { generateOpenApiDocument, type OpenApiConfig, type OpenApiDocument, type OpenApiInfo, type OpenApiServer, openApiRoute, } from './openapi';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,iBAAiB,EACjB,QAAQ,EACR,WAAW,EACX,mBAAmB,EACnB,KAAK,eAAe,EACpB,YAAY,GACb,MAAM,aAAa,CAAC;AAIrB,OAAO,EACL,SAAS,EACT,cAAc,EACd,cAAc,EACd,KAAK,eAAe,EACpB,SAAS,GACV,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,iBAAiB,EACjB,QAAQ,EACR,WAAW,EACX,mBAAmB,EACnB,KAAK,eAAe,EACpB,YAAY,GACb,MAAM,aAAa,CAAC;AAIrB,OAAO,EACL,SAAS,EACT,cAAc,EACd,cAAc,EACd,KAAK,eAAe,EACpB,SAAS,GACV,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EACL,eAAe,EACf,KAAK,eAAe,EACpB,KAAK,aAAa,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EACL,KAAK,SAAS,EACd,cAAc,EACd,KAAK,gBAAgB,EACrB,SAAS,EACT,QAAQ,GACT,MAAM,QAAQ,CAAC;AAChB,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,oBAAoB,EACzB,cAAc,EACd,oBAAoB,EACpB,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,OAAO,EACP,SAAS,GACV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,YAAY,EACZ,YAAY,EACZ,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,KAAK,UAAU,EACf,WAAW,EACX,qBAAqB,EACrB,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,mBAAmB,EAAE,KAAK,UAAU,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACrF,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EACL,uBAAuB,EACvB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,YAAY,GACb,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAC9D,OAAO,EACL,KAAK,eAAe,EACpB,SAAS,EACT,eAAe,EACf,aAAa,EACb,eAAe,EACf,cAAc,GACf,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,YAAY,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,KAAK,eAAe,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrE,YAAY,EACV,SAAS,EACT,eAAe,EACf,aAAa,EACb,QAAQ,EACR,cAAc,EACd,SAAS,EACT,QAAQ,EACR,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,UAAU,EACV,YAAY,GACb,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,KAAK,YAAY,EACjB,wBAAwB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,aAAa,EAClB,aAAa,GACd,MAAM,aAAa,CAAC"}
|
package/dist/server/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
socketIoLane,
|
|
11
11
|
staticRoute,
|
|
12
12
|
webSocketLane
|
|
13
|
-
} from "../index-
|
|
13
|
+
} from "../index-y4132gqh.js";
|
|
14
14
|
import {
|
|
15
15
|
createAuthHook,
|
|
16
16
|
createBearerResolver,
|
|
@@ -23,12 +23,13 @@ import {
|
|
|
23
23
|
signJwt,
|
|
24
24
|
verifyJwt,
|
|
25
25
|
verifyPkce
|
|
26
|
-
} from "../index-
|
|
26
|
+
} from "../index-jvescqgr.js";
|
|
27
27
|
import {
|
|
28
28
|
DEFAULT_CORS_ALLOW_HEADERS,
|
|
29
|
+
DEFAULT_CORS_EXPOSE_HEADERS,
|
|
29
30
|
corsHeaders,
|
|
30
31
|
corsPreflightResponse
|
|
31
|
-
} from "../index-
|
|
32
|
+
} from "../index-zfscdskj.js";
|
|
32
33
|
import {
|
|
33
34
|
jsonSchemaFields,
|
|
34
35
|
toJsonSchema
|
|
@@ -43,12 +44,13 @@ import {
|
|
|
43
44
|
forbidden,
|
|
44
45
|
formatZodError,
|
|
45
46
|
isStitchErrorCode,
|
|
47
|
+
isWithinDir,
|
|
46
48
|
normalizeError,
|
|
47
49
|
notFound,
|
|
48
50
|
rateLimited,
|
|
49
51
|
unauthorized,
|
|
50
52
|
zodIssues
|
|
51
|
-
} from "../index-
|
|
53
|
+
} from "../index-zza375qp.js";
|
|
52
54
|
import {
|
|
53
55
|
extractIp,
|
|
54
56
|
generateTraceId,
|
|
@@ -425,7 +427,16 @@ function generateOpenApiDocument(config) {
|
|
|
425
427
|
}
|
|
426
428
|
}
|
|
427
429
|
const responses = { ...errorResponses(method.scope) };
|
|
428
|
-
if (method.
|
|
430
|
+
if (method.rawResponse) {
|
|
431
|
+
responses["200"] = {
|
|
432
|
+
description: "Success",
|
|
433
|
+
content: {
|
|
434
|
+
[method.contentType ?? "application/octet-stream"]: {
|
|
435
|
+
schema: { type: "string", format: "binary" }
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
} else if (method.outputSchema) {
|
|
429
440
|
responses["200"] = {
|
|
430
441
|
description: "Success",
|
|
431
442
|
content: { "application/json": { schema: safeJson(method.outputSchema, "output") } }
|
|
@@ -645,6 +656,7 @@ export {
|
|
|
645
656
|
openApiRoute,
|
|
646
657
|
notFound,
|
|
647
658
|
normalizeError,
|
|
659
|
+
isWithinDir,
|
|
648
660
|
isStitchErrorCode,
|
|
649
661
|
implement,
|
|
650
662
|
getClientInfo,
|
|
@@ -676,6 +688,7 @@ export {
|
|
|
676
688
|
badRequest,
|
|
677
689
|
appError,
|
|
678
690
|
STITCH_ERROR_STATUS,
|
|
691
|
+
DEFAULT_CORS_EXPOSE_HEADERS,
|
|
679
692
|
DEFAULT_CORS_ALLOW_HEADERS,
|
|
680
693
|
AppError
|
|
681
694
|
};
|
|
@@ -3,6 +3,12 @@ export interface CorsConfig {
|
|
|
3
3
|
credentials?: boolean;
|
|
4
4
|
methods?: string;
|
|
5
5
|
headers?: string;
|
|
6
|
+
/**
|
|
7
|
+
* Response headers a cross-origin caller is allowed to *read*
|
|
8
|
+
* (`Access-Control-Expose-Headers`). Defaults to
|
|
9
|
+
* {@link DEFAULT_CORS_EXPOSE_HEADERS}; pass `[]` to emit none.
|
|
10
|
+
*/
|
|
11
|
+
exposeHeaders?: string | string[];
|
|
6
12
|
}
|
|
7
13
|
/**
|
|
8
14
|
* The default `Access-Control-Allow-Headers` — the request headers stitchkit's
|
|
@@ -17,6 +23,19 @@ export interface CorsConfig {
|
|
|
17
23
|
* feature dies on the cross-origin preflight.
|
|
18
24
|
*/
|
|
19
25
|
export declare const DEFAULT_CORS_ALLOW_HEADERS = "Content-Type, Authorization, X-Trace-Id, traceparent, tracestate";
|
|
26
|
+
/**
|
|
27
|
+
* The default `Access-Control-Expose-Headers`. Without it a cross-origin
|
|
28
|
+
* `fetch` can read only the CORS-safelisted response headers, so a browser
|
|
29
|
+
* downloading a file cannot recover its name (`Content-Disposition`), and a
|
|
30
|
+
* client cannot revalidate (`ETag`) or resume (`Content-Range`) — the very
|
|
31
|
+
* headers `serveFile` exists to emit.
|
|
32
|
+
*
|
|
33
|
+
* An explicit list rather than `*`, because the wildcard is ignored whenever
|
|
34
|
+
* the request carries credentials — exactly the authenticated download case.
|
|
35
|
+
* These are headers the server already chose to send; exposing them reveals
|
|
36
|
+
* nothing new. Opt out with `exposeHeaders: []`.
|
|
37
|
+
*/
|
|
38
|
+
export declare const DEFAULT_CORS_EXPOSE_HEADERS = "Content-Disposition, Content-Length, Content-Range, Accept-Ranges, ETag, Last-Modified, X-Trace-Id";
|
|
20
39
|
/**
|
|
21
40
|
* Reject an unsafe CORS config at construction. `credentials: true` with a
|
|
22
41
|
* wildcard origin would reflect *any* caller's `Origin` with
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cors.d.ts","sourceRoot":"","sources":["../../../src/server/middleware/cors.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"cors.d.ts","sourceRoot":"","sources":["../../../src/server/middleware/cors.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CACnC;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,0BAA0B,qEAC6B,CAAC;AAErE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,2BAA2B,uGAC8D,CAAC;AAEvG;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAOzD;AAoBD,wBAAgB,WAAW,CACzB,MAAM,EAAE,UAAU,EAClB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,GAC5B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA2BxB;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,GAAG,QAAQ,CAKhF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../../src/server/openapi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE/D,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;IACxB,iFAAiF;IACjF,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,UAAU,EAAE,CAAA;KAAE,CAAC,CAAC;IAChE,oCAAoC;IACpC,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAC1B;;;;;;;;;;;OAWG;IACH,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,SAAS,CAAC,KAAK,OAAO,CAAC;CAC1D;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAChD;AAsED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,aAAa,GAAG,eAAe,
|
|
1
|
+
{"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../../src/server/openapi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE/D,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;IACxB,iFAAiF;IACjF,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,UAAU,EAAE,CAAA;KAAE,CAAC,CAAC;IAChE,oCAAoC;IACpC,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAC1B;;;;;;;;;;;OAWG;IACH,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,SAAS,CAAC,KAAK,OAAO,CAAC;CAC1D;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAChD;AAsED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,aAAa,GAAG,eAAe,CAmI9E;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,QAAQ,CAM9E"}
|
package/dist/server/router.d.ts
CHANGED
|
@@ -27,6 +27,33 @@ export declare function matchRoute(routeMap: RouteMap, httpMethod: string, pathn
|
|
|
27
27
|
export declare function allowedMethods(routeMap: RouteMap, pathname: string): string[];
|
|
28
28
|
/** Startup guard — throws when two routes collapse to the same shape. */
|
|
29
29
|
export declare function validateRoutes(routeMap: RouteMap): void;
|
|
30
|
+
/** One contract route that a raw route matches first, so the contract route is dead. */
|
|
31
|
+
export interface ShadowedRoute {
|
|
32
|
+
/** The contract route pattern, e.g. `GET /documents/:id/pdf`. */
|
|
33
|
+
pattern: string;
|
|
34
|
+
/** `serviceName.key` of the endpoint that will never run. */
|
|
35
|
+
endpoint: string;
|
|
36
|
+
/** The raw route that wins, e.g. `GET /documents/:id/pdf` or `ALL /files/*`. */
|
|
37
|
+
rawRoute: string;
|
|
38
|
+
/** The shadowed endpoint's scope — the auth gate the raw route bypasses. */
|
|
39
|
+
scope?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Startup diagnostic — raw routes are matched **before** contract routes, so a
|
|
43
|
+
* raw route covering a contract path silently wins and the endpoint never runs.
|
|
44
|
+
*
|
|
45
|
+
* This matters most for the migration raw-response endpoints exist to enable
|
|
46
|
+
* (→ ADR 0038): move a download out of `rawRoutes` into the contract to gain the
|
|
47
|
+
* auth gate, forget to delete the old raw route, and the bytes keep being served
|
|
48
|
+
* ungated — with no error anywhere. Reported, not thrown: an overlapping
|
|
49
|
+
* wildcard (a SPA fallback) can be deliberate, and refusing to boot a working
|
|
50
|
+
* app would be the worse failure.
|
|
51
|
+
*
|
|
52
|
+
* Detection runs the **real** `matchRawRoute` against a concrete probe path
|
|
53
|
+
* built from each contract route, so it can never disagree with what the
|
|
54
|
+
* dispatcher actually does.
|
|
55
|
+
*/
|
|
56
|
+
export declare function findShadowedRoutes(routeMap: RouteMap, rawRoutes: RawRoute[] | undefined): ShadowedRoute[];
|
|
30
57
|
export declare function matchRawRoute(rawRoutes: RawRoute[], httpMethod: string, pathname: string): {
|
|
31
58
|
route: RawRoute;
|
|
32
59
|
params: Record<string, string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/server/router.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE/E,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,UAAU,CAAC;IACpB,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB;AAED,UAAU,UAAU;IAClB,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B;AAED,+EAA+E;AAC/E,MAAM,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;AAEjD,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,SAAS,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B;AAqCD,wBAAgB,aAAa,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,QAAQ,CAmCjE;AAED,wBAAgB,UAAU,CACxB,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,UAAU,GAAG,IAAI,CAkBnB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAc7E;AAED,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAiBvD;AAID,wBAAgB,aAAa,CAC3B,SAAS,EAAE,QAAQ,EAAE,EACrB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf;IAAE,KAAK,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,IAAI,CAkC5D;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ,CAkCjE"}
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/server/router.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE/E,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,UAAU,CAAC;IACpB,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB;AAED,UAAU,UAAU;IAClB,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B;AAED,+EAA+E;AAC/E,MAAM,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;AAEjD,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,SAAS,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B;AAqCD,wBAAgB,aAAa,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,QAAQ,CAmCjE;AAED,wBAAgB,UAAU,CACxB,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,UAAU,GAAG,IAAI,CAkBnB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAc7E;AAED,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAiBvD;AAED,wFAAwF;AACxF,MAAM,WAAW,aAAa;IAC5B,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,QAAQ,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,QAAQ,EAAE,GAAG,SAAS,GAChC,aAAa,EAAE,CAmBjB;AAID,wBAAgB,aAAa,CAC3B,SAAS,EAAE,QAAQ,EAAE,EACrB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf;IAAE,KAAK,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,IAAI,CAkC5D;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ,CAkCjE"}
|
package/dist/server/types.d.ts
CHANGED
|
@@ -5,11 +5,33 @@ type Prop<T, K extends string> = K extends keyof T ? T[K] : undefined;
|
|
|
5
5
|
type InferParams<E> = Prop<E, 'params'> extends ZodType<infer P> ? P : undefined;
|
|
6
6
|
type InferInput<E> = Prop<E, 'input'> extends ZodType<infer I> ? I : undefined;
|
|
7
7
|
type InferOutput<E> = Prop<E, 'output'> extends ZodType<infer O> ? O : never;
|
|
8
|
+
/**
|
|
9
|
+
* What an endpoint's handler must return: the `Response` itself for a `raw`
|
|
10
|
+
* endpoint, the output type when there is an output schema, nothing otherwise.
|
|
11
|
+
* Enforced in both directions — a raw handler returning data and a normal
|
|
12
|
+
* handler returning a `Response` are both compile errors (the latter used to
|
|
13
|
+
* be accepted and silently serialized to `{}`).
|
|
14
|
+
*/
|
|
15
|
+
type HandlerReturn<E> = E extends {
|
|
16
|
+
rawResponse: true;
|
|
17
|
+
} ? Response | Promise<Response> : Prop<E, 'output'> extends ZodType ? Promise<InferOutput<E>> | InferOutput<E> : void | Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* `ctx.req` is optional in general — a tool call has no `Request`. A raw
|
|
20
|
+
* endpoint is HTTP-only by declaration, and its handler needs the request
|
|
21
|
+
* (`serveFile(ctx.req, …)` reads `Range` / `If-None-Match`), so it is narrowed
|
|
22
|
+
* to a guaranteed `Request` there rather than making every raw handler write
|
|
23
|
+
* a non-null assertion. → ADR 0038.
|
|
24
|
+
*/
|
|
25
|
+
type RequiredRequest<E> = E extends {
|
|
26
|
+
rawResponse: true;
|
|
27
|
+
} ? {
|
|
28
|
+
req: Request;
|
|
29
|
+
} : unknown;
|
|
8
30
|
export type Handlers<C extends Record<string, EndpointDef>, TCtx extends RuntimeContext = HandlerContext> = {
|
|
9
31
|
[K in keyof C]: (ctx: TCtx & {
|
|
10
32
|
params: InferParams<C[K]>;
|
|
11
33
|
input: InferInput<C[K]>;
|
|
12
|
-
}
|
|
34
|
+
} & RequiredRequest<C[K]>) => HandlerReturn<C[K]>;
|
|
13
35
|
};
|
|
14
36
|
export interface MethodDef<TParams = unknown, TInput = unknown, TOutput = unknown> {
|
|
15
37
|
method: HttpMethod;
|
|
@@ -54,6 +76,14 @@ export interface MethodDef<TParams = unknown, TInput = unknown, TOutput = unknow
|
|
|
54
76
|
* the consumer narrows the type. Never serialized to OpenAPI. → ADR 0021.
|
|
55
77
|
*/
|
|
56
78
|
meta?: Record<string, unknown>;
|
|
79
|
+
/**
|
|
80
|
+
* The handler returns the `Response` itself — from `EndpointDef.rawResponse`. Routed
|
|
81
|
+
* and gated like any endpoint, but never serialized, never validated against
|
|
82
|
+
* an output schema and never mounted as a tool. → ADR 0038.
|
|
83
|
+
*/
|
|
84
|
+
rawResponse?: true;
|
|
85
|
+
/** Documented response media type of a raw-response endpoint — OpenAPI only. */
|
|
86
|
+
contentType?: string;
|
|
57
87
|
handler: (ctx: RuntimeContext) => Promise<TOutput> | TOutput;
|
|
58
88
|
}
|
|
59
89
|
export interface ServiceDef {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACnC,OAAO,KAAK,EACV,WAAW,EACX,uBAAuB,EACvB,cAAc,EACd,cAAc,EACd,UAAU,EACV,cAAc,EACd,SAAS,EACV,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;AACtE,KAAK,WAAW,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;AACjF,KAAK,UAAU,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;AAC/E,KAAK,WAAW,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAE7E,MAAM,MAAM,QAAQ,CAClB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACrC,IAAI,SAAS,cAAc,GAAG,cAAc,IAC1C;KACD,CAAC,IAAI,MAAM,CAAC,GAAG,CACd,GAAG,EAAE,IAAI,GAAG;QAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;KAAE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -25,7 +25,8 @@ export interface ToolNameEntry {
|
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
27
|
* Resolve every tool name the given services expose, sorted by name (then
|
|
28
|
-
* service) — a stable shape to snapshot. Multipart
|
|
28
|
+
* service) — a stable shape to snapshot. Multipart and raw-response endpoints
|
|
29
|
+
* are absent
|
|
29
30
|
* (never mounted as tools) and CLI appears only where `expose` opts in,
|
|
30
31
|
* mirroring the real mounts.
|
|
31
32
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-names.d.ts","sourceRoot":"","sources":["../../src/tools/list-names.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGlD,qDAAqD;AACrD,MAAM,WAAW,aAAa;IAC5B,qFAAqF;IACrF,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,UAAU,EAAE,SAAS,EAAE,CAAC;CACzB;AAID
|
|
1
|
+
{"version":3,"file":"list-names.d.ts","sourceRoot":"","sources":["../../src/tools/list-names.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGlD,qDAAqD;AACrD,MAAM,WAAW,aAAa;IAC5B,qFAAqF;IACrF,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,UAAU,EAAE,SAAS,EAAE,CAAC;CACzB;AAID;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,aAAa,EAAE,CA2BrE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../src/tools/mount.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,UAAU,EAChB,MAAM,WAAW,CAAC;AAKnB;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU,CACzB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAElE,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IAClC,qEAAqE;IACrE,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC3F,uEAAuE;IACvE,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC;CAC9D;AAED,2DAA2D;AAC3D,MAAM,WAAW,aAAa;IAC5B,2CAA2C;IAC3C,MAAM,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC7C,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;IACb,sFAAsF;IACtF,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC;IAClB,mDAAmD;IACnD,YAAY,EAAE,OAAO,CAAC;CACvB;AAyBD,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,uFAAuF;IACvF,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,UAAU,EACnB,SAAS,EAAE,SAAS,EACpB,MAAM,GAAE,kBAAuB,GAC9B,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../src/tools/mount.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote.d.ts","sourceRoot":"","sources":["../../src/tools/remote.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,WAAW,EAEjB,MAAM,aAAa,CAAC;AAGrB,OAAO,KAAK,EAAa,UAAU,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"remote.d.ts","sourceRoot":"","sources":["../../src/tools/remote.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,WAAW,EAEjB,MAAM,aAAa,CAAC;AAGrB,OAAO,KAAK,EAAa,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAiB7D,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,aAAa,CAAC,EAAE,CACd,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC1B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACjE;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACnE,QAAQ,EAAE,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,EAChC,IAAI,EAAE,UAAU,EAChB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,UAAU,CAgFZ"}
|
package/dist/tools.js
CHANGED
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
inputIsQuery,
|
|
3
3
|
signJwt,
|
|
4
4
|
verifyPkce
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-jvescqgr.js";
|
|
6
6
|
import {
|
|
7
7
|
DEFAULT_CORS_ALLOW_HEADERS
|
|
8
|
-
} from "./index-
|
|
8
|
+
} from "./index-zfscdskj.js";
|
|
9
9
|
import {
|
|
10
10
|
assertToolName,
|
|
11
11
|
assertUniqueToolName,
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
readCapped,
|
|
22
22
|
toolResultFromError,
|
|
23
23
|
writeDownload
|
|
24
|
-
} from "./index-
|
|
24
|
+
} from "./index-4whcb3c3.js";
|
|
25
25
|
import {
|
|
26
26
|
toJsonSchema
|
|
27
27
|
} from "./index-0ed3bx43.js";
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
AppError,
|
|
30
30
|
isWithinDir,
|
|
31
31
|
mergeMeta
|
|
32
|
-
} from "./index-
|
|
32
|
+
} from "./index-zza375qp.js";
|
|
33
33
|
import"./index-khwedj16.js";
|
|
34
34
|
import {
|
|
35
35
|
isRecord,
|
|
@@ -929,10 +929,15 @@ function parseApiErrorBody(body) {
|
|
|
929
929
|
}
|
|
930
930
|
|
|
931
931
|
// src/browser/client.ts
|
|
932
|
-
function withTimeout(options,
|
|
933
|
-
|
|
932
|
+
function withTimeout(options, endpoint) {
|
|
933
|
+
const responseType = endpoint.rawResponse ? "response" : undefined;
|
|
934
|
+
if (endpoint.timeout === undefined && responseType === undefined)
|
|
934
935
|
return options;
|
|
935
|
-
return {
|
|
936
|
+
return {
|
|
937
|
+
...options,
|
|
938
|
+
...endpoint.timeout !== undefined && { timeout: endpoint.timeout },
|
|
939
|
+
...responseType && { responseType }
|
|
940
|
+
};
|
|
936
941
|
}
|
|
937
942
|
function withOutput(endpoint, result) {
|
|
938
943
|
const schema = endpoint.output;
|
|
@@ -1009,15 +1014,15 @@ function createHttpMethod(endpoint, prefix, client, config) {
|
|
|
1009
1014
|
const formData = new FormData;
|
|
1010
1015
|
appendMultipartFile(formData, endpoint.multipart, file);
|
|
1011
1016
|
appendFormFields(formData, firstArg, new Set([...prefixKeys, endpoint.multipart]));
|
|
1012
|
-
return withOutput(endpoint, client[httpMethod](url, formData, withTimeout(undefined, endpoint
|
|
1017
|
+
return withOutput(endpoint, client[httpMethod](url, formData, withTimeout(undefined, endpoint)));
|
|
1013
1018
|
}
|
|
1014
1019
|
if (isGet) {
|
|
1015
1020
|
const params = collectQueryParams(firstArg, prefixKeys, endpoint);
|
|
1016
|
-
return withOutput(endpoint, client.get(url, withTimeout(params ? { params } : undefined, endpoint
|
|
1021
|
+
return withOutput(endpoint, client.get(url, withTimeout(params ? { params } : undefined, endpoint)));
|
|
1017
1022
|
}
|
|
1018
1023
|
if (httpMethod === "delete") {
|
|
1019
1024
|
const params = collectQueryParams(firstArg, prefixKeys, endpoint);
|
|
1020
|
-
return withOutput(endpoint, client.delete(url, withTimeout(params ? { params } : undefined, endpoint
|
|
1025
|
+
return withOutput(endpoint, client.delete(url, withTimeout(params ? { params } : undefined, endpoint)));
|
|
1021
1026
|
}
|
|
1022
1027
|
const payload = {};
|
|
1023
1028
|
for (const [key, value] of Object.entries(firstArg)) {
|
|
@@ -1025,7 +1030,7 @@ function createHttpMethod(endpoint, prefix, client, config) {
|
|
|
1025
1030
|
payload[key] = value;
|
|
1026
1031
|
}
|
|
1027
1032
|
}
|
|
1028
|
-
return withOutput(endpoint, client[httpMethod](url, Object.keys(payload).length > 0 ? payload : undefined, withTimeout(undefined, endpoint
|
|
1033
|
+
return withOutput(endpoint, client[httpMethod](url, Object.keys(payload).length > 0 ? payload : undefined, withTimeout(undefined, endpoint)));
|
|
1029
1034
|
};
|
|
1030
1035
|
}
|
|
1031
1036
|
function createFetchMethod(endpoint, prefix, config, contractConfig) {
|
|
@@ -1081,6 +1086,8 @@ function createFetchMethod(endpoint, prefix, config, contractConfig) {
|
|
|
1081
1086
|
if (!res2.ok) {
|
|
1082
1087
|
await throwForErrorResponse(res2, config, null);
|
|
1083
1088
|
}
|
|
1089
|
+
if (endpoint.rawResponse)
|
|
1090
|
+
return res2;
|
|
1084
1091
|
if (res2.status === 204)
|
|
1085
1092
|
return;
|
|
1086
1093
|
const json3 = await res2.json();
|
|
@@ -1098,6 +1105,8 @@ function createFetchMethod(endpoint, prefix, config, contractConfig) {
|
|
|
1098
1105
|
if (!res.ok) {
|
|
1099
1106
|
await throwForErrorResponse(res, config, { error: res.statusText });
|
|
1100
1107
|
}
|
|
1108
|
+
if (endpoint.rawResponse)
|
|
1109
|
+
return res;
|
|
1101
1110
|
if (res.status === 204)
|
|
1102
1111
|
return;
|
|
1103
1112
|
const json2 = await res.json();
|
|
@@ -1145,6 +1154,7 @@ function stripParams(args, path, extra) {
|
|
|
1145
1154
|
}
|
|
1146
1155
|
|
|
1147
1156
|
// src/tools/remote.ts
|
|
1157
|
+
var HTTP_ONLY = Object.freeze(["HTTP"]);
|
|
1148
1158
|
function toArgs(ctx) {
|
|
1149
1159
|
const { params, input } = ctx;
|
|
1150
1160
|
return {
|
|
@@ -1164,7 +1174,7 @@ function implementRemote(contract, http, options) {
|
|
|
1164
1174
|
serviceName: contract.meta.prefix,
|
|
1165
1175
|
key,
|
|
1166
1176
|
toolName: "toolName" in endpoint ? endpoint.toolName : undefined,
|
|
1167
|
-
expose: endpoint.expose,
|
|
1177
|
+
expose: endpoint.rawResponse ? HTTP_ONLY : endpoint.expose,
|
|
1168
1178
|
ui: "ui" in endpoint ? endpoint.ui : undefined,
|
|
1169
1179
|
annotations: "annotations" in endpoint ? endpoint.annotations : undefined,
|
|
1170
1180
|
meta: mergeMeta(contract.meta.meta, endpoint.meta),
|
|
@@ -1174,6 +1184,8 @@ function implementRemote(contract, http, options) {
|
|
|
1174
1184
|
outputSchema: endpoint.output,
|
|
1175
1185
|
multipart: endpoint.multipart,
|
|
1176
1186
|
idempotent: endpoint.idempotent,
|
|
1187
|
+
rawResponse: endpoint.rawResponse,
|
|
1188
|
+
contentType: "contentType" in endpoint ? endpoint.contentType : undefined,
|
|
1177
1189
|
handler: async (ctx) => {
|
|
1178
1190
|
const call = client[key];
|
|
1179
1191
|
if (!call) {
|
package/llms-full.txt
CHANGED
|
@@ -242,6 +242,8 @@ export const users = defineContract({ prefix: 'users' }, {
|
|
|
242
242
|
| `timeout` | no | per-endpoint client timeout in ms, for slow endpoints |
|
|
243
243
|
| `idempotent` | no | safe to call twice with the same input (like `PUT`/`DELETE`); a retrying transport reads it — see [Realtime](./realtime.md#bring-your-own-transport) |
|
|
244
244
|
| `meta` | no | opaque app metadata — read in hooks / on tool mounts, never in OpenAPI ([below](#endpoint-metadata-meta)) |
|
|
245
|
+
| `rawResponse` | no | the handler returns the `Response` itself — a download, a file, an SSE stream. HTTP-only, never a tool, no `output`. See [Raw-response endpoints](./server.md#raw-response-endpoints) |
|
|
246
|
+
| `contentType` | no | documented response media type of a `rawResponse` endpoint (OpenAPI only) |
|
|
245
247
|
|
|
246
248
|
## `params` vs `input` vs `output`
|
|
247
249
|
|
|
@@ -313,8 +315,10 @@ tools. Narrow it with `expose`:
|
|
|
313
315
|
- `expose: ['MCP', 'AGENT']` — a tool only; no HTTP route.
|
|
314
316
|
- omit `expose` — all transports.
|
|
315
317
|
|
|
316
|
-
Tool transports (`MCP`, `AGENT`) skip
|
|
317
|
-
file upload is not a tool call
|
|
318
|
+
Tool transports (`MCP`, `AGENT`) skip two kinds of endpoint automatically:
|
|
319
|
+
`multipart` (a file upload is not a tool call) and
|
|
320
|
+
[`rawResponse`](./server.md#raw-response-endpoints) (its answer is bytes, which
|
|
321
|
+
a tool result cannot carry — it would serialize to `{}`).
|
|
318
322
|
|
|
319
323
|
## `toolName`
|
|
320
324
|
|
|
@@ -356,10 +360,22 @@ defineContract({ prefix: 'admin', meta: { public: true } }, {
|
|
|
356
360
|
})
|
|
357
361
|
```
|
|
358
362
|
|
|
359
|
-
One level deep — no deep merge
|
|
360
|
-
|
|
361
|
-
|
|
363
|
+
One level deep — no deep merge. To **opt an endpoint out** of an inherited key,
|
|
364
|
+
declare it with an explicit `undefined`:
|
|
365
|
+
|
|
366
|
+
```ts
|
|
367
|
+
defineContract({ prefix: 'leads', meta: { page: 'LEADS' } }, {
|
|
368
|
+
// Public website form inside an otherwise admin-gated contract:
|
|
369
|
+
submit: { method: 'POST', path: '/', desc: 'Submit', meta: { page: undefined } },
|
|
370
|
+
// meta → { page: undefined } — gate off
|
|
371
|
+
list: { method: 'GET', path: '/list', desc: 'List' }, // meta → { page: 'LEADS' }
|
|
372
|
+
})
|
|
373
|
+
```
|
|
362
374
|
|
|
375
|
+
The key stays *present* with value `undefined`, so read `meta` by **value**
|
|
376
|
+
(`method.meta?.page`), never by key membership. `expose` deliberately has **no**
|
|
377
|
+
contract-level equivalent
|
|
378
|
+
(→ [ADR 0036](../decisions/0036-contract-level-meta.md)).
|
|
363
379
|
|
|
364
380
|
`meta` is an **opaque, app-defined** bag the core attaches no meaning to — the
|
|
365
381
|
same escape-hatch spirit as `scope` being a free string ([ADR 0002](../decisions/0002-generic-core.md) /
|
|
@@ -602,7 +618,7 @@ server. See [Testing & deployment](./testing-and-deployment.md).
|
|
|
602
618
|
| `rawRoutes` | non-contract routes (see below) |
|
|
603
619
|
| `maxUploadBytes` | default multipart upload cap (bytes); per-route `EndpointDef.maxUploadBytes` overrides |
|
|
604
620
|
| `port` / `hostname` | listen address — port defaults to `3000` |
|
|
605
|
-
| `cors` | CORS policy — `{ origin,
|
|
621
|
+
| `cors` | CORS policy — `{ origin, credentials, methods, headers, exposeHeaders }` |
|
|
606
622
|
| `hooks` | lifecycle hooks (see below) |
|
|
607
623
|
| `logging` | `true` for built-in request logs, or a custom `StitchLogger` |
|
|
608
624
|
| `traceId` | override per-request trace-id resolution |
|
|
@@ -722,6 +738,87 @@ createServer({
|
|
|
722
738
|
Hooks see `RuntimeContext` (loose types); handlers see `HandlerContext` (typed).
|
|
723
739
|
That split is deliberate — see [ADR 0003](../decisions/0003-two-context-types.md).
|
|
724
740
|
|
|
741
|
+
## Raw-response endpoints
|
|
742
|
+
|
|
743
|
+
An endpoint that answers with **bytes rather than data** — a PDF download, a
|
|
744
|
+
file, an SSE stream — declares `rawResponse: true` and returns the `Response` itself:
|
|
745
|
+
|
|
746
|
+
```ts
|
|
747
|
+
// contract
|
|
748
|
+
export const documents = defineContract(
|
|
749
|
+
{ prefix: 'documents', scope: 'admin' },
|
|
750
|
+
{
|
|
751
|
+
download: {
|
|
752
|
+
method: 'GET', path: '/:id/pdf', desc: 'Download a document as a PDF',
|
|
753
|
+
params: z.object({ id: z.uuid() }),
|
|
754
|
+
rawResponse: true, contentType: 'application/pdf',
|
|
755
|
+
},
|
|
756
|
+
},
|
|
757
|
+
)
|
|
758
|
+
|
|
759
|
+
// handler — no guard on the first line; `beforeHandle` already ran
|
|
760
|
+
download: (ctx) => serveFile(ctx.req, { path: pathFor(ctx.params.id),
|
|
761
|
+
filename: 'offer.pdf' }),
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
The request half is untouched: `params`, `input` and `multipart` parse and
|
|
765
|
+
validate exactly as elsewhere, and the endpoint goes through `beforeHandle` — so
|
|
766
|
+
the **auth gate applies without a guard in the handler**. Only the response is
|
|
767
|
+
handed over, so there is no `output` schema, `afterHandle` is skipped (it
|
|
768
|
+
transforms data; there is none) and the endpoint is HTTP-only: never an MCP
|
|
769
|
+
tool, an agent tool or a CLI command. Declaring `output`, `toolName`, `ui`,
|
|
770
|
+
`annotations` or a non-HTTP `expose` alongside `rawResponse` is a type error, and throws
|
|
771
|
+
at definition time for a contract assembled at runtime.
|
|
772
|
+
|
|
773
|
+
On the typed client the method resolves to the untouched `Response` — the
|
|
774
|
+
filename lives in `Content-Disposition`, so a `Blob` alone would lose it:
|
|
775
|
+
|
|
776
|
+
```ts
|
|
777
|
+
const client = createClient(documents, http)
|
|
778
|
+
const res = await client.download({ id }) // Response
|
|
779
|
+
const name = res.headers.get('Content-Disposition')
|
|
780
|
+
const blob = await res.blob()
|
|
781
|
+
```
|
|
782
|
+
|
|
783
|
+
Cross-origin, remember that those headers are readable only because CORS exposes
|
|
784
|
+
them — see [`cors.exposeHeaders`](#serving-files--range-requests).
|
|
785
|
+
|
|
786
|
+
**Raw response or [raw route](#raw-routes)?** Both hand the `Response` to your
|
|
787
|
+
code. A raw-response *endpoint* stays in the contract: only its response is
|
|
788
|
+
raw — it is still routed, gated, typed and documented like every other endpoint.
|
|
789
|
+
A raw *route* is outside the contract entirely — no schemas, no auth gate, no
|
|
790
|
+
client — which is what you want for an OAuth redirect or a webhook, and what you
|
|
791
|
+
do not want for a download.
|
|
792
|
+
|
|
793
|
+
⚠️ **Delete the old raw route when you move an endpoint into the contract.** Raw
|
|
794
|
+
routes are matched **first**, so a leftover one keeps serving the bytes and the
|
|
795
|
+
contract endpoint — with its auth gate — never runs. stitchkit warns at startup
|
|
796
|
+
when a raw route shadows a contract route, naming both and the scope being
|
|
797
|
+
bypassed; treat that warning as a bug.
|
|
798
|
+
|
|
799
|
+
⚠️ **A path built from user input needs a containment check.** `staticRoute`
|
|
800
|
+
enforces it; `serveFile` deliberately leaves it to the caller, so an endpoint
|
|
801
|
+
serving `/:filename` must not pass it through:
|
|
802
|
+
|
|
803
|
+
```ts
|
|
804
|
+
import { isWithinDir, serveFile } from 'stitchkit/server'
|
|
805
|
+
import { resolve } from 'node:path'
|
|
806
|
+
|
|
807
|
+
const ROOT = resolve('./uploads')
|
|
808
|
+
|
|
809
|
+
file: (ctx) => {
|
|
810
|
+
const target = resolve(ROOT, ctx.params.filename)
|
|
811
|
+
// `../../etc/passwd` resolves outside ROOT — reject before touching disk.
|
|
812
|
+
if (!isWithinDir(ROOT, target)) throw notFound('File not found')
|
|
813
|
+
return serveFile(ctx.req, { path: target })
|
|
814
|
+
},
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
`implementRemote` proxies a raw-response endpoint like any other — the remote
|
|
818
|
+
`Response` is forwarded verbatim. Request headers are not relayed, so a `Range`
|
|
819
|
+
sent to the proxy does not reach the origin and the full body comes back.
|
|
820
|
+
→ ADR 0038.
|
|
821
|
+
|
|
725
822
|
## Raw routes
|
|
726
823
|
|
|
727
824
|
Some routes cannot be a clean JSON contract — an OAuth redirect, a webhook with
|
|
@@ -815,6 +912,13 @@ It always sets `Accept-Ranges: bytes`, a weak `ETag` and `Last-Modified` (so
|
|
|
815
912
|
and `nosniff`. `Content-Type` is auto-detected from the path — override it, or
|
|
816
913
|
pass `disposition` / `cacheControl` / `etag: false`, via the options.
|
|
817
914
|
|
|
915
|
+
Cross-origin, the browser lets JavaScript read only the CORS-safelisted response
|
|
916
|
+
headers. stitchkit therefore exposes the download-relevant ones by default
|
|
917
|
+
(`Content-Disposition`, `Content-Range`, `ETag`, …) — without that a `fetch`-based
|
|
918
|
+
download cannot recover the file's name. Override with `cors.exposeHeaders`
|
|
919
|
+
(extend `DEFAULT_CORS_EXPOSE_HEADERS` rather than replacing it), or pass `[]` to
|
|
920
|
+
emit none.
|
|
921
|
+
|
|
818
922
|
`serveFile` takes an explicit `path` and trusts it — **the caller owns
|
|
819
923
|
containment**. For a URL-derived path use `staticRoute` (which enforces it) or
|
|
820
924
|
`isWithinDir` first. The byte-range parser is exported on its own as
|
|
@@ -836,11 +940,20 @@ focused helper — not a sub-framework.
|
|
|
836
940
|
|
|
837
941
|
### SSE streaming
|
|
838
942
|
|
|
943
|
+
`streamSSE` returns a `Response`, so its endpoint declares
|
|
944
|
+
[`rawResponse: true`](#raw-response-endpoints) — in a plain contract handler the response
|
|
945
|
+
would be serialized into `{}` (that now fails loudly instead of shipping silently).
|
|
946
|
+
|
|
839
947
|
```ts
|
|
840
948
|
import { streamSSE } from 'stitchkit/server'
|
|
841
949
|
|
|
950
|
+
// contract
|
|
951
|
+
stream: { method: 'GET', path: '/stream', desc: 'Stream tokens',
|
|
952
|
+
rawResponse: true, contentType: 'text/event-stream' },
|
|
953
|
+
|
|
954
|
+
// handler
|
|
842
955
|
async function* tokens() { yield 'a'; yield 'b' }
|
|
843
|
-
|
|
956
|
+
stream: () => streamSSE(tokens()), // → a text/event-stream Response
|
|
844
957
|
```
|
|
845
958
|
|
|
846
959
|
The client side is [`parseSSE`](./client.md#sse).
|
|
@@ -1202,8 +1315,14 @@ By default every endpoint is a tool on every transport. `expose` narrows it:
|
|
|
1202
1315
|
{ method: 'GET', path: '/lookup', desc: 'Look up a price', expose: ['MCP'] } // MCP tool only
|
|
1203
1316
|
```
|
|
1204
1317
|
|
|
1318
|
+
Two kinds of endpoint are **never** tools, whatever `expose` says: a `multipart`
|
|
1319
|
+
upload (not a tool call), and a
|
|
1320
|
+
[`rawResponse`](./server.md#raw-response-endpoints) endpoint (its answer is
|
|
1321
|
+
bytes — a tool result cannot carry them, and it would reach the model as `{}`).
|
|
1322
|
+
Pin the full list with `listToolNames` in a snapshot test.
|
|
1323
|
+
|
|
1205
1324
|
`desc` is the tool description the model reads — write it for the model, not
|
|
1206
|
-
just for a human.
|
|
1325
|
+
just for a human. The tool name defaults
|
|
1207
1326
|
to a verb-aware name from the method + prefix (`list` → `list_widgets`, `get` →
|
|
1208
1327
|
`get_widget`); set `toolName` for an explicit one. Derivation normalises every
|
|
1209
1328
|
character outside `[a-zA-Z0-9_]` to `_` — the hyphen included, so `bot-status`
|
|
@@ -3366,6 +3485,7 @@ Also re-exports the error helpers from `stitchkit/contract`.
|
|
|
3366
3485
|
| `staticRoute` | function | a raw route that serves a directory |
|
|
3367
3486
|
| `serveFile` | function | serve a file with `Range` / `304` / `HEAD` — [guide](../guide/server.md#serving-files--range-requests) |
|
|
3368
3487
|
| `parseByteRange` | function | parse a single `Range` header → range / `unsatisfiable` / `null` |
|
|
3488
|
+
| `isWithinDir` | function | path containment — `(root, resolvedTarget) => boolean`; call it before `serveFile` on any URL-derived path |
|
|
3369
3489
|
| `weakETag` | function | a weak `ETag` from size + mtime |
|
|
3370
3490
|
| `ServeFileOptions` | _type_ | options for `serveFile` |
|
|
3371
3491
|
| `ByteRange` | _type_ | an inclusive `{ start, end }` byte range |
|
|
@@ -3422,6 +3542,7 @@ Also re-exports the error helpers from `stitchkit/contract`.
|
|
|
3422
3542
|
| `corsHeaders` | function | compute CORS response headers |
|
|
3423
3543
|
| `corsPreflightResponse` | function | build a preflight `Response` |
|
|
3424
3544
|
| `DEFAULT_CORS_ALLOW_HEADERS` | const | the default `Access-Control-Allow-Headers` (incl. `traceparent`) — extend it when overriding `cors.headers` |
|
|
3545
|
+
| `DEFAULT_CORS_EXPOSE_HEADERS` | const | the default `Access-Control-Expose-Headers` (incl. `Content-Disposition`, `ETag`, `Content-Range`) — extend it when overriding `cors.exposeHeaders` |
|
|
3425
3546
|
| `CookieDef` | _type_ | the `defineCookie` handle |
|
|
3426
3547
|
| `CookieOptions` | _type_ | cookie attributes |
|
|
3427
3548
|
| `CorsConfig` | _type_ | CORS policy |
|
package/llms.txt
CHANGED
|
@@ -7,7 +7,7 @@ Build with stitchkit: define a contract once, then `implement` it and serve it (
|
|
|
7
7
|
## Guide
|
|
8
8
|
- [Getting started](https://github.com/max-listov/stitchkit/blob/master/docs/guide/getting-started.md): install, entrypoints, and a first contract → server → client app
|
|
9
9
|
- [Contracts](https://github.com/max-listov/stitchkit/blob/master/docs/guide/contracts.md): every endpoint field — method, path, params/input/output, scope, expose, meta, multipart
|
|
10
|
-
- [HTTP server](https://github.com/max-listov/stitchkit/blob/master/docs/guide/server.md): createServer/createHandler, implement, lifecycle hooks, raw routes + helpers, scopePrefixes, serveFile, primitives
|
|
10
|
+
- [HTTP server](https://github.com/max-listov/stitchkit/blob/master/docs/guide/server.md): createServer/createHandler, implement, lifecycle hooks, raw routes + raw-response endpoints + helpers, scopePrefixes, serveFile, primitives
|
|
11
11
|
- [Typed client](https://github.com/max-listov/stitchkit/blob/master/docs/guide/client.md): createClient/createHttpClient, the typed call surface, scoped clients, SSE
|
|
12
12
|
- [MCP & agents](https://github.com/max-listov/stitchkit/blob/master/docs/guide/mcp-and-agents.md): contracts as MCP tools (createMcpHandler) and AI-agent tools (mountAgent); tool lifecycle, extend, identity
|
|
13
13
|
- [CLI](https://github.com/max-listov/stitchkit/blob/master/docs/guide/cli.md): contracts as a command-line program
|
package/package.json
CHANGED
|
File without changes
|