ts-procedures 5.10.0 → 5.12.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 (252) hide show
  1. package/agent_config/bin/postinstall.mjs +3 -3
  2. package/agent_config/bin/setup.mjs +22 -11
  3. package/agent_config/claude-code/agents/ts-procedures-architect.md +2 -2
  4. package/agent_config/claude-code/skills/{guide → ts-procedures}/SKILL.md +1 -1
  5. package/agent_config/claude-code/skills/{guide → ts-procedures}/api-reference.md +11 -8
  6. package/agent_config/claude-code/skills/{guide → ts-procedures}/patterns.md +8 -2
  7. package/agent_config/claude-code/skills/{review → ts-procedures-review}/SKILL.md +3 -3
  8. package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/SKILL.md +2 -2
  9. package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/client.md +4 -4
  10. package/agent_config/copilot/copilot-instructions.md +6 -5
  11. package/agent_config/cursor/cursorrules +6 -5
  12. package/agent_config/lib/install-claude.mjs +35 -87
  13. package/build/codegen/e2e.test.js +21 -14
  14. package/build/codegen/e2e.test.js.map +1 -1
  15. package/build/codegen/emit-index.d.ts +7 -3
  16. package/build/codegen/emit-index.js +33 -20
  17. package/build/codegen/emit-index.js.map +1 -1
  18. package/build/codegen/emit-index.test.js +69 -45
  19. package/build/codegen/emit-index.test.js.map +1 -1
  20. package/build/codegen/pipeline.js +4 -5
  21. package/build/codegen/pipeline.js.map +1 -1
  22. package/build/codegen/pipeline.test.js +4 -4
  23. package/build/codegen/pipeline.test.js.map +1 -1
  24. package/build/src/client/call.d.ts +14 -0
  25. package/build/src/client/call.js +47 -0
  26. package/build/src/client/call.js.map +1 -0
  27. package/build/src/client/call.test.d.ts +1 -0
  28. package/build/src/client/call.test.js +124 -0
  29. package/build/src/client/call.test.js.map +1 -0
  30. package/build/src/client/errors.d.ts +25 -0
  31. package/build/src/client/errors.js +33 -0
  32. package/build/src/client/errors.js.map +1 -0
  33. package/build/src/client/errors.test.d.ts +1 -0
  34. package/build/src/client/errors.test.js +41 -0
  35. package/build/src/client/errors.test.js.map +1 -0
  36. package/build/src/client/fetch-adapter.d.ts +12 -0
  37. package/build/src/client/fetch-adapter.js +156 -0
  38. package/build/src/client/fetch-adapter.js.map +1 -0
  39. package/build/src/client/fetch-adapter.test.d.ts +1 -0
  40. package/build/src/client/fetch-adapter.test.js +271 -0
  41. package/build/src/client/fetch-adapter.test.js.map +1 -0
  42. package/build/src/client/hooks.d.ts +17 -0
  43. package/build/src/client/hooks.js +40 -0
  44. package/build/src/client/hooks.js.map +1 -0
  45. package/build/src/client/hooks.test.d.ts +1 -0
  46. package/build/src/client/hooks.test.js +163 -0
  47. package/build/src/client/hooks.test.js.map +1 -0
  48. package/build/src/client/index.d.ts +22 -0
  49. package/build/src/client/index.js +67 -0
  50. package/build/src/client/index.js.map +1 -0
  51. package/build/src/client/index.test.d.ts +1 -0
  52. package/build/src/client/index.test.js +231 -0
  53. package/build/src/client/index.test.js.map +1 -0
  54. package/build/src/client/request-builder.d.ts +13 -0
  55. package/build/src/client/request-builder.js +53 -0
  56. package/build/src/client/request-builder.js.map +1 -0
  57. package/build/src/client/request-builder.test.d.ts +1 -0
  58. package/build/src/client/request-builder.test.js +160 -0
  59. package/build/src/client/request-builder.test.js.map +1 -0
  60. package/build/src/client/stream.d.ts +27 -0
  61. package/build/src/client/stream.js +118 -0
  62. package/build/src/client/stream.js.map +1 -0
  63. package/build/src/client/stream.test.d.ts +1 -0
  64. package/build/src/client/stream.test.js +228 -0
  65. package/build/src/client/stream.test.js.map +1 -0
  66. package/build/src/client/types.d.ts +78 -0
  67. package/build/src/client/types.js +3 -0
  68. package/build/src/client/types.js.map +1 -0
  69. package/build/src/codegen/bin/cli.d.ts +45 -0
  70. package/build/src/codegen/bin/cli.js +246 -0
  71. package/build/src/codegen/bin/cli.js.map +1 -0
  72. package/build/src/codegen/bin/cli.test.d.ts +1 -0
  73. package/build/src/codegen/bin/cli.test.js +220 -0
  74. package/build/src/codegen/bin/cli.test.js.map +1 -0
  75. package/build/src/codegen/constants.d.ts +1 -0
  76. package/build/src/codegen/constants.js +2 -0
  77. package/build/src/codegen/constants.js.map +1 -0
  78. package/build/src/codegen/e2e.test.d.ts +1 -0
  79. package/build/src/codegen/e2e.test.js +464 -0
  80. package/build/src/codegen/e2e.test.js.map +1 -0
  81. package/build/src/codegen/emit-client-runtime.d.ts +9 -0
  82. package/build/src/codegen/emit-client-runtime.js +99 -0
  83. package/build/src/codegen/emit-client-runtime.js.map +1 -0
  84. package/build/src/codegen/emit-client-runtime.test.d.ts +1 -0
  85. package/build/src/codegen/emit-client-runtime.test.js +78 -0
  86. package/build/src/codegen/emit-client-runtime.test.js.map +1 -0
  87. package/build/src/codegen/emit-client-types.d.ts +8 -0
  88. package/build/src/codegen/emit-client-types.js +25 -0
  89. package/build/src/codegen/emit-client-types.js.map +1 -0
  90. package/build/src/codegen/emit-client-types.test.d.ts +1 -0
  91. package/build/src/codegen/emit-client-types.test.js +33 -0
  92. package/build/src/codegen/emit-client-types.test.js.map +1 -0
  93. package/build/src/codegen/emit-errors.d.ts +19 -0
  94. package/build/src/codegen/emit-errors.js +59 -0
  95. package/build/src/codegen/emit-errors.js.map +1 -0
  96. package/build/src/codegen/emit-errors.test.d.ts +1 -0
  97. package/build/src/codegen/emit-errors.test.js +175 -0
  98. package/build/src/codegen/emit-errors.test.js.map +1 -0
  99. package/build/src/codegen/emit-index.d.ts +12 -0
  100. package/build/src/codegen/emit-index.js +41 -0
  101. package/build/src/codegen/emit-index.js.map +1 -0
  102. package/build/src/codegen/emit-index.test.d.ts +1 -0
  103. package/build/src/codegen/emit-index.test.js +106 -0
  104. package/build/src/codegen/emit-index.test.js.map +1 -0
  105. package/build/src/codegen/emit-scope.d.ts +15 -0
  106. package/build/src/codegen/emit-scope.js +299 -0
  107. package/build/src/codegen/emit-scope.js.map +1 -0
  108. package/build/src/codegen/emit-scope.test.d.ts +1 -0
  109. package/build/src/codegen/emit-scope.test.js +559 -0
  110. package/build/src/codegen/emit-scope.test.js.map +1 -0
  111. package/build/src/codegen/emit-types.d.ts +43 -0
  112. package/build/src/codegen/emit-types.js +111 -0
  113. package/build/src/codegen/emit-types.js.map +1 -0
  114. package/build/src/codegen/emit-types.test.d.ts +1 -0
  115. package/build/src/codegen/emit-types.test.js +184 -0
  116. package/build/src/codegen/emit-types.test.js.map +1 -0
  117. package/build/src/codegen/group-routes.d.ts +23 -0
  118. package/build/src/codegen/group-routes.js +46 -0
  119. package/build/src/codegen/group-routes.js.map +1 -0
  120. package/build/src/codegen/group-routes.test.d.ts +1 -0
  121. package/build/src/codegen/group-routes.test.js +131 -0
  122. package/build/src/codegen/group-routes.test.js.map +1 -0
  123. package/build/src/codegen/index.d.ts +15 -0
  124. package/build/src/codegen/index.js +16 -0
  125. package/build/src/codegen/index.js.map +1 -0
  126. package/build/src/codegen/naming.d.ts +7 -0
  127. package/build/src/codegen/naming.js +21 -0
  128. package/build/src/codegen/naming.js.map +1 -0
  129. package/build/src/codegen/naming.test.d.ts +1 -0
  130. package/build/src/codegen/naming.test.js +40 -0
  131. package/build/src/codegen/naming.test.js.map +1 -0
  132. package/build/src/codegen/pipeline.d.ts +17 -0
  133. package/build/src/codegen/pipeline.js +78 -0
  134. package/build/src/codegen/pipeline.js.map +1 -0
  135. package/build/src/codegen/pipeline.test.d.ts +1 -0
  136. package/build/src/codegen/pipeline.test.js +269 -0
  137. package/build/src/codegen/pipeline.test.js.map +1 -0
  138. package/build/src/codegen/resolve-envelope.d.ts +7 -0
  139. package/build/src/codegen/resolve-envelope.js +46 -0
  140. package/build/src/codegen/resolve-envelope.js.map +1 -0
  141. package/build/src/codegen/resolve-envelope.test.d.ts +1 -0
  142. package/build/src/codegen/resolve-envelope.test.js +69 -0
  143. package/build/src/codegen/resolve-envelope.test.js.map +1 -0
  144. package/build/src/errors.d.ts +33 -0
  145. package/build/src/errors.js +91 -0
  146. package/build/src/errors.js.map +1 -0
  147. package/build/src/errors.test.d.ts +1 -0
  148. package/build/src/errors.test.js +122 -0
  149. package/build/src/errors.test.js.map +1 -0
  150. package/build/src/exports.d.ts +7 -0
  151. package/build/src/exports.js +8 -0
  152. package/build/src/exports.js.map +1 -0
  153. package/build/src/implementations/http/doc-registry.d.ts +12 -0
  154. package/build/src/implementations/http/doc-registry.js +114 -0
  155. package/build/src/implementations/http/doc-registry.js.map +1 -0
  156. package/build/src/implementations/http/doc-registry.test.d.ts +1 -0
  157. package/build/src/implementations/http/doc-registry.test.js +347 -0
  158. package/build/src/implementations/http/doc-registry.test.js.map +1 -0
  159. package/build/src/implementations/http/express-rpc/index.d.ts +94 -0
  160. package/build/src/implementations/http/express-rpc/index.js +185 -0
  161. package/build/src/implementations/http/express-rpc/index.js.map +1 -0
  162. package/build/src/implementations/http/express-rpc/index.test.d.ts +1 -0
  163. package/build/src/implementations/http/express-rpc/index.test.js +684 -0
  164. package/build/src/implementations/http/express-rpc/index.test.js.map +1 -0
  165. package/build/src/implementations/http/express-rpc/types.d.ts +11 -0
  166. package/build/src/implementations/http/express-rpc/types.js +2 -0
  167. package/build/src/implementations/http/express-rpc/types.js.map +1 -0
  168. package/build/src/implementations/http/hono-api/index.d.ts +102 -0
  169. package/build/src/implementations/http/hono-api/index.js +341 -0
  170. package/build/src/implementations/http/hono-api/index.js.map +1 -0
  171. package/build/src/implementations/http/hono-api/index.test.d.ts +1 -0
  172. package/build/src/implementations/http/hono-api/index.test.js +992 -0
  173. package/build/src/implementations/http/hono-api/index.test.js.map +1 -0
  174. package/build/src/implementations/http/hono-api/types.d.ts +13 -0
  175. package/build/src/implementations/http/hono-api/types.js +2 -0
  176. package/build/src/implementations/http/hono-api/types.js.map +1 -0
  177. package/build/src/implementations/http/hono-rpc/index.d.ts +92 -0
  178. package/build/src/implementations/http/hono-rpc/index.js +161 -0
  179. package/build/src/implementations/http/hono-rpc/index.js.map +1 -0
  180. package/build/src/implementations/http/hono-rpc/index.test.d.ts +1 -0
  181. package/build/src/implementations/http/hono-rpc/index.test.js +803 -0
  182. package/build/src/implementations/http/hono-rpc/index.test.js.map +1 -0
  183. package/build/src/implementations/http/hono-rpc/types.d.ts +11 -0
  184. package/build/src/implementations/http/hono-rpc/types.js +2 -0
  185. package/build/src/implementations/http/hono-rpc/types.js.map +1 -0
  186. package/build/src/implementations/http/hono-stream/index.d.ts +120 -0
  187. package/build/src/implementations/http/hono-stream/index.js +309 -0
  188. package/build/src/implementations/http/hono-stream/index.js.map +1 -0
  189. package/build/src/implementations/http/hono-stream/index.test.d.ts +1 -0
  190. package/build/src/implementations/http/hono-stream/index.test.js +1356 -0
  191. package/build/src/implementations/http/hono-stream/index.test.js.map +1 -0
  192. package/build/src/implementations/http/hono-stream/types.d.ts +15 -0
  193. package/build/src/implementations/http/hono-stream/types.js +2 -0
  194. package/build/src/implementations/http/hono-stream/types.js.map +1 -0
  195. package/build/src/implementations/types.d.ts +142 -0
  196. package/build/src/implementations/types.js +2 -0
  197. package/build/src/implementations/types.js.map +1 -0
  198. package/build/src/index.d.ts +165 -0
  199. package/build/src/index.js +253 -0
  200. package/build/src/index.js.map +1 -0
  201. package/build/src/index.test.d.ts +1 -0
  202. package/build/src/index.test.js +890 -0
  203. package/build/src/index.test.js.map +1 -0
  204. package/build/src/schema/compute-schema.d.ts +35 -0
  205. package/build/src/schema/compute-schema.js +41 -0
  206. package/build/src/schema/compute-schema.js.map +1 -0
  207. package/build/src/schema/compute-schema.test.d.ts +1 -0
  208. package/build/src/schema/compute-schema.test.js +107 -0
  209. package/build/src/schema/compute-schema.test.js.map +1 -0
  210. package/build/src/schema/extract-json-schema.d.ts +2 -0
  211. package/build/src/schema/extract-json-schema.js +12 -0
  212. package/build/src/schema/extract-json-schema.js.map +1 -0
  213. package/build/src/schema/extract-json-schema.test.d.ts +1 -0
  214. package/build/src/schema/extract-json-schema.test.js +23 -0
  215. package/build/src/schema/extract-json-schema.test.js.map +1 -0
  216. package/build/src/schema/parser.d.ts +28 -0
  217. package/build/src/schema/parser.js +170 -0
  218. package/build/src/schema/parser.js.map +1 -0
  219. package/build/src/schema/parser.test.d.ts +1 -0
  220. package/build/src/schema/parser.test.js +120 -0
  221. package/build/src/schema/parser.test.js.map +1 -0
  222. package/build/src/schema/resolve-schema-lib.d.ts +12 -0
  223. package/build/src/schema/resolve-schema-lib.js +11 -0
  224. package/build/src/schema/resolve-schema-lib.js.map +1 -0
  225. package/build/src/schema/resolve-schema-lib.test.d.ts +1 -0
  226. package/build/src/schema/resolve-schema-lib.test.js +17 -0
  227. package/build/src/schema/resolve-schema-lib.test.js.map +1 -0
  228. package/build/src/schema/types.d.ts +8 -0
  229. package/build/src/schema/types.js +2 -0
  230. package/build/src/schema/types.js.map +1 -0
  231. package/build/src/stack-utils.d.ts +25 -0
  232. package/build/src/stack-utils.js +95 -0
  233. package/build/src/stack-utils.js.map +1 -0
  234. package/build/src/stack-utils.test.d.ts +1 -0
  235. package/build/src/stack-utils.test.js +80 -0
  236. package/build/src/stack-utils.test.js.map +1 -0
  237. package/docs/ai-agent-setup.md +7 -6
  238. package/docs/client-and-codegen.md +9 -6
  239. package/package.json +1 -1
  240. package/src/codegen/e2e.test.ts +23 -14
  241. package/src/codegen/emit-index.test.ts +72 -45
  242. package/src/codegen/emit-index.ts +43 -20
  243. package/src/codegen/pipeline.test.ts +4 -4
  244. package/src/codegen/pipeline.ts +4 -5
  245. /package/agent_config/claude-code/skills/{guide → ts-procedures}/anti-patterns.md +0 -0
  246. /package/agent_config/claude-code/skills/{review → ts-procedures-review}/checklist.md +0 -0
  247. /package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/express-rpc.md +0 -0
  248. /package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/hono-api.md +0 -0
  249. /package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/hono-rpc.md +0 -0
  250. /package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/hono-stream.md +0 -0
  251. /package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/procedure.md +0 -0
  252. /package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/stream-procedure.md +0 -0
