stitchkit 0.5.0 → 0.7.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.
Files changed (50) hide show
  1. package/dist/browser/client.d.ts +17 -5
  2. package/dist/browser/client.d.ts.map +1 -1
  3. package/dist/cli.js +3 -3
  4. package/dist/contract/define.d.ts +16 -2
  5. package/dist/contract/define.d.ts.map +1 -1
  6. package/dist/contract/errors.d.ts +26 -1
  7. package/dist/contract/errors.d.ts.map +1 -1
  8. package/dist/contract/index.d.ts +2 -2
  9. package/dist/contract/index.d.ts.map +1 -1
  10. package/dist/contract/index.js +5 -1
  11. package/dist/{index-vhdvv00d.js → index-4843j09b.js} +1 -1
  12. package/dist/{index-kgjnt3hn.js → index-8hsj2qm9.js} +102 -36
  13. package/dist/{index-afzt3nmx.js → index-9bk6r5ff.js} +8 -4
  14. package/dist/{index-1cf8jkhf.js → index-hty3443r.js} +1 -1
  15. package/dist/{index-78q1qm7v.js → index-kdkvp26v.js} +21 -12
  16. package/dist/{index-d4rwrjbc.js → index-mahbaen9.js} +1 -1
  17. package/dist/{index-0ma1eqv4.js → index-p8byjw3e.js} +3 -3
  18. package/dist/index-za2p453b.js +87 -0
  19. package/dist/index.d.ts +1 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +8 -4
  22. package/dist/node.js +3 -3
  23. package/dist/observability/index.js +14 -86
  24. package/dist/server/context.d.ts +1 -1
  25. package/dist/server/context.d.ts.map +1 -1
  26. package/dist/server/create.d.ts.map +1 -1
  27. package/dist/server/file.d.ts +52 -0
  28. package/dist/server/file.d.ts.map +1 -0
  29. package/dist/server/implement.d.ts.map +1 -1
  30. package/dist/server/index.d.ts +3 -1
  31. package/dist/server/index.d.ts.map +1 -1
  32. package/dist/server/index.js +190 -5
  33. package/dist/server/logger.d.ts.map +1 -1
  34. package/dist/server/mime.d.ts +3 -0
  35. package/dist/server/mime.d.ts.map +1 -0
  36. package/dist/server/raw.d.ts +36 -0
  37. package/dist/server/raw.d.ts.map +1 -0
  38. package/dist/server/router.d.ts +4 -3
  39. package/dist/server/router.d.ts.map +1 -1
  40. package/dist/server/socket-io.d.ts +10 -1
  41. package/dist/server/socket-io.d.ts.map +1 -1
  42. package/dist/server/types.d.ts +32 -0
  43. package/dist/server/types.d.ts.map +1 -1
  44. package/dist/tools/execute.d.ts +2 -2
  45. package/dist/tools/execute.d.ts.map +1 -1
  46. package/dist/tools/mcp.d.ts +5 -0
  47. package/dist/tools/mcp.d.ts.map +1 -1
  48. package/dist/tools/remote.d.ts.map +1 -1
  49. package/dist/tools.js +9 -5
  50. package/package.json +1 -1
@@ -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"}
package/dist/cli.js CHANGED
@@ -4,11 +4,11 @@ import {
4
4
  emitResult,
5
5
  parseCliArgs,
6
6
  pollUntilDone
7
- } from "./index-0ma1eqv4.js";
7
+ } from "./index-p8byjw3e.js";
8
8
  import"./index-0ed3bx43.js";
9
9
  import"./index-x3fcszf8.js";
10
- import"./index-vhdvv00d.js";
11
- import"./index-afzt3nmx.js";
10
+ import"./index-4843j09b.js";
11
+ import"./index-9bk6r5ff.js";
12
12
  import"./index-kzfs85xp.js";
13
13
  import"./index-809wc1tt.js";
14
14
  import"./index-37x76zdn.js";
