ts-procedures 5.16.0 → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/agent_config/claude-code/agents/ts-procedures-architect.md +13 -6
- package/agent_config/claude-code/skills/ts-procedures/SKILL.md +26 -4
- package/agent_config/claude-code/skills/ts-procedures/anti-patterns.md +87 -19
- package/agent_config/claude-code/skills/ts-procedures/api-reference.md +162 -16
- package/agent_config/claude-code/skills/ts-procedures/patterns.md +179 -16
- package/agent_config/claude-code/skills/ts-procedures-review/SKILL.md +1 -1
- package/agent_config/claude-code/skills/ts-procedures-review/checklist.md +20 -12
- package/agent_config/claude-code/skills/ts-procedures-scaffold/SKILL.md +2 -1
- package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/client.md +22 -15
- package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/express-rpc.md +20 -17
- package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/hono-api.md +20 -16
- package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/hono-rpc.md +20 -17
- package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/hono-stream.md +16 -3
- package/agent_config/copilot/copilot-instructions.md +78 -12
- package/agent_config/cursor/cursorrules +78 -12
- package/build/client/call.d.ts +2 -1
- package/build/client/call.js +9 -1
- package/build/client/call.js.map +1 -1
- package/build/client/error-dispatch.d.ts +13 -0
- package/build/client/error-dispatch.js +26 -0
- package/build/client/error-dispatch.js.map +1 -0
- package/build/client/error-dispatch.test.d.ts +1 -0
- package/build/client/error-dispatch.test.js +56 -0
- package/build/client/error-dispatch.test.js.map +1 -0
- package/build/client/fetch-adapter.js +10 -4
- package/build/client/fetch-adapter.js.map +1 -1
- package/build/client/index.d.ts +2 -1
- package/build/client/index.js +5 -1
- package/build/client/index.js.map +1 -1
- package/build/client/stream.d.ts +2 -1
- package/build/client/stream.js +13 -3
- package/build/client/stream.js.map +1 -1
- package/build/client/typed-error-dispatch.test.d.ts +1 -0
- package/build/client/typed-error-dispatch.test.js +168 -0
- package/build/client/typed-error-dispatch.test.js.map +1 -0
- package/build/client/types.d.ts +37 -0
- package/build/codegen/e2e.test.js +9 -4
- package/build/codegen/e2e.test.js.map +1 -1
- package/build/codegen/emit-client-runtime.js +4 -0
- package/build/codegen/emit-client-runtime.js.map +1 -1
- package/build/codegen/emit-errors.d.ts +17 -6
- package/build/codegen/emit-errors.integration.test.d.ts +1 -0
- package/build/codegen/emit-errors.integration.test.js +162 -0
- package/build/codegen/emit-errors.integration.test.js.map +1 -0
- package/build/codegen/emit-errors.js +50 -39
- package/build/codegen/emit-errors.js.map +1 -1
- package/build/codegen/emit-errors.test.js +75 -78
- package/build/codegen/emit-errors.test.js.map +1 -1
- package/build/codegen/emit-index.d.ts +7 -0
- package/build/codegen/emit-index.js +26 -4
- package/build/codegen/emit-index.js.map +1 -1
- package/build/codegen/emit-index.test.js +55 -23
- package/build/codegen/emit-index.test.js.map +1 -1
- package/build/codegen/emit-scope.d.ts +8 -0
- package/build/codegen/emit-scope.js +82 -7
- package/build/codegen/emit-scope.js.map +1 -1
- package/build/codegen/pipeline.js +22 -2
- package/build/codegen/pipeline.js.map +1 -1
- package/build/implementations/http/doc-registry.d.ts +17 -1
- package/build/implementations/http/doc-registry.js +47 -79
- package/build/implementations/http/doc-registry.js.map +1 -1
- package/build/implementations/http/doc-registry.test.js +149 -16
- package/build/implementations/http/doc-registry.test.js.map +1 -1
- package/build/implementations/http/error-taxonomy.d.ts +249 -0
- package/build/implementations/http/error-taxonomy.js +252 -0
- package/build/implementations/http/error-taxonomy.js.map +1 -0
- package/build/implementations/http/error-taxonomy.test.d.ts +1 -0
- package/build/implementations/http/error-taxonomy.test.js +399 -0
- package/build/implementations/http/error-taxonomy.test.js.map +1 -0
- package/build/implementations/http/express-rpc/error-taxonomy.test.d.ts +1 -0
- package/build/implementations/http/express-rpc/error-taxonomy.test.js +83 -0
- package/build/implementations/http/express-rpc/error-taxonomy.test.js.map +1 -0
- package/build/implementations/http/express-rpc/index.d.ts +39 -8
- package/build/implementations/http/express-rpc/index.js +39 -8
- package/build/implementations/http/express-rpc/index.js.map +1 -1
- package/build/implementations/http/hono-api/error-taxonomy.test.d.ts +1 -0
- package/build/implementations/http/hono-api/error-taxonomy.test.js +137 -0
- package/build/implementations/http/hono-api/error-taxonomy.test.js.map +1 -0
- package/build/implementations/http/hono-api/index.d.ts +38 -1
- package/build/implementations/http/hono-api/index.js +32 -0
- package/build/implementations/http/hono-api/index.js.map +1 -1
- package/build/implementations/http/hono-rpc/error-taxonomy.test.d.ts +1 -0
- package/build/implementations/http/hono-rpc/error-taxonomy.test.js +64 -0
- package/build/implementations/http/hono-rpc/error-taxonomy.test.js.map +1 -0
- package/build/implementations/http/hono-rpc/index.d.ts +34 -7
- package/build/implementations/http/hono-rpc/index.js +31 -4
- package/build/implementations/http/hono-rpc/index.js.map +1 -1
- package/build/implementations/http/hono-stream/error-taxonomy.test.d.ts +1 -0
- package/build/implementations/http/hono-stream/error-taxonomy.test.js +87 -0
- package/build/implementations/http/hono-stream/error-taxonomy.test.js.map +1 -0
- package/build/implementations/http/hono-stream/index.d.ts +40 -3
- package/build/implementations/http/hono-stream/index.js +37 -10
- package/build/implementations/http/hono-stream/index.js.map +1 -1
- package/build/implementations/http/hono-stream/index.test.js +45 -18
- package/build/implementations/http/hono-stream/index.test.js.map +1 -1
- package/build/implementations/http/on-request-error.test.d.ts +1 -0
- package/build/implementations/http/on-request-error.test.js +173 -0
- package/build/implementations/http/on-request-error.test.js.map +1 -0
- package/build/implementations/http/route-errors.test.d.ts +1 -0
- package/build/implementations/http/route-errors.test.js +139 -0
- package/build/implementations/http/route-errors.test.js.map +1 -0
- package/build/implementations/types.d.ts +43 -3
- package/docs/client-and-codegen.md +105 -12
- package/docs/core.md +14 -5
- package/docs/http-integrations.md +138 -5
- package/docs/streaming.md +3 -1
- package/docs/superpowers/plans/2026-04-24-doc-registry-simplification.md +886 -0
- package/package.json +7 -2
- package/src/client/call.ts +10 -1
- package/src/client/error-dispatch.test.ts +72 -0
- package/src/client/error-dispatch.ts +27 -0
- package/src/client/fetch-adapter.ts +11 -5
- package/src/client/index.ts +9 -0
- package/src/client/stream.ts +14 -3
- package/src/client/typed-error-dispatch.test.ts +211 -0
- package/src/client/types.ts +42 -0
- package/src/codegen/e2e.test.ts +9 -4
- package/src/codegen/emit-client-runtime.ts +4 -0
- package/src/codegen/emit-errors.integration.test.ts +183 -0
- package/src/codegen/emit-errors.test.ts +91 -87
- package/src/codegen/emit-errors.ts +123 -41
- package/src/codegen/emit-index.test.ts +68 -24
- package/src/codegen/emit-index.ts +66 -4
- package/src/codegen/emit-scope.ts +124 -7
- package/src/codegen/pipeline.ts +25 -2
- package/src/implementations/http/README.md +21 -7
- package/src/implementations/http/doc-registry.test.ts +164 -16
- package/src/implementations/http/doc-registry.ts +58 -82
- package/src/implementations/http/error-taxonomy.test.ts +438 -0
- package/src/implementations/http/error-taxonomy.ts +361 -0
- package/src/implementations/http/express-rpc/README.md +23 -24
- package/src/implementations/http/express-rpc/error-taxonomy.test.ts +103 -0
- package/src/implementations/http/express-rpc/index.ts +75 -14
- package/src/implementations/http/hono-api/README.md +284 -0
- package/src/implementations/http/hono-api/error-taxonomy.test.ts +179 -0
- package/src/implementations/http/hono-api/index.ts +76 -1
- package/src/implementations/http/hono-rpc/README.md +20 -21
- package/src/implementations/http/hono-rpc/error-taxonomy.test.ts +82 -0
- package/src/implementations/http/hono-rpc/index.ts +65 -9
- package/src/implementations/http/hono-stream/README.md +44 -25
- package/src/implementations/http/hono-stream/error-taxonomy.test.ts +98 -0
- package/src/implementations/http/hono-stream/index.test.ts +54 -18
- package/src/implementations/http/hono-stream/index.ts +83 -13
- package/src/implementations/http/on-request-error.test.ts +201 -0
- package/src/implementations/http/route-errors.test.ts +176 -0
- package/src/implementations/types.ts +43 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"on-request-error.test.js","sourceRoot":"","sources":["../../../src/implementations/http/on-request-error.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AACnD,OAAO,OAAO,MAAM,WAAW,CAAA;AAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAC9B,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAE3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAE7D,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;IAClD,SAAS,OAAO,CAAC,MAA0D;QACzE,MAAM,GAAG,GAAG,UAAU,EAAiB,CAAA;QACvC,GAAG,CAAC,MAAM,CACR,MAAM,EACN,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,EACzE,KAAK,IAAI,EAAE;YACT,MAAM,IAAI,SAAS,CAAC,MAAM,CAAC,CAAA;QAC7B,CAAC,CACF,CAAA;QACD,OAAO,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAA;IACxE,CAAC;IAED,IAAI,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,KAAK,GAAa,EAAE,CAAA;QAC1B,MAAM,cAAc,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE;YAChC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QACxB,CAAC,CAAC,CAAA;QACF,MAAM,OAAO,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EAAO,EAAE,CAAM,EAAE,EAAE;YACxC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;YACrB,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,GAAG,CAAC,CAAA;QACvC,CAAC,CAAC,CAAA;QAEF,MAAM,GAAG,GAAG,OAAO,CAAC,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,CAAA;QAChD,MAAM,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QAC1B,MAAM,CAAC,cAAc,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;QAC/C,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QAC3E,MAAM,GAAG,GAAa,EAAE,CAAA;QACxB,MAAM,cAAc,GAAG,KAAK,IAAI,EAAE;YAChC,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;YAC1C,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;QAC3B,CAAC,CAAA;QACD,MAAM,GAAG,GAAG,OAAO,CAAC;YAClB,cAAc;YACd,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE;gBACjB,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;gBAC1B,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,CAAC,CAAA;YAClC,CAAC;SACF,CAAC,CAAA;QACF,MAAM,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QAC1B,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAAC,CAAA;IAC1D,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;QAC3F,MAAM,UAAU,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAC1E,MAAM,GAAG,GAAG,OAAO,CAAC;YAClB,cAAc,EAAE,GAAG,EAAE;gBACnB,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAA;YACtC,CAAC;SACF,CAAC,CAAA;QACF,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QACtC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC5B,UAAU,CAAC,WAAW,EAAE,CAAA;IAC1B,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,GAAG,GAAG,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAA;QACtE,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QACtC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC9B,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;IAClD,SAAS,OAAO,CAAC,MAA0D;QACzE,MAAM,GAAG,GAAG,UAAU,EAAiB,CAAA;QACvC,GAAG,CAAC,MAAM,CACR,MAAM,EACN,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,EAClE,KAAK,IAAI,EAAE;YACT,MAAM,IAAI,SAAS,CAAC,MAAM,CAAC,CAAA;QAC7B,CAAC,CACF,CAAA;QACD,OAAO,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAA;IACxE,CAAC;IAED,IAAI,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QACjD,MAAM,KAAK,GAAa,EAAE,CAAA;QAC1B,MAAM,cAAc,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE;YAChC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QACxB,CAAC,CAAC,CAAA;QACF,MAAM,OAAO,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EAAO,EAAE,CAAM,EAAE,EAAE;YACxC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;YACrB,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA;QACxB,CAAC,CAAC,CAAA;QAEF,MAAM,GAAG,GAAG,OAAO,CAAC,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,CAAA;QAChD,MAAM,GAAG,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;QACjE,MAAM,CAAC,cAAc,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;QAC/C,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;QAC/C,MAAM,UAAU,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAC1E,MAAM,GAAG,GAAG,OAAO,CAAC;YAClB,cAAc,EAAE,GAAG,EAAE;gBACnB,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAA;YACrC,CAAC;SACF,CAAC,CAAA;QACF,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;QAC7E,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC5B,UAAU,CAAC,WAAW,EAAE,CAAA;IAC1B,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,uCAAuC,EAAE,GAAG,EAAE;IACrD,SAAS,OAAO,CAAC,MAA6D;QAC5E,MAAM,GAAG,GAAG,UAAU,EAAiB,CAAA;QACvC,GAAG,CAAC,MAAM,CACR,MAAM,EACN,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,EAClE,KAAK,IAAI,EAAE;YACT,MAAM,IAAI,SAAS,CAAC,MAAM,CAAC,CAAA;QAC7B,CAAC,CACF,CAAA;QACD,OAAO,IAAI,oBAAoB,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAA;IAC3E,CAAC;IAED,IAAI,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QACjD,IAAI,OAAY,CAAA;QAChB,MAAM,GAAG,GAAG,OAAO,CAAC;YAClB,cAAc,EAAE,CAAC,GAAG,EAAE,EAAE;gBACtB,OAAO,GAAG,GAAG,CAAC,GAAG,CAAA;YACnB,CAAC;SACF,CAAC,CAAA;QACF,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAChD,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAA;QACjC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAA;IACnC,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;QAC/C,MAAM,UAAU,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAC1E,MAAM,GAAG,GAAG,OAAO,CAAC;YAClB,cAAc,EAAE,GAAG,EAAE;gBACnB,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAA;YACjC,CAAC;SACF,CAAC,CAAA;QACF,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAC5D,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC5B,UAAU,CAAC,WAAW,EAAE,CAAA;IAC1B,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,oDAAoD,EAAE,GAAG,EAAE;IAClE,SAAS,OAAO,CAAC,MAA6D;QAC5E,MAAM,GAAG,GAAG,UAAU,EAAiB,CAAA;QACvC,GAAG,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,KAAK,SAAS,CAAC;YACvE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,CAAA;QACpB,CAAC,CAAC,CAAA;QACF,OAAO,IAAI,oBAAoB,CAAC,MAAM,CAAC;aACpC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE;YAClB,MAAM,IAAI,SAAS,CAAC,gBAAgB,CAAC,CAAA;QACvC,CAAC,CAAC;aACD,KAAK,EAAE,CAAA;IACZ,CAAC;IAED,IAAI,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QAClD,MAAM,cAAc,GAAG,EAAE,CAAC,EAAE,EAAE,CAAA;QAC9B,MAAM,GAAG,GAAG,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC,CAAA;QACvC,MAAM,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAA;QACnC,MAAM,CAAC,cAAc,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;QAC/C,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,CAAA;IACxE,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;QAC/C,MAAM,UAAU,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAC1E,MAAM,GAAG,GAAG,OAAO,CAAC;YAClB,cAAc,EAAE,GAAG,EAAE;gBACnB,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAA;YAClC,CAAC;SACF,CAAC,CAAA;QACF,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAA;QAC/C,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC5B,UAAU,CAAC,WAAW,EAAE,CAAA;IAC1B,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-empty-object-type */
|
|
2
|
+
import { describe, expect, test } from 'vitest';
|
|
3
|
+
import { Type } from 'typebox';
|
|
4
|
+
import { Procedures } from '../../index.js';
|
|
5
|
+
import { HonoAPIAppBuilder } from './hono-api/index.js';
|
|
6
|
+
import { HonoRPCAppBuilder } from './hono-rpc/index.js';
|
|
7
|
+
import { ExpressRPCAppBuilder } from './express-rpc/index.js';
|
|
8
|
+
import { HonoStreamAppBuilder } from './hono-stream/index.js';
|
|
9
|
+
import { DocRegistry } from './doc-registry.js';
|
|
10
|
+
import { defineErrorTaxonomy } from './error-taxonomy.js';
|
|
11
|
+
class UseCaseError extends Error {
|
|
12
|
+
externalMsg;
|
|
13
|
+
constructor(externalMsg) {
|
|
14
|
+
super(externalMsg);
|
|
15
|
+
this.externalMsg = externalMsg;
|
|
16
|
+
this.name = 'UseCaseError';
|
|
17
|
+
Object.setPrototypeOf(this, UseCaseError.prototype);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
class AuthError extends Error {
|
|
21
|
+
}
|
|
22
|
+
const appErrors = defineErrorTaxonomy({
|
|
23
|
+
UseCaseError: { class: UseCaseError, statusCode: 422 },
|
|
24
|
+
AuthError: { class: AuthError, statusCode: 401 },
|
|
25
|
+
});
|
|
26
|
+
describe('per-route errors declaration', () => {
|
|
27
|
+
test('hono-api copies config.errors onto the route doc', () => {
|
|
28
|
+
const API = Procedures();
|
|
29
|
+
API.Create('GetUser', {
|
|
30
|
+
path: '/users/:id',
|
|
31
|
+
method: 'get',
|
|
32
|
+
errors: ['UseCaseError', 'AuthError'],
|
|
33
|
+
schema: {
|
|
34
|
+
input: { pathParams: Type.Object({ id: Type.String() }) },
|
|
35
|
+
returnType: Type.Object({}),
|
|
36
|
+
},
|
|
37
|
+
}, async () => ({}));
|
|
38
|
+
const builder = new HonoAPIAppBuilder().register(API, () => ({}));
|
|
39
|
+
builder.build();
|
|
40
|
+
expect(builder.docs[0].errors).toEqual(['UseCaseError', 'AuthError']);
|
|
41
|
+
});
|
|
42
|
+
test('hono-api route doc omits errors when not declared', () => {
|
|
43
|
+
const API = Procedures();
|
|
44
|
+
API.Create('Health', { path: '/health', method: 'get', schema: { returnType: Type.Object({}) } }, async () => ({}));
|
|
45
|
+
const builder = new HonoAPIAppBuilder().register(API, () => ({}));
|
|
46
|
+
builder.build();
|
|
47
|
+
expect(builder.docs[0].errors).toBeUndefined();
|
|
48
|
+
});
|
|
49
|
+
test('hono-rpc copies config.errors onto the route doc', () => {
|
|
50
|
+
const RPC = Procedures();
|
|
51
|
+
RPC.Create('DoThing', {
|
|
52
|
+
scope: 'things',
|
|
53
|
+
version: 1,
|
|
54
|
+
errors: ['UseCaseError'],
|
|
55
|
+
schema: { params: Type.Object({}) },
|
|
56
|
+
}, async () => ({}));
|
|
57
|
+
const builder = new HonoRPCAppBuilder().register(RPC, () => ({}));
|
|
58
|
+
builder.build();
|
|
59
|
+
expect(builder.docs[0].errors).toEqual(['UseCaseError']);
|
|
60
|
+
});
|
|
61
|
+
test('express-rpc copies config.errors onto the route doc', () => {
|
|
62
|
+
const RPC = Procedures();
|
|
63
|
+
RPC.Create('DoThing', {
|
|
64
|
+
scope: 'things',
|
|
65
|
+
version: 1,
|
|
66
|
+
errors: ['AuthError'],
|
|
67
|
+
schema: { params: Type.Object({}) },
|
|
68
|
+
}, async () => ({}));
|
|
69
|
+
const builder = new ExpressRPCAppBuilder().register(RPC, () => ({}));
|
|
70
|
+
builder.build();
|
|
71
|
+
expect(builder.docs[0].errors).toEqual(['AuthError']);
|
|
72
|
+
});
|
|
73
|
+
test('hono-stream copies config.errors onto the route doc', () => {
|
|
74
|
+
const Stream = Procedures();
|
|
75
|
+
Stream.CreateStream('Watch', { scope: 'watch', version: 1, errors: ['AuthError'] }, async function* () {
|
|
76
|
+
yield { ok: true };
|
|
77
|
+
});
|
|
78
|
+
const builder = new HonoStreamAppBuilder().register(Stream, () => ({}));
|
|
79
|
+
builder.build();
|
|
80
|
+
expect(builder.docs[0].errors).toEqual(['AuthError']);
|
|
81
|
+
});
|
|
82
|
+
test('compile-time: errors typed as keyof taxonomy narrows valid keys', () => {
|
|
83
|
+
const _valid = ['UseCaseError', 'AuthError'];
|
|
84
|
+
// @ts-expect-error - 'NotRegistered' is not in the taxonomy
|
|
85
|
+
const _invalid = ['NotRegistered'];
|
|
86
|
+
expect(_valid).toBeDefined();
|
|
87
|
+
expect(_invalid).toBeDefined();
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
describe('DocRegistry with taxonomy input', () => {
|
|
91
|
+
test('seeds envelope errors from the taxonomy + framework defaults', () => {
|
|
92
|
+
const registry = new DocRegistry({ errors: appErrors, basePath: '/api' });
|
|
93
|
+
const envelope = registry.toJSON();
|
|
94
|
+
const names = envelope.errors.map((e) => e.name);
|
|
95
|
+
expect(names).toContain('UseCaseError');
|
|
96
|
+
expect(names).toContain('AuthError');
|
|
97
|
+
expect(names).toContain('ProcedureValidationError');
|
|
98
|
+
expect(names).toContain('ProcedureRegistrationError');
|
|
99
|
+
expect(envelope.basePath).toBe('/api');
|
|
100
|
+
});
|
|
101
|
+
test('includeDefaults: false omits framework entries', () => {
|
|
102
|
+
const registry = new DocRegistry({ errors: appErrors, includeDefaults: false });
|
|
103
|
+
const names = registry.toJSON().errors.map((e) => e.name);
|
|
104
|
+
expect(names).toEqual(['UseCaseError', 'AuthError']);
|
|
105
|
+
});
|
|
106
|
+
test('user entry with same key as default takes precedence (deduped)', () => {
|
|
107
|
+
const overridden = defineErrorTaxonomy({
|
|
108
|
+
ProcedureError: {
|
|
109
|
+
class: Error,
|
|
110
|
+
statusCode: 418,
|
|
111
|
+
description: 'custom override',
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
const envelope = new DocRegistry({ errors: overridden }).toJSON();
|
|
115
|
+
const proc = envelope.errors.find((e) => e.name === 'ProcedureError');
|
|
116
|
+
expect(proc?.statusCode).toBe(418);
|
|
117
|
+
expect(proc?.description).toBe('custom override');
|
|
118
|
+
const count = envelope.errors.filter((e) => e.name === 'ProcedureError').length;
|
|
119
|
+
expect(count).toBe(1);
|
|
120
|
+
});
|
|
121
|
+
test('registered route errors survive DocRegistry composition', () => {
|
|
122
|
+
const API = Procedures();
|
|
123
|
+
API.Create('GetUser', {
|
|
124
|
+
path: '/users/:id',
|
|
125
|
+
method: 'get',
|
|
126
|
+
errors: ['UseCaseError'],
|
|
127
|
+
schema: {
|
|
128
|
+
input: { pathParams: Type.Object({ id: Type.String() }) },
|
|
129
|
+
returnType: Type.Object({}),
|
|
130
|
+
},
|
|
131
|
+
}, async () => ({}));
|
|
132
|
+
const app = new HonoAPIAppBuilder().register(API, () => ({}));
|
|
133
|
+
app.build();
|
|
134
|
+
const envelope = new DocRegistry({ errors: appErrors }).from(app).toJSON();
|
|
135
|
+
const route = envelope.routes.find((r) => r.kind === 'api' && r.name === 'GetUser');
|
|
136
|
+
expect(route?.errors).toEqual(['UseCaseError']);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
//# sourceMappingURL=route-errors.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-errors.test.js","sourceRoot":"","sources":["../../../src/implementations/http/route-errors.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
import { Procedures } from '../index.js';
|
|
2
|
-
|
|
2
|
+
import type { ErrorTaxonomy } from './http/error-taxonomy.js';
|
|
3
|
+
/**
|
|
4
|
+
* @typeParam TErrorKey - Union of valid taxonomy keys. Defaults to `string`
|
|
5
|
+
* (unconstrained). Narrow it by passing `keyof typeof yourTaxonomy & string`
|
|
6
|
+
* to get compile-time typo protection on `errors`.
|
|
7
|
+
*/
|
|
8
|
+
export interface RPCConfig<TErrorKey extends string = string> {
|
|
3
9
|
scope: string | string[];
|
|
4
10
|
version: number;
|
|
11
|
+
/**
|
|
12
|
+
* Taxonomy keys for errors this procedure may emit. Purely informational at
|
|
13
|
+
* runtime (nothing is rejected), but populates the DocEnvelope per-route
|
|
14
|
+
* error list so generated clients can narrow their catch types.
|
|
15
|
+
*/
|
|
16
|
+
errors?: TErrorKey[];
|
|
5
17
|
}
|
|
6
18
|
export type FactoryItem<C> = {
|
|
7
19
|
factory: ReturnType<typeof Procedures<C, RPCConfig>>;
|
|
@@ -16,10 +28,17 @@ export interface RPCHttpRouteDoc extends RPCConfig {
|
|
|
16
28
|
body?: Record<string, unknown>;
|
|
17
29
|
response?: Record<string, unknown>;
|
|
18
30
|
};
|
|
31
|
+
/** Taxonomy keys for errors this route may emit. */
|
|
32
|
+
errors?: string[];
|
|
19
33
|
}
|
|
20
34
|
export type StreamMode = 'sse' | 'text';
|
|
21
35
|
export type HttpMethod = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head';
|
|
22
|
-
|
|
36
|
+
/**
|
|
37
|
+
* @typeParam TErrorKey - Union of valid taxonomy keys. Defaults to `string`.
|
|
38
|
+
* Narrow it by passing `keyof typeof yourTaxonomy & string` for compile-time
|
|
39
|
+
* typo protection on `errors`.
|
|
40
|
+
*/
|
|
41
|
+
export interface APIConfig<TErrorKey extends string = string> {
|
|
23
42
|
/** HTTP route path (supports Hono path params, e.g., '/users/:id') */
|
|
24
43
|
path: string;
|
|
25
44
|
/** HTTP method for this endpoint */
|
|
@@ -28,6 +47,12 @@ export interface APIConfig {
|
|
|
28
47
|
successStatus?: number;
|
|
29
48
|
/** Optional scope for grouping API routes in generated client files */
|
|
30
49
|
scope?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Taxonomy keys for errors this procedure may emit. Purely informational at
|
|
52
|
+
* runtime (nothing is rejected), but populates the DocEnvelope per-route
|
|
53
|
+
* error list so generated clients can narrow their catch types.
|
|
54
|
+
*/
|
|
55
|
+
errors?: TErrorKey[];
|
|
31
56
|
}
|
|
32
57
|
export interface APIHttpRouteDoc extends APIConfig {
|
|
33
58
|
kind: 'api';
|
|
@@ -41,6 +66,8 @@ export interface APIHttpRouteDoc extends APIConfig {
|
|
|
41
66
|
headers?: Record<string, unknown>;
|
|
42
67
|
response?: Record<string, unknown>;
|
|
43
68
|
};
|
|
69
|
+
/** Taxonomy keys for errors this route may emit. */
|
|
70
|
+
errors?: string[];
|
|
44
71
|
}
|
|
45
72
|
/**
|
|
46
73
|
* Constrains schema.input channel names to valid HTTP input sources.
|
|
@@ -76,6 +103,8 @@ export interface StreamHttpRouteDoc extends RPCConfig {
|
|
|
76
103
|
yieldType?: Record<string, unknown>;
|
|
77
104
|
returnType?: Record<string, unknown>;
|
|
78
105
|
};
|
|
106
|
+
/** Taxonomy keys for errors this route may emit (pre-stream only). */
|
|
107
|
+
errors?: string[];
|
|
79
108
|
}
|
|
80
109
|
/**
|
|
81
110
|
* Extracts the TContext type from a Procedures factory return type.
|
|
@@ -128,7 +157,18 @@ export interface ErrorDoc {
|
|
|
128
157
|
export interface DocRegistryConfig {
|
|
129
158
|
basePath?: string;
|
|
130
159
|
headers?: HeaderDoc[];
|
|
131
|
-
|
|
160
|
+
/**
|
|
161
|
+
* Errors to document in the envelope. Accepts either your runtime
|
|
162
|
+
* {@link ErrorTaxonomy} (from `defineErrorTaxonomy`) — the common case — or
|
|
163
|
+
* a raw `ErrorDoc[]` for consumers who aren't using a taxonomy.
|
|
164
|
+
*
|
|
165
|
+
* Framework defaults (`ProcedureError`, `ProcedureValidationError`,
|
|
166
|
+
* `ProcedureYieldValidationError`, `ProcedureRegistrationError`) are merged
|
|
167
|
+
* in automatically and deduped. Opt out via `includeDefaults: false`.
|
|
168
|
+
*/
|
|
169
|
+
errors?: ErrorTaxonomy | ErrorDoc[];
|
|
170
|
+
/** Whether to auto-merge framework error defaults. Defaults to `true`. */
|
|
171
|
+
includeDefaults?: boolean;
|
|
132
172
|
}
|
|
133
173
|
export interface DocRegistryOutputOptions<TEnvelope = DocEnvelope> {
|
|
134
174
|
filter?: (route: AnyHttpRouteDoc) => boolean;
|
|
@@ -20,14 +20,14 @@ npx ts-procedures-codegen --url http://localhost:3000/docs --out ./src/generated
|
|
|
20
20
|
|
|
21
21
|
**Step 3 — Use the client:**
|
|
22
22
|
|
|
23
|
+
The recommended entrypoint is the generated `create${Service}Client` factory. It calls `createClient` under the hood with the generated error registry pre-wired, so non-2xx responses arrive as typed class instances you can catch with `instanceof`.
|
|
24
|
+
|
|
23
25
|
```typescript
|
|
24
|
-
import {
|
|
25
|
-
import { createApiBindings, Api } from './generated/api'
|
|
26
|
+
import { createApiClient, ApiErrors, createFetchAdapter } from './generated/api'
|
|
26
27
|
|
|
27
|
-
const
|
|
28
|
+
const api = createApiClient({
|
|
28
29
|
adapter: createFetchAdapter(),
|
|
29
30
|
basePath: 'http://localhost:3000',
|
|
30
|
-
scopes: createApiBindings,
|
|
31
31
|
hooks: {
|
|
32
32
|
onBeforeRequest(ctx) {
|
|
33
33
|
ctx.request.headers = { ...ctx.request.headers, Authorization: `Bearer ${getToken()}` }
|
|
@@ -36,11 +36,32 @@ const client = createClient({
|
|
|
36
36
|
},
|
|
37
37
|
})
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
const user = await
|
|
39
|
+
try {
|
|
40
|
+
const user = await api.users.GetUser({ pathParams: { id: '123' } })
|
|
41
|
+
} catch (err) {
|
|
42
|
+
if (err instanceof ApiErrors.UseCaseError) {
|
|
43
|
+
// err.body, err.status, err.procedureName, err.scope all typed
|
|
44
|
+
} else if (err instanceof ApiErrors.ApiProcedureError) {
|
|
45
|
+
// Catch-all for any service error (shared base class)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
41
48
|
|
|
42
|
-
// Types live under the service namespace: Api.Users.GetUser.Params, Api.Errors.
|
|
43
|
-
// Pass --service-name <Name> to rename `Api` → `<Name>`
|
|
49
|
+
// Types live under the service namespace: Api.Users.GetUser.Params, Api.Errors.UseCaseError, etc.
|
|
50
|
+
// Pass --service-name <Name> to rename `Api` → `<Name>` throughout.
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
For advanced control (sharing one `ClientInstance` across services, composing with a custom registry), use `createClient` + `create${Service}Bindings` directly:
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { createClient, createFetchAdapter } from 'ts-procedures/client'
|
|
57
|
+
import { createApiBindings, ApiErrors } from './generated/api'
|
|
58
|
+
|
|
59
|
+
const api = createClient({
|
|
60
|
+
adapter: createFetchAdapter(),
|
|
61
|
+
basePath: 'http://localhost:3000',
|
|
62
|
+
scopes: createApiBindings,
|
|
63
|
+
errorRegistry: ApiErrors.ApiErrorRegistry, // opt in to typed dispatch — omit to get the plain ClientRequestError transport shape
|
|
64
|
+
})
|
|
44
65
|
```
|
|
45
66
|
|
|
46
67
|
## Generated File Structure
|
|
@@ -54,8 +75,8 @@ generated/
|
|
|
54
75
|
notifications.ts # Types + callables for stream procedures
|
|
55
76
|
_types.ts # Client type definitions (self-contained mode)
|
|
56
77
|
_client.ts # Client runtime bundle (self-contained mode)
|
|
57
|
-
_errors.ts #
|
|
58
|
-
index.ts # Service namespace
|
|
78
|
+
_errors.ts # Runtime error classes extending ${ServiceName}ProcedureError + static fromResponse + ${ServiceName}ErrorRegistry + ${ServiceName}ProcedureErrorUnion (default: ApiProcedureError / ApiErrorRegistry / ApiProcedureErrorUnion)
|
|
79
|
+
index.ts # Service namespace + create${ServiceName}Bindings (manual wiring) and create${ServiceName}Client (convenience; registry pre-wired). Default: Api / createApiBindings / createApiClient.
|
|
59
80
|
```
|
|
60
81
|
|
|
61
82
|
## CLI Reference
|
|
@@ -217,6 +238,68 @@ await client.users.GetUser(
|
|
|
217
238
|
|
|
218
239
|
If `RequestMeta` declares required fields, the merged meta (defaults + per-call) must contain them at runtime. TypeScript can't statically verify this across the merge boundary, so supply required fields in `defaults.meta` or per-call `options.meta`.
|
|
219
240
|
|
|
241
|
+
## Typed Error Handling
|
|
242
|
+
|
|
243
|
+
Non-2xx responses whose body has a `name` field matching a registry key are dispatched into typed class instances. The generated `_errors.ts` exports:
|
|
244
|
+
|
|
245
|
+
- A shared base class `${ServiceName}ProcedureError<TBody>` — carries `status`, `procedureName`, `scope`, and `body`. Catch any service error with `instanceof ${ServiceName}Errors.${ServiceName}ProcedureError`.
|
|
246
|
+
- One concrete class per taxonomy entry in the envelope, each with a static `fromResponse(body, meta)` factory.
|
|
247
|
+
- `${ServiceName}ErrorRegistry` — a `{ [name]: ErrorClass }` object consumed by the client's `dispatchTypedError`.
|
|
248
|
+
- `${ServiceName}ProcedureErrorUnion` — a type union of every generated class for annotating catch clauses.
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
import { createApiClient, ApiErrors } from './generated/api'
|
|
252
|
+
|
|
253
|
+
const api = createApiClient({ adapter, basePath: '...' })
|
|
254
|
+
|
|
255
|
+
try {
|
|
256
|
+
await api.users.GetUser({ pathParams: { id: 'x' } })
|
|
257
|
+
} catch (err) {
|
|
258
|
+
if (err instanceof ApiErrors.UseCaseError) {
|
|
259
|
+
// err.body is typed to UseCaseErrorBody; err.status, err.procedureName, err.scope available
|
|
260
|
+
} else if (err instanceof ApiErrors.ApiProcedureError) {
|
|
261
|
+
// Catch-all for any generated service error
|
|
262
|
+
} else if (err instanceof ClientRequestError) {
|
|
263
|
+
// Transport-level error (unmatched body.name, or non-JSON response)
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Per-route error narrowing
|
|
269
|
+
|
|
270
|
+
When a server route declares `errors: ['UseCaseError', 'AuthError']` on its config, the generated scope file emits an `Errors` type union inside that route's namespace:
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
// Generated scope file:
|
|
274
|
+
export namespace Users {
|
|
275
|
+
export namespace GetUser {
|
|
276
|
+
export type Params = { /* ... */ }
|
|
277
|
+
export type Response = { /* ... */ }
|
|
278
|
+
export type Errors = ApiErrors.UseCaseError | ApiErrors.AuthError
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Consumer:
|
|
283
|
+
try { await api.users.GetUser({ pathParams: { id: 'x' } }) }
|
|
284
|
+
catch (err) {
|
|
285
|
+
const e = err as Users.GetUser.Errors | ClientRequestError // TS has no typed-throws; manual annotation
|
|
286
|
+
if (e instanceof ApiErrors.UseCaseError) { /* ... */ }
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Route-errors that reference keys missing from `_errors.ts` are filtered out at codegen time so generated code never references undefined types.
|
|
291
|
+
|
|
292
|
+
### How dispatch works
|
|
293
|
+
|
|
294
|
+
`src/client/error-dispatch.ts` exports a pure `dispatchTypedError(registry, body, meta)` helper. The client's `call.ts` invokes it on non-2xx responses:
|
|
295
|
+
|
|
296
|
+
1. If no registry, or body isn't an object with a string `name`, or no registry key matches → returns `null`.
|
|
297
|
+
2. Otherwise calls `registry[body.name].fromResponse(body, meta)` and returns the typed `Error` instance.
|
|
298
|
+
|
|
299
|
+
When the helper returns `null`, the call falls back to `ClientRequestError` — the plain transport-error shape, used for unmatched names, non-JSON bodies, and when no registry is configured.
|
|
300
|
+
|
|
301
|
+
Stream endpoints get the same treatment for **pre-stream** errors (thrown before the first yield — e.g. validation or auth). The fetch adapter's `stream()` eagerly parses a JSON body when status is non-2xx and exposes it via `AdapterStreamResponse.errorBody`, which `executeStream` passes through the registry. **Mid-stream** SSE error events continue to flow through `onMidStreamError` on the server and re-throw on the client without registry dispatch.
|
|
302
|
+
|
|
220
303
|
## Hooks
|
|
221
304
|
|
|
222
305
|
Hooks let you intercept requests and responses globally or per-procedure call. Global hooks apply to every call made through the client instance; per-procedure hooks run after global ones for a single invocation.
|
|
@@ -307,12 +390,22 @@ import { createClient, createFetchAdapter } from './generated/_client'
|
|
|
307
390
|
import { createClient, createFetchAdapter } from 'ts-procedures/client'
|
|
308
391
|
```
|
|
309
392
|
|
|
393
|
+
- **`_client.ts`** also bundles `error-dispatch.ts`, so registry-based typed error dispatch works without importing `ts-procedures/client` at runtime.
|
|
394
|
+
|
|
310
395
|
## Type Exports
|
|
311
396
|
|
|
312
397
|
```typescript
|
|
313
398
|
// Client Runtime
|
|
314
|
-
import { createClient, createFetchAdapter } from 'ts-procedures/client'
|
|
315
|
-
import type {
|
|
399
|
+
import { createClient, createFetchAdapter, dispatchTypedError } from 'ts-procedures/client'
|
|
400
|
+
import type {
|
|
401
|
+
ClientAdapter,
|
|
402
|
+
ClientHooks,
|
|
403
|
+
TypedStream,
|
|
404
|
+
ClientInstance,
|
|
405
|
+
ErrorRegistry,
|
|
406
|
+
ErrorFactory,
|
|
407
|
+
ErrorResponseMeta,
|
|
408
|
+
} from 'ts-procedures/client'
|
|
316
409
|
|
|
317
410
|
// Code Generation
|
|
318
411
|
import { generateClient } from 'ts-procedures/codegen'
|
package/docs/core.md
CHANGED
|
@@ -31,7 +31,7 @@ Create(name, config, handler)
|
|
|
31
31
|
**Returns:**
|
|
32
32
|
- `{ [name]: handler }` - Named export for the handler
|
|
33
33
|
- `procedure` - Generic reference to the handler
|
|
34
|
-
- `info` - Procedure
|
|
34
|
+
- `info` - Procedure metadata (name, description, schema, `TExtendedConfig` properties, etc.)
|
|
35
35
|
|
|
36
36
|
## Structured Input with schema.input
|
|
37
37
|
|
|
@@ -234,7 +234,8 @@ Create(
|
|
|
234
234
|
async (ctx, params) => {
|
|
235
235
|
const resource = await db.find(params.id)
|
|
236
236
|
if (!resource) {
|
|
237
|
-
|
|
237
|
+
// Signature: ctx.error(message: string, meta?: object) => ProcedureError
|
|
238
|
+
throw ctx.error('Resource not found', { code: 'NOT_FOUND', id: params.id })
|
|
238
239
|
}
|
|
239
240
|
return resource
|
|
240
241
|
},
|
|
@@ -249,6 +250,7 @@ Create(
|
|
|
249
250
|
| ProcedureValidationError | Schema validation failure (params) |
|
|
250
251
|
| ProcedureYieldValidationError | Yield validation failure (streaming with `validateYields: true`) |
|
|
251
252
|
| ProcedureRegistrationError | Invalid schema at registration |
|
|
253
|
+
| `${Service}ProcedureError` (client-side) | Base class for every generated error class on the client — see [Client & Codegen → Typed Error Handling](./client-and-codegen.md#typed-error-handling) |
|
|
252
254
|
|
|
253
255
|
### Error Properties
|
|
254
256
|
|
|
@@ -264,6 +266,12 @@ try {
|
|
|
264
266
|
}
|
|
265
267
|
```
|
|
266
268
|
|
|
269
|
+
### Error Taxonomy (HTTP builders)
|
|
270
|
+
|
|
271
|
+
For structured HTTP error responses, declare an error taxonomy once with `defineErrorTaxonomy` and pass it to any HTTP builder via the `errors` option — handlers `throw` their classes and the builder serializes to the configured status + body. `ctx.error()` continues to work as the ad-hoc ProcedureError path.
|
|
272
|
+
|
|
273
|
+
The taxonomy also drives typed `catch` blocks on generated clients and per-route error documentation. See [HTTP Integrations → Error Handling](./http-integrations.md#error-handling) for the full contract, and [Client & Codegen → Typed Error Handling](./client-and-codegen.md#typed-error-handling) for the client-side surface.
|
|
274
|
+
|
|
267
275
|
## Abort Signal
|
|
268
276
|
|
|
269
277
|
For regular procedures, `ctx.signal` is available when the server implementation provides it. The built-in HTTP integrations (Hono RPC, Express RPC) inject the request's abort signal automatically:
|
|
@@ -394,10 +402,11 @@ describe('GetUser', () => {
|
|
|
394
402
|
})
|
|
395
403
|
|
|
396
404
|
test('has correct schema', () => {
|
|
405
|
+
// `info.schema.params` is the JSON Schema derived from the TypeBox
|
|
406
|
+
// definition above: `Type.Object({ hideName: Type.Optional(Type.Boolean()) })`.
|
|
397
407
|
expect(info.schema.params).toEqual({
|
|
398
408
|
type: 'object',
|
|
399
|
-
properties: {
|
|
400
|
-
required: ['id'],
|
|
409
|
+
properties: { hideName: { type: 'boolean' } },
|
|
401
410
|
})
|
|
402
411
|
})
|
|
403
412
|
})
|
|
@@ -431,7 +440,7 @@ Defines a procedure.
|
|
|
431
440
|
**Returns:**
|
|
432
441
|
- `{ [name]: handler }` - Named handler export
|
|
433
442
|
- `procedure` - Generic handler reference
|
|
434
|
-
- `info` - Procedure
|
|
443
|
+
- `info` - Procedure metadata (name, description, schema, extended-config properties)
|
|
435
444
|
|
|
436
445
|
### Type Exports
|
|
437
446
|
|