@@ -0,0 +1,120 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { extractSingleJsonSchema, v } from 'suretype';
3
+ import { schemaParser } from './parser.js';
4
+ import { Type } from 'typebox';
5
+ describe('schemaParser', () => {
6
+ test('it parses params to json-schema', async () => {
7
+ let done = () => void 0;
8
+ const promise = new Promise((r) => {
9
+ done = r;
10
+ });
11
+ const params = v.object({
12
+ name: v.string(),
13
+ age: v.number(),
14
+ });
15
+ const result = schemaParser({
16
+ params: params,
17
+ }, (errors) => {
18
+ throw new Error(JSON.stringify(errors));
19
+ });
20
+ expect(result.jsonSchema.params).toEqual(extractSingleJsonSchema(params)?.schema);
21
+ done();
22
+ await promise;
23
+ await promise;
24
+ });
25
+ test('it parses params and generates a validator function', async () => {
26
+ let done = () => void 0;
27
+ const promise = new Promise((r) => {
28
+ done = r;
29
+ });
30
+ const params = v.object({
31
+ name: v.string(),
32
+ age: v.number().required(),
33
+ });
34
+ const result = schemaParser({
35
+ params: params,
36
+ }, (errors) => {
37
+ throw new Error(JSON.stringify(errors));
38
+ });
39
+ expect(result.validation.params?.({
40
+ name: 'John',
41
+ age: 30,
42
+ })?.errors).toBeUndefined();
43
+ expect(result.validation.params?.({
44
+ name: { name: '' },
45
+ age: 'poop',
46
+ })?.errors).toBeDefined();
47
+ expect(result.validation.params?.({
48
+ name: { name: '' },
49
+ age: 'poop',
50
+ })?.errors?.length).toEqual(2);
51
+ done();
52
+ await promise;
53
+ });
54
+ test('it parses returnType to json-schema', async () => {
55
+ let done = () => void 0;
56
+ const promise = new Promise((r) => {
57
+ done = r;
58
+ });
59
+ const returnType = v.object({
60
+ name: v.string(),
61
+ age: v.number(),
62
+ });
63
+ const result = schemaParser({
64
+ returnType: returnType,
65
+ }, (errors) => {
66
+ throw new Error(JSON.stringify(errors));
67
+ });
68
+ expect(result.jsonSchema.returnType).toEqual(extractSingleJsonSchema(returnType)?.schema);
69
+ done();
70
+ await promise;
71
+ });
72
+ test('it throws a meaningful error to the dev', async () => {
73
+ schemaParser(
74
+ // invalid params schema
75
+ { params: { test: Type.String() } }, (errors) => {
76
+ expect(errors.params).toMatch(/Error extracting json schema schema.params/);
77
+ });
78
+ schemaParser(
79
+ // invalid returnType schema
80
+ { returnType: 'string value' }, (errors) => {
81
+ expect(errors.returnType).toMatch(/Error extracting json schema schema.returnType/);
82
+ });
83
+ });
84
+ test('it parses multiple schemas correct', async () => {
85
+ const schema = schemaParser({
86
+ params: Type.Object({ a: Type.String() }),
87
+ returnType: Type.Object({ b: Type.Null() }),
88
+ }, (error) => {
89
+ throw new Error(JSON.stringify(error));
90
+ });
91
+ const schema2 = schemaParser({
92
+ params: Type.Object({ c: Type.String() }),
93
+ returnType: Type.Object({ d: Type.Number() }),
94
+ }, (error) => {
95
+ throw new Error(JSON.stringify(error));
96
+ });
97
+ expect(schema.validation.params?.({}).errors?.[0]?.message).toMatch(/must have required property 'a'/);
98
+ expect(schema2.validation.params?.({ c: 'test' })).toMatchObject({});
99
+ expect(schema.validation.params?.({}).errors?.[0]?.message).toMatch(/must have required property 'a'/);
100
+ });
101
+ test('validation returns error if validator fails to initialize', async () => {
102
+ // Create a schema that will pass extraction but creates a validation function
103
+ // that handles the uninitialized case gracefully
104
+ let parseErrorCalled = false;
105
+ const result = schemaParser({
106
+ // Using a valid schema to get through extraction, but we'll test the guard
107
+ params: Type.Object({ name: Type.String() }),
108
+ }, () => {
109
+ parseErrorCalled = true;
110
+ });
111
+ // The validator should be initialized for valid schemas
112
+ expect(result.validation.params).toBeDefined();
113
+ // Test that the validation function works correctly
114
+ const validResult = result.validation.params?.({ name: 'test' });
115
+ expect(validResult?.errors).toBeUndefined();
116
+ const invalidResult = result.validation.params?.({});
117
+ expect(invalidResult?.errors).toBeDefined();
118
+ });
119
+ });
120
+ //# sourceMappingURL=parser.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.test.js","sourceRoot":"","sources":["../../../src/schema/parser.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { CoreValidator } from 'suretype';
2
+ import { Type } from 'typebox';
3
+ export type IsTypeboxSchema<TSchema> = TSchema extends {
4
+ static: unknown;
5
+ params: unknown;
6
+ } ? true : false;
7
+ export declare function isTypeboxSchema(schema: any): schema is Type.TSchema;
8
+ export type IsSuretypeSchema<TSchema> = TSchema extends {
9
+ required: () => object;
10
+ nullable?: never;
11
+ } ? true : false;
12
+ export declare function isSuretypeSchema(schema: any): schema is CoreValidator<any>;
@@ -0,0 +1,11 @@
1
+ export function isTypeboxSchema(schema) {
2
+ return (
3
+ // typebox v1
4
+ (typeof schema === 'object' && '~kind' in schema) ||
5
+ // @sinclair/typebox v0.3x
6
+ (typeof schema === 'object' && Symbol.for('TypeBox.Kind') in schema));
7
+ }
8
+ export function isSuretypeSchema(schema) {
9
+ return typeof schema === 'object' && 'getJsonSchemaObject' in schema;
10
+ }
11
+ //# sourceMappingURL=resolve-schema-lib.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-schema-lib.js","sourceRoot":"","sources":["../../../src/schema/resolve-schema-lib.ts"],"names":[],"mappings":"AAUA,MAAM,UAAU,eAAe,CAAC,MAAW;IACzC,OAAO;IACL,cAAc;IACd,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,IAAI,MAAM,CAAC;QACjD,0BAA0B;QAC1B,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,MAAM,CAAC,CACrE,CAAA;AACH,CAAC;AASD,MAAM,UAAU,gBAAgB,CAAC,MAAW;IAC1C,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,qBAAqB,IAAI,MAAM,CAAA;AACtE,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,17 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { isSuretypeSchema, isTypeboxSchema } from './resolve-schema-lib.js';
3
+ import { Type } from 'typebox';
4
+ import { v } from 'suretype';
5
+ describe('lib schema resolvers', () => {
6
+ const typebox = Type.Object({ name: Type.String() });
7
+ const suretype = v.object({ name: v.string() });
8
+ test('it recognizes TypeBox schema', async () => {
9
+ expect(isTypeboxSchema(typebox)).toBe(true);
10
+ expect(isTypeboxSchema(suretype)).toBe(false);
11
+ });
12
+ test('it recognizes Suretype schema', async () => {
13
+ expect(isSuretypeSchema(suretype)).toBe(true);
14
+ expect(isSuretypeSchema(typebox)).toBe(false);
15
+ });
16
+ });
17
+ //# sourceMappingURL=resolve-schema-lib.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-schema-lib.test.js","sourceRoot":"","sources":["../../../src/schema/resolve-schema-lib.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAC3E,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAC9B,OAAO,EAAE,CAAC,EAAE,MAAM,UAAU,CAAA;AAE5B,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IACpD,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IAE/C,IAAI,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC3C,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC/C,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;QAC/C,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC7C,MAAM,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC/C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,8 @@
1
+ import { CoreValidator, TypeOf } from 'suretype';
2
+ import { Static, TSchema } from 'typebox';
3
+ export type TSchemaLib<SchemaLibType> = SchemaLibType extends CoreValidator<any> ? TypeOf<SchemaLibType> : SchemaLibType extends TSchema ? Static<SchemaLibType> : unknown;
4
+ export type TSchemaLibGenerator<TYield, TReturn = void> = AsyncGenerator<TSchemaLib<TYield>, TSchemaLib<TReturn>, unknown>;
5
+ export type TJSONSchema = Record<string, any>;
6
+ export type Prettify<TObject> = {
7
+ [Key in keyof TObject]: TObject[Key];
8
+ } & {};
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/schema/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Represents a specific location in source code where a procedure was defined.
3
+ */
4
+ export type DefinitionLocation = {
5
+ file: string;
6
+ line: number;
7
+ column: number;
8
+ raw: string;
9
+ };
10
+ /**
11
+ * Contains information about where a procedure was defined.
12
+ */
13
+ export type DefinitionInfo = {
14
+ definedAt?: DefinitionLocation;
15
+ definitionStack?: string;
16
+ };
17
+ /**
18
+ * Captures the stack trace at the call site and extracts the definition location.
19
+ * Finds the first stack frame outside of ts-procedures internal files.
20
+ */
21
+ export declare function captureDefinitionInfo(): DefinitionInfo;
22
+ /**
23
+ * Formats definition info for appending to error stacks.
24
+ */
25
+ export declare function formatDefinitionInfo(info: DefinitionInfo, procedureName: string): string | undefined;
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Internal ts-procedures files that should be skipped when finding user code.
3
+ * Only skip the core library files, not test files or user code.
4
+ */
5
+ const INTERNAL_FILES = [
6
+ '/index.ts',
7
+ '/index.js',
8
+ '/errors.ts',
9
+ '/errors.js',
10
+ '/stack-utils.ts',
11
+ '/stack-utils.js',
12
+ '/compute-schema.ts',
13
+ '/compute-schema.js',
14
+ '/parser.ts',
15
+ '/parser.js',
16
+ ];
17
+ /**
18
+ * Captures the stack trace at the call site and extracts the definition location.
19
+ * Finds the first stack frame outside of ts-procedures internal files.
20
+ */
21
+ export function captureDefinitionInfo() {
22
+ const err = new Error();
23
+ const stack = err.stack;
24
+ if (!stack) {
25
+ return {};
26
+ }
27
+ const lines = stack.split('\n');
28
+ // Find the first frame that's not from ts-procedures internals
29
+ // Skip the first line (Error message) and frames from this module
30
+ let userFrame;
31
+ for (let i = 1; i < lines.length; i++) {
32
+ const rawLine = lines[i];
33
+ if (!rawLine)
34
+ continue;
35
+ const line = rawLine.trim();
36
+ // Skip empty or invalid frames
37
+ if (!line.startsWith('at ')) {
38
+ continue;
39
+ }
40
+ // Skip frames from ts-procedures internal source files
41
+ const isInternalFile = INTERNAL_FILES.some(file => line.includes(file));
42
+ if (isInternalFile) {
43
+ continue;
44
+ }
45
+ // Skip frames from ts-procedures in node_modules (when used as a dependency)
46
+ if (line.includes('/node_modules/ts-procedures/') || line.includes('\\node_modules\\ts-procedures\\')) {
47
+ continue;
48
+ }
49
+ // Skip internal node frames
50
+ if (line.includes('node:') || line.startsWith('at Module.') || line.startsWith('at Object.<anonymous> (node:')) {
51
+ continue;
52
+ }
53
+ userFrame = line;
54
+ break;
55
+ }
56
+ if (!userFrame) {
57
+ return { definitionStack: stack };
58
+ }
59
+ const definedAt = parseStackFrame(userFrame);
60
+ return {
61
+ definedAt,
62
+ definitionStack: stack,
63
+ };
64
+ }
65
+ /**
66
+ * Parses a V8 stack frame line to extract file, line, and column info.
67
+ * Handles formats like:
68
+ * - "at Object.<anonymous> (/path/to/file.ts:10:5)"
69
+ * - "at functionName (/path/to/file.ts:10:5)"
70
+ * - "at /path/to/file.ts:10:5"
71
+ */
72
+ function parseStackFrame(frame) {
73
+ // Match patterns like "(path:line:column)" or just "path:line:column"
74
+ const match = frame.match(/\(([^)]+):(\d+):(\d+)\)$/) || frame.match(/at ([^:]+):(\d+):(\d+)$/);
75
+ if (match && match[1] && match[2] && match[3]) {
76
+ return {
77
+ file: match[1],
78
+ line: parseInt(match[2], 10),
79
+ column: parseInt(match[3], 10),
80
+ raw: frame,
81
+ };
82
+ }
83
+ return undefined;
84
+ }
85
+ /**
86
+ * Formats definition info for appending to error stacks.
87
+ */
88
+ export function formatDefinitionInfo(info, procedureName) {
89
+ if (!info.definedAt) {
90
+ return undefined;
91
+ }
92
+ const { file, line, column } = info.definedAt;
93
+ return `\n--- Procedure "${procedureName}" defined at ---\n at ${file}:${line}:${column}`;
94
+ }
95
+ //# sourceMappingURL=stack-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stack-utils.js","sourceRoot":"","sources":["../../src/stack-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,80 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { captureDefinitionInfo, formatDefinitionInfo } from './stack-utils.js';
3
+ describe('Stack Utils', () => {
4
+ describe('captureDefinitionInfo', () => {
5
+ test('returns definition info with definedAt', () => {
6
+ const info = captureDefinitionInfo();
7
+ // Should capture the call site in this test file
8
+ expect(info).toBeDefined();
9
+ expect(info.definitionStack).toBeDefined();
10
+ expect(typeof info.definitionStack).toBe('string');
11
+ });
12
+ test('definedAt contains file, line, column when available', () => {
13
+ const info = captureDefinitionInfo();
14
+ // The definedAt should be present since we're calling from user code (test file)
15
+ if (info.definedAt) {
16
+ expect(info.definedAt.file).toBeDefined();
17
+ expect(typeof info.definedAt.file).toBe('string');
18
+ expect(info.definedAt.line).toBeDefined();
19
+ expect(typeof info.definedAt.line).toBe('number');
20
+ expect(info.definedAt.line).toBeGreaterThan(0);
21
+ expect(info.definedAt.column).toBeDefined();
22
+ expect(typeof info.definedAt.column).toBe('number');
23
+ expect(info.definedAt.column).toBeGreaterThan(0);
24
+ expect(info.definedAt.raw).toBeDefined();
25
+ expect(typeof info.definedAt.raw).toBe('string');
26
+ }
27
+ });
28
+ test('definitionStack contains Error stack trace', () => {
29
+ const info = captureDefinitionInfo();
30
+ expect(info.definitionStack).toContain('Error');
31
+ expect(info.definitionStack).toContain('at ');
32
+ });
33
+ });
34
+ describe('formatDefinitionInfo', () => {
35
+ test('returns undefined when definedAt is not present', () => {
36
+ const info = {};
37
+ const result = formatDefinitionInfo(info, 'TestProcedure');
38
+ expect(result).toBeUndefined();
39
+ });
40
+ test('returns formatted string when definedAt is present', () => {
41
+ const info = {
42
+ definedAt: {
43
+ file: '/app/procedures/test.ts',
44
+ line: 42,
45
+ column: 5,
46
+ raw: 'at Object.<anonymous> (/app/procedures/test.ts:42:5)',
47
+ },
48
+ };
49
+ const result = formatDefinitionInfo(info, 'TestProcedure');
50
+ expect(result).toBeDefined();
51
+ expect(result).toContain('--- Procedure "TestProcedure" defined at ---');
52
+ expect(result).toContain('/app/procedures/test.ts:42:5');
53
+ });
54
+ test('includes procedure name in formatted output', () => {
55
+ const info = {
56
+ definedAt: {
57
+ file: '/path/to/file.ts',
58
+ line: 10,
59
+ column: 3,
60
+ raw: 'at /path/to/file.ts:10:3',
61
+ },
62
+ };
63
+ const result = formatDefinitionInfo(info, 'MyCustomProcedure');
64
+ expect(result).toContain('"MyCustomProcedure"');
65
+ });
66
+ });
67
+ describe('integration with procedure creation', () => {
68
+ test('captures location from calling code', () => {
69
+ // Helper to simulate what happens in Create()
70
+ function simulateCreate() {
71
+ return captureDefinitionInfo();
72
+ }
73
+ const info = simulateCreate();
74
+ // Should have captured the location of the simulateCreate() call
75
+ expect(info).toBeDefined();
76
+ expect(info.definitionStack).toBeDefined();
77
+ });
78
+ });
79
+ });
80
+ //# sourceMappingURL=stack-utils.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stack-utils.test.js","sourceRoot":"","sources":["../../src/stack-utils.test.ts"],"names":[],"mappings":"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"}
@@ -22,7 +22,7 @@ npx ts-procedures-setup copilot # GitHub Copilot only
22
22
 
