ts-procedures 5.9.1 → 5.10.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 (80) hide show
  1. package/README.md +1 -1
  2. package/agent_config/claude-code/agents/ts-procedures-architect.md +46 -101
  3. package/agent_config/claude-code/skills/guide/SKILL.md +49 -34
  4. package/agent_config/claude-code/skills/guide/anti-patterns.md +6 -5
  5. package/agent_config/claude-code/skills/guide/api-reference.md +60 -49
  6. package/agent_config/claude-code/skills/review/SKILL.md +12 -17
  7. package/agent_config/claude-code/skills/scaffold/SKILL.md +18 -23
  8. package/agent_config/claude-code/skills/scaffold/templates/client.md +115 -0
  9. package/agent_config/lib/install-claude.mjs +22 -22
  10. package/docs/core.md +5 -9
  11. package/docs/streaming.md +9 -9
  12. package/package.json +2 -13
  13. package/src/client/call.test.ts +162 -0
  14. package/src/client/errors.test.ts +43 -0
  15. package/src/client/fetch-adapter.test.ts +340 -0
  16. package/src/client/hooks.test.ts +191 -0
  17. package/src/client/index.test.ts +290 -0
  18. package/src/client/request-builder.test.ts +184 -0
  19. package/src/client/stream.test.ts +331 -0
  20. package/src/codegen/bin/cli.test.ts +260 -0
  21. package/src/codegen/bin/cli.ts +282 -0
  22. package/src/codegen/constants.ts +1 -0
  23. package/src/codegen/e2e.test.ts +565 -0
  24. package/src/codegen/emit-client-runtime.test.ts +93 -0
  25. package/src/codegen/emit-client-runtime.ts +114 -0
  26. package/src/codegen/emit-client-types.test.ts +39 -0
  27. package/src/codegen/emit-client-types.ts +27 -0
  28. package/src/codegen/emit-errors.test.ts +202 -0
  29. package/src/codegen/emit-errors.ts +80 -0
  30. package/src/codegen/emit-index.test.ts +127 -0
  31. package/src/codegen/emit-index.ts +58 -0
  32. package/src/codegen/emit-scope.test.ts +624 -0
  33. package/src/codegen/emit-scope.ts +389 -0
  34. package/src/codegen/emit-types.test.ts +205 -0
  35. package/src/codegen/emit-types.ts +158 -0
  36. package/src/codegen/group-routes.test.ts +159 -0
  37. package/src/codegen/group-routes.ts +61 -0
  38. package/src/codegen/index.ts +30 -0
  39. package/src/codegen/naming.test.ts +50 -0
  40. package/src/codegen/naming.ts +25 -0
  41. package/src/codegen/pipeline.test.ts +316 -0
  42. package/src/codegen/pipeline.ts +108 -0
  43. package/src/codegen/resolve-envelope.test.ts +76 -0
  44. package/src/codegen/resolve-envelope.ts +61 -0
  45. package/src/errors.test.ts +163 -0
  46. package/src/errors.ts +107 -0
  47. package/src/exports.ts +7 -0
  48. package/src/implementations/http/doc-registry.test.ts +415 -0
  49. package/src/implementations/http/doc-registry.ts +143 -0
  50. package/src/implementations/http/express-rpc/README.md +6 -6
  51. package/src/implementations/http/express-rpc/index.test.ts +957 -0
  52. package/src/implementations/http/express-rpc/index.ts +266 -0
  53. package/src/implementations/http/express-rpc/types.ts +16 -0
  54. package/src/implementations/http/hono-api/index.test.ts +1341 -0
  55. package/src/implementations/http/hono-api/index.ts +463 -0
  56. package/src/implementations/http/hono-api/types.ts +16 -0
  57. package/src/implementations/http/hono-rpc/README.md +6 -6
  58. package/src/implementations/http/hono-rpc/index.test.ts +1075 -0
  59. package/src/implementations/http/hono-rpc/index.ts +238 -0
  60. package/src/implementations/http/hono-rpc/types.ts +16 -0
  61. package/src/implementations/http/hono-stream/README.md +12 -12
  62. package/src/implementations/http/hono-stream/index.test.ts +1768 -0
  63. package/src/implementations/http/hono-stream/index.ts +456 -0
  64. package/src/implementations/http/hono-stream/types.ts +20 -0
  65. package/src/implementations/types.ts +174 -0
  66. package/src/index.test.ts +1185 -0
  67. package/src/index.ts +522 -0
  68. package/src/schema/compute-schema.test.ts +128 -0
  69. package/src/schema/compute-schema.ts +88 -0
  70. package/src/schema/extract-json-schema.test.ts +25 -0
  71. package/src/schema/extract-json-schema.ts +15 -0
  72. package/src/schema/parser.test.ts +182 -0
  73. package/src/schema/parser.ts +215 -0
  74. package/src/schema/resolve-schema-lib.test.ts +19 -0
  75. package/src/schema/resolve-schema-lib.ts +29 -0
  76. package/src/schema/types.ts +20 -0
  77. package/src/stack-utils.test.ts +94 -0
  78. package/src/stack-utils.ts +129 -0
  79. package/docs/superpowers/plans/2026-03-30-client-codegen.md +0 -2833
  80. package/docs/superpowers/specs/2026-03-30-client-codegen-design.md +0 -632