@@ -12,6 +12,13 @@ interface EndpointDefBase {
12
12
  input?: ZodType<unknown>;
13
13
  output?: ZodType<unknown>;
14
14
  multipart?: string;
15
+ /**
16
+ * Per-route upload ceiling in bytes for a `multipart` endpoint. Overrides the
17
+ * server's `maxUploadBytes` default; without either, the 25 MB framework
18
+ * default applies. Lets an avatar (5 MB) and a video (200 MB) declare their
19
+ * own caps. Ignored on non-multipart endpoints.
20
+ */
21
+ maxUploadBytes?: number;
15
22
  /**
16
23
  * HTTP client timeout in ms for this endpoint. Use it for slow synchronous
17
24
  * endpoints (AI generation) that need more than the client default. A
@@ -26,6 +33,10 @@ interface EndpointDefBase {
26
33
  * app concerns the generic core does not model — a feature gate, a rate tier,
27
34
  * a cache hint, a doc/owner tag. The consumer narrows the type when reading.
28
35
  * Never surfaced in the OpenAPI document (app-private, not the HTTP contract).
36
+ *
37
+ * Declare its type as a `type` / inline literal / `satisfies` — **not an
38
+ * `interface`** (an interface has no implicit index signature, so it is not
39
+ * assignable to `Record<string, unknown>`).
29
40
  */
30
41
  meta?: Record<string, unknown>;
31
42
  }
