ts-procedures 10.1.1 → 10.2.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 (244) hide show
  1. package/CHANGELOG.md +26 -65
  2. package/README.md +2 -0
  3. package/agent_config/claude-code/skills/ts-procedures/anti-patterns.md +8 -0
  4. package/agent_config/claude-code/skills/ts-procedures/api-reference.md +25 -22
  5. package/agent_config/claude-code/skills/ts-procedures/patterns.md +24 -13
  6. package/agent_config/copilot/copilot-instructions.md +1 -1
  7. package/agent_config/cursor/cursorrules +1 -1
  8. package/build/adapters/hono/envelope-parity.test.js +6 -17
  9. package/build/adapters/hono/envelope-parity.test.js.map +1 -1
  10. package/build/adapters/hono/handlers/http-stream.d.ts +2 -1
  11. package/build/adapters/hono/handlers/http-stream.js +9 -2
  12. package/build/adapters/hono/handlers/http-stream.js.map +1 -1
  13. package/build/adapters/hono/handlers/http.d.ts +2 -1
  14. package/build/adapters/hono/handlers/http.js +9 -2
  15. package/build/adapters/hono/handlers/http.js.map +1 -1
  16. package/build/adapters/hono/handlers/rpc.d.ts +2 -1
  17. package/build/adapters/hono/handlers/rpc.js +9 -2
  18. package/build/adapters/hono/handlers/rpc.js.map +1 -1
  19. package/build/adapters/hono/handlers/stream.d.ts +2 -1
  20. package/build/adapters/hono/handlers/stream.js +9 -2
  21. package/build/adapters/hono/handlers/stream.js.map +1 -1
  22. package/build/adapters/hono/index.d.ts +14 -7
  23. package/build/adapters/hono/index.js +45 -5
  24. package/build/adapters/hono/index.js.map +1 -1
  25. package/build/adapters/hono/index.test.js +55 -0
  26. package/build/adapters/hono/index.test.js.map +1 -1
  27. package/build/adapters/hono/request.d.ts +7 -0
  28. package/build/adapters/hono/request.js +15 -0
  29. package/build/adapters/hono/request.js.map +1 -1
  30. package/build/adapters/hono/types.d.ts +31 -0
  31. package/build/adapters/hono/types.js.map +1 -1
  32. package/build/codegen/bin/cli.js +1 -1
  33. package/build/codegen/bin/cli.js.map +1 -1
  34. package/build/codegen/constants.js +2 -2
  35. package/build/codegen/constants.js.map +1 -1
  36. package/build/codegen/emit/api-route.js +1 -1
  37. package/build/codegen/emit/api-route.js.map +1 -1
  38. package/build/codegen/emit/scope-file.js +1 -1
  39. package/build/codegen/emit/scope-file.js.map +1 -1
  40. package/build/codegen/emit-errors.integration.test.js +2 -2
  41. package/build/codegen/emit-errors.integration.test.js.map +1 -1
  42. package/build/codegen/resolve-envelope.js +1 -1
  43. package/build/codegen/resolve-envelope.js.map +1 -1
  44. package/build/codegen/test-helpers/run-tsc.js +1 -1
  45. package/build/codegen/test-helpers/run-tsc.js.map +1 -1
  46. package/build/core/create-http-stream.d.ts +3 -14
  47. package/build/core/create-http-stream.js +4 -2
  48. package/build/core/create-http-stream.js.map +1 -1
  49. package/build/core/create-http.d.ts +2 -9
  50. package/build/core/create-http.js +3 -2
  51. package/build/core/create-http.js.map +1 -1
  52. package/build/core/create-http.test-d.d.ts +1 -0
  53. package/build/core/create-http.test-d.js +104 -0
  54. package/build/core/create-http.test-d.js.map +1 -0
  55. package/build/core/create-stream.js +6 -2
  56. package/build/core/create-stream.js.map +1 -1
  57. package/build/core/create.js +5 -4
  58. package/build/core/create.js.map +1 -1
  59. package/build/core/create.test.js +63 -0
  60. package/build/core/create.test.js.map +1 -1
  61. package/build/core/internal.d.ts +16 -0
  62. package/build/core/internal.js +22 -0
  63. package/build/core/internal.js.map +1 -1
  64. package/build/core/procedures.d.ts +9 -16
  65. package/build/core/procedures.js +4 -0
  66. package/build/core/procedures.js.map +1 -1
  67. package/build/core/types.d.ts +85 -4
  68. package/build/errors.d.ts +33 -0
  69. package/build/errors.js +91 -0
  70. package/build/errors.js.map +1 -0
  71. package/build/errors.test.d.ts +1 -0
  72. package/build/errors.test.js +122 -0
  73. package/build/errors.test.js.map +1 -0
  74. package/build/exports.d.ts +1 -2
  75. package/build/exports.js +0 -4
  76. package/build/exports.js.map +1 -1
  77. package/build/implementations/http/doc-registry.d.ts +28 -0
  78. package/build/implementations/http/doc-registry.js +96 -0
  79. package/build/implementations/http/doc-registry.js.map +1 -0
  80. package/build/implementations/http/doc-registry.test.d.ts +1 -0
  81. package/build/implementations/http/doc-registry.test.js +516 -0
  82. package/build/implementations/http/doc-registry.test.js.map +1 -0
  83. package/build/implementations/http/error-taxonomy.d.ts +249 -0
  84. package/build/implementations/http/error-taxonomy.js +252 -0
  85. package/build/implementations/http/error-taxonomy.js.map +1 -0
  86. package/build/implementations/http/error-taxonomy.test.d.ts +1 -0
  87. package/build/implementations/http/error-taxonomy.test.js +399 -0
  88. package/build/implementations/http/error-taxonomy.test.js.map +1 -0
  89. package/build/implementations/http/express-rpc/error-taxonomy.test.d.ts +1 -0
  90. package/build/implementations/http/express-rpc/error-taxonomy.test.js +83 -0
  91. package/build/implementations/http/express-rpc/error-taxonomy.test.js.map +1 -0
  92. package/build/implementations/http/express-rpc/index.d.ts +125 -0
  93. package/build/implementations/http/express-rpc/index.js +216 -0
  94. package/build/implementations/http/express-rpc/index.js.map +1 -0
  95. package/build/implementations/http/express-rpc/index.test.d.ts +1 -0
  96. package/build/implementations/http/express-rpc/index.test.js +684 -0
  97. package/build/implementations/http/express-rpc/index.test.js.map +1 -0
  98. package/build/implementations/http/express-rpc/types.d.ts +11 -0
  99. package/build/implementations/http/express-rpc/types.js +2 -0
  100. package/build/implementations/http/express-rpc/types.js.map +1 -0
  101. package/build/implementations/http/hono-api/error-taxonomy.test.d.ts +1 -0
  102. package/build/implementations/http/hono-api/error-taxonomy.test.js +137 -0
  103. package/build/implementations/http/hono-api/error-taxonomy.test.js.map +1 -0
  104. package/build/implementations/http/hono-api/index.d.ts +151 -0
  105. package/build/implementations/http/hono-api/index.js +344 -0
  106. package/build/implementations/http/hono-api/index.js.map +1 -0
  107. package/build/implementations/http/hono-api/index.test.d.ts +1 -0
  108. package/build/implementations/http/hono-api/index.test.js +992 -0
  109. package/build/implementations/http/hono-api/index.test.js.map +1 -0
  110. package/build/implementations/http/hono-api/types.d.ts +13 -0
  111. package/build/implementations/http/hono-api/types.js +2 -0
  112. package/build/implementations/http/hono-api/types.js.map +1 -0
  113. package/build/implementations/http/hono-rpc/error-taxonomy.test.d.ts +1 -0
  114. package/build/implementations/http/hono-rpc/error-taxonomy.test.js +64 -0
  115. package/build/implementations/http/hono-rpc/error-taxonomy.test.js.map +1 -0
  116. package/build/implementations/http/hono-rpc/index.d.ts +130 -0
  117. package/build/implementations/http/hono-rpc/index.js +209 -0
  118. package/build/implementations/http/hono-rpc/index.js.map +1 -0
  119. package/build/implementations/http/hono-rpc/index.test.d.ts +1 -0
  120. package/build/implementations/http/hono-rpc/index.test.js +828 -0
  121. package/build/implementations/http/hono-rpc/index.test.js.map +1 -0
  122. package/build/implementations/http/hono-rpc/types.d.ts +11 -0
  123. package/build/implementations/http/hono-rpc/types.js +2 -0
  124. package/build/implementations/http/hono-rpc/types.js.map +1 -0
  125. package/build/implementations/http/hono-stream/error-taxonomy.test.d.ts +1 -0
  126. package/build/implementations/http/hono-stream/error-taxonomy.test.js +159 -0
  127. package/build/implementations/http/hono-stream/error-taxonomy.test.js.map +1 -0
  128. package/build/implementations/http/hono-stream/index.d.ts +171 -0
  129. package/build/implementations/http/hono-stream/index.js +415 -0
  130. package/build/implementations/http/hono-stream/index.js.map +1 -0
  131. package/build/implementations/http/hono-stream/index.test.d.ts +1 -0
  132. package/build/implementations/http/hono-stream/index.test.js +1383 -0
  133. package/build/implementations/http/hono-stream/index.test.js.map +1 -0
  134. package/build/implementations/http/hono-stream/types.d.ts +15 -0
  135. package/build/implementations/http/hono-stream/types.js +2 -0
  136. package/build/implementations/http/hono-stream/types.js.map +1 -0
  137. package/build/implementations/http/on-request-error.test.d.ts +1 -0
  138. package/build/implementations/http/on-request-error.test.js +173 -0
  139. package/build/implementations/http/on-request-error.test.js.map +1 -0
  140. package/build/implementations/http/route-errors.test.d.ts +1 -0
  141. package/build/implementations/http/route-errors.test.js +139 -0
  142. package/build/implementations/http/route-errors.test.js.map +1 -0
  143. package/build/implementations/types.d.ts +192 -0
  144. package/build/implementations/types.js +2 -0
  145. package/build/implementations/types.js.map +1 -0
  146. package/build/index.d.ts +165 -0
  147. package/build/index.js +258 -0
  148. package/build/index.js.map +1 -0
  149. package/build/index.test.d.ts +1 -0
  150. package/build/index.test.js +920 -0
  151. package/build/index.test.js.map +1 -0
  152. package/build/schema/extract-json-schema.d.ts +2 -0
  153. package/build/schema/extract-json-schema.js +12 -0
  154. package/build/schema/extract-json-schema.js.map +1 -0
  155. package/build/schema/extract-json-schema.test.d.ts +1 -0
  156. package/build/schema/extract-json-schema.test.js +23 -0
  157. package/build/schema/extract-json-schema.test.js.map +1 -0
  158. package/build/schema/parser.d.ts +28 -0
  159. package/build/schema/parser.js +170 -0
  160. package/build/schema/parser.js.map +1 -0
  161. package/build/schema/parser.test.d.ts +1 -0
  162. package/build/schema/parser.test.js +120 -0
  163. package/build/schema/parser.test.js.map +1 -0
  164. package/build/schema/resolve-schema-lib.d.ts +12 -0
  165. package/build/schema/resolve-schema-lib.js +11 -0
  166. package/build/schema/resolve-schema-lib.js.map +1 -0
  167. package/build/schema/resolve-schema-lib.test.d.ts +1 -0
  168. package/build/schema/resolve-schema-lib.test.js +17 -0
  169. package/build/schema/resolve-schema-lib.test.js.map +1 -0
  170. package/build/schema/typebox.d.ts +1 -1
  171. package/build/schema/typebox.js +2 -20
  172. package/build/schema/typebox.js.map +1 -1
  173. package/build/schema/typebox.test.js +0 -10
  174. package/build/schema/typebox.test.js.map +1 -1
  175. package/build/schema/types.d.ts +8 -0
  176. package/build/schema/types.js +2 -0
  177. package/build/schema/types.js.map +1 -0
  178. package/build/server/context.d.ts +12 -2
  179. package/build/server/context.js +49 -4
  180. package/build/server/context.js.map +1 -1
  181. package/build/server/context.test.js +32 -1
  182. package/build/server/context.test.js.map +1 -1
  183. package/build/server/doc-registry.js +0 -3
  184. package/build/server/doc-registry.js.map +1 -1
  185. package/build/server/doc-registry.test.js +0 -31
  186. package/build/server/doc-registry.test.js.map +1 -1
  187. package/build/server/index.d.ts +0 -1
  188. package/build/server/index.js +0 -1
  189. package/build/server/index.js.map +1 -1
  190. package/build/server/types.d.ts +6 -27
  191. package/build/stack-utils.d.ts +25 -0
  192. package/build/stack-utils.js +95 -0
  193. package/build/stack-utils.js.map +1 -0
  194. package/build/stack-utils.test.d.ts +1 -0
  195. package/build/stack-utils.test.js +80 -0
  196. package/build/stack-utils.test.js.map +1 -0
  197. package/docs/core.md +8 -0
  198. package/docs/http-integrations.md +41 -27
  199. package/package.json +8 -8
  200. package/src/adapters/astro/README.md +2 -0
  201. package/src/adapters/hono/envelope-parity.test.ts +6 -18
  202. package/src/adapters/hono/handlers/http-stream.ts +12 -3
  203. package/src/adapters/hono/handlers/http.ts +12 -3
  204. package/src/adapters/hono/handlers/rpc.ts +12 -3
  205. package/src/adapters/hono/handlers/stream.ts +12 -3
  206. package/src/adapters/hono/index.test.ts +70 -0
  207. package/src/adapters/hono/index.ts +53 -11
  208. package/src/adapters/hono/request.ts +18 -0
  209. package/src/adapters/hono/types.ts +37 -0
  210. package/src/codegen/bin/cli.ts +1 -1
  211. package/src/codegen/constants.ts +2 -2
  212. package/src/codegen/emit/api-route.ts +1 -1
  213. package/src/codegen/emit/scope-file.ts +1 -2
  214. package/src/codegen/emit-errors.integration.test.ts +2 -2
  215. package/src/codegen/resolve-envelope.ts +1 -1
  216. package/src/codegen/test-helpers/run-tsc.ts +0 -1
  217. package/src/core/create-http-stream.ts +20 -13
  218. package/src/core/create-http.test-d.ts +154 -0
  219. package/src/core/create-http.ts +19 -8
  220. package/src/core/create-stream.ts +12 -4
  221. package/src/core/create.test.ts +74 -0
  222. package/src/core/create.ts +10 -5
  223. package/src/core/internal.ts +35 -0
  224. package/src/core/procedures.ts +4 -0
  225. package/src/core/types.ts +99 -4
  226. package/src/exports.ts +6 -4
  227. package/src/schema/typebox.test.ts +0 -12
  228. package/src/schema/typebox.ts +2 -21
  229. package/src/server/context.test.ts +39 -1
  230. package/src/server/context.ts +54 -4
  231. package/src/server/doc-registry.test.ts +0 -34
  232. package/src/server/doc-registry.ts +0 -3
  233. package/src/server/index.ts +0 -1
  234. package/src/server/types.ts +8 -27
  235. package/build/server/spec-version.d.ts +0 -24
  236. package/build/server/spec-version.js +0 -26
  237. package/build/server/spec-version.js.map +0 -1
  238. package/build/version.d.ts +0 -9
  239. package/build/version.js +0 -11
  240. package/build/version.js.map +0 -1
  241. package/docs/doc-envelope-spec-v1.md +0 -296
  242. package/docs/doc-envelope-v1.schema.json +0 -253
  243. package/src/server/spec-version.ts +0 -27
  244. package/src/version.ts +0 -11
