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,142 +0,0 @@
|
|
|
1
|
-
# Hono RPC Template: {{Name}}
|
|
2
|
-
|
|
3
|
-
## Implementation — `{{Name}}.rpc.ts`
|
|
4
|
-
|
|
5
|
-
```typescript
|
|
6
|
-
import { Procedures } from 'ts-procedures'
|
|
7
|
-
import { HonoRPCAppBuilder, defineErrorTaxonomy } from 'ts-procedures/hono-rpc'
|
|
8
|
-
import type { RPCConfig } from 'ts-procedures/http'
|
|
9
|
-
import { Type } from 'typebox'
|
|
10
|
-
|
|
11
|
-
// ─── Context ──────────────────────────────────────────────
|
|
12
|
-
|
|
13
|
-
type {{Name}}Context = {
|
|
14
|
-
userId: string
|
|
15
|
-
requestId: string
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// ─── Procedures ───────────────────────────────────────────
|
|
19
|
-
|
|
20
|
-
const RPC = Procedures<{{Name}}Context, RPCConfig>()
|
|
21
|
-
|
|
22
|
-
export const { GetItem } = RPC.Create(
|
|
23
|
-
'GetItem',
|
|
24
|
-
{
|
|
25
|
-
scope: '{{name}}', // TODO: set URL scope
|
|
26
|
-
version: 1,
|
|
27
|
-
description: 'Fetch item by ID',
|
|
28
|
-
schema: {
|
|
29
|
-
params: Type.Object({
|
|
30
|
-
id: Type.String(),
|
|
31
|
-
}),
|
|
32
|
-
returnType: Type.Object({
|
|
33
|
-
id: Type.String(),
|
|
34
|
-
name: Type.String(),
|
|
35
|
-
}),
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
async (ctx, params) => {
|
|
39
|
-
// TODO: implement
|
|
40
|
-
return { id: params.id, name: 'Example' }
|
|
41
|
-
}
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
export const { ListItems } = RPC.Create(
|
|
45
|
-
'ListItems',
|
|
46
|
-
{
|
|
47
|
-
scope: '{{name}}',
|
|
48
|
-
version: 1,
|
|
49
|
-
description: 'List all items',
|
|
50
|
-
schema: {
|
|
51
|
-
params: Type.Object({
|
|
52
|
-
page: Type.Optional(Type.Number()),
|
|
53
|
-
limit: Type.Optional(Type.Number()),
|
|
54
|
-
}),
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
async (ctx, params) => {
|
|
58
|
-
// TODO: implement
|
|
59
|
-
return { items: [], total: 0 }
|
|
60
|
-
}
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
// ─── Error Taxonomy ───────────────────────────────────────
|
|
64
|
-
// Declare the error classes this service throws. Framework errors
|
|
65
|
-
// (ProcedureValidationError → 400, ctx.error() → 500) are caught by the
|
|
66
|
-
// default taxonomy automatically. Add your own classes here — handlers just
|
|
67
|
-
// `throw` them and the builder serializes via this map. See
|
|
68
|
-
// docs/http-integrations.md#error-handling for the full contract.
|
|
69
|
-
|
|
70
|
-
const {{name}}Errors = defineErrorTaxonomy({
|
|
71
|
-
// Example — replace with your app's error classes:
|
|
72
|
-
// NotFoundError: { class: NotFoundError, statusCode: 404 },
|
|
73
|
-
// AuthError: { class: AuthError, statusCode: 401 },
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
// ─── Hono App Builder ─────────────────────────────────────
|
|
77
|
-
|
|
78
|
-
export const {{name}}App = new HonoRPCAppBuilder({
|
|
79
|
-
pathPrefix: '/api',
|
|
80
|
-
errors: {{name}}Errors,
|
|
81
|
-
unknownError: {
|
|
82
|
-
statusCode: 500,
|
|
83
|
-
toResponse: () => ({ name: 'InternalServerError', message: 'Unexpected error' }),
|
|
84
|
-
onCatch: (err, { procedure }) => console.error(`[${procedure.name}]`, err),
|
|
85
|
-
},
|
|
86
|
-
})
|
|
87
|
-
.register(RPC, (c) => ({
|
|
88
|
-
userId: c.req.header('x-user-id') || 'anonymous',
|
|
89
|
-
requestId: c.req.header('x-request-id') || crypto.randomUUID(),
|
|
90
|
-
}))
|
|
91
|
-
.build()
|
|
92
|
-
|
|
93
|
-
// Route map:
|
|
94
|
-
// POST /api/{{name}}/get-item/1
|
|
95
|
-
// POST /api/{{name}}/list-items/1
|
|
96
|
-
|
|
97
|
-
// Documentation: {{name}}App.docs
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
## Test — `{{Name}}.rpc.test.ts`
|
|
101
|
-
|
|
102
|
-
```typescript
|
|
103
|
-
import { describe, test, expect } from 'vitest'
|
|
104
|
-
import { {{name}}App } from './{{Name}}.rpc'
|
|
105
|
-
|
|
106
|
-
describe('{{Name}} RPC', () => {
|
|
107
|
-
test('GET item returns expected result', async () => {
|
|
108
|
-
const res = await {{name}}App.request('/api/{{name}}/get-item/1', {
|
|
109
|
-
method: 'POST',
|
|
110
|
-
headers: { 'Content-Type': 'application/json' },
|
|
111
|
-
body: JSON.stringify({ id: 'item-1' }),
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
expect(res.status).toBe(200)
|
|
115
|
-
const body = await res.json()
|
|
116
|
-
expect(body).toEqual({ id: 'item-1', name: 'Example' })
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
test('returns 400 for invalid params', async () => {
|
|
120
|
-
const res = await {{name}}App.request('/api/{{name}}/get-item/1', {
|
|
121
|
-
method: 'POST',
|
|
122
|
-
headers: { 'Content-Type': 'application/json' },
|
|
123
|
-
body: JSON.stringify({}),
|
|
124
|
-
})
|
|
125
|
-
|
|
126
|
-
expect(res.status).toBe(400)
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
test('LIST items returns array', async () => {
|
|
130
|
-
const res = await {{name}}App.request('/api/{{name}}/list-items/1', {
|
|
131
|
-
method: 'POST',
|
|
132
|
-
headers: { 'Content-Type': 'application/json' },
|
|
133
|
-
body: JSON.stringify({ page: 1, limit: 10 }),
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
expect(res.status).toBe(200)
|
|
137
|
-
const body = await res.json()
|
|
138
|
-
expect(body).toHaveProperty('items')
|
|
139
|
-
expect(body).toHaveProperty('total')
|
|
140
|
-
})
|
|
141
|
-
})
|
|
142
|
-
```
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
# Hono Stream Template: {{Name}}
|
|
2
|
-
|
|
3
|
-
## Implementation — `{{Name}}.stream-rpc.ts`
|
|
4
|
-
|
|
5
|
-
```typescript
|
|
6
|
-
import { Procedures } from 'ts-procedures'
|
|
7
|
-
import { HonoStreamAppBuilder, sse, defineErrorTaxonomy } from 'ts-procedures/hono-stream'
|
|
8
|
-
import type { RPCConfig } from 'ts-procedures/http'
|
|
9
|
-
import { Type } from 'typebox'
|
|
10
|
-
|
|
11
|
-
// ─── Context ──────────────────────────────────────────────
|
|
12
|
-
|
|
13
|
-
type {{Name}}Context = {
|
|
14
|
-
userId: string
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// ─── Stream Procedures ────────────────────────────────────
|
|
18
|
-
|
|
19
|
-
const StreamRPC = Procedures<{{Name}}Context, RPCConfig>()
|
|
20
|
-
|
|
21
|
-
export const { {{Name}}Stream } = StreamRPC.CreateStream(
|
|
22
|
-
'{{Name}}Stream',
|
|
23
|
-
{
|
|
24
|
-
scope: '{{name}}', // TODO: set URL scope
|
|
25
|
-
version: 1,
|
|
26
|
-
description: 'TODO: describe what this streams',
|
|
27
|
-
schema: {
|
|
28
|
-
params: Type.Object({
|
|
29
|
-
// TODO: define input parameters
|
|
30
|
-
channel: Type.String(),
|
|
31
|
-
}),
|
|
32
|
-
yieldType: Type.Object({
|
|
33
|
-
// TODO: define shape of each yielded value
|
|
34
|
-
type: Type.String(),
|
|
35
|
-
payload: Type.Any(),
|
|
36
|
-
timestamp: Type.Number(),
|
|
37
|
-
}),
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
async function* (ctx, params) {
|
|
41
|
-
// ctx.signal is ALWAYS present in stream handlers
|
|
42
|
-
|
|
43
|
-
// TODO: implement streaming logic
|
|
44
|
-
let counter = 0
|
|
45
|
-
while (!ctx.signal.aborted) {
|
|
46
|
-
const event = await pollForEvents(params.channel, { signal: ctx.signal })
|
|
47
|
-
|
|
48
|
-
// Use sse() to attach SSE metadata (event type, id, retry)
|
|
49
|
-
yield sse(
|
|
50
|
-
{ type: event.type, payload: event.data, timestamp: Date.now() },
|
|
51
|
-
{ event: event.type, id: String(counter++) }
|
|
52
|
-
)
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
// Placeholder — replace with real event source
|
|
58
|
-
async function pollForEvents(channel: string, opts?: { signal?: AbortSignal }) {
|
|
59
|
-
await new Promise(r => setTimeout(r, 1000))
|
|
60
|
-
return { type: 'update', data: { value: Math.random() } }
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// ─── Error Taxonomy (pre-stream) ──────────────────────────
|
|
64
|
-
// Pre-stream errors (validation, context resolution) flow through the
|
|
65
|
-
// taxonomy — framework errors are caught by the default taxonomy automatically.
|
|
66
|
-
// Mid-stream errors (thrown after the first yield) still go through
|
|
67
|
-
// onMidStreamError since the HTTP status is already committed.
|
|
68
|
-
|
|
69
|
-
const {{name}}Errors = defineErrorTaxonomy({
|
|
70
|
-
// Example — replace with your app's error classes:
|
|
71
|
-
// AuthError: { class: AuthError, statusCode: 401 },
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
// ─── Hono Stream App Builder ──────────────────────────────
|
|
75
|
-
|
|
76
|
-
export const {{name}}StreamApp = new HonoStreamAppBuilder({
|
|
77
|
-
pathPrefix: '/api',
|
|
78
|
-
defaultStreamMode: 'sse', // or 'text' for newline-delimited JSON
|
|
79
|
-
errors: {{name}}Errors,
|
|
80
|
-
unknownError: {
|
|
81
|
-
statusCode: 500,
|
|
82
|
-
toResponse: () => ({ name: 'InternalServerError', message: 'Unexpected error' }),
|
|
83
|
-
},
|
|
84
|
-
onMidStreamError: (procedure, c, error) => ({
|
|
85
|
-
data: { type: 'error', payload: { message: error.message }, timestamp: Date.now() },
|
|
86
|
-
closeStream: true,
|
|
87
|
-
}),
|
|
88
|
-
})
|
|
89
|
-
.register(StreamRPC, (c) => ({
|
|
90
|
-
userId: c.req.header('x-user-id') || 'anonymous',
|
|
91
|
-
}))
|
|
92
|
-
.build()
|
|
93
|
-
|
|
94
|
-
// Routes:
|
|
95
|
-
// GET /api/{{name}}/{{name}}-stream/1?channel=test
|
|
96
|
-
// POST /api/{{name}}/{{name}}-stream/1 (body: { channel: "test" })
|
|
97
|
-
|
|
98
|
-
// SSE output per yield:
|
|
99
|
-
// event: {{Name}}Stream
|
|
100
|
-
// id: 0
|
|
101
|
-
// data: {"type":"update","payload":{...},"timestamp":1234567890}
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
## Test — `{{Name}}.stream-rpc.test.ts`
|
|
105
|
-
|
|
106
|
-
```typescript
|
|
107
|
-
import { describe, test, expect } from 'vitest'
|
|
108
|
-
import { {{name}}StreamApp } from './{{Name}}.stream-rpc'
|
|
109
|
-
|
|
110
|
-
describe('{{Name}} Stream RPC', () => {
|
|
111
|
-
test('GET returns SSE stream', async () => {
|
|
112
|
-
const res = await {{name}}StreamApp.request(
|
|
113
|
-
'/api/{{name}}/{{name}}-stream/1?channel=test'
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
expect(res.status).toBe(200)
|
|
117
|
-
expect(res.headers.get('content-type')).toContain('text/event-stream')
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
test('POST returns SSE stream', async () => {
|
|
121
|
-
const res = await {{name}}StreamApp.request(
|
|
122
|
-
'/api/{{name}}/{{name}}-stream/1',
|
|
123
|
-
{
|
|
124
|
-
method: 'POST',
|
|
125
|
-
headers: { 'Content-Type': 'application/json' },
|
|
126
|
-
body: JSON.stringify({ channel: 'test' }),
|
|
127
|
-
}
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
expect(res.status).toBe(200)
|
|
131
|
-
expect(res.headers.get('content-type')).toContain('text/event-stream')
|
|
132
|
-
})
|
|
133
|
-
|
|
134
|
-
test('returns 400 for invalid params', async () => {
|
|
135
|
-
const res = await {{name}}StreamApp.request(
|
|
136
|
-
'/api/{{name}}/{{name}}-stream/1',
|
|
137
|
-
{
|
|
138
|
-
method: 'POST',
|
|
139
|
-
headers: { 'Content-Type': 'application/json' },
|
|
140
|
-
body: JSON.stringify({}),
|
|
141
|
-
}
|
|
142
|
-
)
|
|
143
|
-
|
|
144
|
-
expect(res.status).toBe(400)
|
|
145
|
-
})
|
|
146
|
-
})
|
|
147
|
-
```
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test, vi } from 'vitest';
|
|
2
|
-
import request from 'supertest';
|
|
3
|
-
import { Type } from 'typebox';
|
|
4
|
-
import { Procedures } from '../../../index.js';
|
|
5
|
-
import { ExpressRPCAppBuilder, defineErrorTaxonomy } from './index.js';
|
|
6
|
-
class UseCaseError extends Error {
|
|
7
|
-
externalMsg;
|
|
8
|
-
internalMsg;
|
|
9
|
-
constructor(externalMsg, internalMsg) {
|
|
10
|
-
super(externalMsg);
|
|
11
|
-
this.externalMsg = externalMsg;
|
|
12
|
-
this.internalMsg = internalMsg;
|
|
13
|
-
this.name = 'UseCaseError';
|
|
14
|
-
Object.setPrototypeOf(this, UseCaseError.prototype);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
describe('ExpressRPCAppBuilder — error taxonomy', () => {
|
|
18
|
-
test('taxonomy catches user error thrown from RPC handler', async () => {
|
|
19
|
-
const errors = defineErrorTaxonomy({
|
|
20
|
-
UseCaseError: {
|
|
21
|
-
class: UseCaseError,
|
|
22
|
-
statusCode: 422,
|
|
23
|
-
toResponse: (err) => ({ name: 'UseCaseError', message: err.externalMsg }),
|
|
24
|
-
},
|
|
25
|
-
});
|
|
26
|
-
const RPC = Procedures();
|
|
27
|
-
RPC.Create('Boom', { scope: 'test', version: 1, schema: { params: Type.Object({}) } }, async () => {
|
|
28
|
-
throw new UseCaseError('ext', 'int');
|
|
29
|
-
});
|
|
30
|
-
const app = new ExpressRPCAppBuilder({ errors }).register(RPC, () => ({})).build();
|
|
31
|
-
const res = await request(app).post('/test/boom/1').send({});
|
|
32
|
-
expect(res.status).toBe(422);
|
|
33
|
-
expect(res.body).toEqual({ name: 'UseCaseError', message: 'ext' });
|
|
34
|
-
});
|
|
35
|
-
test('unknownError catches unmapped errors', async () => {
|
|
36
|
-
const RPC = Procedures();
|
|
37
|
-
RPC.Create('Boom', { scope: 'test', version: 1, schema: { params: Type.Object({}) } }, async () => {
|
|
38
|
-
throw new TypeError('db down');
|
|
39
|
-
});
|
|
40
|
-
const app = new ExpressRPCAppBuilder({
|
|
41
|
-
unknownError: { statusCode: 503, toResponse: () => ({ name: 'ServiceUnavailable' }) },
|
|
42
|
-
})
|
|
43
|
-
.register(RPC, () => ({}))
|
|
44
|
-
.build();
|
|
45
|
-
const res = await request(app).post('/test/boom/1').send({});
|
|
46
|
-
expect(res.status).toBe(503);
|
|
47
|
-
expect(res.body).toEqual({ name: 'ServiceUnavailable' });
|
|
48
|
-
});
|
|
49
|
-
test('onCatch receives { req, res } as raw context', async () => {
|
|
50
|
-
let rawSeen;
|
|
51
|
-
const errors = defineErrorTaxonomy({
|
|
52
|
-
UseCaseError: {
|
|
53
|
-
class: UseCaseError,
|
|
54
|
-
statusCode: 422,
|
|
55
|
-
onCatch: (_err, ctx) => {
|
|
56
|
-
rawSeen = ctx.raw;
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
});
|
|
60
|
-
const RPC = Procedures();
|
|
61
|
-
RPC.Create('Boom', { scope: 'test', version: 1, schema: { params: Type.Object({}) } }, async () => {
|
|
62
|
-
throw new UseCaseError('ext', 'int');
|
|
63
|
-
});
|
|
64
|
-
const app = new ExpressRPCAppBuilder({ errors }).register(RPC, () => ({})).build();
|
|
65
|
-
await request(app).post('/test/boom/1').send({});
|
|
66
|
-
expect(rawSeen.req).toBeDefined();
|
|
67
|
-
expect(rawSeen.res).toBeDefined();
|
|
68
|
-
});
|
|
69
|
-
test('onError callback handles errors not matched by the taxonomy', async () => {
|
|
70
|
-
const onError = vi.fn((_p, _req, res) => {
|
|
71
|
-
res.status(418).json({ legacy: true });
|
|
72
|
-
});
|
|
73
|
-
const RPC = Procedures();
|
|
74
|
-
RPC.Create('Boom', { scope: 'test', version: 1, schema: { params: Type.Object({}) } }, async () => {
|
|
75
|
-
throw new TypeError('legacy');
|
|
76
|
-
});
|
|
77
|
-
const app = new ExpressRPCAppBuilder({ onError }).register(RPC, () => ({})).build();
|
|
78
|
-
const res = await request(app).post('/test/boom/1').send({});
|
|
79
|
-
expect(res.status).toBe(418);
|
|
80
|
-
expect(onError).toHaveBeenCalledOnce();
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
//# sourceMappingURL=error-taxonomy.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"error-taxonomy.test.js","sourceRoot":"","sources":["../../../../src/implementations/http/express-rpc/error-taxonomy.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import express from 'express';
|
|
2
|
-
import { TProcedureRegistration } from '../../../index.js';
|
|
3
|
-
import { ExtractConfig, ExtractContext, ProceduresFactory, RPCConfig, RPCHttpRouteDoc } from '../../types.js';
|
|
4
|
-
import { ErrorTaxonomy, ErrorTaxonomyEntry, UnknownErrorConfig, defineErrorTaxonomy } from '../error-taxonomy.js';
|
|
5
|
-
export type { RPCConfig, RPCHttpRouteDoc };
|
|
6
|
-
export { defineErrorTaxonomy };
|
|
7
|
-
export type { ErrorTaxonomy, ErrorTaxonomyEntry, UnknownErrorConfig };
|
|
8
|
-
export type ExpressRPCAppBuilderConfig = {
|
|
9
|
-
/**
|
|
10
|
-
* An existing Express application instance to use.
|
|
11
|
-
* When provided, ensure to set up necessary middleware (e.g., json/body parser) beforehand.
|
|
12
|
-
* If not provided, a new instance will be created.
|
|
13
|
-
*/
|
|
14
|
-
app?: express.Express;
|
|
15
|
-
/** Optional path prefix for all RPC routes. */
|
|
16
|
-
pathPrefix?: string;
|
|
17
|
-
onRequestStart?: (req: express.Request) => void;
|
|
18
|
-
onRequestEnd?: (req: express.Request, res: express.Response) => void;
|
|
19
|
-
onSuccess?: (procedure: TProcedureRegistration, req: express.Request, res: express.Response) => void;
|
|
20
|
-
/**
|
|
21
|
-
* Declarative error-to-response mapping (one of the two peer error modes).
|
|
22
|
-
* See hono-api for the full taxonomy contract. The `raw` field passed to
|
|
23
|
-
* taxonomy callbacks is `{ req, res }`.
|
|
24
|
-
*/
|
|
25
|
-
errors?: ErrorTaxonomy;
|
|
26
|
-
/** Fallback serializer for errors not matched by the taxonomy. */
|
|
27
|
-
unknownError?: UnknownErrorConfig;
|
|
28
|
-
/**
|
|
29
|
-
* Imperative error callback — the other peer error mode. Receives every
|
|
30
|
-
* error directly and writes the response via `res`. Use this when you want
|
|
31
|
-
* full control, or alongside `errors` for the tail of errors the taxonomy
|
|
32
|
-
* doesn't cover.
|
|
33
|
-
*/
|
|
34
|
-
onError?: (procedure: TProcedureRegistration, req: express.Request, res: express.Response, error: Error) => void;
|
|
35
|
-
/**
|
|
36
|
-
* Cross-cutting observer — fires for every caught error, BEFORE dispatch.
|
|
37
|
-
* Awaited. Cannot write to `res` (observer only — check `res.headersSent`
|
|
38
|
-
* if you must touch it). Thrown errors inside the observer are swallowed
|
|
39
|
-
* and logged.
|
|
40
|
-
*/
|
|
41
|
-
onRequestError?: (ctx: OnRequestErrorContext) => void | Promise<void>;
|
|
42
|
-
};
|
|
43
|
-
/**
|
|
44
|
-
* Context passed to the `onRequestError` observer. `raw` is `{ req, res }`
|
|
45
|
-
* for the in-flight request.
|
|
46
|
-
*/
|
|
47
|
-
export type OnRequestErrorContext = {
|
|
48
|
-
err: unknown;
|
|
49
|
-
procedure: TProcedureRegistration;
|
|
50
|
-
raw: {
|
|
51
|
-
req: express.Request;
|
|
52
|
-
res: express.Response;
|
|
53
|
-
};
|
|
54
|
-
};
|
|
55
|
-
/**
|
|
56
|
-
* Builder class for creating an Express application with RPC routes.
|
|
57
|
-
*
|
|
58
|
-
* Usage:
|
|
59
|
-
* const PublicRPC = Procedures<PublicRPCContext, RPCConfig>()
|
|
60
|
-
* const ProtectedRPC = Procedures<ProtectedRPCContext, RPCConfig>()
|
|
61
|
-
*
|
|
62
|
-
* const rpcApp = new ExpressRPCAppBuilder()
|
|
63
|
-
* .register(PublicRPC, (req): Promise<PublicRPCContext> => { /* context resolution logic * / })
|
|
64
|
-
* .register(ProtectedRPC, (req): Promise<ProtectedRPCContext> => { /* context resolution logic * / })
|
|
65
|
-
* .build();
|
|
66
|
-
*
|
|
67
|
-
* const app = rpcApp.app; // Express application
|
|
68
|
-
* const docs = rpcApp.docs; // RPC route documentation
|
|
69
|
-
*/
|
|
70
|
-
export declare class ExpressRPCAppBuilder {
|
|
71
|
-
readonly config?: ExpressRPCAppBuilderConfig | undefined;
|
|
72
|
-
/**
|
|
73
|
-
* Constructor for ExpressRPCAppBuilder.
|
|
74
|
-
*
|
|
75
|
-
* @param config
|
|
76
|
-
*/
|
|
77
|
-
constructor(config?: ExpressRPCAppBuilderConfig | undefined);
|
|
78
|
-
/**
|
|
79
|
-
* Generates the RPC route path based on the RPC configuration.
|
|
80
|
-
* `RPCConfig.scope` can be a string or an array of strings to form nested paths.
|
|
81
|
-
*
|
|
82
|
-
* Example
|
|
83
|
-
* name: 'GetUser'
|
|
84
|
-
* scope: ['users', 'profile']
|
|
85
|
-
* version: 1
|
|
86
|
-
* path: /users/profile/get-user/1
|
|
87
|
-
* @param config
|
|
88
|
-
*/
|
|
89
|
-
static makeRPCHttpRoutePath({ name, config, prefix, }: {
|
|
90
|
-
name: string;
|
|
91
|
-
prefix?: string;
|
|
92
|
-
config: RPCConfig;
|
|
93
|
-
}): string;
|
|
94
|
-
/**
|
|
95
|
-
* Instance method wrapper for makeRPCHttpRoutePath that uses the builder's pathPrefix.
|
|
96
|
-
* @param config - The RPC configuration
|
|
97
|
-
*/
|
|
98
|
-
makeRPCHttpRoutePath(name: string, config: RPCConfig): string;
|
|
99
|
-
private factories;
|
|
100
|
-
private _app;
|
|
101
|
-
private _docs;
|
|
102
|
-
get app(): express.Express;
|
|
103
|
-
get docs(): RPCHttpRouteDoc[];
|
|
104
|
-
/**
|
|
105
|
-
* Registers a procedure factory with its context.
|
|
106
|
-
* @param factory - The procedure factory created by Procedures<Context, RPCConfig>()
|
|
107
|
-
* @param factoryContext - The context for procedure handlers. Can be a direct value,
|
|
108
|
-
* a sync function (req) => Context, or an async function (req) => Promise<Context>
|
|
109
|
-
* @param extendProcedureDoc - A custom function to extend the generated RPC route documentation for each procedure.
|
|
110
|
-
*/
|
|
111
|
-
register<TFactory extends ProceduresFactory>(factory: TFactory, factoryContext: ExtractContext<TFactory> | ((req: express.Request) => ExtractContext<TFactory> | Promise<ExtractContext<TFactory>>), extendProcedureDoc?: (params: {
|
|
112
|
-
base: RPCHttpRouteDoc;
|
|
113
|
-
procedure: TProcedureRegistration<any, ExtractConfig<TFactory>>;
|
|
114
|
-
}) => Record<string, any>): this;
|
|
115
|
-
/**
|
|
116
|
-
* Builds and returns the Express application with registered RPC routes.
|
|
117
|
-
* @return express.Application
|
|
118
|
-
*/
|
|
119
|
-
build(): express.Application;
|
|
120
|
-
/**
|
|
121
|
-
* Generates the RPC HTTP route for the given procedure.
|
|
122
|
-
* @param procedure
|
|
123
|
-
*/
|
|
124
|
-
private buildRpcHttpRouteDoc;
|
|
125
|
-
}
|