stitchkit 0.4.0 → 0.6.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.
@@ -1,4 +1,4 @@
1
- import type { ContractDef, EndpointDef, TypedHttpClient } from '../contract';
1
+ import type { ContractDef, EndpointDef, ScopedHttpClient, TypedHttpClient } from '../contract';
2
2
  import { type HttpClient as HttpAdapter } from './http';
3
3
  /** Config for the built-in fetch client — used when no `HttpClient` is passed. */
4
4
  export interface ClientConfig {
@@ -7,10 +7,22 @@ export interface ClientConfig {
7
7
  credentials?: RequestCredentials;
8
8
  onError?: (status: number, body: unknown) => void;
9
9
  }
10
- /** Per-contract client tweaks — a dynamic URL `pathPrefix` and the keys it consumes. */
11
- export interface ContractClientConfig {
10
+ /**
11
+ * The keys a `pathPrefix` consumes, as required `string` args. `never` (a plain
12
+ * client) collapses to `unknown`, so `EndpointArgs & unknown = EndpointArgs`.
13
+ */
14
+ export type ScopedKeys<K extends string> = [K] extends [never] ? unknown : {
15
+ [P in K]: string;
16
+ };
17
+ /**
18
+ * Per-contract client tweaks — a dynamic URL `pathPrefix` and the keys it
19
+ * consumes. List the consumed keys in `stripPrefixKeys` (e.g. `['tenantId']`)
20
+ * and they become required, typed args on every method of the returned client —
21
+ * no hand-written scoped-client wrapper.
22
+ */
23
+ export interface ContractClientConfig<K extends string = never> {
12
24
  pathPrefix?: string | ((args: Record<string, unknown>) => string);
13
- stripPrefixKeys?: string[];
25
+ stripPrefixKeys?: readonly K[];
14
26
  }
15
27
  /**
16
28
  * Build a fully-typed client from a contract. Every endpoint becomes a typed
@@ -18,7 +30,7 @@ export interface ContractClientConfig {
18
30
  * (from `createHttpClient`) for cookie auth, SSR and retry, or a plain
19
31
  * `ClientConfig` for a bare fetch client.
20
32
  */
21
- export declare function createClient<T extends Record<string, EndpointDef>>(contract: ContractDef<T, string>, configOrClient: ClientConfig | HttpAdapter, contractConfig?: ContractClientConfig): TypedHttpClient<T>;
33
+ export declare function createClient<T extends Record<string, EndpointDef>, const K extends string = never>(contract: ContractDef<T, string>, configOrClient: ClientConfig | HttpAdapter, contractConfig?: ContractClientConfig<K>): ScopedHttpClient<T, ScopedKeys<K>>;
22
34
  /**
23
35
  * Batch form of `createClient` — one fully-typed client per contract, built
24
36
  * from a `name → contract` registry. Each key keeps its own client type, so
@@ -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,eAAe,EAAE,MAAM,aAAa,CAAC;AAG7E,OAAO,EAEL,KAAK,UAAU,IAAI,WAAW,EAG/B,MAAM,QAAQ,CAAC;AA8ChB,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,wFAAwF;AACxF,MAAM,WAAW,oBAAoB;IACnC,UAAU,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC,CAAC;IAClE,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EAChE,QAAQ,EAAE,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,EAChC,cAAc,EAAE,YAAY,GAAG,WAAW,EAC1C,cAAc,CAAC,EAAE,oBAAoB,GACpC,eAAe,CAAC,CAAC,CAAC,CAepB;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"}
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;AAG/F,OAAO,EAEL,KAAK,UAAU,IAAI,WAAW,EAG/B,MAAM,QAAQ,CAAC;AA8ChB,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"}
@@ -18,6 +18,20 @@ interface EndpointDefBase {
18
18
  * property of the endpoint — declared once, the typed client applies it.
19
19
  */
20
20
  timeout?: number;
21
+ /**
22
+ * Opaque, app-defined per-endpoint metadata. The core attaches **no** meaning
23
+ * to it (like `scope`, it is a free escape-hatch — ADR 0002/0021): it rides
24
+ * through to `MethodDef.meta`, readable in lifecycle hooks
25
+ * (`beforeHandle`/`afterHandle`/`onError`) and on tool mounts. Use it for
26
+ * app concerns the generic core does not model — a feature gate, a rate tier,
27
+ * a cache hint, a doc/owner tag. The consumer narrows the type when reading.
28
+ * Never surfaced in the OpenAPI document (app-private, not the HTTP contract).
29
+ *
30
+ * Declare its type as a `type` / inline literal / `satisfies` — **not an
31
+ * `interface`** (an interface has no implicit index signature, so it is not
32
+ * assignable to `Record<string, unknown>`).
33
+ */
34
+ meta?: Record<string, unknown>;
21
35
  }
22
36
  /**
23
37
  * MCP Apps UI metadata for a tool (SEP-1865). When set, the tool's MCP
@@ -120,8 +134,11 @@ export type TypedClient<C extends Record<string, EndpointDef>> = {
120
134
  type ExposesHttp<E> = E extends {
121
135
  expose: readonly Transport[];
122
136
  } ? 'HTTP' extends E['expose'][number] ? true : false : true;
123
- export type TypedHttpClient<C extends Record<string, EndpointDef>> = {
124
- [K in keyof C as ExposesHttp<C[K]> extends true ? K : never]: EndpointFn<C[K]>;
137
+ type ArgsWith<E, Extra> = EndpointArgs<E> & Extra;
138
+ export type ScopedEndpointFn<E, Extra> = [keyof ArgsWith<E, Extra>] extends [never] ? () => Promise<EndpointOutput<E>> : (args: ArgsWith<E, Extra>) => Promise<EndpointOutput<E>>;
139
+ export type ScopedHttpClient<C extends Record<string, EndpointDef>, Extra> = {
140
+ [K in keyof C as ExposesHttp<C[K]> extends true ? K : never]: ScopedEndpointFn<C[K], Extra>;
125
141
  };
142
+ export type TypedHttpClient<C extends Record<string, EndpointDef>> = ScopedHttpClient<C, unknown>;
126
143
  export {};
127
144
  //# sourceMappingURL=define.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../../src/contract/define.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../../src/contract/define.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- export { ALL_TRANSPORTS, type ContractDef, type ContractMeta, defineContract, type EndpointDef, type EndpointFn, type EndpointToolAnnotations, type EndpointUiMeta, type HandlerContext, type HttpMethod, type RuntimeContext, type Transport, type TransportSource, type TypedClient, type TypedHttpClient, } from './define';
1
+ export { ALL_TRANSPORTS, type ContractDef, type ContractMeta, defineContract, type EndpointDef, type EndpointFn, type EndpointToolAnnotations, type EndpointUiMeta, type HandlerContext, type HttpMethod, type RuntimeContext, type ScopedEndpointFn, type ScopedHttpClient, type Transport, type TransportSource, type TypedClient, type TypedHttpClient, } from './define';
2
2
  export { AppError, appError, badRequest, conflict, type ErrorEnvelope, forbidden, notFound, rateLimited, unauthorized, } from './errors';
3
3
  export { type Paginated, paginatedSchema } from './pagination';
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/contract/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,uBAAuB,EAC5B,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,eAAe,GACrB,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,KAAK,aAAa,EAClB,SAAS,EACT,QAAQ,EACR,WAAW,EACX,YAAY,GACb,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,KAAK,SAAS,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/contract/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,uBAAuB,EAC5B,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,eAAe,GACrB,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,KAAK,aAAa,EAClB,SAAS,EACT,QAAQ,EACR,WAAW,EACX,YAAY,GACb,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,KAAK,SAAS,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
@@ -190,7 +190,7 @@ function collectQueryParams(args, skipKeys) {
190
190
  }
191
191
  function createClient(contract, configOrClient, contractConfig) {
192
192
  const client = {};
193
- const makeMethod = isHttpAdapter(configOrClient) ? (endpoint) => createHttpMethod(endpoint, contract.meta.prefix, configOrClient, contractConfig) : (endpoint) => createFetchMethod(endpoint, contract.meta.prefix, configOrClient);
193
+ const makeMethod = isHttpAdapter(configOrClient) ? (endpoint) => createHttpMethod(endpoint, contract.meta.prefix, configOrClient, contractConfig) : (endpoint) => createFetchMethod(endpoint, contract.meta.prefix, configOrClient, contractConfig);
194
194
  for (const [key, endpoint] of typedEntries(contract.endpoints)) {
195
195
  if (endpoint.expose && !endpoint.expose.includes("HTTP"))
196
196
  continue;
@@ -257,9 +257,16 @@ function createHttpMethod(endpoint, prefix, client, config) {
257
257
  return client[httpMethod](url, Object.keys(payload).length > 0 ? payload : undefined, withTimeout(undefined, endpoint.timeout));
258
258
  };
259
259
  }
260
- function createFetchMethod(endpoint, prefix, config) {
260
+ function createFetchMethod(endpoint, prefix, config, contractConfig) {
261
+ const prefixKeys = new Set(contractConfig?.stripPrefixKeys ?? []);
261
262
  return async (args) => {
262
- let url = buildFetchUrl(config.baseUrl, prefix, endpoint.path, args);
263
+ let pathPrefixStr = "";
264
+ if (contractConfig?.pathPrefix) {
265
+ pathPrefixStr = typeof contractConfig.pathPrefix === "function" ? contractConfig.pathPrefix(args ?? {}) : contractConfig.pathPrefix;
266
+ if (pathPrefixStr && !pathPrefixStr.endsWith("/"))
267
+ pathPrefixStr += "/";
268
+ }
269
+ let url = buildFetchUrl(config.baseUrl, prefix, endpoint.path, args, pathPrefixStr);
263
270
  const headers = {
264
271
  Accept: "application/json",
265
272
  ...typeof config.headers === "function" ? config.headers() : config.headers
@@ -267,7 +274,7 @@ function createFetchMethod(endpoint, prefix, config) {
267
274
  const isQuery = inputIsQuery(endpoint.method);
268
275
  const hasBody = !isQuery && !endpoint.multipart && endpoint.input && args;
269
276
  if (isQuery && args) {
270
- const remaining = stripParams(args, endpoint.path);
277
+ const remaining = stripParams(args, endpoint.path, prefixKeys);
271
278
  const searchParams = new URLSearchParams;
272
279
  for (const [k, v] of Object.entries(remaining)) {
273
280
  if (v === undefined || v === null)
@@ -291,7 +298,7 @@ function createFetchMethod(endpoint, prefix, config) {
291
298
  }
292
299
  const formData = new FormData;
293
300
  formData.append(endpoint.multipart, file);
294
- appendFormFields(formData, stripParams(args, endpoint.path), new Set([endpoint.multipart]));
301
+ appendFormFields(formData, stripParams(args, endpoint.path, prefixKeys), new Set([endpoint.multipart]));
295
302
  const res2 = await fetch(url, {
296
303
  method: endpoint.method,
297
304
  headers,
@@ -310,7 +317,9 @@ function createFetchMethod(endpoint, prefix, config) {
310
317
  method: endpoint.method,
311
318
  headers,
312
319
  credentials: config.credentials,
313
- ...hasBody && { body: JSON.stringify(stripParams(hasBody, endpoint.path)) }
320
+ ...hasBody && {
321
+ body: JSON.stringify(stripParams(hasBody, endpoint.path, prefixKeys))
322
+ }
314
323
  });
315
324
  if (!res.ok) {
316
325
  await throwForErrorResponse(res, config, { error: res.statusText });
@@ -341,8 +350,8 @@ function extractParamNames(path) {
341
350
  const matches = path.match(/:(\w+)/g);
342
351
  return matches ? matches.map((m) => m.slice(1)) : [];
343
352
  }
344
- function buildFetchUrl(baseUrl, prefix, path, args) {
345
- let fullPath = `/${prefix}${path === "/" ? "" : path}`;
353
+ function buildFetchUrl(baseUrl, prefix, path, args, pathPrefix = "") {
354
+ let fullPath = `/${pathPrefix}${prefix}${path === "/" ? "" : path}`;
346
355
  if (args) {
347
356
  fullPath = fullPath.replace(/:(\w+)/g, (_, key) => {
348
357
  const val = args[key];
@@ -354,15 +363,15 @@ function buildFetchUrl(baseUrl, prefix, path, args) {
354
363
  }
355
364
  return `${baseUrl}${fullPath}`;
356
365
  }
357
- function stripParams(args, path) {
358
- const paramNames = new Set;
366
+ function stripParams(args, path, extra) {
367
+ const skip = new Set(extra);
359
368
  for (const match of path.matchAll(/:(\w+)/g)) {
360
369
  if (match[1])
361
- paramNames.add(match[1]);
370
+ skip.add(match[1]);
362
371
  }
363
372
  const result = {};
364
373
  for (const [k, v] of Object.entries(args)) {
365
- if (!paramNames.has(k))
374
+ if (!skip.has(k))
366
375
  result[k] = v;
367
376
  }
368
377
  return result;
@@ -129,7 +129,45 @@ function corsPreflightResponse(config, req) {
129
129
 
130
130
  // src/server/router.ts
131
131
  import { readFile, stat } from "node:fs/promises";
132
- import { extname, resolve } from "node:path";
132
+ import { resolve } from "node:path";
133
+
134
+ // src/server/mime.ts
135
+ import { extname } from "node:path";
136
+ var MIME_BY_EXT = {
137
+ ".html": "text/html; charset=utf-8",
138
+ ".css": "text/css; charset=utf-8",
139
+ ".js": "text/javascript; charset=utf-8",
140
+ ".mjs": "text/javascript; charset=utf-8",
141
+ ".json": "application/json; charset=utf-8",
142
+ ".svg": "image/svg+xml",
143
+ ".png": "image/png",
144
+ ".jpg": "image/jpeg",
145
+ ".jpeg": "image/jpeg",
146
+ ".gif": "image/gif",
147
+ ".webp": "image/webp",
148
+ ".avif": "image/avif",
149
+ ".ico": "image/x-icon",
150
+ ".woff2": "font/woff2",
151
+ ".txt": "text/plain; charset=utf-8",
152
+ ".wasm": "application/wasm",
153
+ ".mp4": "video/mp4",
154
+ ".webm": "video/webm",
155
+ ".mov": "video/quicktime",
156
+ ".ogv": "video/ogg",
157
+ ".mp3": "audio/mpeg",
158
+ ".m4a": "audio/mp4",
159
+ ".wav": "audio/wav",
160
+ ".flac": "audio/flac",
161
+ ".oga": "audio/ogg",
162
+ ".ogg": "audio/ogg",
163
+ ".pdf": "application/pdf",
164
+ ".zip": "application/zip"
165
+ };
166
+ function mimeForPath(path) {
167
+ return MIME_BY_EXT[extname(path).toLowerCase()] ?? "application/octet-stream";
168
+ }
169
+
170
+ // src/server/router.ts
133
171
  function joinPath(...parts) {
134
172
  const joined = parts.filter(Boolean).map((part) => part.replace(/^\/+|\/+$/g, "")).filter(Boolean).join("/");
135
173
  return `/${joined}`;
@@ -247,22 +285,6 @@ function matchRawRoute(rawRoutes, httpMethod, pathname) {
247
285
  }
248
286
  return null;
249
287
  }
250
- var STATIC_MIME = {
251
- ".html": "text/html; charset=utf-8",
252
- ".css": "text/css; charset=utf-8",
253
- ".js": "text/javascript; charset=utf-8",
254
- ".mjs": "text/javascript; charset=utf-8",
255
- ".json": "application/json; charset=utf-8",
256
- ".svg": "image/svg+xml",
257
- ".png": "image/png",
258
- ".jpg": "image/jpeg",
259
- ".jpeg": "image/jpeg",
260
- ".gif": "image/gif",
261
- ".webp": "image/webp",
262
- ".ico": "image/x-icon",
263
- ".woff2": "font/woff2",
264
- ".txt": "text/plain; charset=utf-8"
265
- };
266
288
  function staticRoute(prefix, dir) {
267
289
  const cleanPrefix = prefix.replace(/\/+$/, "");
268
290
  const root = resolve(dir.replace(/\/+$/, ""));
@@ -288,7 +310,7 @@ function staticRoute(prefix, dir) {
288
310
  const body = await readFile(target);
289
311
  return new Response(body, {
290
312
  headers: {
291
- "Content-Type": STATIC_MIME[extname(target).toLowerCase()] ?? "application/octet-stream",
313
+ "Content-Type": mimeForPath(target),
292
314
  "X-Content-Type-Options": "nosniff"
293
315
  }
294
316
  });
@@ -410,7 +432,13 @@ function elapsedMs(startTime) {
410
432
  return performance.now() - startTime;
411
433
  }
412
434
  function safePath(pathname) {
413
- return pathname.replace(/[-]/g, "");
435
+ let out = "";
436
+ for (let i = 0;i < pathname.length; i++) {
437
+ const code = pathname.charCodeAt(i);
438
+ if (code > 31 && code !== 127)
439
+ out += pathname.charAt(i);
440
+ }
441
+ return out;
414
442
  }
415
443
  function levelForStatus(status) {
416
444
  if (status >= 500)
@@ -646,7 +674,8 @@ function normalizeGroups(config) {
646
674
  const result = [];
647
675
  if (config.services) {
648
676
  for (const service of config.services) {
649
- result.push({ prefix: "", service });
677
+ const prefix = config.scopePrefixes?.[service.scope] ?? "";
678
+ result.push({ prefix, service });
650
679
  }
651
680
  }
652
681
  if (config.groups) {
@@ -690,6 +719,8 @@ function implement(contract, handlers) {
690
719
  method: endpoint.method,
691
720
  path: endpoint.path,
692
721
  desc: endpoint.desc,
722
+ serviceName: contract.meta.prefix,
723
+ key: String(key),
693
724
  toolName: "toolName" in endpoint ? endpoint.toolName : undefined,
694
725
  expose: endpoint.expose,
695
726
  scope: endpoint.scope ?? groupScope,
@@ -699,6 +730,7 @@ function implement(contract, handlers) {
699
730
  multipart: endpoint.multipart,
700
731
  ui: "ui" in endpoint ? endpoint.ui : undefined,
701
732
  annotations: "annotations" in endpoint ? endpoint.annotations : undefined,
733
+ meta: endpoint.meta,
702
734
  handler: (ctx) => typedHandler(ctx)
703
735
  };
704
736
  }
@@ -777,21 +809,37 @@ async function createSocketIOServer(config) {
777
809
  const path = config.path ?? "/socket.io/";
778
810
  const onBun = "Bun" in globalThis;
779
811
  const transports = config.transports ?? (onBun ? ["websocket", "polling"] : ["websocket"]);
812
+ const pingTimeout = config.pingTimeout ?? 20000;
813
+ const pingInterval = config.pingInterval ?? 1e4;
814
+ const cors = {
815
+ origin: config.cors.origin,
816
+ credentials: config.cors.credentials ?? true,
817
+ methods: ["GET", "POST"]
818
+ };
780
819
  const { Server } = await import("socket.io");
781
820
  const io = new Server({
821
+ ...config.serverOptions,
782
822
  path,
783
- cors: {
784
- origin: config.cors.origin,
785
- credentials: config.cors.credentials ?? true,
786
- methods: ["GET", "POST"]
787
- },
823
+ cors,
788
824
  transports,
789
- pingTimeout: config.pingTimeout ?? 20000,
790
- pingInterval: config.pingInterval ?? 1e4
825
+ pingTimeout,
826
+ pingInterval
791
827
  });
792
828
  if (onBun) {
793
829
  const { Server: Engine } = await import("@socket.io/bun-engine");
794
- const engine = new Engine({ path });
830
+ const engineOpts = {
831
+ path,
832
+ cors,
833
+ pingTimeout,
834
+ pingInterval
835
+ };
836
+ if (config.serverOptions?.maxHttpBufferSize !== undefined) {
837
+ engineOpts.maxHttpBufferSize = config.serverOptions.maxHttpBufferSize;
838
+ }
839
+ if (config.serverOptions?.upgradeTimeout !== undefined) {
840
+ engineOpts.upgradeTimeout = config.serverOptions.upgradeTimeout;
841
+ }
842
+ const engine = new Engine(engineOpts);
795
843
  io.bind(engine);
796
844
  const { websocket } = engine.handler();
797
845
  const route = {
@@ -826,4 +874,4 @@ function socketIoLane(websocket) {
826
874
  });
827
875
  }
828
876
 
829
- export { parseMultipart, corsHeaders, corsPreflightResponse, staticRoute, createHandler, createServer, implement, createImplement, webSocketLane, composeWebSocketHandlers, createSocketIOServer, socketIoLane };
877
+ export { parseMultipart, corsHeaders, corsPreflightResponse, mimeForPath, staticRoute, createHandler, createServer, implement, createImplement, webSocketLane, composeWebSocketHandlers, createSocketIOServer, socketIoLane };
@@ -0,0 +1,87 @@
1
+ import {
2
+ getClientInfo,
3
+ resolveSocketIp
4
+ } from "./index-mwmpw6j1.js";
5
+
6
+ // src/observability/trace.ts
7
+ var TRACEPARENT_RE = /^00-([0-9a-f]{32})-([0-9a-f]{16})-[0-9a-f]{2}$/i;
8
+ function randomHex(bytes) {
9
+ const arr = new Uint8Array(bytes);
10
+ crypto.getRandomValues(arr);
11
+ let hex = "";
12
+ for (const byte of arr)
13
+ hex += byte.toString(16).padStart(2, "0");
14
+ return hex;
15
+ }
16
+ function createTraceContext() {
17
+ return { traceId: randomHex(16), spanId: randomHex(8) };
18
+ }
19
+ function parseTraceparent(header) {
20
+ if (!header)
21
+ return null;
22
+ const match = TRACEPARENT_RE.exec(header.trim());
23
+ if (!match?.[1] || !match[2])
24
+ return null;
25
+ const traceId = match[1].toLowerCase();
26
+ const parentSpanId = match[2].toLowerCase();
27
+ if (/^0+$/.test(traceId) || /^0+$/.test(parentSpanId))
28
+ return null;
29
+ return { traceId, spanId: randomHex(8), parentSpanId };
30
+ }
31
+ function formatTraceparent(ctx) {
32
+ return `00-${ctx.traceId}-${ctx.spanId}-01`;
33
+ }
34
+ function resolveTraceContext(req) {
35
+ return parseTraceparent(req.headers.get("traceparent")) ?? createTraceContext();
36
+ }
37
+ function childSpan(parent) {
38
+ return {
39
+ traceId: parent.traceId,
40
+ spanId: randomHex(8),
41
+ parentSpanId: parent.spanId
42
+ };
43
+ }
44
+
45
+ // src/observability/context.ts
46
+ import { AsyncLocalStorage } from "node:async_hooks";
47
+ var storage = new AsyncLocalStorage;
48
+ function runWithRequestContext(ctx, fn) {
49
+ return storage.run(ctx, fn);
50
+ }
51
+ function getRequestContext() {
52
+ return storage.getStore();
53
+ }
54
+ function getTraceId() {
55
+ return storage.getStore()?.trace.traceId;
56
+ }
57
+ function getUserId() {
58
+ return storage.getStore()?.userId;
59
+ }
60
+ function setRequestUser(userId) {
61
+ const ctx = storage.getStore();
62
+ if (ctx)
63
+ ctx.userId = userId;
64
+ }
65
+ function setRequestError(error) {
66
+ const ctx = storage.getStore();
67
+ if (ctx)
68
+ ctx.error = error;
69
+ }
70
+ function wrapInRequestContext(handler, options = {}) {
71
+ return (req, server) => {
72
+ const ctx = {
73
+ trace: resolveTraceContext(req),
74
+ source: "http",
75
+ method: req.method,
76
+ path: new URL(req.url, "http://localhost").pathname,
77
+ startedAt: process.hrtime.bigint(),
78
+ ...getClientInfo(req, {
79
+ trustProxy: options.trustProxy,
80
+ socketIp: resolveSocketIp(req, server)
81
+ })
82
+ };
83
+ return runWithRequestContext(ctx, () => handler(req, server));
84
+ };
85
+ }
86
+
87
+ export { createTraceContext, parseTraceparent, formatTraceparent, resolveTraceContext, childSpan, runWithRequestContext, getRequestContext, getTraceId, getUserId, setRequestUser, setRequestError, wrapInRequestContext };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { createClient, createClients } from './browser/client';
1
+ export { type ClientConfig, type ContractClientConfig, createClient, createClients, } from './browser/client';
2
2
  export { ApiError, type ApiEvent, type ApiEventListener, createHttpClient, type HeaderProvider, type HttpClient, type HttpClientConfig, type RequestOptions, } from './browser/http';
3
3
  export type { SocketEventMap, SocketIOClient, SocketIOClientConfig, } from './browser/socket-io';
4
4
  export { createSocketIOClient } from './browser/socket-io';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EACL,QAAQ,EACR,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,cAAc,GACpB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,cAAc,EACd,cAAc,EACd,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,KAAK,eAAe,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAClE,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,YAAY,EACZ,aAAa,GACd,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,QAAQ,EACR,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,cAAc,GACpB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,cAAc,EACd,cAAc,EACd,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,KAAK,eAAe,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAClE,cAAc,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  createClient,
4
4
  createClients,
5
5
  createHttpClient
6
- } from "./index-78q1qm7v.js";
6
+ } from "./index-kdkvp26v.js";
7
7
  import {
8
8
  parseSSE
9
9
  } from "./index-d4rwrjbc.js";
package/dist/node.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  createImplement,
4
4
  createSocketIOServer,
5
5
  implement
6
- } from "./index-3qmtdfpa.js";
6
+ } from "./index-m9328d8z.js";
7
7
  import"./index-x3fcszf8.js";
8
8
  import"./index-vhdvv00d.js";
9
9
  import {
@@ -1,7 +1,18 @@
1
1
  import {
2
- getClientInfo,
3
- resolveSocketIp
4
- } from "../index-mwmpw6j1.js";
2
+ childSpan,
3
+ createTraceContext,
4
+ formatTraceparent,
5
+ getRequestContext,
6
+ getTraceId,
7
+ getUserId,
8
+ parseTraceparent,
9
+ resolveTraceContext,
10
+ runWithRequestContext,
11
+ setRequestError,
12
+ setRequestUser,
13
+ wrapInRequestContext
14
+ } from "../index-za2p453b.js";
15
+ import"../index-mwmpw6j1.js";
5
16
  import {
6
17
  isUnsafeKey
7
18
  } from "../index-kzfs85xp.js";
@@ -10,89 +21,6 @@ import {
10
21
  } from "../index-809wc1tt.js";
11
22
  import"../index-37x76zdn.js";
12
23
 
13
- // src/observability/context.ts
14
- import { AsyncLocalStorage } from "node:async_hooks";
15
-
16
- // src/observability/trace.ts
17
- var TRACEPARENT_RE = /^00-([0-9a-f]{32})-([0-9a-f]{16})-[0-9a-f]{2}$/i;
18
- function randomHex(bytes) {
19
- const arr = new Uint8Array(bytes);
20
- crypto.getRandomValues(arr);
21
- let hex = "";
22
- for (const byte of arr)
23
- hex += byte.toString(16).padStart(2, "0");
24
- return hex;
25
- }
26
- function createTraceContext() {
27
- return { traceId: randomHex(16), spanId: randomHex(8) };
28
- }
29
- function parseTraceparent(header) {
30
- if (!header)
31
- return null;
32
- const match = TRACEPARENT_RE.exec(header.trim());
33
- if (!match?.[1] || !match[2])
34
- return null;
35
- const traceId = match[1].toLowerCase();
36
- const parentSpanId = match[2].toLowerCase();
37
- if (/^0+$/.test(traceId) || /^0+$/.test(parentSpanId))
38
- return null;
39
- return { traceId, spanId: randomHex(8), parentSpanId };
40
- }
41
- function formatTraceparent(ctx) {
42
- return `00-${ctx.traceId}-${ctx.spanId}-01`;
43
- }
44
- function resolveTraceContext(req) {
45
- return parseTraceparent(req.headers.get("traceparent")) ?? createTraceContext();
46
- }
47
- function childSpan(parent) {
48
- return {
49
- traceId: parent.traceId,
50
- spanId: randomHex(8),
51
- parentSpanId: parent.spanId
52
- };
53
- }
54
-
55
- // src/observability/context.ts
56
- var storage = new AsyncLocalStorage;
57
- function runWithRequestContext(ctx, fn) {
58
- return storage.run(ctx, fn);
59
- }
60
- function getRequestContext() {
61
- return storage.getStore();
62
- }
63
- function getTraceId() {
64
- return storage.getStore()?.trace.traceId;
65
- }
66
- function getUserId() {
67
- return storage.getStore()?.userId;
68
- }
69
- function setRequestUser(userId) {
70
- const ctx = storage.getStore();
71
- if (ctx)
72
- ctx.userId = userId;
73
- }
74
- function setRequestError(error) {
75
- const ctx = storage.getStore();
76
- if (ctx)
77
- ctx.error = error;
78
- }
79
- function wrapInRequestContext(handler, options = {}) {
80
- return (req, server) => {
81
- const ctx = {
82
- trace: resolveTraceContext(req),
83
- source: "http",
84
- method: req.method,
85
- path: new URL(req.url, "http://localhost").pathname,
86
- startedAt: process.hrtime.bigint(),
87
- ...getClientInfo(req, {
88
- trustProxy: options.trustProxy,
89
- socketIp: resolveSocketIp(req, server)
90
- })
91
- };
92
- return runWithRequestContext(ctx, () => handler(req, server));
93
- };
94
- }
95
-
96
24
  // src/observability/sanitize.ts
97
25
  var DEFAULT_SENSITIVE_KEYS = /(password|passwd|pwd|secret|token|apikey|api[-_ ]?key|auth|authorization|bearer|session|cookie|init[-_ ]?data|credential|private[-_ ]?key)/i;
98
26
  var DEFAULT_MAX_BYTES = 16000;
@@ -0,0 +1,52 @@
1
+ /** An inclusive byte range `[start, end]`. */
2
+ export interface ByteRange {
3
+ start: number;
4
+ end: number;
5
+ }
6
+ /**
7
+ * Parse a single-range `Range` header against a known `size`.
8
+ *
9
+ * - `null` — no header, malformed, or multiple ranges (caller serves the full
10
+ * `200` body; ignoring an unparseable Range is RFC-compliant).
11
+ * - `'unsatisfiable'` — a well-formed range that lies outside the file (the
12
+ * caller answers `416` with `Content-Range: bytes * /size`).
13
+ * - `{ start, end }` — an inclusive, clamped range to serve as `206`.
14
+ *
15
+ * Multiple ranges (`bytes=0-9,20-29`) are intentionally unsupported and return
16
+ * `null` (no `multipart/byteranges`). → ADR 0023.
17
+ */
18
+ export declare function parseByteRange(header: string | null, size: number): ByteRange | 'unsatisfiable' | null;
19
+ /**
20
+ * A weak entity tag derived from size + mtime — cheap (no content hashing) and
21
+ * stable across requests. Weak because two files with the same size and mtime
22
+ * are treated as equivalent, which is the right trade for static media.
23
+ */
24
+ export declare function weakETag(size: number, mtimeMs: number): string;
25
+ export interface ServeFileOptions {
26
+ /** Absolute (or cwd-relative) path to the file. The caller owns containment. */
27
+ path: string;
28
+ /** MIME type. Auto-detected from the path extension when omitted. */
29
+ contentType?: string;
30
+ /** Sets `Content-Disposition` with this filename. */
31
+ filename?: string;
32
+ /** `Content-Disposition` type. Defaults to `inline` (set with `filename`). */
33
+ disposition?: 'inline' | 'attachment';
34
+ /** Value for the `Cache-Control` header, verbatim. */
35
+ cacheControl?: string;
36
+ /** Emit a weak `ETag` (default `true`). */
37
+ etag?: boolean;
38
+ /** Emit `Last-Modified` (default `true`). */
39
+ lastModified?: boolean;
40
+ }
41
+ /**
42
+ * Serve a file with full Range + conditional-request support. Returns:
43
+ * `405` (non GET/HEAD), `404` (missing), `304` (fresh per `If-None-Match` /
44
+ * `If-Modified-Since`), `200` (full — no/ignored Range), `206` (range), or `416`
45
+ * (unsatisfiable range). Always sets `Accept-Ranges: bytes` and `nosniff`; a
46
+ * `HEAD` returns every header with an empty body.
47
+ *
48
+ * Bun-first (`Bun.file`). The caller is responsible for path containment — for
49
+ * URL-derived paths use `staticRoute` or `isWithinDir`. → ADR 0023.
50
+ */
51
+ export declare function serveFile(req: Request, opts: ServeFileOptions): Promise<Response>;
52
+ //# sourceMappingURL=file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/server/file.ts"],"names":[],"mappings":"AAaA,8CAA8C;AAC9C,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,IAAI,EAAE,MAAM,GACX,SAAS,GAAG,eAAe,GAAG,IAAI,CAkCpC;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE9D;AA6ED,MAAM,WAAW,gBAAgB;IAC/B,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,QAAQ,GAAG,YAAY,CAAC;IACtC,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,6CAA6C;IAC7C,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;;;;;;GASG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAwEvF"}
@@ -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;AAE5E,OAAO,KAAK,EAAE,QAAQ,EAAa,UAAU,EAAE,MAAM,SAAS,CAAC;AAE/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,CAsC3E;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"}
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;AAE5E,OAAO,KAAK,EAAE,QAAQ,EAAa,UAAU,EAAE,MAAM,SAAS,CAAC;AAE/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,CA4C3E;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"}
@@ -2,6 +2,7 @@ export { AppError, appError, badRequest, conflict, forbidden, notFound, rateLimi
2
2
  export { cacheHeaders, createCache } from './cache';
3
3
  export { createHandler, createServer } from './create';
4
4
  export { createEventBus, type EventBus } from './event-bus';
5
+ export { type ByteRange, parseByteRange, type ServeFileOptions, serveFile, weakETag, } from './file';
5
6
  export { createImplement, implement } from './implement';
6
7
  export { type AuthHook, type AuthHookConfig, type AuthRule, type BearerResolverConfig, createAuthHook, createBearerResolver, extractToken, type JwtPayload, type SignJwtOptions, signJwt, verifyJwt, } from './middleware/auth';
7
8
  export { type CookieDef, type CookieOptions, defineCookie, parseCookies, serializeCookie, } from './middleware/cookies';
@@ -10,6 +11,7 @@ export { deriveCodeChallenge, type PkceMethod, verifyPkce } from './middleware/p
10
11
  export { parseMultipart } from './multipart';
11
12
  export { generateOpenApiDocument, type OpenApiConfig, type OpenApiDocument, type OpenApiInfo, type OpenApiServer, openApiRoute, } from './openapi';
12
13
  export { createRateLimiter, type RateLimitConfig } from './rate-limit';
14
+ export { errorResponse, parseBody, respondJson } from './raw';
13
15
  export { type ClientIpOptions, extractIp, generateTraceId, getClientInfo, resolveSocketIp, resolveTraceId, } from './request';
14
16
  export { staticRoute } from './router';
15
17
  export type { SocketIOServerConfig, SocketIOServerHandle } from './socket-io';
@@ -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,QAAQ,EACR,WAAW,EACX,YAAY,GACb,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5D,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,GACtB,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,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"}
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,QAAQ,EACR,WAAW,EACX,YAAY,GACb,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACvD,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,GACtB,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"}
@@ -21,6 +21,9 @@ import {
21
21
  jsonSchemaFields,
22
22
  toJsonSchema
23
23
  } from "../index-0ed3bx43.js";
24
+ import {
25
+ getTraceId
26
+ } from "../index-za2p453b.js";
24
27
  import {
25
28
  composeWebSocketHandlers,
26
29
  corsHeaders,
@@ -30,13 +33,16 @@ import {
30
33
  createServer,
31
34
  createSocketIOServer,
32
35
  implement,
36
+ mimeForPath,
33
37
  parseMultipart,
34
38
  socketIoLane,
35
39
  staticRoute,
36
40
  webSocketLane
37
- } from "../index-3qmtdfpa.js";
41
+ } from "../index-m9328d8z.js";
38
42
  import"../index-x3fcszf8.js";
39
- import"../index-vhdvv00d.js";
43
+ import {
44
+ normalizeError
45
+ } from "../index-vhdvv00d.js";
40
46
  import {
41
47
  AppError,
42
48
  appError,
@@ -169,6 +175,154 @@ function createEventBus(options = {}) {
169
175
  }
170
176
  };
171
177
  }
178
+ // src/server/file.ts
179
+ function parseByteRange(header, size) {
180
+ if (!header)
181
+ return null;
182
+ const match = /^bytes=(.+)$/.exec(header.trim());
183
+ const rawSpec = match?.[1];
184
+ if (rawSpec === undefined)
185
+ return null;
186
+ const spec = rawSpec.trim();
187
+ if (spec.includes(","))
188
+ return null;
189
+ const dash = spec.indexOf("-");
190
+ if (dash === -1)
191
+ return null;
192
+ const startStr = spec.slice(0, dash).trim();
193
+ const endStr = spec.slice(dash + 1).trim();
194
+ if (startStr === "") {
195
+ if (!/^\d+$/.test(endStr))
196
+ return null;
197
+ const suffix = Number(endStr);
198
+ if (suffix === 0 || size === 0)
199
+ return "unsatisfiable";
200
+ return { start: Math.max(0, size - suffix), end: size - 1 };
201
+ }
202
+ if (!/^\d+$/.test(startStr))
203
+ return null;
204
+ const start = Number(startStr);
205
+ if (size === 0 || start >= size)
206
+ return "unsatisfiable";
207
+ if (endStr === "")
208
+ return { start, end: size - 1 };
209
+ if (!/^\d+$/.test(endStr))
210
+ return null;
211
+ const end = Number(endStr);
212
+ if (end < start)
213
+ return null;
214
+ return { start, end: end >= size ? size - 1 : end };
215
+ }
216
+ function weakETag(size, mtimeMs) {
217
+ return `W/"${size.toString(16)}-${Math.floor(mtimeMs).toString(16)}"`;
218
+ }
219
+ function leSeconds(aMs, bMs) {
220
+ return Math.floor(aMs / 1000) <= Math.floor(bMs / 1000);
221
+ }
222
+ function isNotModified(req, v) {
223
+ const inm = req.headers.get("if-none-match");
224
+ if (inm !== null) {
225
+ const value = inm.trim();
226
+ if (value === "*")
227
+ return true;
228
+ if (v.etag === undefined)
229
+ return false;
230
+ return value.split(",").map((t) => t.trim()).includes(v.etag);
231
+ }
232
+ const ims = req.headers.get("if-modified-since");
233
+ if (ims !== null) {
234
+ if (v.lastModifiedMs === undefined)
235
+ return false;
236
+ const since = Date.parse(ims);
237
+ if (Number.isNaN(since))
238
+ return false;
239
+ return leSeconds(v.lastModifiedMs, since);
240
+ }
241
+ return false;
242
+ }
243
+ function ifRangeMatches(req, v) {
244
+ const ir = req.headers.get("if-range");
245
+ if (ir === null)
246
+ return true;
247
+ const value = ir.trim();
248
+ if (v.etag !== undefined && value === v.etag)
249
+ return true;
250
+ if (v.lastModifiedMs !== undefined) {
251
+ const asDate = Date.parse(value);
252
+ if (!Number.isNaN(asDate))
253
+ return leSeconds(v.lastModifiedMs, asDate);
254
+ }
255
+ return false;
256
+ }
257
+ function asciiFilename(filename) {
258
+ let out = "";
259
+ for (let i = 0;i < filename.length; i++) {
260
+ const code = filename.charCodeAt(i);
261
+ out += code >= 32 && code < 127 && code !== 34 && code !== 92 ? filename.charAt(i) : "_";
262
+ }
263
+ return out;
264
+ }
265
+ function contentDisposition(disposition, filename) {
266
+ return `${disposition}; filename="${asciiFilename(filename)}"; filename*=UTF-8''${encodeURIComponent(filename)}`;
267
+ }
268
+ async function serveFile(req, opts) {
269
+ if (req.method !== "GET" && req.method !== "HEAD") {
270
+ return new Response("Method not allowed", {
271
+ status: 405,
272
+ headers: { Allow: "GET, HEAD" }
273
+ });
274
+ }
275
+ const file = Bun.file(opts.path);
276
+ if (!await file.exists()) {
277
+ return new Response("Not found", { status: 404 });
278
+ }
279
+ const size = file.size;
280
+ const mtimeMs = file.lastModified;
281
+ const contentType = opts.contentType ?? mimeForPath(opts.path);
282
+ const useEtag = opts.etag !== false;
283
+ const useLastModified = opts.lastModified !== false;
284
+ const etag = useEtag ? weakETag(size, mtimeMs) : undefined;
285
+ const validators = {
286
+ etag,
287
+ lastModifiedMs: useLastModified ? mtimeMs : undefined
288
+ };
289
+ const isHead = req.method === "HEAD";
290
+ const base = new Headers;
291
+ base.set("Accept-Ranges", "bytes");
292
+ base.set("X-Content-Type-Options", "nosniff");
293
+ if (etag)
294
+ base.set("ETag", etag);
295
+ if (useLastModified)
296
+ base.set("Last-Modified", new Date(mtimeMs).toUTCString());
297
+ if (opts.cacheControl)
298
+ base.set("Cache-Control", opts.cacheControl);
299
+ if (opts.filename) {
300
+ base.set("Content-Disposition", contentDisposition(opts.disposition ?? "inline", opts.filename));
301
+ } else if (opts.disposition) {
302
+ base.set("Content-Disposition", opts.disposition);
303
+ }
304
+ if ((useEtag || useLastModified) && isNotModified(req, validators)) {
305
+ return new Response(null, { status: 304, headers: base });
306
+ }
307
+ const rangeHeader = req.headers.get("range");
308
+ const range = rangeHeader !== null && ifRangeMatches(req, validators) ? parseByteRange(rangeHeader, size) : null;
309
+ if (range === "unsatisfiable") {
310
+ base.set("Content-Range", `bytes */${size}`);
311
+ base.set("Content-Type", contentType);
312
+ return new Response(null, { status: 416, headers: base });
313
+ }
314
+ if (range) {
315
+ const length = range.end - range.start + 1;
316
+ base.set("Content-Type", contentType);
317
+ base.set("Content-Range", `bytes ${range.start}-${range.end}/${size}`);
318
+ base.set("Content-Length", String(length));
319
+ const body = isHead ? null : file.slice(range.start, range.end + 1);
320
+ return new Response(body, { status: 206, headers: base });
321
+ }
322
+ base.set("Content-Type", contentType);
323
+ base.set("Content-Length", String(size));
324
+ return new Response(isHead ? null : file, { status: 200, headers: base });
325
+ }
172
326
  // src/server/openapi.ts
173
327
  var ERROR_ENVELOPE_SCHEMA = {
174
328
  type: "object",
@@ -362,8 +516,30 @@ function createRateLimiter() {
362
516
  }
363
517
  };
364
518
  }