23
23
  | Tool | Files | Auto-updates? |
24
24
  |------|-------|---------------|
25
- | **Claude Code** | `.claude/rules/ts-procedures.md`, `.claude/commands/ts-procedures-scaffold.md`, `.claude/commands/ts-procedures-review.md`, `.claude/agents/ts-procedures-architect.md` | Yes |
25
+ | **Claude Code** | `.claude/skills/ts-procedures/`, `.claude/skills/ts-procedures-scaffold/`, `.claude/skills/ts-procedures-review/`, `.claude/agents/ts-procedures-architect.md` | Yes |
26
26
  | **Cursor** | `.cursorrules` (marker-based section) | Yes |
27
27
  | **GitHub Copilot** | `.github/copilot-instructions.md` (marker-based section) | Yes |
28
28
 
@@ -34,9 +34,9 @@ After initial setup, rules are automatically refreshed on every `npm install` or
34
34
 
35
35
  Once installed, Claude Code gets:
36
36
 
37
- - **Framework reference** — auto-loaded rules with core API, schema system, error handling, and decision framework
38
- - **Scaffold command** — `/project:ts-procedures-scaffold <type> <Name>` generates procedures, streams, and HTTP setups with correct patterns
39
- - **Review command** — `/project:ts-procedures-review <path>` checks code against a 60+ item checklist
37
+ - **Framework reference skill** — `ts-procedures` with core API, schema system, error handling, and decision framework (auto-discovered by Claude Code)
38
+ - **Scaffold skill** — `/ts-procedures-scaffold <type> <Name>` generates procedures, streams, and HTTP setups with correct patterns
39
+ - **Review skill** — `/ts-procedures-review <path>` checks code against a 60+ item checklist
40
40
  - **Architecture agent** — `ts-procedures-architect` helps plan procedure structure, schema design, and HTTP implementation choices
