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
|
@@ -1,559 +0,0 @@
|
|
|
1
|
-
# Hono Stream Implementation
|
|
2
|
-
|
|
3
|
-
HTTP streaming and SSE endpoints for streaming procedures created with `CreateStream`.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
`HonoStreamAppBuilder` provides a builder pattern for creating streaming HTTP endpoints in Hono. It handles `AsyncGenerator` handlers and supports both Server-Sent Events (SSE) and plain text streaming modes.
|
|
8
|
-
|
|
9
|
-
## Installation
|
|
10
|
-
|
|
11
|
-
Requires `hono` as a peer dependency:
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
npm install hono
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
## Quick Start
|
|
18
|
-
|
|
19
|
-
```typescript
|
|
20
|
-
import { Procedures } from 'ts-procedures'
|
|
21
|
-
import { HonoStreamAppBuilder, sse } from 'ts-procedures/hono-stream'
|
|
22
|
-
|
|
23
|
-
// Define your context and config types
|
|
24
|
-
type StreamContext = { userId: string }
|
|
25
|
-
interface RPCConfig {
|
|
26
|
-
scope: string | string[]
|
|
27
|
-
version: number
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Create a procedures factory
|
|
31
|
-
const StreamRPC = Procedures<StreamContext, RPCConfig>()
|
|
32
|
-
|
|
33
|
-
// Create a streaming procedure — yield domain data directly
|
|
34
|
-
StreamRPC.CreateStream(
|
|
35
|
-
'WatchNotifications',
|
|
36
|
-
{
|
|
37
|
-
scope: ['user', 'notifications'],
|
|
38
|
-
version: 1,
|
|
39
|
-
schema: {
|
|
40
|
-
yieldType: Type.Object({ id: Type.Number(), message: Type.String() }),
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
async function* (ctx) {
|
|
44
|
-
for (let i = 1; i <= 10; i++) {
|
|
45
|
-
// Yield domain data directly — matches yieldType schema
|
|
46
|
-
yield { id: i, message: `Notification ${i}` }
|
|
47
|
-
await new Promise((r) => setTimeout(r, 1000))
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
// Build the Hono app
|
|
53
|
-
const builder = new HonoStreamAppBuilder()
|
|
54
|
-
.register(StreamRPC, (c) => ({
|
|
55
|
-
userId: c.req.header('x-user-id') || 'anonymous',
|
|
56
|
-
}))
|
|
57
|
-
|
|
58
|
-
const app = builder.build()
|
|
59
|
-
|
|
60
|
-
// Access documentation
|
|
61
|
-
const docs = builder.docs
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## HTTP Methods
|
|
65
|
-
|
|
66
|
-
Both GET and POST methods are supported for each streaming endpoint:
|
|
67
|
-
|
|
68
|
-
```
|
|
69
|
-
GET /{pathPrefix}/{scope...}/{procedureName}/{version}?param1=value1
|
|
70
|
-
POST /{pathPrefix}/{scope...}/{procedureName}/{version} (JSON body)
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
- **GET**: For EventSource/SSE clients, params passed via query string
|
|
74
|
-
- **POST**: For clients needing complex JSON body params
|
|
75
|
-
|
|
76
|
-
## Yielding in SSE Mode
|
|
77
|
-
|
|
78
|
-
Procedures yield **domain data directly** — the same shape as your `yieldType` schema. `HonoStreamAppBuilder` handles the SSE envelope (`event:`, `id:`, `data:`) automatically.
|
|
79
|
-
|
|
80
|
-
```typescript
|
|
81
|
-
async function* (ctx) {
|
|
82
|
-
// Domain objects are JSON.stringify'd into the SSE data: field
|
|
83
|
-
yield { count: 1 }
|
|
84
|
-
|
|
85
|
-
// Strings are passed through as-is (no double-stringify)
|
|
86
|
-
yield 'raw string value'
|
|
87
|
-
}
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
By default, SSE events use the procedure name as the `event:` field and auto-increment the `id:` field.
|
|
91
|
-
|
|
92
|
-
### `sse()` Helper
|
|
93
|
-
|
|
94
|
-
To override SSE metadata (event name, id, retry) for individual yields, use the `sse()` helper:
|
|
95
|
-
|
|
96
|
-
```typescript
|
|
97
|
-
import { sse } from 'ts-procedures/hono-stream'
|
|
98
|
-
|
|
99
|
-
async function* (ctx) {
|
|
100
|
-
// Custom event name
|
|
101
|
-
yield sse({ type: 'heartbeat' }, { event: 'ping' })
|
|
102
|
-
|
|
103
|
-
// Custom id
|
|
104
|
-
yield sse({ msg: 'hello' }, { id: 'msg-001' })
|
|
105
|
-
|
|
106
|
-
// All SSE options
|
|
107
|
-
yield sse({ done: true }, { event: 'complete', id: 'final', retry: 5000 })
|
|
108
|
-
|
|
109
|
-
// sse() with no options — same as plain yield (uses defaults)
|
|
110
|
-
yield sse({ count: 1 })
|
|
111
|
-
}
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
`sse()` attaches metadata via a `WeakMap` side-channel, so:
|
|
115
|
-
- The domain object passes through core validation (`validateYields`) unmodified
|
|
116
|
-
- `JSON.stringify` only sees domain properties
|
|
117
|
-
- AJV's `removeAdditional: true` doesn't affect the metadata
|
|
118
|
-
|
|
119
|
-
> **Note:** `sse()` requires object values (used as `WeakMap` keys). Strings and other primitives cannot carry SSE metadata — they use the default event name (procedure name) and auto-incremented id.
|
|
120
|
-
|
|
121
|
-
**Text mode is unaffected** — both plain objects and `sse()`-tagged objects are JSON-stringified identically. SSE metadata is ignored in text mode.
|
|
122
|
-
|
|
123
|
-
## Stream Modes
|
|
124
|
-
|
|
125
|
-
### SSE Mode (default)
|
|
126
|
-
|
|
127
|
-
Returns `text/event-stream` content type with SSE-formatted messages:
|
|
128
|
-
|
|
129
|
-
```typescript
|
|
130
|
-
const builder = new HonoStreamAppBuilder({ defaultStreamMode: 'sse' })
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
Response format:
|
|
134
|
-
```
|
|
135
|
-
event: WatchNotifications
|
|
136
|
-
data: {"id":1,"message":"Notification 1"}
|
|
137
|
-
id: 0
|
|
138
|
-
|
|
139
|
-
event: WatchNotifications
|
|
140
|
-
data: {"id":2,"message":"Notification 2"}
|
|
141
|
-
id: 1
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
Client usage:
|
|
145
|
-
```typescript
|
|
146
|
-
const eventSource = new EventSource('/user/notifications/watch-notifications/1')
|
|
147
|
-
// Listen for default event (procedure name)
|
|
148
|
-
eventSource.addEventListener('WatchNotifications', (event) => {
|
|
149
|
-
const data = JSON.parse(event.data)
|
|
150
|
-
console.log(data)
|
|
151
|
-
})
|
|
152
|
-
// Listen for custom events (when using sse() helper)
|
|
153
|
-
eventSource.addEventListener('notification', (event) => {
|
|
154
|
-
const data = JSON.parse(event.data)
|
|
155
|
-
console.log(data)
|
|
156
|
-
})
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
### Text Mode
|
|
160
|
-
|
|
161
|
-
Returns `text/plain` content type with newline-delimited JSON:
|
|
162
|
-
|
|
163
|
-
```typescript
|
|
164
|
-
const builder = new HonoStreamAppBuilder({ defaultStreamMode: 'text' })
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
Response format:
|
|
168
|
-
```
|
|
169
|
-
{"key":"value"}
|
|
170
|
-
{"key":"value2"}
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
Client usage:
|
|
174
|
-
```typescript
|
|
175
|
-
const response = await fetch('/user/notifications/watch-notifications/1')
|
|
176
|
-
const reader = response.body.getReader()
|
|
177
|
-
const decoder = new TextDecoder()
|
|
178
|
-
|
|
179
|
-
while (true) {
|
|
180
|
-
const { done, value } = await reader.read()
|
|
181
|
-
if (done) break
|
|
182
|
-
const lines = decoder.decode(value).split('\n')
|
|
183
|
-
for (const line of lines) {
|
|
184
|
-
if (line) console.log(JSON.parse(line))
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
## Configuration
|
|
190
|
-
|
|
191
|
-
### Builder Config
|
|
192
|
-
|
|
193
|
-
```typescript
|
|
194
|
-
interface HonoStreamAppBuilderConfig<TErrorData = unknown> {
|
|
195
|
-
app?: Hono // Use existing Hono instance
|
|
196
|
-
pathPrefix?: string // Prefix for all routes
|
|
197
|
-
defaultStreamMode?: 'sse' | 'text' // Default: 'sse'
|
|
198
|
-
onRequestStart?: (c: Context) => void
|
|
199
|
-
onRequestEnd?: (c: Context) => void
|
|
200
|
-
onStreamStart?: (procedure: TStreamProcedureRegistration, c: Context, streamMode: StreamMode) => void
|
|
201
|
-
onStreamEnd?: (procedure: TStreamProcedureRegistration, c: Context, streamMode: StreamMode) => void
|
|
202
|
-
|
|
203
|
-
// Error handling (see Error Handling section)
|
|
204
|
-
errors?: ErrorTaxonomy
|
|
205
|
-
unknownError?: UnknownErrorConfig
|
|
206
|
-
onError?: (procedure, c, error: ProcedureValidationError | Error) => Response | Promise<Response>
|
|
207
|
-
onRequestError?: (ctx) => void | Promise<void>
|
|
208
|
-
onMidStreamError?: (procedure, c, error) => MidStreamErrorResult<TErrorData> | undefined
|
|
209
|
-
}
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
### Per-Factory Options
|
|
213
|
-
|
|
214
|
-
```typescript
|
|
215
|
-
builder.register(factory, context, {
|
|
216
|
-
streamMode: 'text', // Override default mode for this factory
|
|
217
|
-
extendProcedureDoc: ({ base, procedure }) => ({
|
|
218
|
-
summary: 'Custom documentation',
|
|
219
|
-
tags: ['streaming'],
|
|
220
|
-
}),
|
|
221
|
-
})
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
## Using an Existing Hono App
|
|
225
|
-
|
|
226
|
-
Pass an existing `Hono` instance to mount stream routes alongside other routes — including those registered by `HonoRPCAppBuilder` and `HonoAPIAppBuilder`. One Hono server can host all three builders.
|
|
227
|
-
|
|
228
|
-
```typescript
|
|
229
|
-
const app = new Hono()
|
|
230
|
-
app.use('*', cors())
|
|
231
|
-
|
|
232
|
-
new HonoStreamAppBuilder({ app })
|
|
233
|
-
.register(StreamFactory, contextResolver)
|
|
234
|
-
.build()
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
For the full single-server pattern (RPC + API + Stream + `DocRegistry` on one app), see [docs/http-integrations.md § One Hono Server, Multiple Builders](../../../../docs/http-integrations.md#one-hono-server-multiple-builders).
|
|
238
|
-
|
|
239
|
-
## Lifecycle Hooks
|
|
240
|
-
|
|
241
|
-
Hooks execute in the following order:
|
|
242
|
-
|
|
243
|
-
```
|
|
244
|
-
onRequestStart → [validation] → onStreamStart(proc, c, streamMode) → [yields...] → onStreamEnd(proc, c, streamMode) → onRequestEnd
|
|
245
|
-
↓ ↓
|
|
246
|
-
(validation error) (stream error)
|
|
247
|
-
↓ ↓
|
|
248
|
-
HTTP 400 response error sent in stream
|
|
249
|
-
↓
|
|
250
|
-
onStreamEnd
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
`onStreamStart` and `onStreamEnd` receive the resolved `streamMode` (`'sse'` or `'text'`) as their third argument.
|
|
254
|
-
|
|
255
|
-
## Validation
|
|
256
|
-
|
|
257
|
-
### Pre-validation
|
|
258
|
-
|
|
259
|
-
`HonoStreamAppBuilder` validates parameters **before** starting the stream to return proper HTTP error responses. It passes `isPrevalidated: true` internally to skip redundant procedure-level validation. This is transparent to handler authors — the flag is not exposed on the handler context type.
|
|
260
|
-
|
|
261
|
-
1. Params are validated by `HonoStreamAppBuilder` at the HTTP layer
|
|
262
|
-
2. If validation fails, a 400 response is returned (no stream starts)
|
|
263
|
-
3. If validation passes, the procedure handler runs without duplicate validation
|
|
264
|
-
|
|
265
|
-
This design allows for:
|
|
266
|
-
- Clean HTTP error responses (400 status code, JSON body) instead of stream errors
|
|
267
|
-
- No duplicate validation overhead
|
|
268
|
-
- Consistent error handling at the framework level
|
|
269
|
-
|
|
270
|
-
## Error Handling
|
|
271
|
-
|
|
272
|
-
Streaming has two distinct error phases with different semantics:
|
|
273
|
-
|
|
274
|
-
| Phase | When | Handling |
|
|
275
|
-
|-------|------|---------|
|
|
276
|
-
| **Pre-stream** | Validation, auth, context resolution | Declarative taxonomy via `errors` + `unknownError` — same shape as all other HTTP builders |
|
|
277
|
-
| **Mid-stream** | Generator throws during iteration | `onMidStreamError` — writes a value into the open stream (status is already committed) |
|
|
278
|
-
|
|
279
|
-
### Pre-Stream — Error Taxonomy
|
|
280
|
-
|
|
281
|
-
```typescript
|
|
282
|
-
import { defineErrorTaxonomy } from 'ts-procedures/hono-stream'
|
|
283
|
-
|
|
284
|
-
const builder = new HonoStreamAppBuilder({
|
|
285
|
-
errors: defineErrorTaxonomy({
|
|
286
|
-
AuthError: { class: AuthError, statusCode: 401 },
|
|
287
|
-
}),
|
|
288
|
-
unknownError: { toResponse: () => ({ error: 'Internal server error' }) },
|
|
289
|
-
onMidStreamError: (/* ... */) => ({ /* mid-stream only */ }),
|
|
290
|
-
})
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
Full contract (both peer error modes, `onRequestError` observer, per-route `errors` narrowing): see **[docs/http-integrations.md § Error Handling](../../../../docs/http-integrations.md#error-handling)** — the canonical explanation shared across all four HTTP builders.
|
|
294
|
-
|
|
295
|
-
### Mid-Stream Errors (`onMidStreamError`)
|
|
296
|
-
|
|
297
|
-
Errors that occur **during** streaming (generator throws). Since the stream is already open, HTTP status cannot change. Return `{ data, closeStream? }` — the `data` value is written as the SSE `data:` field content.
|
|
298
|
-
|
|
299
|
-
To control SSE metadata (event name, id, retry) on the error yield, wrap the data object with `sse()`:
|
|
300
|
-
|
|
301
|
-
```typescript
|
|
302
|
-
const builder = new HonoStreamAppBuilder({
|
|
303
|
-
onMidStreamError: (procedure, c, error) => {
|
|
304
|
-
return {
|
|
305
|
-
// Data written as the SSE data: field (should match your yieldType schema)
|
|
306
|
-
// Use sse() to attach custom event/id/retry metadata
|
|
307
|
-
data: sse({
|
|
308
|
-
type: 'error',
|
|
309
|
-
code: 'STREAM_ERROR',
|
|
310
|
-
message: error.message,
|
|
311
|
-
retryable: false,
|
|
312
|
-
}, { event: 'error', id: 'err-001' }),
|
|
313
|
-
// Optional: whether to close stream after (default: true)
|
|
314
|
-
closeStream: true,
|
|
315
|
-
}
|
|
316
|
-
},
|
|
317
|
-
})
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
**Return values:**
|
|
321
|
-
- `{ data, closeStream? }` - Write `data` to stream. Use `sse(data, opts)` for custom SSE event/id/retry
|
|
322
|
-
- `undefined` - Use default behavior: `{ error: message }` with `event: 'error'`
|
|
323
|
-
|
|
324
|
-
Without `sse()`, the event defaults to the procedure name when custom data is provided, or `'error'` when using the default error format. The id auto-increments.
|
|
325
|
-
|
|
326
|
-
### Type-Safe Error Handling with Union Types
|
|
327
|
-
|
|
328
|
-
Use the generic `TErrorData` parameter on `HonoStreamAppBuilder` to constrain the `onMidStreamError` return type:
|
|
329
|
-
|
|
330
|
-
```typescript
|
|
331
|
-
type ErrorPayload = {
|
|
332
|
-
type: 'error'
|
|
333
|
-
code: string
|
|
334
|
-
message: string
|
|
335
|
-
retryable: boolean
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// TErrorData constrains what onMidStreamError can return
|
|
339
|
-
const builder = new HonoStreamAppBuilder<ErrorPayload>({
|
|
340
|
-
onMidStreamError: (proc, c, error) => ({
|
|
341
|
-
data: {
|
|
342
|
-
type: 'error',
|
|
343
|
-
code: 'STREAM_ERROR',
|
|
344
|
-
message: error.message,
|
|
345
|
-
retryable: false,
|
|
346
|
-
}
|
|
347
|
-
})
|
|
348
|
-
})
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
For type-safe error handling, define your `yieldType` as a discriminated union:
|
|
352
|
-
|
|
353
|
-
```typescript
|
|
354
|
-
StreamRPC.CreateStream('WatchEvents', {
|
|
355
|
-
scope: 'events',
|
|
356
|
-
version: 1,
|
|
357
|
-
schema: {
|
|
358
|
-
params: Type.Object({ roomId: Type.String() }),
|
|
359
|
-
// Union type: clients know exactly what to expect
|
|
360
|
-
yieldType: Type.Union([
|
|
361
|
-
Type.Object({
|
|
362
|
-
type: Type.Literal('event'),
|
|
363
|
-
eventType: Type.String(),
|
|
364
|
-
data: Type.Any()
|
|
365
|
-
}),
|
|
366
|
-
Type.Object({
|
|
367
|
-
type: Type.Literal('error'),
|
|
368
|
-
code: Type.String(),
|
|
369
|
-
message: Type.String(),
|
|
370
|
-
retryable: Type.Boolean()
|
|
371
|
-
})
|
|
372
|
-
])
|
|
373
|
-
}
|
|
374
|
-
}, async function* (ctx, params) {
|
|
375
|
-
// Yield domain data directly — matches yieldType schema
|
|
376
|
-
yield { type: 'event', eventType: 'user_joined', data: { userId: ctx.userId } }
|
|
377
|
-
// On error, the procedure throws and onMidStreamError handles it
|
|
378
|
-
})
|
|
379
|
-
```
|
|
380
|
-
|
|
381
|
-
**Output (SSE mode):**
|
|
382
|
-
```
|
|
383
|
-
event: WatchEvents
|
|
384
|
-
data: {"type":"event","eventType":"user_joined","data":{"userId":"123"}}
|
|
385
|
-
|
|
386
|
-
event: WatchEvents
|
|
387
|
-
data: {"type":"error","code":"STREAM_ERROR","message":"Connection lost","retryable":false}
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
### Default Error Output
|
|
391
|
-
|
|
392
|
-
Without custom callbacks, errors are written as:
|
|
393
|
-
|
|
394
|
-
**SSE Mode:**
|
|
395
|
-
```
|
|
396
|
-
event: error
|
|
397
|
-
data: {"error":"Error message"}
|
|
398
|
-
```
|
|
399
|
-
|
|
400
|
-
**Text Mode:**
|
|
401
|
-
```
|
|
402
|
-
{"error":"Error message"}
|
|
403
|
-
```
|
|
404
|
-
|
|
405
|
-
## Route Documentation
|
|
406
|
-
|
|
407
|
-
Access generated documentation via `builder.docs`:
|
|
408
|
-
|
|
409
|
-
```typescript
|
|
410
|
-
interface StreamHttpRouteDoc {
|
|
411
|
-
name: string
|
|
412
|
-
path: string
|
|
413
|
-
methods: ('get' | 'post')[]
|
|
414
|
-
streamMode: 'sse' | 'text'
|
|
415
|
-
scope: string | string[]
|
|
416
|
-
version: number
|
|
417
|
-
jsonSchema: {
|
|
418
|
-
params?: Record<string, unknown> // From schema.params
|
|
419
|
-
yieldType?: Record<string, unknown> // SSE: envelope with data/event/id/retry; Text: from schema.yieldType
|
|
420
|
-
returnType?: Record<string, unknown> // From schema.returnType
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
```
|
|
424
|
-
|
|
425
|
-
In SSE mode, the documented `yieldType` is an SSE envelope schema with the user's `yieldType` nested under the `data` property:
|
|
426
|
-
|
|
427
|
-
```json
|
|
428
|
-
{
|
|
429
|
-
"type": "object",
|
|
430
|
-
"description": "SSE message envelope. The data field contains the procedure yield value.",
|
|
431
|
-
"required": ["data", "event", "id"],
|
|
432
|
-
"properties": {
|
|
433
|
-
"data": { /* user's yieldType schema */ },
|
|
434
|
-
"event": { "type": "string" },
|
|
435
|
-
"id": { "type": "string" },
|
|
436
|
-
"retry": { "type": "number" }
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
```
|
|
440
|
-
|
|
441
|
-
## Procedure Filtering
|
|
442
|
-
|
|
443
|
-
Only streaming procedures (created with `CreateStream`) are registered. Regular procedures created with `Create` are ignored by this builder.
|
|
444
|
-
|
|
445
|
-
```typescript
|
|
446
|
-
const RPC = Procedures<Context, RPCConfig>()
|
|
447
|
-
|
|
448
|
-
// This will NOT be registered by HonoStreamAppBuilder
|
|
449
|
-
RPC.Create('GetUser', config, async (ctx) => ({ user: 'data' }))
|
|
450
|
-
|
|
451
|
-
// This WILL be registered
|
|
452
|
-
RPC.CreateStream('WatchUser', config, async function* (ctx) {
|
|
453
|
-
yield { update: 'data' }
|
|
454
|
-
})
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
## Client Disconnect Handling
|
|
458
|
-
|
|
459
|
-
When a client disconnects, the stream's `onAbort` handler is triggered, which calls `generator.return()` to clean up. The `ctx.signal` in your handler will be aborted.
|
|
460
|
-
|
|
461
|
-
`HonoStreamAppBuilder` injects the HTTP request's `AbortSignal` (`c.req.raw.signal`) into the handler context. This is combined with the stream's internal `AbortController` via `AbortSignal.any()`, so `ctx.signal` aborts on either client disconnect or normal stream completion.
|
|
462
|
-
|
|
463
|
-
Use `signal.reason` to distinguish between the two:
|
|
464
|
-
|
|
465
|
-
```typescript
|
|
466
|
-
RPC.CreateStream('LongStream', config, async function* (ctx) {
|
|
467
|
-
try {
|
|
468
|
-
while (!ctx.signal.aborted) {
|
|
469
|
-
yield { tick: Date.now() }
|
|
470
|
-
await new Promise((r) => setTimeout(r, 1000))
|
|
471
|
-
}
|
|
472
|
-
} finally {
|
|
473
|
-
if (ctx.signal.reason === 'stream-completed') {
|
|
474
|
-
// Generator finished normally
|
|
475
|
-
} else {
|
|
476
|
-
// Client disconnected — clean up resources
|
|
477
|
-
await releaseResources()
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
})
|
|
481
|
-
```
|
|
482
|
-
|
|
483
|
-
## TypeScript Types
|
|
484
|
-
|
|
485
|
-
```typescript
|
|
486
|
-
import {
|
|
487
|
-
HonoStreamAppBuilder,
|
|
488
|
-
defineErrorTaxonomy,
|
|
489
|
-
sse, // Helper to attach SSE metadata (event/id/retry) to yielded objects
|
|
490
|
-
} from 'ts-procedures/hono-stream'
|
|
491
|
-
import type {
|
|
492
|
-
HonoStreamAppBuilderConfig, // Generic: HonoStreamAppBuilderConfig<TErrorData = unknown>
|
|
493
|
-
StreamHttpRouteDoc,
|
|
494
|
-
StreamMode,
|
|
495
|
-
SSEOptions, // Type for sse() options: { event?, id?, retry? }
|
|
496
|
-
MidStreamErrorResult, // Generic: MidStreamErrorResult<TErrorData = unknown>
|
|
497
|
-
ErrorTaxonomy,
|
|
498
|
-
ErrorTaxonomyEntry,
|
|
499
|
-
UnknownErrorConfig,
|
|
500
|
-
OnRequestErrorContext, // Passed to the onRequestError observer: { err, procedure, raw: Context }
|
|
501
|
-
} from 'ts-procedures/hono-stream'
|
|
502
|
-
```
|
|
503
|
-
|
|
504
|
-
## Migration Notes
|
|
505
|
-
|
|
506
|
-
### Migrating from v5
|
|
507
|
-
|
|
508
|
-
**Breaking: `MidStreamErrorResult` no longer has `event` and `id` fields.** Use `sse()` to attach SSE metadata to error data instead:
|
|
509
|
-
|
|
510
|
-
```typescript
|
|
511
|
-
// Before (v5)
|
|
512
|
-
onMidStreamError: (proc, c, error) => ({
|
|
513
|
-
data: { type: 'error', message: error.message },
|
|
514
|
-
event: 'custom-error',
|
|
515
|
-
id: 'err-1',
|
|
516
|
-
})
|
|
517
|
-
|
|
518
|
-
// After (v6)
|
|
519
|
-
onMidStreamError: (proc, c, error) => ({
|
|
520
|
-
data: sse(
|
|
521
|
-
{ type: 'error', message: error.message },
|
|
522
|
-
{ event: 'custom-error', id: 'err-1' }
|
|
523
|
-
),
|
|
524
|
-
})
|
|
525
|
-
```
|
|
526
|
-
|
|
527
|
-
**Breaking: `onStreamStart` / `onStreamEnd` now receive `streamMode` as a third parameter.**
|
|
528
|
-
|
|
529
|
-
```typescript
|
|
530
|
-
// Before (v5)
|
|
531
|
-
onStreamStart: (procedure, c) => { ... }
|
|
532
|
-
onStreamEnd: (procedure, c) => { ... }
|
|
533
|
-
|
|
534
|
-
// After (v6)
|
|
535
|
-
onStreamStart: (procedure, c, streamMode) => { ... }
|
|
536
|
-
onStreamEnd: (procedure, c, streamMode) => { ... }
|
|
537
|
-
```
|
|
538
|
-
|
|
539
|
-
**Breaking: `StreamHttpRouteDoc.jsonSchema` fields narrowed from `object` to `Record<string, unknown>`.**
|
|
540
|
-
|
|
541
|
-
**New: Generic `TErrorData` parameter** on `HonoStreamAppBuilder` and `MidStreamErrorResult` for type-safe `onMidStreamError` callbacks.
|
|
542
|
-
|
|
543
|
-
**Breaking: `onPreStreamError` renamed to `onError`** for consistency with the other three HTTP builders. Signature unchanged.
|
|
544
|
-
|
|
545
|
-
```typescript
|
|
546
|
-
// Before (v5)
|
|
547
|
-
new HonoStreamAppBuilder({
|
|
548
|
-
onPreStreamError: (proc, c, err) => c.json({ error: err.message }, 400),
|
|
549
|
-
})
|
|
550
|
-
|
|
551
|
-
// After (v6)
|
|
552
|
-
new HonoStreamAppBuilder({
|
|
553
|
-
onError: (proc, c, err) => c.json({ error: err.message }, 400),
|
|
554
|
-
})
|
|
555
|
-
```
|
|
556
|
-
|
|
557
|
-
**Breaking: hard-default status for `ProcedureValidationError` changed from 400 to 500.** Previously, `HonoStreamAppBuilder` special-cased validation errors to 400 when no `errors` / `onError` was configured. v6 drops this inconsistency — the hard default is now 500 across all four builders. To preserve the 400 response, configure the taxonomy (`errors: {}` engages framework defaults) or handle it in `onError`.
|
|
558
|
-
|
|
559
|
-
**New: `onRequestError` cross-cutting observer.** Fires for every caught pre-stream error, before dispatch. Awaited, cannot mutate the response. Use for logging, tracing, metrics. See [docs/http-integrations.md § Error Handling](../../../../docs/http-integrations.md#error-handling).
|