519
+ // src/server/raw.ts
520
+ function respondJson(data) {
521
+ if (data === null || data === undefined)
522
+ return new Response(null, { status: 204 });
523
+ return Response.json(data);
524
+ }
525
+ function errorResponse2(error) {
526
+ const appErr = normalizeError(error);
527
+ const res = Response.json(appErr.toJSON(), { status: appErr.status });
528
+ const traceId = getTraceId();
529
+ if (traceId)
530
+ res.headers.set("x-request-id", traceId);
531
+ return res;
532
+ }
533
+ async function parseBody(req, schema) {
534
+ const raw = await req.json().catch(() => null);
535
+ if (raw === null)
536
+ return null;
537
+ const parsed = schema.safeParse(raw);
538
+ return parsed.success ? parsed.data : null;
539
+ }
365
540
  export {
366
541
  webSocketLane,
542
+ weakETag,
367
543
  verifyPkce,
368
544
  verifyJwt,
369
545
  unauthorized,
@@ -371,13 +547,17 @@ export {
371
547
  staticRoute,
372
548
  socketIoLane,
373
549
  signJwt,
550
+ serveFile,
374
551
  serializeCookie,
552
+ respondJson,
375
553
  resolveTraceId,
376
554
  resolveSocketIp,
377
555
  rateLimited,
378
556
  parseSSE,
379
557
  parseMultipart,
380
558
  parseCookies,
559
+ parseByteRange,
560
+ parseBody,
381
561
  openApiRoute,
382
562
  notFound,
383
563
  implement,
@@ -387,6 +567,7 @@ export {
387
567
  forbidden,
388
568
  extractToken,
389
569
  extractIp,
570
+ errorResponse2 as errorResponse,
390
571
  deriveCodeChallenge,
391
572
  defineCookie,
392
573
  createSocketIOServer,
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/server/logger.ts"],"names":[],"mappings":"AAwCA,6DAA6D;AAC7D,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEnD;AAQD,yCAAyC;AACzC,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAIxE;AAED,wEAAwE;AACxE,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACd;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAEvF;AA0BD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAID,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAGnE;AAED,2EAA2E;AAC3E,wBAAgB,WAAW,CACzB,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,GACjB,UAAU,CASZ;AAED,oFAAoF;AACpF,wBAAgB,WAAW,CACzB,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,UAAU,EACf,SAAS,CAAC,EAAE,MAAM,GACjB,IAAI,CAoBN"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/server/logger.ts"],"names":[],"mappings":"AAwCA,6DAA6D;AAC7D,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEnD;AAoBD,yCAAyC;AACzC,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAIxE;AAED,wEAAwE;AACxE,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACd;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAEvF;AA0BD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAID,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAGnE;AAED,2EAA2E;AAC3E,wBAAgB,WAAW,CACzB,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,GACjB,UAAU,CASZ;AAED,oFAAoF;AACpF,wBAAgB,WAAW,CACzB,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,UAAU,EACf,SAAS,CAAC,EAAE,MAAM,GACjB,IAAI,CAoBN"}
@@ -0,0 +1,3 @@
1
+ /** MIME type for a path's extension, or `application/octet-stream` if unknown. */
2
+ export declare function mimeForPath(path: string): string;
3
+ //# sourceMappingURL=mime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mime.d.ts","sourceRoot":"","sources":["../../src/server/mime.ts"],"names":[],"mappings":"AA2CA,kFAAkF;AAClF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Raw-route conveniences. A `RawRoute` is full `Request → Response` control (file
3
+ * streaming, webhooks, public SDK endpoints) — it deliberately skips the contract
4
+ * pipeline. These three helpers give back the boilerplate that pipeline does for
5
+ * free, reusing the **same** error envelope and trace id, so raw routes and
6
+ * contract routes stay consistent. They are conveniences, not a second pipeline:
7
+ * no auth, no schema gate beyond `parseBody`.
8
+ */
9
+ import type { ZodType } from 'zod';
10
+ /** A JSON response for `data`; `204 No Content` when `data` is null/undefined. */
11
+ export declare function respondJson(data: unknown): Response;
12
+ /**
13
+ * Turn any thrown value into the framework's error envelope + HTTP status — the
14
+ * identical shape (`{ error: { code, message, details?, hint? } }`) a contract
15
+ * route returns, via `normalizeError`. Stamps `x-request-id` with the current
16
+ * trace id when called inside a request context.
17
+ */
18
+ export declare function errorResponse(error: unknown): Response;
19
+ /**
20
+ * Parse and validate a JSON request body. Returns the typed value, or `null` for
21
+ * a non-JSON or schema-invalid body (never throws — the caller decides the error
22
+ * response). The error helpers (`badRequest`, …) **throw**, so raise one inside a
23
+ * `try` and render it in the `catch` with `errorResponse(err)`:
24
+ *
25
+ * ```ts
26
+ * try {
27
+ * const body = await parseBody(req, Schema)
28
+ * if (!body) throw badRequest('invalid body')
29
+ * return respondJson(await handle(body))
30
+ * } catch (err) {
31
+ * return errorResponse(err)
32
+ * }
33
+ * ```
34
+ */
35
+ export declare function parseBody<T>(req: Request, schema: ZodType<T>): Promise<T | null>;
36
+ //# sourceMappingURL=raw.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw.d.ts","sourceRoot":"","sources":["../../src/server/raw.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAInC,kFAAkF;AAClF,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAGnD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAMtD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAKtF"}
@@ -35,9 +35,10 @@ export declare function matchRawRoute(rawRoutes: RawRoute[], httpMethod: string,
35
35
  } | null;