@@ -0,0 +1,143 @@
1
+ import type {
2
+ AnyHttpRouteDoc,
3
+ DocEnvelope,
4
+ DocRegistryConfig,
5
+ DocRegistryOutputOptions,
6
+ DocSource,
7
+ ErrorDoc,
8
+ HeaderDoc,
9
+ } from '../types.js'
10
+
11
+ export type {
12
+ AnyHttpRouteDoc,
13
+ DocEnvelope,
14
+ DocRegistryConfig,
15
+ DocRegistryOutputOptions,
16
+ DocSource,
17
+ ErrorDoc,
18
+ HeaderDoc,
19
+ } from '../types.js'
20
+
21
+ export class DocRegistry {
22
+ private readonly basePath: string
23
+ private readonly headers: HeaderDoc[]
24
+ private readonly errors: ErrorDoc[]
25
+ private readonly sources: DocSource<AnyHttpRouteDoc>[] = []
26
+
27
+ constructor(config?: DocRegistryConfig) {
28
+ this.basePath = config?.basePath ?? ''
29
+ this.headers = config?.headers ?? []
30
+ this.errors = config?.errors ?? []
31
+ }
32
+
33
+ from(source: DocSource<AnyHttpRouteDoc>): this {
34
+ this.sources.push(source)
35
+ return this
36
+ }
37
+
38
+ toJSON<T = DocEnvelope>(options?: DocRegistryOutputOptions<T>): T {
39
+ let routes = this.sources.flatMap((source) => source.docs)
40
+
41
+ if (options?.filter) {
42
+ routes = routes.filter(options.filter)
43
+ }
44
+
45
+ const envelope: DocEnvelope = {
46
+ basePath: this.basePath,
47
+ headers: [...this.headers],
48
+ errors: [...this.errors],
49
+ routes,
50
+ }
51
+
52
+ if (options?.transform) {
53
+ return options.transform(envelope)
54
+ }
55
+
56
+ return envelope as T
57
+ }
58
+
59
+ // Keep in sync with src/errors.ts
60
+ static defaultErrors(): ErrorDoc[] {
61
+ return [
62
+ {
63
+ name: 'ProcedureError',
64
+ statusCode: 500,
65
+ description: 'An error thrown from within a procedure handler via ctx.error().',
66
+ schema: {
67
+ type: 'object',
68
+ properties: {
69
+ name: { type: 'string', const: 'ProcedureError' },
70
+ procedureName: { type: 'string' },
71
+ message: { type: 'string' },
72
+ meta: { type: 'object' },
73
+ },
74
+ required: ['name', 'procedureName', 'message'],
75
+ },
76
+ },
77
+ {
78
+ name: 'ProcedureValidationError',
79
+ statusCode: 400,
80
+ description: 'Schema validation failed for the procedure input parameters.',
81
+ schema: {
82
+ type: 'object',
83
+ properties: {
84
+ name: { type: 'string', const: 'ProcedureValidationError' },
85
+ procedureName: { type: 'string' },
86
+ message: { type: 'string' },
87
+ errors: {
88
+ type: 'array',
89
+ items: {
90
+ type: 'object',
91
+ properties: {
92
+ instancePath: { type: 'string' },
93
+ message: { type: 'string' },
94
+ },
95
+ },
96
+ },
97
+ },
98
+ required: ['name', 'procedureName', 'message'],
99
+ },
100
+ },
101
+ {
102
+ name: 'ProcedureYieldValidationError',
103
+ statusCode: 500,
104
+ description:
105
+ 'Schema validation failed for a yielded value in a streaming procedure.',
106
+ schema: {
107
+ type: 'object',
108
+ properties: {
109
+ name: { type: 'string', const: 'ProcedureYieldValidationError' },
110
+ procedureName: { type: 'string' },
111
+ message: { type: 'string' },
112
+ errors: {
113
+ type: 'array',
114
+ items: {
115
+ type: 'object',
116
+ properties: {
117
+ instancePath: { type: 'string' },
118
+ message: { type: 'string' },
119
+ },
120
+ },
121
+ },
122
+ },
123
+ required: ['name', 'procedureName', 'message'],
124
+ },
125
+ },
126
+ {
127
+ name: 'ProcedureRegistrationError',
128
+ statusCode: 500,
129
+ description:
130
+ 'An invalid schema or configuration was detected at procedure registration time.',
131
+ schema: {
132
+ type: 'object',
133
+ properties: {
134
+ name: { type: 'string', const: 'ProcedureRegistrationError' },
135
+ procedureName: { type: 'string' },
136
+ message: { type: 'string' },
137
+ },
138
+ required: ['name', 'procedureName', 'message'],
139
+ },
140
+ },
141
+ ]
142
+ }
143
+ }
@@ -14,7 +14,7 @@ npm install ts-procedures express
14
14
  import express from 'express'
