ts-procedures 7.2.0 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -3
- package/agent_config/claude-code/agents/ts-procedures-architect.md +6 -8
- package/agent_config/claude-code/skills/ts-procedures/SKILL.md +30 -33
- package/agent_config/claude-code/skills/ts-procedures/anti-patterns.md +139 -53
- package/agent_config/claude-code/skills/ts-procedures/api-reference.md +208 -231
- package/agent_config/claude-code/skills/ts-procedures/patterns.md +80 -153
- package/agent_config/claude-code/skills/ts-procedures-review/SKILL.md +1 -1
- package/agent_config/claude-code/skills/ts-procedures-review/checklist.md +4 -5
- package/agent_config/claude-code/skills/ts-procedures-scaffold/SKILL.md +4 -7
- package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/hono.md +223 -0
- package/agent_config/copilot/copilot-instructions.md +36 -48
- package/agent_config/cursor/cursorrules +36 -48
- package/build/client/call.js +4 -1
- package/build/client/call.js.map +1 -1
- package/build/client/call.test.js +23 -0
- package/build/client/call.test.js.map +1 -1
- package/build/client/fetch-adapter.js +3 -1
- package/build/client/fetch-adapter.js.map +1 -1
- package/build/client/fetch-adapter.test.js +11 -1
- package/build/client/fetch-adapter.test.js.map +1 -1
- package/build/client/index.test.js +7 -7
- package/build/client/index.test.js.map +1 -1
- package/build/client/request-builder.d.ts +1 -1
- package/build/client/request-builder.js +2 -2
- package/build/client/request-builder.js.map +1 -1
- package/build/client/stream.js +13 -2
- package/build/client/stream.js.map +1 -1
- package/build/client/stream.test.js +32 -7
- package/build/client/stream.test.js.map +1 -1
- package/build/client/typed-error-dispatch.test.js +8 -92
- package/build/client/typed-error-dispatch.test.js.map +1 -1
- package/build/client/types.d.ts +21 -3
- package/build/codegen/bin/cli.js +0 -0
- package/build/codegen/e2e.test.js +87 -23
- package/build/codegen/e2e.test.js.map +1 -1
- package/build/codegen/emit-errors.integration.test.js +1 -1
- package/build/codegen/emit-errors.integration.test.js.map +1 -1
- package/build/codegen/emit-scope.js +308 -47
- package/build/codegen/emit-scope.js.map +1 -1
- package/build/codegen/emit-scope.test.js +363 -110
- package/build/codegen/emit-scope.test.js.map +1 -1
- package/build/codegen/pipeline.test.js +7 -7
- package/build/codegen/pipeline.test.js.map +1 -1
- package/build/codegen/resolve-envelope.js +1 -1
- package/build/codegen/resolve-envelope.js.map +1 -1
- package/build/codegen/resolve-envelope.test.js +5 -5
- package/build/codegen/resolve-envelope.test.js.map +1 -1
- package/build/codegen/targets/_shared/route-slots.d.ts +8 -3
- package/build/codegen/targets/_shared/route-slots.js +49 -8
- package/build/codegen/targets/_shared/route-slots.js.map +1 -1
- package/build/codegen/targets/_shared/route-slots.test.js +99 -26
- package/build/codegen/targets/_shared/route-slots.test.js.map +1 -1
- package/build/codegen/targets/kotlin/emit-route-kotlin.test.js +88 -17
- package/build/codegen/targets/kotlin/emit-route-kotlin.test.js.map +1 -1
- package/build/codegen/targets/kotlin/emit-scope-kotlin.test.js +9 -6
- package/build/codegen/targets/kotlin/emit-scope-kotlin.test.js.map +1 -1
- package/build/codegen/targets/kotlin/integration.test.js +6 -0
- package/build/codegen/targets/kotlin/integration.test.js.map +1 -1
- package/build/codegen/targets/swift/access-level.test.js +8 -11
- package/build/codegen/targets/swift/access-level.test.js.map +1 -1
- package/build/codegen/targets/swift/emit-route-swift.test.js +91 -20
- package/build/codegen/targets/swift/emit-route-swift.test.js.map +1 -1
- package/build/codegen/targets/swift/emit-scope-swift.test.js +12 -9
- package/build/codegen/targets/swift/emit-scope-swift.test.js.map +1 -1
- package/build/codegen/targets/swift/integration.test.js +6 -0
- package/build/codegen/targets/swift/integration.test.js.map +1 -1
- package/build/create-http-stream.d.ts +58 -0
- package/build/create-http-stream.js +122 -0
- package/build/create-http-stream.js.map +1 -0
- package/build/create-http-stream.test.js +88 -0
- package/build/create-http-stream.test.js.map +1 -0
- package/build/create-http.d.ts +49 -0
- package/build/create-http.js +108 -0
- package/build/create-http.js.map +1 -0
- package/build/create-http.test.js +137 -0
- package/build/create-http.test.js.map +1 -0
- package/build/create-stream.d.ts +35 -0
- package/build/create-stream.js +123 -0
- package/build/create-stream.js.map +1 -0
- package/build/create-stream.test.js +428 -0
- package/build/create-stream.test.js.map +1 -0
- package/build/create.d.ts +28 -0
- package/build/create.js +82 -0
- package/build/create.js.map +1 -0
- package/build/create.test.js +483 -0
- package/build/create.test.js.map +1 -0
- package/build/exports.d.ts +2 -0
- package/build/implementations/http/astro/index.test.js +20 -12
- package/build/implementations/http/astro/index.test.js.map +1 -1
- package/build/implementations/http/doc-registry.js +1 -1
- package/build/implementations/http/doc-registry.js.map +1 -1
- package/build/implementations/http/doc-registry.test.js +36 -5
- package/build/implementations/http/doc-registry.test.js.map +1 -1
- package/build/implementations/http/error-dispatch.d.ts +76 -0
- package/build/implementations/http/error-dispatch.js +77 -0
- package/build/implementations/http/error-dispatch.js.map +1 -0
- package/build/implementations/http/error-dispatch.test.js +254 -0
- package/build/implementations/http/error-dispatch.test.js.map +1 -0
- package/build/implementations/http/error-taxonomy.d.ts +5 -5
- package/build/implementations/http/hono/docs/http-doc.d.ts +6 -0
- package/build/implementations/http/hono/docs/http-doc.js +42 -0
- package/build/implementations/http/hono/docs/http-doc.js.map +1 -0
- package/build/implementations/http/hono/docs/http-stream-doc.d.ts +6 -0
- package/build/implementations/http/hono/docs/http-stream-doc.js +40 -0
- package/build/implementations/http/hono/docs/http-stream-doc.js.map +1 -0
- package/build/implementations/http/hono/docs/rpc-doc.d.ts +6 -0
- package/build/implementations/http/hono/docs/rpc-doc.js +24 -0
- package/build/implementations/http/hono/docs/rpc-doc.js.map +1 -0
- package/build/implementations/http/hono/docs/stream-doc.d.ts +6 -0
- package/build/implementations/http/hono/docs/stream-doc.js +42 -0
- package/build/implementations/http/hono/docs/stream-doc.js.map +1 -0
- package/build/implementations/http/hono/handlers/http-stream.d.ts +10 -0
- package/build/implementations/http/hono/handlers/http-stream.js +123 -0
- package/build/implementations/http/hono/handlers/http-stream.js.map +1 -0
- package/build/implementations/http/hono/handlers/http-stream.test.js +128 -0
- package/build/implementations/http/hono/handlers/http-stream.test.js.map +1 -0
- package/build/implementations/http/hono/handlers/http.d.ts +10 -0
- package/build/implementations/http/hono/handlers/http.js +115 -0
- package/build/implementations/http/hono/handlers/http.js.map +1 -0
- package/build/implementations/http/hono/handlers/http.test.js +118 -0
- package/build/implementations/http/hono/handlers/http.test.js.map +1 -0
- package/build/implementations/http/hono/handlers/rpc.d.ts +11 -0
- package/build/implementations/http/hono/handlers/rpc.js +32 -0
- package/build/implementations/http/hono/handlers/rpc.js.map +1 -0
- package/build/implementations/http/hono/handlers/rpc.test.js +73 -0
- package/build/implementations/http/hono/handlers/rpc.test.js.map +1 -0
- package/build/implementations/http/hono/handlers/stream.d.ts +23 -0
- package/build/implementations/http/hono/handlers/stream.js +147 -0
- package/build/implementations/http/hono/handlers/stream.js.map +1 -0
- package/build/implementations/http/hono/handlers/stream.test.d.ts +1 -0
- package/build/implementations/http/hono/handlers/stream.test.js +177 -0
- package/build/implementations/http/hono/handlers/stream.test.js.map +1 -0
- package/build/implementations/http/hono/index.d.ts +57 -0
- package/build/implementations/http/hono/index.js +149 -0
- package/build/implementations/http/hono/index.js.map +1 -0
- package/build/implementations/http/hono/index.test.d.ts +1 -0
- package/build/implementations/http/hono/index.test.js +274 -0
- package/build/implementations/http/hono/index.test.js.map +1 -0
- package/build/implementations/http/hono/path.d.ts +17 -0
- package/build/implementations/http/hono/path.js +39 -0
- package/build/implementations/http/hono/path.js.map +1 -0
- package/build/implementations/http/hono/path.test.d.ts +1 -0
- package/build/implementations/http/hono/path.test.js +83 -0
- package/build/implementations/http/hono/path.test.js.map +1 -0
- package/build/implementations/http/hono/types.d.ts +51 -0
- package/build/implementations/http/hono/types.js.map +1 -0
- package/build/implementations/http/on-request-error.test.js +6 -96
- package/build/implementations/http/on-request-error.test.js.map +1 -1
- package/build/implementations/http/route-errors.test.js +11 -59
- package/build/implementations/http/route-errors.test.js.map +1 -1
- package/build/implementations/types.d.ts +43 -9
- package/build/index.d.ts +125 -115
- package/build/index.js +10 -222
- package/build/index.js.map +1 -1
- package/build/index.test.js +30 -822
- package/build/index.test.js.map +1 -1
- package/build/migration.test.d.ts +1 -0
- package/build/migration.test.js +34 -0
- package/build/migration.test.js.map +1 -0
- package/build/schema/compute-schema.d.ts +11 -3
- package/build/schema/compute-schema.js +13 -7
- package/build/schema/compute-schema.js.map +1 -1
- package/build/schema/parser.d.ts +11 -3
- package/build/schema/parser.js +49 -9
- package/build/schema/parser.js.map +1 -1
- package/build/stack-utils.js +8 -0
- package/build/stack-utils.js.map +1 -1
- package/build/types.d.ts +142 -0
- package/build/types.js.map +1 -0
- package/docs/astro-adapter.md +5 -5
- package/docs/core.md +34 -17
- package/docs/http-integrations.md +83 -170
- package/docs/streaming.md +3 -60
- package/docs/superpowers/plans/2026-05-07-astro-adapter.md +2 -7
- package/docs/superpowers/plans/2026-05-08-create-http.md +3355 -0
- package/docs/superpowers/plans/2026-05-08-hono-app-builder-convergence.md +3365 -0
- package/docs/superpowers/specs/2026-05-07-astro-adapter-design.md +1 -3
- package/docs/superpowers/specs/2026-05-08-create-http-design.md +409 -0
- package/docs/superpowers/specs/2026-05-08-hono-app-builder-convergence-design.md +411 -0
- package/package.json +4 -22
- package/src/client/call.test.ts +26 -0
- package/src/client/call.ts +4 -1
- package/src/client/fetch-adapter.test.ts +14 -1
- package/src/client/fetch-adapter.ts +3 -1
- package/src/client/index.test.ts +7 -7
- package/src/client/request-builder.ts +2 -2
- package/src/client/stream.test.ts +39 -7
- package/src/client/stream.ts +16 -2
- package/src/client/typed-error-dispatch.test.ts +7 -97
- package/src/client/types.ts +21 -3
- package/src/codegen/__fixtures__/users-envelope.json +119 -38
- package/src/codegen/e2e.test.ts +98 -24
- package/src/codegen/emit-errors.integration.test.ts +1 -1
- package/src/codegen/emit-scope.test.ts +395 -110
- package/src/codegen/emit-scope.ts +350 -55
- package/src/codegen/pipeline.test.ts +7 -7
- package/src/codegen/resolve-envelope.test.ts +5 -5
- package/src/codegen/resolve-envelope.ts +1 -1
- package/src/codegen/targets/_shared/route-slots.test.ts +109 -26
- package/src/codegen/targets/_shared/route-slots.ts +48 -11
- package/src/codegen/targets/kotlin/__fixtures__/users-golden.kt +73 -0
- package/src/codegen/targets/kotlin/emit-route-kotlin.test.ts +100 -17
- package/src/codegen/targets/kotlin/emit-scope-kotlin.test.ts +9 -6
- package/src/codegen/targets/kotlin/integration.test.ts +19 -0
- package/src/codegen/targets/swift/__fixtures__/users-golden.swift +79 -0
- package/src/codegen/targets/swift/access-level.test.ts +8 -11
- package/src/codegen/targets/swift/emit-route-swift.test.ts +103 -20
- package/src/codegen/targets/swift/emit-scope-swift.test.ts +12 -9
- package/src/codegen/targets/swift/integration.test.ts +17 -0
- package/src/create-http-stream.test.ts +97 -0
- package/src/create-http-stream.ts +191 -0
- package/src/create-http.test.ts +163 -0
- package/src/create-http.ts +211 -0
- package/src/create-stream.test.ts +565 -0
- package/src/create-stream.ts +228 -0
- package/src/create.test.ts +658 -0
- package/src/create.ts +172 -0
- package/src/exports.ts +2 -0
- package/src/implementations/http/README.md +135 -95
- package/src/implementations/http/astro/README.md +4 -5
- package/src/implementations/http/astro/index.test.ts +25 -18
- package/src/implementations/http/doc-registry.test.ts +42 -5
- package/src/implementations/http/doc-registry.ts +1 -1
- package/src/implementations/http/error-dispatch.test.ts +283 -0
- package/src/implementations/http/error-dispatch.ts +176 -0
- package/src/implementations/http/error-taxonomy.ts +5 -5
- package/src/implementations/http/hono/docs/http-doc.ts +43 -0
- package/src/implementations/http/hono/docs/http-stream-doc.ts +44 -0
- package/src/implementations/http/hono/docs/rpc-doc.ts +34 -0
- package/src/implementations/http/hono/docs/stream-doc.ts +53 -0
- package/src/implementations/http/hono/handlers/http-stream.test.ts +150 -0
- package/src/implementations/http/hono/handlers/http-stream.ts +152 -0
- package/src/implementations/http/hono/handlers/http.test.ts +130 -0
- package/src/implementations/http/hono/handlers/http.ts +147 -0
- package/src/implementations/http/hono/handlers/rpc.test.ts +81 -0
- package/src/implementations/http/hono/handlers/rpc.ts +54 -0
- package/src/implementations/http/hono/handlers/stream.test.ts +198 -0
- package/src/implementations/http/hono/handlers/stream.ts +208 -0
- package/src/implementations/http/hono/index.test.ts +329 -0
- package/src/implementations/http/hono/index.ts +204 -0
- package/src/implementations/http/hono/path.test.ts +96 -0
- package/src/implementations/http/hono/path.ts +59 -0
- package/src/implementations/http/hono/types.ts +93 -0
- package/src/implementations/http/on-request-error.test.ts +10 -116
- package/src/implementations/http/route-errors.test.ts +11 -77
- package/src/implementations/types.ts +44 -9
- package/src/index.test.ts +35 -1091
- package/src/index.ts +50 -474
- package/src/migration.test.ts +48 -0
- package/src/schema/compute-schema.ts +26 -12
- package/src/schema/parser.ts +62 -12
- package/src/stack-utils.ts +8 -0
- package/src/types.ts +133 -0
- package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/express-rpc.md +0 -137
- package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/hono-api.md +0 -173
- package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/hono-rpc.md +0 -142
- package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/hono-stream.md +0 -147
- package/build/implementations/http/express-rpc/error-taxonomy.test.js +0 -83
- package/build/implementations/http/express-rpc/error-taxonomy.test.js.map +0 -1
- package/build/implementations/http/express-rpc/index.d.ts +0 -125
- package/build/implementations/http/express-rpc/index.js +0 -216
- package/build/implementations/http/express-rpc/index.js.map +0 -1
- package/build/implementations/http/express-rpc/index.test.js +0 -684
- package/build/implementations/http/express-rpc/index.test.js.map +0 -1
- package/build/implementations/http/express-rpc/types.d.ts +0 -11
- package/build/implementations/http/express-rpc/types.js.map +0 -1
- package/build/implementations/http/hono-api/error-taxonomy.test.js +0 -137
- package/build/implementations/http/hono-api/error-taxonomy.test.js.map +0 -1
- package/build/implementations/http/hono-api/index.d.ts +0 -151
- package/build/implementations/http/hono-api/index.js +0 -344
- package/build/implementations/http/hono-api/index.js.map +0 -1
- package/build/implementations/http/hono-api/index.test.js +0 -992
- package/build/implementations/http/hono-api/index.test.js.map +0 -1
- package/build/implementations/http/hono-api/types.d.ts +0 -13
- package/build/implementations/http/hono-api/types.js.map +0 -1
- package/build/implementations/http/hono-rpc/error-taxonomy.test.js +0 -64
- package/build/implementations/http/hono-rpc/error-taxonomy.test.js.map +0 -1
- package/build/implementations/http/hono-rpc/index.d.ts +0 -130
- package/build/implementations/http/hono-rpc/index.js +0 -209
- package/build/implementations/http/hono-rpc/index.js.map +0 -1
- package/build/implementations/http/hono-rpc/index.test.js +0 -828
- package/build/implementations/http/hono-rpc/index.test.js.map +0 -1
- package/build/implementations/http/hono-rpc/types.d.ts +0 -11
- package/build/implementations/http/hono-rpc/types.js +0 -2
- package/build/implementations/http/hono-rpc/types.js.map +0 -1
- package/build/implementations/http/hono-stream/error-taxonomy.test.js +0 -159
- package/build/implementations/http/hono-stream/error-taxonomy.test.js.map +0 -1
- package/build/implementations/http/hono-stream/index.d.ts +0 -171
- package/build/implementations/http/hono-stream/index.js +0 -415
- package/build/implementations/http/hono-stream/index.js.map +0 -1
- package/build/implementations/http/hono-stream/index.test.js +0 -1383
- package/build/implementations/http/hono-stream/index.test.js.map +0 -1
- package/build/implementations/http/hono-stream/types.d.ts +0 -15
- package/build/implementations/http/hono-stream/types.js +0 -2
- package/build/implementations/http/hono-stream/types.js.map +0 -1
- package/src/implementations/http/express-rpc/README.md +0 -280
- package/src/implementations/http/express-rpc/error-taxonomy.test.ts +0 -103
- package/src/implementations/http/express-rpc/index.test.ts +0 -957
- package/src/implementations/http/express-rpc/index.ts +0 -327
- package/src/implementations/http/express-rpc/types.ts +0 -16
- package/src/implementations/http/hono-api/README.md +0 -284
- package/src/implementations/http/hono-api/error-taxonomy.test.ts +0 -179
- package/src/implementations/http/hono-api/index.test.ts +0 -1341
- package/src/implementations/http/hono-api/index.ts +0 -519
- package/src/implementations/http/hono-api/types.ts +0 -16
- package/src/implementations/http/hono-rpc/README.md +0 -357
- package/src/implementations/http/hono-rpc/error-taxonomy.test.ts +0 -82
- package/src/implementations/http/hono-rpc/index.test.ts +0 -1107
- package/src/implementations/http/hono-rpc/index.ts +0 -320
- package/src/implementations/http/hono-rpc/types.ts +0 -16
- package/src/implementations/http/hono-stream/README.md +0 -559
- package/src/implementations/http/hono-stream/error-taxonomy.test.ts +0 -178
- package/src/implementations/http/hono-stream/index.test.ts +0 -1804
- package/src/implementations/http/hono-stream/index.ts +0 -622
- package/src/implementations/http/hono-stream/types.ts +0 -20
- /package/build/{implementations/http/express-rpc/error-taxonomy.test.d.ts → create-http-stream.test.d.ts} +0 -0
- /package/build/{implementations/http/express-rpc/index.test.d.ts → create-http.test.d.ts} +0 -0
- /package/build/{implementations/http/hono-api/error-taxonomy.test.d.ts → create-stream.test.d.ts} +0 -0
- /package/build/{implementations/http/hono-api/index.test.d.ts → create.test.d.ts} +0 -0
- /package/build/implementations/http/{hono-rpc/error-taxonomy.test.d.ts → error-dispatch.test.d.ts} +0 -0
- /package/build/implementations/http/{hono-rpc/index.test.d.ts → hono/handlers/http-stream.test.d.ts} +0 -0
- /package/build/implementations/http/{hono-stream/error-taxonomy.test.d.ts → hono/handlers/http.test.d.ts} +0 -0
- /package/build/implementations/http/{hono-stream/index.test.d.ts → hono/handlers/rpc.test.d.ts} +0 -0
- /package/build/implementations/http/{express-rpc → hono}/types.js +0 -0
- /package/build/{implementations/http/hono-api/types.js → types.js} +0 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { Context, Hono } from 'hono'
|
|
2
|
+
import type { ErrorTaxonomy, UnknownErrorConfig } from '../error-taxonomy.js'
|
|
3
|
+
import type {
|
|
4
|
+
AnyProcedureRegistration,
|
|
5
|
+
OnRequestErrorObserver,
|
|
6
|
+
OnMidStreamError,
|
|
7
|
+
PreStreamOnError,
|
|
8
|
+
} from '../error-dispatch.js'
|
|
9
|
+
import type {
|
|
10
|
+
ProceduresFactory,
|
|
11
|
+
ExtractContext,
|
|
12
|
+
StreamMode,
|
|
13
|
+
AnyHttpRouteDoc,
|
|
14
|
+
RPCHttpRouteDoc,
|
|
15
|
+
APIHttpRouteDoc,
|
|
16
|
+
StreamHttpRouteDoc,
|
|
17
|
+
HttpStreamRouteDoc,
|
|
18
|
+
} from '../../types.js'
|
|
19
|
+
import type {
|
|
20
|
+
TProcedureRegistration,
|
|
21
|
+
TStreamProcedureRegistration,
|
|
22
|
+
THttpProcedureRegistration,
|
|
23
|
+
THttpStreamProcedureRegistration,
|
|
24
|
+
} from '../../../types.js'
|
|
25
|
+
|
|
26
|
+
export type { AnyProcedureRegistration } from '../error-dispatch.js'
|
|
27
|
+
|
|
28
|
+
/** Default query parser using URLSearchParams. */
|
|
29
|
+
export type QueryParser = (queryString: string) => Record<string, unknown>
|
|
30
|
+
|
|
31
|
+
export type OnRequestErrorContext = {
|
|
32
|
+
err: unknown
|
|
33
|
+
procedure: AnyProcedureRegistration
|
|
34
|
+
raw: Context
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type ExtendProcedureDoc = (params: {
|
|
38
|
+
base: RPCHttpRouteDoc | APIHttpRouteDoc | StreamHttpRouteDoc | HttpStreamRouteDoc
|
|
39
|
+
procedure: AnyProcedureRegistration
|
|
40
|
+
}) => Record<string, unknown>
|
|
41
|
+
|
|
42
|
+
export type HonoFactoryItem<TFactory extends ProceduresFactory = ProceduresFactory> = {
|
|
43
|
+
factory: TFactory
|
|
44
|
+
factoryContext:
|
|
45
|
+
| ExtractContext<TFactory>
|
|
46
|
+
| ((c: Context) => ExtractContext<TFactory> | Promise<ExtractContext<TFactory>>)
|
|
47
|
+
streamMode?: StreamMode
|
|
48
|
+
extendProcedureDoc?: ExtendProcedureDoc
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type HonoAppBuilderConfig<TStreamErrorData = unknown> = {
|
|
52
|
+
/** Existing Hono app. If omitted, a new instance is created. */
|
|
53
|
+
app?: Hono
|
|
54
|
+
/** Path prefix applied to every route across all kinds. */
|
|
55
|
+
pathPrefix?: string
|
|
56
|
+
|
|
57
|
+
// Error handling — peers
|
|
58
|
+
errors?: ErrorTaxonomy
|
|
59
|
+
unknownError?: UnknownErrorConfig
|
|
60
|
+
onError?: PreStreamOnError
|
|
61
|
+
/** Cross-cutting observer — fires for every caught error before dispatch. */
|
|
62
|
+
onRequestError?: OnRequestErrorObserver
|
|
63
|
+
|
|
64
|
+
// Lifecycle (every kind)
|
|
65
|
+
onRequestStart?: (c: Context) => void
|
|
66
|
+
onRequestEnd?: (c: Context) => void
|
|
67
|
+
|
|
68
|
+
// Kind-specific blocks
|
|
69
|
+
rpc?: {
|
|
70
|
+
onSuccess?: (procedure: TProcedureRegistration, c: Context) => void
|
|
71
|
+
}
|
|
72
|
+
api?: {
|
|
73
|
+
queryParser?: QueryParser
|
|
74
|
+
onSuccess?: (procedure: THttpProcedureRegistration<any>, c: Context) => void
|
|
75
|
+
}
|
|
76
|
+
stream?: {
|
|
77
|
+
/** Default for both rpc-stream and http-stream. */
|
|
78
|
+
defaultStreamMode?: StreamMode
|
|
79
|
+
onStreamStart?: (
|
|
80
|
+
procedure: TStreamProcedureRegistration | THttpStreamProcedureRegistration<any>,
|
|
81
|
+
c: Context,
|
|
82
|
+
streamMode: StreamMode,
|
|
83
|
+
) => void
|
|
84
|
+
onStreamEnd?: (
|
|
85
|
+
procedure: TStreamProcedureRegistration | THttpStreamProcedureRegistration<any>,
|
|
86
|
+
c: Context,
|
|
87
|
+
streamMode: StreamMode,
|
|
88
|
+
) => void
|
|
89
|
+
onMidStreamError?: OnMidStreamError<TStreamErrorData>
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export type DocAccumulator = AnyHttpRouteDoc[]
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Cross-builder tests for the `onRequestError` observer hook.
|
|
4
4
|
*
|
|
5
|
-
* Invariants verified
|
|
5
|
+
* Invariants verified per builder:
|
|
6
6
|
* 1. Fires exactly once for every caught error.
|
|
7
7
|
* 2. Runs BEFORE dispatch (taxonomy / onError / hard default).
|
|
8
8
|
* 3. Is awaited — async observer work completes before the response is sent.
|
|
@@ -12,82 +12,13 @@
|
|
|
12
12
|
* path still produces a response.
|
|
13
13
|
*/
|
|
14
14
|
import { describe, expect, test, vi } from 'vitest'
|
|
15
|
-
import request from 'supertest'
|
|
16
15
|
import { Type } from 'typebox'
|
|
17
16
|
import { Procedures } from '../../index.js'
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import { HonoRPCAppBuilder } from './hono-rpc/index.js'
|
|
21
|
-
import { ExpressRPCAppBuilder } from './express-rpc/index.js'
|
|
22
|
-
import { HonoStreamAppBuilder } from './hono-stream/index.js'
|
|
17
|
+
import { RPCConfig } from '../types.js'
|
|
18
|
+
import { HonoAppBuilder } from './hono/index.js'
|
|
23
19
|
|
|
24
|
-
describe('onRequestError —
|
|
25
|
-
function boomApp(config: ConstructorParameters<typeof
|
|
26
|
-
const API = Procedures<{}, APIConfig>()
|
|
27
|
-
API.Create(
|
|
28
|
-
'Boom',
|
|
29
|
-
{ path: '/boom', method: 'get', schema: { returnType: Type.Object({}) } },
|
|
30
|
-
async () => {
|
|
31
|
-
throw new TypeError('boom')
|
|
32
|
-
}
|
|
33
|
-
)
|
|
34
|
-
return new HonoAPIAppBuilder(config).register(API, () => ({})).build()
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
test('fires exactly once and before dispatch', async () => {
|
|
38
|
-
const order: string[] = []
|
|
39
|
-
const onRequestError = vi.fn(() => {
|
|
40
|
-
order.push('observer')
|
|
41
|
-
})
|
|
42
|
-
const onError = vi.fn((_p: any, c: any) => {
|
|
43
|
-
order.push('onError')
|
|
44
|
-
return c.json({ handled: true }, 418)
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
const app = boomApp({ onRequestError, onError })
|
|
48
|
-
await app.request('/boom')
|
|
49
|
-
expect(onRequestError).toHaveBeenCalledTimes(1)
|
|
50
|
-
expect(order).toEqual(['observer', 'onError'])
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
test('is awaited — async work completes before response is sent', async () => {
|
|
54
|
-
const log: string[] = []
|
|
55
|
-
const onRequestError = async () => {
|
|
56
|
-
await new Promise((r) => setTimeout(r, 5))
|
|
57
|
-
log.push('observer-done')
|
|
58
|
-
}
|
|
59
|
-
const app = boomApp({
|
|
60
|
-
onRequestError,
|
|
61
|
-
onError: (_p, c) => {
|
|
62
|
-
log.push('onError-called')
|
|
63
|
-
return c.json({ ok: true }, 500)
|
|
64
|
-
},
|
|
65
|
-
})
|
|
66
|
-
await app.request('/boom')
|
|
67
|
-
expect(log).toEqual(['observer-done', 'onError-called'])
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
test('observer-thrown errors are swallowed — dispatch still produces a response', async () => {
|
|
71
|
-
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
72
|
-
const app = boomApp({
|
|
73
|
-
onRequestError: () => {
|
|
74
|
-
throw new Error('observer exploded')
|
|
75
|
-
},
|
|
76
|
-
})
|
|
77
|
-
const res = await app.request('/boom')
|
|
78
|
-
expect(res.status).toBe(500)
|
|
79
|
-
consoleSpy.mockRestore()
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
test('omitting observer preserves existing behavior', async () => {
|
|
83
|
-
const app = boomApp({ onError: (_p, c) => c.json({ ok: true }, 418) })
|
|
84
|
-
const res = await app.request('/boom')
|
|
85
|
-
expect(res.status).toBe(418)
|
|
86
|
-
})
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
describe('onRequestError — HonoRPCAppBuilder', () => {
|
|
90
|
-
function boomApp(config: ConstructorParameters<typeof HonoRPCAppBuilder>[0]) {
|
|
20
|
+
describe('onRequestError — HonoAppBuilder (rpc kind)', () => {
|
|
21
|
+
function boomApp(config: ConstructorParameters<typeof HonoAppBuilder>[0]) {
|
|
91
22
|
const RPC = Procedures<{}, RPCConfig>()
|
|
92
23
|
RPC.Create(
|
|
93
24
|
'Boom',
|
|
@@ -96,7 +27,7 @@ describe('onRequestError — HonoRPCAppBuilder', () => {
|
|
|
96
27
|
throw new TypeError('boom')
|
|
97
28
|
}
|
|
98
29
|
)
|
|
99
|
-
return new
|
|
30
|
+
return new HonoAppBuilder(config).register(RPC, () => ({})).build()
|
|
100
31
|
}
|
|
101
32
|
|
|
102
33
|
test('fires once; runs before onError', async () => {
|
|
@@ -128,51 +59,13 @@ describe('onRequestError — HonoRPCAppBuilder', () => {
|
|
|
128
59
|
})
|
|
129
60
|
})
|
|
130
61
|
|
|
131
|
-
describe('onRequestError —
|
|
132
|
-
function boomApp(config: ConstructorParameters<typeof
|
|
133
|
-
const RPC = Procedures<{}, RPCConfig>()
|
|
134
|
-
RPC.Create(
|
|
135
|
-
'Boom',
|
|
136
|
-
{ scope: 'test', version: 1, schema: { params: Type.Object({}) } },
|
|
137
|
-
async () => {
|
|
138
|
-
throw new TypeError('boom')
|
|
139
|
-
}
|
|
140
|
-
)
|
|
141
|
-
return new ExpressRPCAppBuilder(config).register(RPC, () => ({})).build()
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
test('fires once; raw is { req, res }', async () => {
|
|
145
|
-
let rawSeen: any
|
|
146
|
-
const app = boomApp({
|
|
147
|
-
onRequestError: (ctx) => {
|
|
148
|
-
rawSeen = ctx.raw
|
|
149
|
-
},
|
|
150
|
-
})
|
|
151
|
-
await request(app).post('/test/boom/1').send({})
|
|
152
|
-
expect(rawSeen.req).toBeDefined()
|
|
153
|
-
expect(rawSeen.res).toBeDefined()
|
|
154
|
-
})
|
|
155
|
-
|
|
156
|
-
test('observer throws are swallowed', async () => {
|
|
157
|
-
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
158
|
-
const app = boomApp({
|
|
159
|
-
onRequestError: () => {
|
|
160
|
-
throw new Error('observer bug')
|
|
161
|
-
},
|
|
162
|
-
})
|
|
163
|
-
const res = await request(app).post('/test/boom/1').send({})
|
|
164
|
-
expect(res.status).toBe(500)
|
|
165
|
-
consoleSpy.mockRestore()
|
|
166
|
-
})
|
|
167
|
-
})
|
|
168
|
-
|
|
169
|
-
describe('onRequestError — HonoStreamAppBuilder (pre-stream)', () => {
|
|
170
|
-
function boomApp(config: ConstructorParameters<typeof HonoStreamAppBuilder>[0]) {
|
|
62
|
+
describe('onRequestError — HonoAppBuilder (rpc-stream pre-stream)', () => {
|
|
63
|
+
function boomApp(config: ConstructorParameters<typeof HonoAppBuilder>[0]) {
|
|
171
64
|
const RPC = Procedures<{}, RPCConfig>()
|
|
172
65
|
RPC.CreateStream('Stream', { scope: 'test', version: 1 }, async function* () {
|
|
173
66
|
yield { ok: true }
|
|
174
67
|
})
|
|
175
|
-
return new
|
|
68
|
+
return new HonoAppBuilder(config)
|
|
176
69
|
.register(RPC, () => {
|
|
177
70
|
throw new TypeError('context failed')
|
|
178
71
|
})
|
|
@@ -199,3 +92,4 @@ describe('onRequestError — HonoStreamAppBuilder (pre-stream)', () => {
|
|
|
199
92
|
consoleSpy.mockRestore()
|
|
200
93
|
})
|
|
201
94
|
})
|
|
95
|
+
|
|
@@ -3,10 +3,7 @@ import { describe, expect, test } from 'vitest'
|
|
|
3
3
|
import { Type } from 'typebox'
|
|
4
4
|
import { Procedures } from '../../index.js'
|
|
5
5
|
import { APIConfig, RPCConfig } from '../types.js'
|
|
6
|
-
import {
|
|
7
|
-
import { HonoRPCAppBuilder } from './hono-rpc/index.js'
|
|
8
|
-
import { ExpressRPCAppBuilder } from './express-rpc/index.js'
|
|
9
|
-
import { HonoStreamAppBuilder } from './hono-stream/index.js'
|
|
6
|
+
import { HonoAppBuilder } from './hono/index.js'
|
|
10
7
|
import { DocRegistry } from './doc-registry.js'
|
|
11
8
|
import { defineErrorTaxonomy } from './error-taxonomy.js'
|
|
12
9
|
|
|
@@ -26,39 +23,13 @@ const appErrors = defineErrorTaxonomy({
|
|
|
26
23
|
})
|
|
27
24
|
|
|
28
25
|
describe('per-route errors declaration', () => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
API.Create(
|
|
32
|
-
'GetUser',
|
|
33
|
-
{
|
|
34
|
-
path: '/users/:id',
|
|
35
|
-
method: 'get',
|
|
36
|
-
errors: ['UseCaseError', 'AuthError'],
|
|
37
|
-
schema: {
|
|
38
|
-
input: { pathParams: Type.Object({ id: Type.String() }) },
|
|
39
|
-
returnType: Type.Object({}),
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
async () => ({})
|
|
43
|
-
)
|
|
44
|
-
const builder = new HonoAPIAppBuilder().register(API, () => ({}))
|
|
45
|
-
builder.build()
|
|
46
|
-
expect(builder.docs[0]!.errors).toEqual(['UseCaseError', 'AuthError'])
|
|
47
|
-
})
|
|
26
|
+
// migrated to schema.req in Phase 3+ (CreateHttp)
|
|
27
|
+
test.todo('hono-api copies config.errors onto the route doc')
|
|
48
28
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
API.Create(
|
|
52
|
-
'Health',
|
|
53
|
-
{ path: '/health', method: 'get', schema: { returnType: Type.Object({}) } },
|
|
54
|
-
async () => ({})
|
|
55
|
-
)
|
|
56
|
-
const builder = new HonoAPIAppBuilder().register(API, () => ({}))
|
|
57
|
-
builder.build()
|
|
58
|
-
expect(builder.docs[0]!.errors).toBeUndefined()
|
|
59
|
-
})
|
|
29
|
+
// migrated to schema.req in Phase 3+ (CreateHttp)
|
|
30
|
+
test.todo('hono-api route doc omits errors when not declared')
|
|
60
31
|
|
|
61
|
-
test('hono
|
|
32
|
+
test('hono rpc copies config.errors onto the route doc', () => {
|
|
62
33
|
const RPC = Procedures<{}, RPCConfig<keyof typeof appErrors & string>>()
|
|
63
34
|
RPC.Create(
|
|
64
35
|
'DoThing',
|
|
@@ -70,29 +41,12 @@ describe('per-route errors declaration', () => {
|
|
|
70
41
|
},
|
|
71
42
|
async () => ({})
|
|
72
43
|
)
|
|
73
|
-
const builder = new
|
|
44
|
+
const builder = new HonoAppBuilder().register(RPC, () => ({}))
|
|
74
45
|
builder.build()
|
|
75
46
|
expect(builder.docs[0]!.errors).toEqual(['UseCaseError'])
|
|
76
47
|
})
|
|
77
48
|
|
|
78
|
-
test('
|
|
79
|
-
const RPC = Procedures<{}, RPCConfig<keyof typeof appErrors & string>>()
|
|
80
|
-
RPC.Create(
|
|
81
|
-
'DoThing',
|
|
82
|
-
{
|
|
83
|
-
scope: 'things',
|
|
84
|
-
version: 1,
|
|
85
|
-
errors: ['AuthError'],
|
|
86
|
-
schema: { params: Type.Object({}) },
|
|
87
|
-
},
|
|
88
|
-
async () => ({})
|
|
89
|
-
)
|
|
90
|
-
const builder = new ExpressRPCAppBuilder().register(RPC, () => ({}))
|
|
91
|
-
builder.build()
|
|
92
|
-
expect(builder.docs[0]!.errors).toEqual(['AuthError'])
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
test('hono-stream copies config.errors onto the route doc', () => {
|
|
49
|
+
test('hono stream copies config.errors onto the route doc', () => {
|
|
96
50
|
const Stream = Procedures<{}, RPCConfig<keyof typeof appErrors & string>>()
|
|
97
51
|
Stream.CreateStream(
|
|
98
52
|
'Watch',
|
|
@@ -101,7 +55,7 @@ describe('per-route errors declaration', () => {
|
|
|
101
55
|
yield { ok: true }
|
|
102
56
|
}
|
|
103
57
|
)
|
|
104
|
-
const builder = new
|
|
58
|
+
const builder = new HonoAppBuilder().register(Stream, () => ({}))
|
|
105
59
|
builder.build()
|
|
106
60
|
expect(builder.docs[0]!.errors).toEqual(['AuthError'])
|
|
107
61
|
})
|
|
@@ -151,26 +105,6 @@ describe('DocRegistry with taxonomy input', () => {
|
|
|
151
105
|
expect(count).toBe(1)
|
|
152
106
|
})
|
|
153
107
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
API.Create(
|
|
157
|
-
'GetUser',
|
|
158
|
-
{
|
|
159
|
-
path: '/users/:id',
|
|
160
|
-
method: 'get',
|
|
161
|
-
errors: ['UseCaseError'],
|
|
162
|
-
schema: {
|
|
163
|
-
input: { pathParams: Type.Object({ id: Type.String() }) },
|
|
164
|
-
returnType: Type.Object({}),
|
|
165
|
-
},
|
|
166
|
-
},
|
|
167
|
-
async () => ({})
|
|
168
|
-
)
|
|
169
|
-
const app = new HonoAPIAppBuilder().register(API, () => ({}))
|
|
170
|
-
app.build()
|
|
171
|
-
|
|
172
|
-
const envelope = new DocRegistry({ errors: appErrors }).from(app).toJSON()
|
|
173
|
-
const route = envelope.routes.find((r) => r.kind === 'api' && r.name === 'GetUser')
|
|
174
|
-
expect(route?.errors).toEqual(['UseCaseError'])
|
|
175
|
-
})
|
|
108
|
+
// migrated to schema.req in Phase 3+ (CreateHttp)
|
|
109
|
+
test.todo('registered route errors survive DocRegistry composition')
|
|
176
110
|
})
|
|
@@ -66,20 +66,28 @@ export interface APIConfig<TErrorKey extends string = string> {
|
|
|
66
66
|
errors?: TErrorKey[]
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
export interface APIHttpRouteDoc
|
|
69
|
+
export interface APIHttpRouteDoc {
|
|
70
70
|
kind: 'api'
|
|
71
71
|
name: string
|
|
72
|
+
scope?: string
|
|
73
|
+
path: string
|
|
74
|
+
method: HttpMethod
|
|
72
75
|
/** Full resolved path including pathPrefix */
|
|
73
76
|
fullPath: string
|
|
77
|
+
successStatus?: number
|
|
78
|
+
errors?: string[]
|
|
74
79
|
jsonSchema: {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
req?: {
|
|
81
|
+
pathParams?: Record<string, unknown>
|
|
82
|
+
query?: Record<string, unknown>
|
|
83
|
+
body?: Record<string, unknown>
|
|
84
|
+
headers?: Record<string, unknown>
|
|
85
|
+
}
|
|
86
|
+
res?: {
|
|
87
|
+
body?: Record<string, unknown>
|
|
88
|
+
headers?: Record<string, unknown>
|
|
89
|
+
}
|
|
80
90
|
}
|
|
81
|
-
/** Taxonomy keys for errors this route may emit. */
|
|
82
|
-
errors?: string[]
|
|
83
91
|
}
|
|
84
92
|
|
|
85
93
|
/**
|
|
@@ -121,6 +129,30 @@ export interface StreamHttpRouteDoc extends RPCConfig {
|
|
|
121
129
|
errors?: string[]
|
|
122
130
|
}
|
|
123
131
|
|
|
132
|
+
export interface HttpStreamRouteDoc {
|
|
133
|
+
kind: 'http-stream'
|
|
134
|
+
name: string
|
|
135
|
+
scope?: string
|
|
136
|
+
path: string
|
|
137
|
+
method: HttpMethod
|
|
138
|
+
fullPath: string
|
|
139
|
+
streamMode: StreamMode
|
|
140
|
+
errors?: string[]
|
|
141
|
+
jsonSchema: {
|
|
142
|
+
req?: {
|
|
143
|
+
pathParams?: Record<string, unknown>
|
|
144
|
+
query?: Record<string, unknown>
|
|
145
|
+
body?: Record<string, unknown>
|
|
146
|
+
headers?: Record<string, unknown>
|
|
147
|
+
}
|
|
148
|
+
res?: {
|
|
149
|
+
headers?: Record<string, unknown>
|
|
150
|
+
}
|
|
151
|
+
yield?: Record<string, unknown>
|
|
152
|
+
returnType?: Record<string, unknown>
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
124
156
|
// ================
|
|
125
157
|
// Utility types
|
|
126
158
|
// ================
|
|
@@ -152,19 +184,22 @@ export type ExtractConfig<TFactory> = TFactory extends {
|
|
|
152
184
|
export type ProceduresFactory = {
|
|
153
185
|
getProcedures: () => Array<{
|
|
154
186
|
name: string
|
|
187
|
+
kind?: import('../types.js').ProcedureKind
|
|
155
188
|
isStream?: boolean
|
|
156
189
|
config: any
|
|
157
190
|
handler: (ctx: any, params?: any) => Promise<any> | AsyncGenerator<any, any, unknown>
|
|
158
191
|
}>
|
|
159
192
|
Create: (...args: any[]) => any
|
|
160
193
|
CreateStream?: (...args: any[]) => any
|
|
194
|
+
CreateHttp?: (...args: any[]) => any
|
|
195
|
+
CreateHttpStream?: (...args: any[]) => any
|
|
161
196
|
}
|
|
162
197
|
|
|
163
198
|
// ================
|
|
164
199
|
// DocRegistry types
|
|
165
200
|
// ================
|
|
166
201
|
|
|
167
|
-
export type AnyHttpRouteDoc = RPCHttpRouteDoc | APIHttpRouteDoc | StreamHttpRouteDoc
|
|
202
|
+
export type AnyHttpRouteDoc = RPCHttpRouteDoc | APIHttpRouteDoc | StreamHttpRouteDoc | HttpStreamRouteDoc
|
|
168
203
|
|
|
169
204
|
export interface DocSource<T = AnyHttpRouteDoc> {
|
|
170
205
|
readonly docs: T[]
|