@@ -130,8 +141,11 @@ export type TypedClient<C extends Record<string, EndpointDef>> = {
130
141
  type ExposesHttp<E> = E extends {
131
142
  expose: readonly Transport[];
132
143
  } ? 'HTTP' extends E['expose'][number] ? true : false : true;
133
- export type TypedHttpClient<C extends Record<string, EndpointDef>> = {
134
- [K in keyof C as ExposesHttp<C[K]> extends true ? K : never]: EndpointFn<C[K]>;
144
+ type ArgsWith<E, Extra> = EndpointArgs<E> & Extra;
145
+ export type ScopedEndpointFn<E, Extra> = [keyof ArgsWith<E, Extra>] extends [never] ? () => Promise<EndpointOutput<E>> : (args: ArgsWith<E, Extra>) => Promise<EndpointOutput<E>>;
146
+ export type ScopedHttpClient<C extends Record<string, EndpointDef>, Extra> = {
147
+ [K in keyof C as ExposesHttp<C[K]> extends true ? K : never]: ScopedEndpointFn<C[K], Extra>;
135
148
  };
149
+ export type TypedHttpClient<C extends Record<string, EndpointDef>> = ScopedHttpClient<C, unknown>;
136
150
  export {};
137
151
  //# 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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"}
@@ -42,6 +42,31 @@ export declare function forbidden(message?: string): never;
42
42
  export declare function conflict(message?: string, details?: Record<string, unknown>): never;
43
43
  /** Throw a `429 RATE_LIMITED` error. */
44
44
  export declare function rateLimited(message?: string): never;
45
- /** Throw an `AppError` for any `code`, mapping known codes to their HTTP status (else 500). */
45
+ /**
46
+ * `code → HTTP status` for the error codes **stitchkit itself** emits — the
47
+ * typed helpers above, `normalizeError` (`VALIDATION_ERROR` /
48
+ * `INTERNAL_SERVER_ERROR`) and the router (`METHOD_NOT_ALLOWED`). This map is the
49
+ * single source of truth: `StitchErrorCode` is derived from its keys, so the two
50
+ * never drift. App-defined codes are free strings the core never sees (ADR 0002);
51
+ * these are stitchkit's own, published so a consumer can map stitch → app codes
52
+ * against a stable, typed reference instead of a hand-copied string list.
53
+ * → ADR 0026.
54
+ */
55
+ export declare const STITCH_ERROR_STATUS: {
56
+ BAD_REQUEST: number;
57
+ UNAUTHORIZED: number;
58
+ FORBIDDEN: number;
59
+ NOT_FOUND: number;
60
+ METHOD_NOT_ALLOWED: number;
61
+ CONFLICT: number;
62
+ RATE_LIMITED: number;
63
+ VALIDATION_ERROR: number;
64
+ INTERNAL_SERVER_ERROR: number;
65
+ };
66
+ /** A code stitchkit itself emits — derived from `STITCH_ERROR_STATUS` (no dup). */
67
+ export type StitchErrorCode = keyof typeof STITCH_ERROR_STATUS;
68
+ /** Type guard — is `code` one of stitchkit's own error codes? */
69
+ export declare function isStitchErrorCode(code: string): code is StitchErrorCode;
70
+ /** Throw an `AppError` for any `code`, mapping a stitch code to its HTTP status (else 500). */
46
71
  export declare function appError(code: string, message?: string, details?: Record<string, unknown>): never;
47
72
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/contract/errors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE;QACL,2CAA2C;QAC3C,IAAI,EAAE,MAAM,CAAC;QACb,8BAA8B;QAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,gCAAgC;QAChC,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,0BAA0B;QAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED;;;;GAIG;AACH,qBAAa,QAAS,SAAQ,KAAK;aAEf,IAAI,EAAE,MAAM;aAEZ,MAAM,EAAE,MAAM;aACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;aACjC,IAAI,CAAC,EAAE,MAAM;gBAJb,IAAI,EAAE,MAAM,EAC5B,OAAO,CAAC,EAAE,MAAM,EACA,MAAM,GAAE,MAAY,EACpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YAAA,EACjC,IAAI,CAAC,EAAE,MAAM,YAAA;IAM/B,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,QAAQ;IAIxC,MAAM,IAAI,aAAa;CAUxB;AAED,qCAAqC;AACrC,wBAAgB,QAAQ,CAAC,OAAO,SAAc,GAAG,KAAK,CAErD;AAED,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,CAEpF;AAED,wCAAwC;AACxC,wBAAgB,YAAY,CAAC,OAAO,SAAiB,GAAG,KAAK,CAE5D;AAED,qCAAqC;AACrC,wBAAgB,SAAS,CAAC,OAAO,SAAc,GAAG,KAAK,CAEtD;AAED,0EAA0E;AAC1E,wBAAgB,QAAQ,CAAC,OAAO,SAAa,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,CAEvF;AAED,wCAAwC;AACxC,wBAAgB,WAAW,CAAC,OAAO,SAAsB,GAAG,KAAK,CAEhE;AAaD,+FAA+F;AAC/F,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,KAAK,CAEP"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/contract/errors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE;QACL,2CAA2C;QAC3C,IAAI,EAAE,MAAM,CAAC;QACb,8BAA8B;QAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,gCAAgC;QAChC,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,0BAA0B;QAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED;;;;GAIG;AACH,qBAAa,QAAS,SAAQ,KAAK;aAEf,IAAI,EAAE,MAAM;aAEZ,MAAM,EAAE,MAAM;aACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;aACjC,IAAI,CAAC,EAAE,MAAM;gBAJb,IAAI,EAAE,MAAM,EAC5B,OAAO,CAAC,EAAE,MAAM,EACA,MAAM,GAAE,MAAY,EACpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YAAA,EACjC,IAAI,CAAC,EAAE,MAAM,YAAA;IAM/B,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,QAAQ;IAIxC,MAAM,IAAI,aAAa;CAUxB;AAED,qCAAqC;AACrC,wBAAgB,QAAQ,CAAC,OAAO,SAAc,GAAG,KAAK,CAErD;AAED,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,CAEpF;AAED,wCAAwC;AACxC,wBAAgB,YAAY,CAAC,OAAO,SAAiB,GAAG,KAAK,CAE5D;AAED,qCAAqC;AACrC,wBAAgB,SAAS,CAAC,OAAO,SAAc,GAAG,KAAK,CAEtD;AAED,0EAA0E;AAC1E,wBAAgB,QAAQ,CAAC,OAAO,SAAa,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,CAEvF;AAED,wCAAwC;AACxC,wBAAgB,WAAW,CAAC,OAAO,SAAsB,GAAG,KAAK,CAEhE;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;CAUE,CAAC;AAEnC,mFAAmF;AACnF,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,mBAAmB,CAAC;AAE/D,iEAAiE;AACjE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,eAAe,CAEvE;AAED,+FAA+F;AAC/F,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,KAAK,CAOP"}
@@ -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';
2
- export { AppError, appError, badRequest, conflict, type ErrorEnvelope, forbidden, notFound, rateLimited, unauthorized, } from './errors';
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
+ export { AppError, appError, badRequest, conflict, type ErrorEnvelope, forbidden, isStitchErrorCode, notFound, rateLimited, STITCH_ERROR_STATUS, type StitchErrorCode, 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,iBAAiB,EACjB,QAAQ,EACR,WAAW,EACX,mBAAmB,EACnB,KAAK,eAAe,EACpB,YAAY,GACb,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,KAAK,SAAS,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
@@ -1,27 +1,31 @@
1
1
  import {
2
2
  ALL_TRANSPORTS,
3
3
  AppError,
4
+ STITCH_ERROR_STATUS,
4
5
  appError,
5
6
  badRequest,
6
7
  conflict,
7
8
  defineContract,
8
9
  forbidden,
10
+ isStitchErrorCode,
9
11
  notFound,
10
12
  paginatedSchema,
11
13
  rateLimited,
12
14
  unauthorized
13
- } from "../index-afzt3nmx.js";
15
+ } from "../index-9bk6r5ff.js";
14
16
  import"../index-37x76zdn.js";
15
17
  export {
16
18
  unauthorized,
17
19
  rateLimited,
18
20
  paginatedSchema,
19
21
  notFound,
22
+ isStitchErrorCode,
20
23
  forbidden,
21
24
  defineContract,
22
25
  conflict,
23
26
  badRequest,
24
27
  appError,
28
+ STITCH_ERROR_STATUS,
25
29
  AppError,
26
30
  ALL_TRANSPORTS
27
31
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  AppError
3
- } from "./index-afzt3nmx.js";
3
+ } from "./index-9bk6r5ff.js";
4
4
 