36
36
  /**
37
37
  * Build a `RawRoute` that serves files from `dir` under `prefix`. Basic by
38
- * design — no Range, no conditional requests; put a CDN in front for those.
39
- * Rejects path traversal (including the percent-encoded form); 404 for a
40
- * missing file. Uses `node:fs`, so it runs on both Bun and Node.
38
+ * design — no Range, no conditional requests, reads the whole file into memory;
39
+ * for media seeking / caching use `serveFile`, or put a CDN in front. Rejects
40
+ * path traversal (including the percent-encoded form); 404 for a missing file.
41
+ * Uses `node:fs`, so it runs on both Bun and Node.
41
42
  */
42
43
  export declare function staticRoute(prefix: string, dir: string): RawRoute;
43
44
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/server/router.ts"],"names":[],"mappings":"AAOA,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,UAAU,CAAC;IACpB,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,OAAO,EAAE,UAAU,CAAC;IACpB,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,CAmBnB;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,CAyB5D;AAoBD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ,CAmCjE"}
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,UAAU,CAAC;IACpB,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,OAAO,EAAE,UAAU,CAAC;IACpB,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,CAmBnB;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,CAyB5D;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ,CAkCjE"}
@@ -17,7 +17,7 @@
17
17
  */
18
18
  import type { Server as HttpServer } from 'node:http';