@@ -0,0 +1,249 @@
1
+ import { ProcedureError, ProcedureValidationError, ProcedureYieldValidationError } from '../../errors.js';
2
+ import type { TProcedureRegistration, TStreamProcedureRegistration } from '../../index.js';
3
+ import type { ErrorDoc } from '../types.js';
4
+ /** Either a regular or stream procedure registration — accepted by taxonomy callbacks. */
5
+ export type TAnyProcedureRegistration = TProcedureRegistration | TStreamProcedureRegistration;
6
+ /**
7
+ * An entry in an {@link ErrorTaxonomy}. Describes how to recognize a thrown
8
+ * error at runtime and how to serialize it into an HTTP response.
9
+ *
10
+ * Exactly one of `class` or `match` must be provided.
11
+ */
12
+ export type ErrorTaxonomyEntry<TError = any, TBody = unknown> = {
13
+ /** `instanceof` discriminator. Mutually exclusive with `match`. */
14
+ class?: new (...args: any[]) => TError;
15
+ /** Predicate discriminator — for 3rd-party errors that can't subclass a framework type. */
16
+ match?: (err: unknown) => err is TError;
17
+ /** HTTP status code to send when this error is caught. */
18
+ statusCode: number;
19
+ /** One-line description used by DocRegistry to document the error in the envelope. */
20
+ description?: string;
21
+ /** Optional response-body JSON Schema — consumed by DocRegistry. */
22
+ schema?: Record<string, unknown>;
23
+ /**
24
+ * Maps the caught error to a response body. When omitted, the body is
25
+ * `{ name: <key>, message: err.message }` where `<key>` is this entry's key.
26
+ * When the returned object lacks a `name` field, one is auto-injected —
27
+ * wire-protocol consistency (needed by the client dispatcher) is guaranteed.
28
+ */
29
+ toResponse?: (err: TError, meta: {
30
+ key: string;
31
+ }) => TBody;
32
+ /**
33
+ * Side effect on catch (logging, metrics). Awaited before the response is sent.
34
+ * `raw` is the framework-specific request context (Hono `Context` /
35
+ * `{ req, res }` for Express) — cast as needed.
36
+ */
37
+ onCatch?: (err: TError, ctx: {
38
+ procedure: TAnyProcedureRegistration;
39
+ key: string;
40
+ raw: unknown;
41
+ }) => void | Promise<void>;
42
+ };
43
+ /**
44
+ * A named collection of {@link ErrorTaxonomyEntry} values. First match wins at
45
+ * resolution time. `defineErrorTaxonomy` topologically sorts class-based
46
+ * entries so a subclass is always checked before its ancestors regardless of
47
+ * declaration order; predicate entries retain declared order.
48
+ */
49
+ export type ErrorTaxonomy = Record<string, ErrorTaxonomyEntry>;
50
+ /**
51
+ * Identity helper that preserves literal inference and:
52
+ * 1. validates each entry has exactly one discriminator (`class` xor `match`);
53
+ * 2. topologically sorts `class:` entries so subclasses precede base classes.
54
+ *
55
+ * The sort is stable — entries unrelated by inheritance keep their declared
56
+ * order. Predicate entries (with `match:`) always keep declared order relative
57
+ * to class entries, so a predicate that's intentionally narrower can be placed
58
+ * before a class entry to take precedence.
59
+ */
60
+ export declare function defineErrorTaxonomy<T extends ErrorTaxonomy>(entries: T): T;
61
+ /**
62
+ * Default taxonomy covering framework error classes that can be thrown by a
63
+ * handler at request time. Layered after the user taxonomy during resolution.
64
+ *
65
+ * `ProcedureError` uses `match:` rather than `class:` so it matches only
66
+ * direct throws (e.g. from `ctx.error()`). When the core wraps a non-ProcedureError
67
+ * into a ProcedureError with `cause`, that wrapper falls through — the
68
+ * resolver unwraps the cause and the user taxonomy / `unknownError` sees the
69
+ * real thrown value.
70
+ */
71
+ export declare const defaultErrorTaxonomy: {
72
+ ProcedureValidationError: {
73
+ class: typeof ProcedureValidationError;
74
+ statusCode: number;
75
+ description: string;
76
+ toResponse: (err: any) => {
77
+ name: "ProcedureValidationError";
78
+ procedureName: any;
79
+ message: any;
80
+ errors: any;
81
+ };
82
+ schema: {
83
+ type: string;
84
+ properties: {
85
+ name: {
86
+ type: string;
87
+ const: string;
88
+ };
89
+ procedureName: {
90
+ type: string;
91
+ };
92
+ message: {
93
+ type: string;
94
+ };
95
+ errors: {
96
+ type: string;
97
+ items: {
98
+ type: string;
99
+ properties: {
100
+ instancePath: {
101
+ type: string;
102
+ };
103
+ message: {
104
+ type: string;
105
+ };
106
+ };
107
+ };
108
+ };
109
+ };
110
+ required: string[];
111
+ };
112
+ };
113
+ ProcedureYieldValidationError: {
114
+ class: typeof ProcedureYieldValidationError;
115
+ statusCode: number;
116
+ description: string;
117
+ toResponse: (err: any) => {
118
+ name: "ProcedureYieldValidationError";
119
+ procedureName: any;
120
+ message: any;
121
+ errors: any;
122
+ };
123
+ schema: {
124
+ type: string;
125
+ properties: {
126
+ name: {
127
+ type: string;
128
+ const: string;
129
+ };
130
+ procedureName: {
131
+ type: string;
132
+ };
133
+ message: {
134
+ type: string;
135
+ };
136
+ errors: {
137
+ type: string;
138
+ items: {
139
+ type: string;
140
+ properties: {
141
+ instancePath: {
142
+ type: string;
143
+ };
144
+ message: {
145
+ type: string;
146
+ };
147
+ };
148
+ };
149
+ };
150
+ };
151
+ required: string[];
152
+ };
153
+ };
154
+ ProcedureError: {
155
+ match: (err: unknown) => err is ProcedureError;
156
+ statusCode: number;
157
+ description: string;
158
+ toResponse: (err: any) => {
159
+ name: "ProcedureError";
160
+ procedureName: any;
161
+ message: any;
162
+ meta: any;
163
+ };
164
+ schema: {
165
+ type: string;
166
+ properties: {
167
+ name: {
168
+ type: string;
169
+ const: string;
170
+ };
171
+ procedureName: {
172
+ type: string;
173
+ };
174
+ message: {
175
+ type: string;
176
+ };
177
+ meta: {
178
+ type: string;
179
+ };
180
+ };
181
+ required: string[];
182
+ };
183
+ };
184
+ };
185
+ /**
186
+ * Doc-only entry for `ProcedureRegistrationError`, which is thrown at
187
+ * procedure-definition time (never at request time) and therefore doesn't
188
+ * appear in the runtime taxonomy. Consumers still see it in the error catalog
189
+ * via `DocRegistry.defaultErrors()`.
190
+ */
191
+ export declare const PROCEDURE_REGISTRATION_ERROR_DOC: ErrorDoc;
192
+ /**
193
+ * Converts a taxonomy into {@link ErrorDoc} objects suitable for a DocEnvelope.
194
+ *
195
+ * @internal Used by `DocRegistry` to merge taxonomy entries into the envelope.
196
+ * Consumers should pass their taxonomy directly to `new DocRegistry({ errors: taxonomy })`
197
+ * rather than calling this helper — the constructor handles the conversion.
198
+ */
199
+ export declare function taxonomyToErrorDocs(taxonomy: ErrorTaxonomy): ErrorDoc[];
200
+ /**
201
+ * Configuration for the fallback "unknown" error handler — applied when no
202
+ * taxonomy entry (user or default) matches a thrown value.
203
+ */
204
+ export type UnknownErrorConfig = {
205
+ /** HTTP status code. Defaults to 500. */
206
+ statusCode?: number;
207
+ /** Serializes the error into a response body. */
208
+ toResponse: (err: unknown) => unknown;
209
+ /** Awaited before the response is sent. */
210
+ onCatch?: (err: unknown, ctx: {
211
+ procedure: TAnyProcedureRegistration;
212
+ raw: unknown;
213
+ }) => void | Promise<void>;
214
+ };
215
+ /**
216
+ * Result of matching an error against a taxonomy chain. Consumers translate
217
+ * `{ statusCode, body }` into their framework's response primitive and must
218
+ * `await runOnCatch()` before sending.
219
+ */
220
+ export type ResolvedErrorResponse = {
221
+ statusCode: number;
222
+ body: unknown;
223
+ runOnCatch: () => Promise<void>;
224
+ };
225
+ /**
226
+ * Matches a thrown value against the user taxonomy, then (if `includeDefaults`)
227
+ * the default taxonomy, then the `unknownError` config. Returns `null` when
228
+ * nothing matches — callers fall through to their builder's imperative
229
+ * `onError` callback and the hard default.
230
+ *
231
+ * The core wraps any non-ProcedureError thrown by a handler into a
232
+ * ProcedureError with `cause` set to the original. This resolver unwraps that:
233
+ * candidates are checked in the order `[cause, outer]` so a user taxonomy sees
234
+ * its own error classes rather than the wrapper. The default `ProcedureError`
235
+ * entry uses a `match:` predicate that excludes wrappers so they reach
236
+ * `unknownError` instead.
237
+ *
238
+ * Side effects (`onCatch`) are deferred into `runOnCatch` so the caller decides
239
+ * when to execute them relative to writing the response.
240
+ */
241
+ export declare function resolveErrorResponse(params: {
242
+ err: unknown;
243
+ userTaxonomy?: ErrorTaxonomy;
244
+ /** Whether to apply {@link defaultErrorTaxonomy}. Defaults to `true`. */
245
+ includeDefaults?: boolean;
246
+ unknownError?: UnknownErrorConfig;
247
+ procedure: TAnyProcedureRegistration;
248
+ raw: unknown;
249
+ }): ResolvedErrorResponse | null;
@@ -0,0 +1,252 @@
1
+ import { ProcedureError, ProcedureValidationError, ProcedureYieldValidationError, } from '../../errors.js';
2
+ /**
3
+ * Identity helper that preserves literal inference and:
4
+ * 1. validates each entry has exactly one discriminator (`class` xor `match`);
5
+ * 2. topologically sorts `class:` entries so subclasses precede base classes.
6
+ *
7
+ * The sort is stable — entries unrelated by inheritance keep their declared
8
+ * order. Predicate entries (with `match:`) always keep declared order relative
9
+ * to class entries, so a predicate that's intentionally narrower can be placed
10
+ * before a class entry to take precedence.
11
+ */
12
+ export function defineErrorTaxonomy(entries) {
13
+ const pairs = Object.entries(entries);
14
+ for (const [key, entry] of pairs) {
15
+ const hasClass = entry.class !== undefined;
16
+ const hasMatch = entry.match !== undefined;
17
+ if (hasClass === hasMatch) {
18
+ throw new Error(`Error taxonomy entry "${key}" must define exactly one of { class, match }.`);
19
+ }
20
+ }
21
+ // Stable sort: subclass-of-the-other → -1, other-subclass-of-this → 1, else 0.
22
+ pairs.sort(([, a], [, b]) => {
23
+ if (!a.class || !b.class)
24
+ return 0;
25
+ if (a.class === b.class)
26
+ return 0;
27
+ if (a.class.prototype instanceof b.class)
28
+ return -1;
29
+ if (b.class.prototype instanceof a.class)
30
+ return 1;
31
+ return 0;
32
+ });
33
+ return Object.fromEntries(pairs);
34
+ }
35
+ /**
36
+ * Default taxonomy covering framework error classes that can be thrown by a
37
+ * handler at request time. Layered after the user taxonomy during resolution.
38
+ *
39
+ * `ProcedureError` uses `match:` rather than `class:` so it matches only
40
+ * direct throws (e.g. from `ctx.error()`). When the core wraps a non-ProcedureError
41
+ * into a ProcedureError with `cause`, that wrapper falls through — the
42
+ * resolver unwraps the cause and the user taxonomy / `unknownError` sees the
43
+ * real thrown value.
44
+ */
45
+ export const defaultErrorTaxonomy = defineErrorTaxonomy({
46
+ ProcedureValidationError: {
47
+ class: ProcedureValidationError,
48
+ statusCode: 400,
49
+ description: 'Schema validation failed for the procedure input parameters.',
50
+ toResponse: (err) => ({
51
+ name: 'ProcedureValidationError',
52
+ procedureName: err.procedureName,
53
+ message: err.message,
54
+ errors: err.errors,
55
+ }),
56
+ schema: {
57
+ type: 'object',
58
+ properties: {
59
+ name: { type: 'string', const: 'ProcedureValidationError' },
60
+ procedureName: { type: 'string' },
61
+ message: { type: 'string' },
62
+ errors: {
63
+ type: 'array',
64
+ items: {
65
+ type: 'object',
66
+ properties: {
67
+ instancePath: { type: 'string' },
68
+ message: { type: 'string' },
69
+ },
70
+ },
71
+ },
72
+ },
73
+ required: ['name', 'procedureName', 'message'],
74
+ },
75
+ },
76
+ ProcedureYieldValidationError: {
77
+ class: ProcedureYieldValidationError,
78
+ statusCode: 500,
79
+ description: 'Schema validation failed for a yielded value in a streaming procedure.',
80
+ toResponse: (err) => ({
81
+ name: 'ProcedureYieldValidationError',
82
+ procedureName: err.procedureName,
83
+ message: err.message,
84
+ errors: err.errors,
85
+ }),
86
+ schema: {
87
+ type: 'object',
88
+ properties: {
89
+ name: { type: 'string', const: 'ProcedureYieldValidationError' },
90
+ procedureName: { type: 'string' },
91
+ message: { type: 'string' },
92
+ errors: {
93
+ type: 'array',
94
+ items: {
95
+ type: 'object',
96
+ properties: {
97
+ instancePath: { type: 'string' },
98
+ message: { type: 'string' },
99
+ },
100
+ },
101
+ },
102
+ },
103
+ required: ['name', 'procedureName', 'message'],
104
+ },
105
+ },
106
+ ProcedureError: {
107
+ match: (err) => err instanceof ProcedureError && err.cause === undefined,
108
+ statusCode: 500,
109
+ description: 'An error thrown from within a procedure handler via ctx.error().',
110
+ toResponse: (err) => ({
111
+ name: 'ProcedureError',
112
+ procedureName: err.procedureName,
113
+ message: err.message,
114
+ meta: err.meta,
115
+ }),
116
+ schema: {
117
+ type: 'object',
118
+ properties: {
119
+ name: { type: 'string', const: 'ProcedureError' },
120
+ procedureName: { type: 'string' },
121
+ message: { type: 'string' },
122
+ meta: { type: 'object' },
123
+ },
124
+ required: ['name', 'procedureName', 'message'],
125
+ },
126
+ },
127
+ });
128
+ /**
129
+ * Doc-only entry for `ProcedureRegistrationError`, which is thrown at
130
+ * procedure-definition time (never at request time) and therefore doesn't
131
+ * appear in the runtime taxonomy. Consumers still see it in the error catalog
132
+ * via `DocRegistry.defaultErrors()`.
133
+ */
134
+ export const PROCEDURE_REGISTRATION_ERROR_DOC = {
135
+ name: 'ProcedureRegistrationError',
136
+ statusCode: 500,
137
+ description: 'An invalid schema or configuration was detected at procedure registration time.',
138
+ schema: {
139
+ type: 'object',
140
+ properties: {
141
+ name: { type: 'string', const: 'ProcedureRegistrationError' },
142
+ procedureName: { type: 'string' },
143
+ message: { type: 'string' },
144
+ },
145
+ required: ['name', 'procedureName', 'message'],
146
+ },
147
+ };
148
+ /**
149
+ * Converts a taxonomy into {@link ErrorDoc} objects suitable for a DocEnvelope.
150
+ *
151
+ * @internal Used by `DocRegistry` to merge taxonomy entries into the envelope.
152
+ * Consumers should pass their taxonomy directly to `new DocRegistry({ errors: taxonomy })`
153
+ * rather than calling this helper — the constructor handles the conversion.
154
+ */
155
+ export function taxonomyToErrorDocs(taxonomy) {
156
+ return Object.entries(taxonomy).map(([key, entry]) => ({
157
+ name: key,
158
+ statusCode: entry.statusCode,
159
+ description: entry.description ?? '',
160
+ schema: entry.schema,
161
+ }));
162
+ }
163
+ /**
164
+ * Injects `{ name: key }` when `rawBody` is an object without a `name` field.
165
+ * Guarantees wire-protocol consistency (client dispatchers discriminate on
166
+ * `body.name`) without forcing every `toResponse` to repeat it.
167
+ */
168
+ function ensureName(rawBody, key) {
169
+ if (rawBody && typeof rawBody === 'object' && !('name' in rawBody)) {
170
+ return { name: key, ...rawBody };
171
+ }
172
+ return rawBody;
173
+ }
174
+ /**
175
+ * Matches a thrown value against the user taxonomy, then (if `includeDefaults`)
176
+ * the default taxonomy, then the `unknownError` config. Returns `null` when
177
+ * nothing matches — callers fall through to their builder's imperative
178
+ * `onError` callback and the hard default.
179
+ *
180
+ * The core wraps any non-ProcedureError thrown by a handler into a
181
+ * ProcedureError with `cause` set to the original. This resolver unwraps that:
182
+ * candidates are checked in the order `[cause, outer]` so a user taxonomy sees
183
+ * its own error classes rather than the wrapper. The default `ProcedureError`
184
+ * entry uses a `match:` predicate that excludes wrappers so they reach
185
+ * `unknownError` instead.
186
+ *
187
+ * Side effects (`onCatch`) are deferred into `runOnCatch` so the caller decides
188
+ * when to execute them relative to writing the response.
189
+ */
190
+ export function resolveErrorResponse(params) {
191
+ const { err, userTaxonomy, includeDefaults = true, unknownError, procedure, raw, } = params;
192
+ const wrappedCause = err instanceof ProcedureError && err.cause !== undefined
193
+ ? err.cause
194
+ : undefined;
195
+ // Most-specific candidate first so a matching user entry on `cause` wins over
196
+ // a matching entry on the outer wrapper.
197
+ const candidates = wrappedCause !== undefined ? [wrappedCause, err] : [err];
198
+ const tryMatch = (tax) => {
199
+ for (const [key, entry] of Object.entries(tax)) {
200
+ for (const candidate of candidates) {
201
+ const matched = entry.class
202
+ ? candidate instanceof entry.class
203
+ : entry.match
204
+ ? entry.match(candidate)
205
+ : false;
206
+ if (!matched)
207
+ continue;
208
+ const rawBody = entry.toResponse
209
+ ? entry.toResponse(candidate, { key })
210
+ : {
211
+ name: key,
212
+ message: candidate instanceof Error ? candidate.message : String(candidate),
213
+ };
214
+ const body = ensureName(rawBody, key);
215
+ return {
216
+ statusCode: entry.statusCode,
217
+ body,
218
+ runOnCatch: async () => {
219
+ if (entry.onCatch) {
220
+ await entry.onCatch(candidate, { procedure, key, raw });
221
+ }
222
+ },
223
+ };
224
+ }
225
+ }
226
+ return null;
227
+ };
228
+ if (userTaxonomy) {
229
+ const hit = tryMatch(userTaxonomy);
230
+ if (hit)
231
+ return hit;
232
+ }
233
+ if (includeDefaults) {
234
+ const hit = tryMatch(defaultErrorTaxonomy);
235
+ if (hit)
236
+ return hit;
237
+ }
238
+ if (unknownError) {
239
+ const mostSpecific = candidates[0];
240
+ return {
241
+ statusCode: unknownError.statusCode ?? 500,
242
+ body: unknownError.toResponse(mostSpecific),
243
+ runOnCatch: async () => {
244
+ if (unknownError.onCatch) {
245
+ await unknownError.onCatch(mostSpecific, { procedure, raw });
246
+ }
247
+ },
248
+ };
249
+ }
250
+ return null;
251
+ }
252
+ //# sourceMappingURL=error-taxonomy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-taxonomy.js","sourceRoot":"","sources":["../../../src/implementations/http/error-taxonomy.ts"],"names":[],"mappings":"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"}