15
15
  import { Procedures } from 'ts-procedures'
16
16
  import { ExpressRPCAppBuilder, RPCConfig } from 'ts-procedures/express-rpc'
17
- import { v } from 'suretype'
17
+ import { Type } from 'typebox'
18
18
 
19
19
  // Define your context type
20
20
  type AppContext = { userId: string }
@@ -29,8 +29,8 @@ RPC.Create(
29
29
  scope: ['users', 'profile'],
30
30
  version: 1,
31
31
  schema: {
32
- params: v.object({ id: v.string() }),
33
- returnType: v.object({ id: v.string(), name: v.string() })
32
+ params: Type.Object({ id: Type.String() }),
33
+ returnType: Type.Object({ id: Type.String(), name: Type.String() })
34
34
  }
35
35
  },
36
36
  async (ctx, params) => {
@@ -209,7 +209,7 @@ import {
209
209
  import express from 'express'
210
210
  import { Procedures } from 'ts-procedures'
211
211
  import { ExpressRPCAppBuilder, RPCConfig } from 'ts-procedures/express-rpc'
212
- import { v } from 'suretype'
212
+ import { Type } from 'typebox'
213
213
 
214
214
  // Context types
215
215
  type PublicContext = { source: 'public' }
@@ -234,7 +234,7 @@ AuthRPC.Create(
234
234
  {
235
235
  scope: ['users', 'profile'],
236
236
  version: 1,
237
- schema: { returnType: v.object({ userId: v.string() }) }
237
+ schema: { returnType: Type.Object({ userId: Type.String() }) }
238
238
  },
239
239
  async (ctx) => ({ userId: ctx.userId })
240
240
  )
@@ -244,7 +244,7 @@ AuthRPC.Create(
244
244
  {
245
245
  scope: ['users', 'profile'],
246
246
  version: 2,
247
- schema: { params: v.object({ name: v.string() }) }
247
+ schema: { params: Type.Object({ name: Type.String() }) }
248
248
  },
249
249
  async (ctx, params) => ({ userId: ctx.userId, name: params.name })
250
250
  )