19
19
  import type { Server as BunEngine } from '@socket.io/bun-engine';
20
- import type { Server as SocketIOServer } from 'socket.io';
20
+ import type { ServerOptions, Server as SocketIOServer } from 'socket.io';
21
21
  import type { SocketEventMap } from '../browser/socket-io';
22
22
  import type { RawRoute } from './types';
23
23
  import { type ComposedLane } from './websocket';
@@ -41,6 +41,15 @@ export interface SocketIOServerConfig {
41
41
  pingTimeout?: number;
42
42
  /** Heartbeat: ms between pings. Default `10000`. */
43
43
  pingInterval?: number;
44
+ /**
45
+ * Typed passthrough for any other Socket.IO `ServerOptions` the wrapper does
46
+ * not own — `maxHttpBufferSize` (raise above the 1 MB default for large
47
+ * emits), `connectionStateRecovery`, `perMessageDeflate`, `connectTimeout`, …
48
+ * Mirrors the `bun` passthrough on `createServer`. The wrapper-owned fields
49
+ * (`cors` / `path` / `transports` / `pingTimeout` / `pingInterval`) take
50
+ * precedence over the same keys here, so transport integration stays correct.
51
+ */
52
+ serverOptions?: Partial<ServerOptions>;
44
53
  }
45
54
  export interface SocketIOServerHandle<TServerEvents extends SocketEventMap, TClientEvents extends SocketEventMap> {
46
55
  /** The typed Socket.IO server — attach `io.on('connection', ...)` handlers. */
@@ -1 +1 @@
1
- {"version":3,"file":"socket-io.d.ts","sourceRoot":"","sources":["../../src/server/socket-io.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,KAAK,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEjE,OAAO,KAAK,EAAE,MAAM,IAAI,cAAc,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,KAAK,YAAY,EAAiB,MAAM,aAAa,CAAC;AAE/D,MAAM,WAAW,oBAAoB;IACnC,6DAA6D;IAC7D,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC3D,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,KAAK,CAAC,WAAW,GAAG,SAAS,CAAC,CAAC;IAC5C,sFAAsF;IACtF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB,CACnC,aAAa,SAAS,cAAc,EACpC,aAAa,SAAS,cAAc;IAEpC,+EAA+E;IAC/E,EAAE,EAAE,cAAc,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;IACjD;;;;;OAKG;IACH,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IACzD;;;;;OAKG;IACH,KAAK,EAAE,QAAQ,CAAC;IAChB;;;;OAIG;IACH,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;CAClC;AAOD,wBAAsB,oBAAoB,CACxC,aAAa,SAAS,cAAc,EACpC,aAAa,SAAS,cAAc,EACpC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC,CA8D3F;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,oBAAoB,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC,WAAW,CAAC,GAC3E,YAAY,CAMd"}
1
+ {"version":3,"file":"socket-io.d.ts","sourceRoot":"","sources":["../../src/server/socket-io.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,KAAK,EACV,MAAM,IAAI,SAAS,EAEpB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,cAAc,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,KAAK,YAAY,EAAiB,MAAM,aAAa,CAAC;AAE/D,MAAM,WAAW,oBAAoB;IACnC,6DAA6D;IAC7D,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC3D,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,KAAK,CAAC,WAAW,GAAG,SAAS,CAAC,CAAC;IAC5C,sFAAsF;IACtF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,oBAAoB,CACnC,aAAa,SAAS,cAAc,EACpC,aAAa,SAAS,cAAc;IAEpC,+EAA+E;IAC/E,EAAE,EAAE,cAAc,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;IACjD;;;;;OAKG;IACH,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IACzD;;;;;OAKG;IACH,KAAK,EAAE,QAAQ,CAAC;IAChB;;;;OAIG;IACH,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;CAClC;AAOD,wBAAsB,oBAAoB,CACxC,aAAa,SAAS,cAAc,EACpC,aAAa,SAAS,cAAc,EACpC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC,CAoF3F;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,oBAAoB,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC,WAAW,CAAC,GAC3E,YAAY,CAMd"}
@@ -15,6 +15,18 @@ export interface MethodDef<TParams = unknown, TInput = unknown, TOutput = unknow
15
15
  method: HttpMethod;
16
16
  path: string;
17
17
  desc: string;
18
+ /**
19
+ * Owning contract's prefix — the "service" half of a stable `(service, action)`
20
+ * identity for hooks / audit / observability. Populated by `implement` /
21
+ * `implementRemote`; not derivable from `path`. → ADR 0022.
22
+ */
23
+ serviceName: string;
24
+ /**
25
+ * Endpoint key in the contract (e.g. `updatePartial`) — the "action" half of
26
+ * the identity. Not in `path`, and `toolName` is absent on HTTP-only endpoints,
27
+ * so this is the only stable per-endpoint key. → ADR 0022.
28
+ */
29
+ key: string;
18
30
  toolName?: string;
19
31
  expose?: readonly Transport[];
20
32
  scope?: string;
@@ -26,6 +38,12 @@ export interface MethodDef<TParams = unknown, TInput = unknown, TOutput = unknow
26
38
  ui?: EndpointUiMeta;
27
39
  /** MCP behavioural hints — carried onto the MCP tool's `annotations`. */
28
40
  annotations?: EndpointToolAnnotations;
41
+ /**
42
+ * Opaque app-defined metadata from `EndpointDef.meta` — the core gives it no
43
+ * meaning. Read it in lifecycle hooks (`endpoint.meta?.X`) or on tool mounts;
44
+ * the consumer narrows the type. Never serialized to OpenAPI. → ADR 0021.
45
+ */
46
+ meta?: Record<string, unknown>;
29
47
  handler: (ctx: RuntimeContext) => Promise<TOutput> | TOutput;
30
48
  }
31
49
  export interface ServiceDef {
@@ -95,6 +113,17 @@ export interface StitchLogger {
95
113
  export interface HandlerConfig {
96
114
  services?: ServiceDef[];
97
115
  groups?: RouteGroup[];
116
+ /**
117
+ * Mount each `services` entry under a path prefix chosen by its `scope` — a
118
+ * `scope → prefix` map, so resource-scoped APIs declare the mapping once
119
+ * instead of hand-partitioning services into `groups`. A prefix may carry
120
+ * `:param` segments (they reach `ctx.pathParams`), e.g.
121
+ * `{ tenant: 'tenants/:tenantId', project: 'projects/:projectId' }`. A service
122
+ * whose `scope` is not in the map mounts flat. Services listed under explicit
123
+ * `groups` are unaffected (the group prefix wins). Scope stays a free string —
124
+ * the core attaches no meaning beyond this lookup. → ADR 0024.
125
+ */
126
+ scopePrefixes?: Record<string, string>;
98
127
  rawRoutes?: RawRoute[];
99
128
  cors?: CorsConfig;
100
129
  hooks?: LifecycleHooks;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"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"}
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,KAC/D,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,SAAS,OAAO,GACrC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAC9C,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;CACzB,CAAC;AAEF,MAAM,WAAW,SAAS,CAAC,OAAO,GAAG,OAAO,EAAE,MAAM,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO;IAC/E,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC,WAAW,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,EAAE,CAAC,EAAE,cAAc,CAAC;IACpB,yEAAyE;IACzE,WAAW,CAAC,EAAE,uBAAuB,CAAC;IACtC;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,OAAO,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;CAC9D;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;CAC/D;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC,SAAS,GAAG,QAAQ,CAAC,CAAC;IACnF,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,EAAE,QAAQ,EAAE,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClF,WAAW,CAAC,EAAE,CACZ,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,SAAS,KAChB,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,CACR,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,OAAO,EACd,QAAQ,CAAC,EAAE,SAAS,KACjB,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC;CAC/C;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB;AAED;;;;;;;;GAQG;AACH,gFAAgF;AAChF,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC;AAErD,0EAA0E;AAC1E,MAAM,WAAW,eAAe;IAC9B,gFAAgF;IAChF,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,UAAU,GAAG,KAAK,CAAC;IAC3B,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,eAAe,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC/E;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxD,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC1D;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;IACxB,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;IACtB;;;;;;;;;OASG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,GAAG,YAAY,CAAC;IACjC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,CAAC;IACnC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAID,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACvD,KAAK,oBAAoB,GAAG,eAAe,SAAS;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,CAAC,GAAG,KAAK,CAAC;AACxF,KAAK,SAAS,GAAG,eAAe,SAAS;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,CAAC,GAAG,KAAK,CAAC;AAC1E,KAAK,qBAAqB,GAAG,eAAe,SAAS;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,CAAC,GAAG,KAAK,CAAC;AAE3F,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAClC,eAAe,EACf,OAAO,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,aAAa,CAChF,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACpD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,WAAW,CAAC,EAAE,qBAAqB,CAAC;IACpC,GAAG,CAAC,EAAE,iBAAiB,CAAC;CACzB;AAED,MAAM,MAAM,kBAAkB,GAAG,iBAAiB,GAAG;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,WAAW,CAAC,EAAE,qBAAqB,CAAC;IACpC,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CACxC,CAAC"}
@@ -68,6 +68,11 @@ export interface McpServerBuildConfig<TAuth> {
68
68
  * same `createAuthHook` result used for the HTTP `beforeHandle` to guard
69
69
  * tools with the identical rules. */
70
70
  lifecycle?: ToolLifecycle;
71
+ /** Add extra tool arguments resolved into handler context (e.g. a `tenantId`
72
+ * for one API key serving many tenants). Same `ToolExtend` accepted by
73
+ * `mountMcp` — without this, the batteries-path (`createMcpHandler`) could not
74
+ * reach it and a consumer had to hand-wrap every service. */
75
+ extend?: ToolExtend;
71
76
  /** What to do when a tool's schema is not MCP-compatible. Default `'throw'`. */
72
77
  onIncompatibleSchema?: IncompatibleSchemaPolicy;
73
78
  /** Logger for schema-incompatibility warnings — defaults to `console`. */
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/tools/mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,aAAa,EAGnB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,KAAK,cAAc,EAAsB,MAAM,WAAW,CAAC;AACpE,OAAO,EAKL,KAAK,UAAU,EAChB,MAAM,SAAS,CAAC;AAEjB;;;;;;;;GAQG;AACH,MAAM,MAAM,wBAAwB,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AA8JjE,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,qCAAqC;IACrC,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,gFAAgF;IAChF,oBAAoB,CAAC,EAAE,wBAAwB,CAAC;IAChD,8DAA8D;IAC9D,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,+EAA+E;IAC/E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,+EAA+E;IAC/E,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,gEAAgE;IAChE,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CACpE;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,UAAU,EAAE,EACtB,oBAAoB,GAAE,wBAAkC,EACxD,MAAM,CAAC,EAAE,YAAY,GACpB,IAAI,CAWN;AAED,wBAAgB,QAAQ,CACtB,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,UAAU,GAAG,UAAU,EAAE,EACnC,MAAM,GAAE,cAAmB,GAC1B,IAAI,CAuEN;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB,CAAC,KAAK;IACzC,4CAA4C;IAC5C,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,2EAA2E;IAC3E,QAAQ,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,KAAK,UAAU,EAAE,CAAC,CAAC;IACzD,uEAAuE;IACvE,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnD;+EAC2E;IAC3E,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB;;0CAEsC;IACtC,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,gFAAgF;IAChF,oBAAoB,CAAC,EAAE,wBAAwB,CAAC;IAChD,0EAA0E;IAC1E,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB;kFAC8E;IAC9E,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,CAAC;IAC1C,2EAA2E;IAC3E,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC;IAC7B;wDACoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,+EAA+E;IAC/E,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,gEAAgE;IAChE,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CACpE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAClC,MAAM,EAAE,oBAAoB,CAAC,KAAK,CAAC,EACnC,IAAI,EAAE,KAAK,GACV,SAAS,CAuBX;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI,CAgBlF"}
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/tools/mcp.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;AAErB,OAAO,KAAK,EAAa,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAc7D,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,CA8DZ"}
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;AAErB,OAAO,KAAK,EAAa,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAc7D,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,CAmEZ"}
package/dist/tools.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ApiError,
3
3
  createClient
4
- } from "./index-78q1qm7v.js";
4
+ } from "./index-kdkvp26v.js";
5
5
  import {
6
6
  coerceJsonArgs,
7
7
  collectTools,
@@ -256,6 +256,7 @@ function buildMcpServer(config, auth) {
256
256
  context,
257
257
  hooks: config.hooks,
258
258
  lifecycle: config.lifecycle,
259
+ extend: config.extend,
259
260
  onIncompatibleSchema: config.onIncompatibleSchema,
260
261
  logger: config.logger,
261
262
  coerceJsonArgs: config.coerceJsonArgs,
@@ -852,10 +853,13 @@ function implementRemote(contract, http, options) {
852
853
  method: endpoint.method,
853
854
  path: endpoint.path,
854
855
  desc: endpoint.desc,
856
+ serviceName: contract.meta.prefix,
857
+ key,
855
858
  toolName: "toolName" in endpoint ? endpoint.toolName : undefined,
856
859
  expose: endpoint.expose,
857
860
  ui: "ui" in endpoint ? endpoint.ui : undefined,
858
861
  annotations: "annotations" in endpoint ? endpoint.annotations : undefined,
862
+ meta: endpoint.meta,
859
863
  scope: endpoint.scope ?? groupScope,
860
864
  paramsSchema: endpoint.params,
861
865
  inputSchema: endpoint.input,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stitchkit",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Contract-first backend framework — one defineContract() into an HTTP API, MCP tools, AI-agent tools and a typed client. Bun and Node.",
5
5
  "keywords": [
6
6
  "bun",