41
41
 
42
42
  ## CLI Options
@@ -53,8 +53,9 @@ The `.claude/` files are auto-generated and regenerated on `npm install`. You ca
53
53
 
54
54
  ```gitignore
55
55
  # Auto-generated AI agent rules (regenerated on npm install)
56
- .claude/rules/ts-procedures.md
57
- .claude/commands/ts-procedures-*.md
56
+ .claude/skills/ts-procedures/
57
+ .claude/skills/ts-procedures-scaffold/
58
+ .claude/skills/ts-procedures-review/
58
59
  .claude/agents/ts-procedures-*.md
59
60
  ```
60
61
 
@@ -22,12 +22,12 @@ npx ts-procedures-codegen --url http://localhost:3000/docs --out ./src/generated
22
22
 
23
23
  ```typescript
24
24
  import { createClient, createFetchAdapter } from 'ts-procedures/client'
25
- import { createScopeBindings } from './generated/api'
25
+ import { createApiBindings, Api } from './generated/api'
26
26
 
27
27
  const client = createClient({
28
28
  adapter: createFetchAdapter(),
29
29
  basePath: 'http://localhost:3000',
30
- scopes: createScopeBindings,
30
+ scopes: createApiBindings,
31
31
  hooks: {
32
32
  onBeforeRequest(ctx) {
33
33
  ctx.request.headers = { ...ctx.request.headers, Authorization: `Bearer ${getToken()}` }
@@ -38,6 +38,9 @@ const client = createClient({
38
38
 
39
39
  // Fully typed — params and response inferred from server schemas
40
40
  const user = await client.users.GetUser({ pathParams: { id: '123' } })
41
+
42
+ // Types live under the service namespace: Api.Users.GetUser.Params, Api.Errors.ProcedureError, etc.
43
+ // Pass --service-name <Name> to rename `Api` → `<Name>` (factory becomes create<Name>Bindings).
41
44
  ```
