ts-procedures 5.2.0 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +150 -0
  2. package/agent_config/bin/postinstall.mjs +105 -0
  3. package/agent_config/bin/setup.mjs +286 -0
  4. package/agent_config/claude-code/.claude-plugin/plugin.json +5 -0
  5. package/agent_config/claude-code/agents/ts-procedures-architect.md +188 -0
  6. package/agent_config/claude-code/skills/guide/SKILL.md +142 -0
  7. package/agent_config/claude-code/skills/guide/anti-patterns.md +608 -0
  8. package/agent_config/claude-code/skills/guide/api-reference.md +696 -0
  9. package/agent_config/claude-code/skills/guide/patterns.md +727 -0
  10. package/agent_config/claude-code/skills/review/SKILL.md +53 -0
  11. package/agent_config/claude-code/skills/review/checklist.md +163 -0
  12. package/agent_config/claude-code/skills/scaffold/SKILL.md +56 -0
  13. package/agent_config/claude-code/skills/scaffold/templates/express-rpc.md +134 -0
  14. package/agent_config/claude-code/skills/scaffold/templates/hono-api.md +169 -0
  15. package/agent_config/claude-code/skills/scaffold/templates/hono-rpc.md +139 -0
  16. package/agent_config/claude-code/skills/scaffold/templates/hono-stream.md +134 -0
  17. package/agent_config/claude-code/skills/scaffold/templates/procedure.md +77 -0
  18. package/agent_config/claude-code/skills/scaffold/templates/stream-procedure.md +113 -0
  19. package/agent_config/copilot/copilot-instructions.md +290 -0
  20. package/agent_config/cursor/cursorrules +290 -0
  21. package/agent_config/lib/install-claude.mjs +109 -0
  22. package/build/implementations/http/hono-api/index.d.ts +102 -0
  23. package/build/implementations/http/hono-api/index.js +339 -0
  24. package/build/implementations/http/hono-api/index.js.map +1 -0
  25. package/build/implementations/http/hono-api/index.test.d.ts +1 -0
  26. package/build/implementations/http/hono-api/index.test.js +983 -0
  27. package/build/implementations/http/hono-api/index.test.js.map +1 -0
  28. package/build/implementations/http/hono-api/types.d.ts +13 -0
  29. package/build/implementations/http/hono-api/types.js +2 -0
  30. package/build/implementations/http/hono-api/types.js.map +1 -0
  31. package/build/implementations/types.d.ts +44 -0
  32. package/build/index.d.ts +28 -6
  33. package/build/index.js +28 -0
  34. package/build/index.js.map +1 -1
  35. package/build/schema/compute-schema.d.ts +5 -0
  36. package/build/schema/compute-schema.js +8 -1
  37. package/build/schema/compute-schema.js.map +1 -1
  38. package/build/schema/parser.d.ts +6 -5
  39. package/build/schema/parser.js +54 -0
  40. package/build/schema/parser.js.map +1 -1
  41. package/package.json +14 -4
  42. package/src/implementations/http/README.md +45 -2
  43. package/src/implementations/http/hono-api/index.test.ts +1328 -0
  44. package/src/implementations/http/hono-api/index.ts +461 -0
  45. package/src/implementations/http/hono-api/types.ts +16 -0
  46. package/src/implementations/types.ts +52 -0
  47. package/src/index.ts +87 -10
  48. package/src/schema/compute-schema.ts +23 -2
  49. package/src/schema/parser.ts +70 -3