5
5
  // src/internal/errors.ts
6
6
  import { z } from "zod";
@@ -4,11 +4,11 @@ import {
4
4
  import {
5
5
  normalizeError,
6
6
  validateHandlerOutput
7
- } from "./index-vhdvv00d.js";
7
+ } from "./index-4843j09b.js";
8
8
  import {
9
9
  AppError,
10
10
  badRequest
11
- } from "./index-afzt3nmx.js";
11
+ } from "./index-9bk6r5ff.js";
12
12
  import {
13
13
  extractIp,
14
14
  getClientInfo,
@@ -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
  });
@@ -322,12 +344,13 @@ async function readJsonBody(req) {
322
344
  badRequest("Invalid JSON body");
323
345
  }
324
346
  }
325
- async function buildContext(req, url, method, pathParams, traceId, clientIp) {
347
+ async function buildContext(req, url, method, pathParams, traceId, clientIp, maxUploadBytes) {
326
348
  const parsedParams = method.paramsSchema ? method.paramsSchema.parse(pathParams) : undefined;
327
349
  let parsedInput;
328
350
  let file;
329
351
  if (method.multipart) {
330
- const multipart = await parseMultipart(req, method.multipart, method.inputSchema);
352
+ const cap = method.maxUploadBytes ?? maxUploadBytes;
353
+ const multipart = await parseMultipart(req, method.multipart, method.inputSchema, cap);
331
354
  parsedInput = multipart.fields;
332
355
  file = multipart.file;
333
356
  } else if (method.inputSchema) {
@@ -410,7 +433,13 @@ function elapsedMs(startTime) {
410
433
  return performance.now() - startTime;
411
434
  }
412
435
  function safePath(pathname) {
413
- return pathname.replace(/[-]/g, "");
436
+ let out = "";
437
+ for (let i = 0;i < pathname.length; i++) {
438
+ const code = pathname.charCodeAt(i);
439
+ if (code > 31 && code !== 127)
440
+ out += pathname.charAt(i);
441
+ }
442
+ return out;
414
443
  }
415
444
  function levelForStatus(status) {
416
445
  if (status >= 500)
@@ -574,7 +603,7 @@ function createHandler(config) {
574
603
  const { method, pathParams, groupHooks } = match;
575
604
  let ctx;
576
605
  try {
577
- ctx = await buildContext(req, url, method, pathParams, traceId, clientIp);
606
+ ctx = await buildContext(req, url, method, pathParams, traceId, clientIp, config.maxUploadBytes);
578
607
  if (hooks?.beforeHandle) {
579
608
  await hooks.beforeHandle(ctx, method);
580
609
  }
@@ -646,7 +675,8 @@ function normalizeGroups(config) {
646
675
  const result = [];
647
676
  if (config.services) {
648
677
  for (const service of config.services) {
649
- result.push({ prefix: "", service });
678
+ const prefix = config.scopePrefixes?.[service.scope] ?? "";
679
+ result.push({ prefix, service });
650
680
  }
651
681
  }
652
682
  if (config.groups) {
@@ -690,6 +720,8 @@ function implement(contract, handlers) {
690
720
  method: endpoint.method,
691
721
  path: endpoint.path,
692
722
  desc: endpoint.desc,
723
+ serviceName: contract.meta.prefix,
724
+ key: String(key),
693
725
  toolName: "toolName" in endpoint ? endpoint.toolName : undefined,
694
726
  expose: endpoint.expose,
695
727
  scope: endpoint.scope ?? groupScope,
@@ -697,6 +729,7 @@ function implement(contract, handlers) {
697
729
  inputSchema: endpoint.input,
698
730
  outputSchema: endpoint.output,
699
731
  multipart: endpoint.multipart,
732
+ maxUploadBytes: endpoint.maxUploadBytes,
700
733
  ui: "ui" in endpoint ? endpoint.ui : undefined,
701
734
  annotations: "annotations" in endpoint ? endpoint.annotations : undefined,
702
735
  meta: endpoint.meta,
@@ -774,25 +807,58 @@ function composeWebSocketHandlers(lanes, config) {
774
807
 
775
808
  // src/server/socket-io.ts
776
809
  var noop = () => {};
810
+ function isModuleNotFound(err) {
811
+ if (typeof err !== "object" || err === null)
812
+ return false;
813
+ const code = "code" in err ? err.code : undefined;
814
+ const message = "message" in err && typeof err.message === "string" ? err.message : "";
815
+ return code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND" || message.includes("Cannot find module") || message.includes("Cannot find package");
816
+ }
817
+ async function importPeer(load, pkg) {
818
+ try {
819
+ return await load();
820
+ } catch (err) {
821
+ if (isModuleNotFound(err)) {
822
+ throw new Error(`[stitchkit] createSocketIOServer needs the optional peer "${pkg}" — install it: bun add ${pkg}`, { cause: err });
823
+ }
824
+ throw err;
825
+ }
826
+ }
777
827
  async function createSocketIOServer(config) {
778
828
  const path = config.path ?? "/socket.io/";
779
829
  const onBun = "Bun" in globalThis;
780
830
  const transports = config.transports ?? (onBun ? ["websocket", "polling"] : ["websocket"]);
781
- const { Server } = await import("socket.io");
831
+ const pingTimeout = config.pingTimeout ?? 20000;
832
+ const pingInterval = config.pingInterval ?? 1e4;
833
+ const cors = {
834
+ origin: config.cors.origin,
835
+ credentials: config.cors.credentials ?? true,
836
+ methods: ["GET", "POST"]
837
+ };
838
+ const { Server } = await importPeer(() => import("socket.io"), "socket.io");
782
839
  const io = new Server({
840
+ ...config.serverOptions,
783
841
  path,
784
- cors: {
785
- origin: config.cors.origin,
786
- credentials: config.cors.credentials ?? true,
787
- methods: ["GET", "POST"]
788
- },
842
+ cors,
789
843
  transports,
790
- pingTimeout: config.pingTimeout ?? 20000,
791
- pingInterval: config.pingInterval ?? 1e4
844
+ pingTimeout,
845
+ pingInterval
792
846
  });
793
847
  if (onBun) {
794
- const { Server: Engine } = await import("@socket.io/bun-engine");
795
- const engine = new Engine({ path });
848
+ const { Server: Engine } = await importPeer(() => import("@socket.io/bun-engine"), "@socket.io/bun-engine");
849
+ const engineOpts = {
850
+ path,
851
+ cors,
852
+ pingTimeout,
853
+ pingInterval
854
+ };
855
+ if (config.serverOptions?.maxHttpBufferSize !== undefined) {
856
+ engineOpts.maxHttpBufferSize = config.serverOptions.maxHttpBufferSize;
857
+ }
858
+ if (config.serverOptions?.upgradeTimeout !== undefined) {
859
+ engineOpts.upgradeTimeout = config.serverOptions.upgradeTimeout;
860
+ }
861
+ const engine = new Engine(engineOpts);
796
862
  io.bind(engine);
797
863
  const { websocket } = engine.handler();
798
864
  const route = {
@@ -827,4 +893,4 @@ function socketIoLane(websocket) {
827
893
  });
828
894
  }
829
895
 
830
- export { parseMultipart, corsHeaders, corsPreflightResponse, staticRoute, createHandler, createServer, implement, createImplement, webSocketLane, composeWebSocketHandlers, createSocketIOServer, socketIoLane };
896
+ export { parseMultipart, corsHeaders, corsPreflightResponse, mimeForPath, staticRoute, createHandler, createServer, implement, createImplement, webSocketLane, composeWebSocketHandlers, createSocketIOServer, socketIoLane };
@@ -72,18 +72,22 @@ function conflict(message = "Conflict", details) {
72
72
  function rateLimited(message = "Too many requests") {
73
73
  throw new AppError("RATE_LIMITED", message, 429);
74
74
  }
75
- var ERROR_STATUS = {
76
- NOT_FOUND: 404,
75
+ var STITCH_ERROR_STATUS = {
77
76
  BAD_REQUEST: 400,
78
77
  UNAUTHORIZED: 401,
79
78
  FORBIDDEN: 403,
79
+ NOT_FOUND: 404,
80
+ METHOD_NOT_ALLOWED: 405,
80
81
  CONFLICT: 409,
81
82
  RATE_LIMITED: 429,
82
83
  VALIDATION_ERROR: 400,
83
84
  INTERNAL_SERVER_ERROR: 500
84
85
  };
86
+ function isStitchErrorCode(code) {
87
+ return code in STITCH_ERROR_STATUS;
88
+ }
85
89
  function appError(code, message, details) {
86
- throw new AppError(code, message, ERROR_STATUS[code] ?? 500, details);
90
+ throw new AppError(code, message, isStitchErrorCode(code) ? STITCH_ERROR_STATUS[code] : 500, details);
87
91
  }
88
92
  // src/contract/pagination.ts
89
93
  import { z } from "zod";
@@ -93,4 +97,4 @@ function paginatedSchema(itemSchema) {
93
97
  nextCursor: z.string().nullable()
94
98
  });
95
99
  }
96
- export { ALL_TRANSPORTS, defineContract, AppError, notFound, badRequest, unauthorized, forbidden, conflict, rateLimited, appError, paginatedSchema };
100
+ export { ALL_TRANSPORTS, defineContract, AppError, notFound, badRequest, unauthorized, forbidden, conflict, rateLimited, STITCH_ERROR_STATUS, isStitchErrorCode, appError, paginatedSchema };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  forbidden,
3
3
  unauthorized
4
- } from "./index-afzt3nmx.js";
4
+ } from "./index-9bk6r5ff.js";
5
5
  import {
6
6
  isUnsafeKey,
7
7
  safeJsonParse
@@ -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;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  normalizeError
3
- } from "./index-vhdvv00d.js";
3
+ } from "./index-4843j09b.js";
4
4
 
5
5
  // src/server/stream.ts
6
6
  function streamSSE(generator) {
@@ -9,7 +9,7 @@ import {
9
9
  formatZodError,
10
10
  normalizeError,
11
11
  validateHandlerOutput
12
- } from "./index-vhdvv00d.js";
12
+ } from "./index-4843j09b.js";
13
13
  import {
14
14
  isUnsafeKey,
15
15
  safeJsonParse
@@ -134,12 +134,12 @@ function toolResultFromError(err) {
134
134
  async function executeToolMethod(method, toolName, rawArgs, context, hooks, lifecycle, coerceJson = false) {
135
135
  const startedAt = Date.now();
136
136
  const finish = async (result) => {
137
- await hooks?.afterToolCall?.(toolName, rawArgs, result, Date.now() - startedAt, context);
137
+ await hooks?.afterToolCall?.(toolName, rawArgs, result, Date.now() - startedAt, context, method);
138
138
  return result;
139
139
  };
140
140
  if (hooks?.beforeToolCall) {
141
141
  try {
142
- await hooks.beforeToolCall(toolName, rawArgs, context);
142
+ await hooks.beforeToolCall(toolName, rawArgs, context, method);
143
143
  } catch (err) {
144
144
  return finish(toolResultFromError(err));
145
145
  }