42
45
 
43
46
  ## Generated File Structure
@@ -51,8 +54,8 @@ generated/
51
54
  notifications.ts # Types + callables for stream procedures
52
55
  _types.ts # Client type definitions (self-contained mode)
53
56
  _client.ts # Client runtime bundle (self-contained mode)
54
- _errors.ts # Typed error classes + ProcedureErrorUnion
55
- index.ts # Barrel exports + createScopeBindings (or create${ServiceName}Bindings)
57
+ _errors.ts # Typed error classes + ${ServiceName}ProcedureErrorUnion (default: ApiProcedureErrorUnion)
58
+ index.ts # Service namespace (`export namespace ${ServiceName}`) + create${ServiceName}Bindings factory (default: Api / createApiBindings)
56
59
  ```
57
60
 
58
61
  ## CLI Reference
@@ -74,7 +77,7 @@ generated/
74
77
  | `--depluralize` | Singularize array item type names (ignored with `--no-namespace-types`) | Off |
75
78
  | `--array-item-naming <value>` | Postfix for array item type names (ignored with `--no-namespace-types`) | Off |
76
79
  | `--uncountable-words <list>` | Comma-separated words to skip singularization (ignored with `--no-namespace-types`) | Off |
77
- | `--service-name <name>` | Customize generated names for multi-service apps (e.g. `Auth` -> `createAuthBindings`) | |
80
+ | `--service-name <name>` | Names the service namespace and binding factory (e.g. `Auth` `export namespace Auth` + `createAuthBindings`). Also prefixes `${Name}Errors` and `${Name}ProcedureErrorUnion` in `_errors.ts`. | `Api` |
78
81
 
79
82
  > **Note:** ajsc formatting options (`--enum-style`, `--depluralize`, `--array-item-naming`, `--uncountable-words`) only take effect in namespace mode (the default). With `--no-namespace-types`, all types are inlined and these options have no effect.
80
83
  >
@@ -111,7 +114,7 @@ Hooks let you intercept requests and responses globally or per-procedure call. G
111
114
  const client = createClient({
112
115
  adapter,
113
116
  basePath: 'http://localhost:3000',
114
- scopes: createScopeBindings,
117
+ scopes: createApiBindings,
115
118
  hooks: {
116
119
  onBeforeRequest(ctx) { /* add auth headers */ return ctx },
117
120
  onAfterResponse(ctx) { /* handle errors, logging */ },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-procedures",
3
- "version": "5.10.0",
3
+ "version": "5.12.0",
4
4
  "description": "A TypeScript RPC framework that creates type-safe, schema-validated procedure calls with a single function definition. Define your procedures once and get full type inference, runtime validation, and framework integration hooks.",
5
5
  "main": "build/exports.js",
6
6
  "types": "build/exports.d.ts",
@@ -290,44 +290,44 @@ describe('E2E: generateClient full pipeline', () => {
290
290
 
291
291
  // ── index.ts ───────────────────────────────────────────────────────────────
292
292
 
293
- it('index.ts contains createScopeBindings', async () => {
293
+ it('index.ts contains the default Api bindings factory', async () => {
294
294
  tmpDir = makeTmpDir()
295
295
  await generateClient({ envelope, outDir: tmpDir })
296
296
 
297
297
  const content = readFileSync(join(tmpDir, 'index.ts'), 'utf-8')
298
- expect(content).toContain('createScopeBindings')
298
+ expect(content).toContain('createApiBindings')
299
299
  })
300
300
 
301
- it('index.ts re-exports from users scope', async () => {
301
+ it('index.ts imports the users scope as a namespace', async () => {
302
302
  tmpDir = makeTmpDir()
303
303
  await generateClient({ envelope, outDir: tmpDir })
304
304
 
305
305
  const content = readFileSync(join(tmpDir, 'index.ts'), 'utf-8')
306
- expect(content).toContain("from './users'")
306
+ expect(content).toContain("import * as users from './users'")
307
307
  })
308
308
 
309
- it('index.ts re-exports from events scope', async () => {
309
+ it('index.ts imports the events scope as a namespace', async () => {
310
310
  tmpDir = makeTmpDir()
311
311
  await generateClient({ envelope, outDir: tmpDir })
312
312
 
313
313
  const content = readFileSync(join(tmpDir, 'index.ts'), 'utf-8')
314
- expect(content).toContain("from './events'")
314
+ expect(content).toContain("import * as events from './events'")
315
315
  })
316
316
 
317
- it('index.ts imports and uses bindUsersScope', async () => {
317
+ it('index.ts uses bindUsersScope through the namespace', async () => {
318
318
  tmpDir = makeTmpDir()
319
319
  await generateClient({ envelope, outDir: tmpDir })
320
320
 
321
321
  const content = readFileSync(join(tmpDir, 'index.ts'), 'utf-8')
322
- expect(content).toContain('bindUsersScope')
322
+ expect(content).toContain('users.bindUsersScope(client)')
323
323
  })
324
324
 
325
- it('index.ts imports and uses bindEventsScope', async () => {
325
+ it('index.ts uses bindEventsScope through the namespace', async () => {
326
326
  tmpDir = makeTmpDir()
327
327
  await generateClient({ envelope, outDir: tmpDir })
328
328
 
329
329
  const content = readFileSync(join(tmpDir, 'index.ts'), 'utf-8')
330
- expect(content).toContain('bindEventsScope')
330
+ expect(content).toContain('events.bindEventsScope(client)')
331
331
  })
332
332
 
333
333
  // ── _errors.ts ─────────────────────────────────────────────────────────────
@@ -347,22 +347,31 @@ describe('E2E: generateClient full pipeline', () => {
347
347
  expect(content).toContain('export type ProcedureError =')
348
348
  })
349
349
 
350
- it('_errors.ts contains ProcedureErrorUnion', async () => {
350
+ it('_errors.ts contains the service-prefixed ProcedureErrorUnion', async () => {
351
351
  tmpDir = makeTmpDir()
352
352
  await generateClient({ envelope, outDir: tmpDir })
353
353
 
354
354
  const content = readFileSync(join(tmpDir, '_errors.ts'), 'utf-8')
355
- expect(content).toContain('export type ProcedureErrorUnion =')
355
+ expect(content).toContain('export type ApiProcedureErrorUnion =')
356
356
  expect(content).toContain('ProcedureError')
357
357
  expect(content).toContain('ProcedureValidationError')
358
358
  })
359
359
 
360
- it('index.ts re-exports from _errors when errors are present', async () => {
360
+ it('index.ts does not import _errors when namespaceTypes is off', async () => {
361
361
  tmpDir = makeTmpDir()
362
362
  await generateClient({ envelope, outDir: tmpDir })
363
363
 
364
364
  const content = readFileSync(join(tmpDir, 'index.ts'), 'utf-8')
365
- expect(content).toContain("export * from './_errors'")
365
+ expect(content).not.toContain("from './_errors'")
366
+ })
367
+
368
+ it('index.ts folds errors into the service namespace when namespaceTypes is on', async () => {
369
+ tmpDir = makeTmpDir()
370
+ await generateClient({ envelope, outDir: tmpDir, namespaceTypes: true })
371
+
372
+ const content = readFileSync(join(tmpDir, 'index.ts'), 'utf-8')
373
+ expect(content).toContain("import * as _errorsModule from './_errors'")
374
+ expect(content).toContain('export import Errors = _errorsModule.ApiErrors')
366
375
  })
367
376
 
368
377
  it('_errors.ts is not generated when no errors have schemas', async () => {