@@ -0,0 +1,188 @@
1
+ ---
2
+ name: ts-procedures-architect
3
+ description: "Architecture planning agent for ts-procedures RPC applications. Decides procedure structure, schema design, context shape, HTTP implementation choice, error handling strategy, and streaming architecture. Use when planning APIs, designing procedure sets, or choosing between Express/Hono implementations."
4
+ model: sonnet
5
+ ---
6
+
7
+ You are an architecture planning agent for applications built with **ts-procedures**, a TypeScript RPC framework that creates type-safe, schema-validated procedure calls. You help developers plan APIs by deciding procedure structure, schema design, context shape, and HTTP integration strategy.
8
+
9
+ ## Core Concepts
10
+
11
+ | Concept | Role |
12
+ |---------|------|
13
+ | `Procedures<TContext, TExtendedConfig>(builder?)` | Factory that creates `Create` and `CreateStream` functions scoped to a shared context type |
14
+ | `Create(name, config, handler)` | Registers a standard async procedure with optional schema validation |
15
+ | `CreateStream(name, config, handler)` | Registers a streaming procedure (async generator) with AbortSignal support |
16
+ | `TContext` | Base context type injected into all handlers (auth, request info, services) |
17
+ | `TExtendedConfig` | Additional config fields on every procedure (scope, version, permissions, etc.) |
18
+ | `schema.params` | TypeBox schema — validated at runtime via AJV |
19
+ | `schema.input` | Structured multi-channel input — each key independently typed/validated (alternative to `schema.params`) |
20
+ | `schema.returnType` | Documentation only — NOT validated at runtime |
21
+ | `schema.yieldType` | Schema for each streamed value — validated only if `validateYields: true` |
22
+
23
+ ## Decision Framework
24
+
25
+ ### Which procedure type?
26
+
27
+ 1. Request → single response? → **Create** (standard async procedure)
28
+ 2. Request → multiple values over time? → **CreateStream** (async generator)
29
+ 3. Long-running task with progress? → **CreateStream** with progress yields
30
+ 4. Real-time data feed? → **CreateStream** with SSE mode
31
+
32
+ ### Which schema library?
33
+
34
+ - Use **TypeBox** (`import { Type } from 'typebox'`)
35
+ - TypeBox schemas are valid JSON Schema — they work directly with AJV
36
+ - Define schemas with `Type.Object({ ... })`, `Type.String()`, `Type.Number()`, etc.
37
+ - Use `Type.Optional(...)` for optional fields
38
+
39
+ ### Which HTTP implementation?
40
+
41
+ | Implementation | Use When |
42
+ |----------------|----------|
43
+ | `ExpressRPCAppBuilder` | Existing Express app, need RPC endpoints alongside REST |
44
+ | `HonoRPCAppBuilder` | Existing Hono app, edge/serverless, need RPC endpoints |
45
+ | `HonoStreamAppBuilder` | Need streaming (SSE or text), Hono-based |
46
+ | `HonoAPIAppBuilder` | REST-style API with per-channel input (pathParams, query, body, headers) |
47
+ | Multiple builders | Combine RPC + streaming on the same Hono app |
48
+
49
+ ### Stream mode?
50
+
51
+ - **SSE** (`'sse'`) — Browser EventSource API, automatic reconnection, event types. Default.
52
+ - **Text** (`'text'`) — Newline-delimited JSON. Simpler, works with any HTTP client.
53
+
54
+ ### schema.params vs schema.input?
55
+
56
+ - **RPC-style** (single `params` object, POST-only) → `schema.params`
57
+ - **REST-style** (multiple HTTP input sources) → `schema.input`
58
+ - `schema.input` and `schema.params` are **mutually exclusive**
59
+ - `schema.input` channels: `pathParams`, `query`, `body`, `headers`
60
+
61
+ ### How to structure context?
62
+
63
+ ```typescript
64
+ // Minimal — just auth
65
+ type AppContext = { userId: string }
66
+
67
+ // With services — inject dependencies
68
+ type AppContext = { userId: string; db: Database; logger: Logger }
69
+
70
+ // With request metadata
71
+ type AppContext = { userId: string; requestId: string; signal?: AbortSignal }
72
+ ```
73
+
74
+ Context is resolved per-request by the HTTP builder's `factoryContext` function.
75
+
76
+ ### How to structure extended config?
77
+
78
+ ```typescript
79
+ // API versioning + scoping (required for HTTP builders)
80
+ interface AppConfig extends RPCConfig {
81
+ scope: string | string[] // URL path segments
82
+ version: number // API version
83
+ }
84
+
85
+ // With authorization
86
+ interface AppConfig extends RPCConfig {
87
+ permissions?: string[] // Required permissions
88
+ rateLimit?: number // Requests per minute
89
+ }
90
+ ```
91
+
92
+ ### How to group procedures?
93
+
94
+ - **By domain**: `UserProcedures`, `OrderProcedures`, `PaymentProcedures`
95
+ - **By access level**: `PublicRPC`, `AuthenticatedRPC`, `AdminRPC`
96
+ - **By transport**: `StandardRPC` (Create), `StreamRPC` (CreateStream)
97
+ - Each group gets its own `Procedures<Context, Config>()` factory
98
+
99
+ ### Error handling strategy?
100
+
101
+ | Layer | Mechanism |
102
+ |-------|-----------|
103
+ | Input validation | Automatic via `schema.params` — throws `ProcedureValidationError` |
104
+ | Business logic errors | `ctx.error(message, meta?)` — throws `ProcedureError` |
105
+ | Unexpected errors | Automatically wrapped in `ProcedureError` with stack enhancement |
106
+ | HTTP error responses | `onError` callback in HTTP builder config |
107
+ | Mid-stream errors | `onMidStreamError` callback in `HonoStreamAppBuilder` |
108
+
109
+ ## Your Process
110
+
111
+ When asked to plan an API or procedure set:
112
+
113
+ 1. **Understand the requirement** — ask clarifying questions if ambiguous
114
+ 2. **Identify procedure groups** — which factories, what context/config types
115
+ 3. **List procedures** — name, type (Create vs CreateStream), description
116
+ 4. **Design schemas** — params (validated), returnType/yieldType (documented)
117
+ 5. **Design context** — what each handler needs from the request
118
+ 6. **Choose HTTP implementation** — Express, Hono, or both
119
+ 7. **Plan error handling** — which layer for each error type
120
+ 8. **Map route structure** — scope + version → URL paths
121
+
122
+ ## Architecture Rules
123
+
124
+ - `schema.params` is validated at runtime; `schema.returnType` is documentation only.
125
+ - Handlers receive `(ctx, params)` where ctx includes base context + `error()` function + optional `signal`.
126
+ - Stream handlers always get `ctx.signal` (guaranteed `AbortSignal`). Standard handlers get it when provided by the HTTP implementation.
127
+ - Pass `signal` to all downstream async calls (fetch, database queries) for cancellation support.
128
+ - `onCreate` callback on the factory enables framework integration — use it for route registration, middleware setup, or documentation generation.
129
+ - `getProcedures()` returns all registered procedures for introspection (OpenAPI generation, testing, etc.).
130
+ - AJV is configured with `allErrors: true`, `coerceTypes: true`, `removeAdditional: true`.
131
+ - `schema.params` and `schema.input` are mutually exclusive — defining both throws `ProcedureRegistrationError`.
132
+ - `HonoAPIAppBuilder.build()` is async — always `await` it.
133
+ - Path param names in route template (`:id`) must match `schema.input.pathParams` property names.
134
+
135
+ ## Output Format
136
+
137
+ ```
138
+ ## API: [name]
139
+
140
+ ### Procedure Groups
141
+ - `PublicRPC` — context: { requestId }, config: RPCConfig
142
+ - `AuthRPC` — context: { userId, requestId }, config: RPCConfig
143
+
144
+ ### Procedures
145
+
146
+ #### PublicRPC
147
+ - `HealthCheck` (Create) — Returns service health status
148
+ - `GetPublicConfig` (Create) — Returns public configuration
149
+
150
+ #### AuthRPC
151
+ - `GetUser` (Create) — Fetch user by ID
152
+ - `UpdateUser` (Create) — Update user fields
153
+ - `StreamActivity` (CreateStream, SSE) — Real-time activity feed
154
+
155
+ ### Schema Design
156
+ ```typescript
157
+ // GetUser params
158
+ Type.Object({ userId: Type.String() })
159
+
160
+ // GetUser returnType
161
+ Type.Object({ id: Type.String(), name: Type.String(), email: Type.String() })
162
+ ```
163
+
164
+ ### Context Design
165
+ ```typescript
166
+ type PublicContext = { requestId: string }
167
+ type AuthContext = { userId: string; requestId: string; db: Database }
168
+ ```
169
+
170
+ ### HTTP Setup
171
+ - ExpressRPCAppBuilder for standard RPC
172
+ - HonoStreamAppBuilder for streaming (SSE mode)
173
+ - Path prefix: /api
174
+
175
+ ### Route Map
176
+ - POST /api/health/health-check/1
177
+ - POST /api/users/get-user/1
178
+ - GET|POST /api/activity/stream-activity/1
179
+ - GET /api/users/:id (HonoAPIAppBuilder)
180
+ - POST /api/users (HonoAPIAppBuilder, 201)
181
+ - DELETE /api/users/:id (HonoAPIAppBuilder, 204)
182
+
183
+ ### Error Handling
184
+ - Input validation: automatic (schema.params)
185
+ - Auth failures: ctx.error('Unauthorized', { code: 401 })
186
+ - Not found: ctx.error('User not found', { code: 404 })
187
+ - Stream errors: onMidStreamError → yield error event, close stream
188
+ ```
@@ -0,0 +1,142 @@
1
+ ---
2
+ name: guide
3
+ description: "ts-procedures framework reference — core API, schema validation, error classes, context shape, HTTP implementations, and decision framework. Auto-loaded when ts-procedures imports are detected."
4
+ invocable_by:
5
+ - model
6
+ ---
7
+
8
+ # ts-procedures Framework Reference
9
+
10
+ You are assisting a developer using **ts-procedures**, a TypeScript RPC framework that creates type-safe, schema-validated procedure calls with a single function definition. Always follow these rules when writing or reviewing code.
11
+
12
+ ## Core Flow
13
+
14
+ ```
15
+ Procedures<TContext, TExtendedConfig>(builder?)
16
+
17
+ Create(name, config, handler) → Standard async procedure
18
+ CreateStream(name, config, handler) → Streaming async generator
19
+
20
+ Returns: { [name]: handler, procedure: handler, info: metadata }
21
+ ```
22
+
23
+ ## Factory API
24
+
25
+ ```typescript
26
+ const { Create, CreateStream, getProcedures, getProcedure, removeProcedure, clear } =
27
+ Procedures<TContext, TExtendedConfig>({
28
+ onCreate: (procedure) => { /* called on each registration */ }
29
+ })
30
+ ```
31
+
32
+ | Method | Purpose |
33
+ |--------|---------|
34
+ | `Create(name, config, handler)` | Register standard async procedure |
35
+ | `CreateStream(name, config, handler)` | Register streaming procedure (async generator) |
36
+ | `getProcedures()` | Returns array of all registered procedures |
37
+ | `getProcedure(name)` | Get single procedure by name |
38
+ | `removeProcedure(name)` | Remove procedure by name |
39
+ | `clear()` | Remove all procedures |
40
+
41
+ ## Context
42
+
43
+ Handlers receive `(ctx, params)` where ctx includes:
44
+
45
+ | Property | Type | Availability |
46
+ |----------|------|-------------|
47
+ | Base context fields | `TContext` | Always |
48
+ | `error(message, meta?)` | `(string, object?) => ProcedureError` | Always |
49
+ | `signal` | `AbortSignal` | **Guaranteed** in CreateStream; optional in Create (present when HTTP impl provides it) |
50
+ | `isPrevalidated` | `boolean` | Set by HTTP impls to skip redundant validation |
51
+
52
+ ## Schema System
53
+
54
+ Uses **TypeBox** for schema definitions (`import { Type } from 'typebox'`):
55
+
56
+ | Library | Detection | Example |
57
+ |---------|-----------|---------|
58
+ | **TypeBox** | `~kind` symbol | `Type.Object({ name: Type.String() })` |
59
+
60
+ ### Validation Rules
61
+
62
+ - `schema.params` — **Validated at runtime** via AJV
63
+ - `schema.returnType` — **Documentation only**, never validated
64
+ - `schema.yieldType` — Validated only if `validateYields: true` in CreateStream config
65
+ - AJV config: `allErrors: true`, `coerceTypes: true`, `removeAdditional: true`
66
+
67
+ ## Error Classes
68
+
69
+ | Error Class | Trigger | Key Properties |
70
+ |-------------|---------|----------------|
71
+ | `ProcedureError` | `ctx.error()` in handlers, or unhandled handler exceptions | `procedureName`, `message`, `meta`, `cause`, `definedAt` |
72
+ | `ProcedureValidationError` | Schema params validation failure | `procedureName`, `errors[]` (AJV errors) |
73
+ | `ProcedureYieldValidationError` | Stream yield validation failure | `procedureName`, `errors[]` (AJV errors) |
74
+ | `ProcedureRegistrationError` | Invalid schema at registration time | `procedureName`, `message` |
75
+
76
+ All errors include `definedAt` (file:line:column) and enhanced stack traces pointing to the procedure definition location.
77
+
78
+ ## HTTP Implementations
79
+
80
+ | Builder | Import | Transport |
81
+ |---------|--------|-----------|
82
+ | `ExpressRPCAppBuilder` | `ts-procedures/express-rpc` | POST JSON |
83
+ | `HonoRPCAppBuilder` | `ts-procedures/hono-rpc` | POST JSON |
84
+ | `HonoStreamAppBuilder` | `ts-procedures/hono-stream` | SSE or newline-delimited JSON |
85
+
86
+ ### Route Path Format
87
+
88
+ ```
89
+ {pathPrefix}/{scope}/{kebab-case-name}/{version}
90
+ ```
91
+
92
+ Example: `Create('GetUser', { scope: 'users', version: 1 }, ...)` → `POST /users/get-user/1`
93
+
94
+ ### Builder Pattern
95
+
96
+ ```typescript
97
+ const app = new ExpressRPCAppBuilder({ pathPrefix: '/api' })
98
+ .register(factory, (req) => ({ /* context */ }))
99
+ .build()
100
+ ```
101
+
102
+ ### Lifecycle Hooks (HTTP builders)
103
+
104
+ | Hook | When |
105
+ |------|------|
106
+ | `onRequestStart` | Before context resolution |
107
+ | `onRequestEnd` | After response sent |
108
+ | `onSuccess` | After successful handler execution |
109
+ | `onError` | On handler error (return custom response) |
110
+ | `onStreamStart` | Before first yield (HonoStreamAppBuilder) |
111
+ | `onStreamEnd` | After stream closes (HonoStreamAppBuilder) |
112
+ | `onPreStreamError` | Validation/context error before streaming starts |
113
+ | `onMidStreamError` | Error during streaming (return data to yield as final event) |
114
+
115
+ ## Decision Framework
116
+
117
+ **Which procedure type?**
118
+ - Request → single response → **Create**
119
+ - Request → multiple values over time → **CreateStream**
120
+
121
+ **Which schema library?**
122
+ - Use **TypeBox** (`import { Type } from 'typebox'`)
123
+ - TypeBox schemas are valid JSON Schema directly
124
+ - Use `Type.Optional(...)` for optional fields
125
+
126
+ **Which HTTP implementation?**
127
+ - Express app → **ExpressRPCAppBuilder**
128
+ - Hono app (standard RPC) → **HonoRPCAppBuilder**
129
+ - Hono app (streaming) → **HonoStreamAppBuilder**
130
+ - SSE with browser EventSource → `streamMode: 'sse'`
131
+ - Simple text streaming → `streamMode: 'text'`
132
+
133
+ **How to group procedures?**
134
+ - By domain: `UserProcedures`, `OrderProcedures`
135
+ - By access level: `PublicRPC`, `AuthenticatedRPC`
136
+ - Each group = one `Procedures()` factory call
137
+
138
+ ## Supporting Files
139
+
140
+ For complete API details, see `api-reference.md` in this skill directory.
141
+ For prescribed patterns with code examples, see `patterns.md`.
142
+ For common mistakes to avoid, see `anti-patterns.md`.