ts-procedures 5.4.0 → 5.5.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 +21 -0
- package/agent_config/claude-code/skills/guide/SKILL.md +1 -0
- package/agent_config/claude-code/skills/guide/anti-patterns.md +37 -4
- package/agent_config/claude-code/skills/guide/api-reference.md +86 -0
- package/agent_config/claude-code/skills/guide/patterns.md +33 -0
- package/agent_config/claude-code/skills/review/checklist.md +2 -0
- package/agent_config/claude-code/skills/scaffold/templates/hono-api.md +1 -1
- package/agent_config/copilot/copilot-instructions.md +4 -0
- package/agent_config/cursor/cursorrules +4 -0
- package/build/implementations/http/doc-registry.d.ts +12 -0
- package/build/implementations/http/doc-registry.js +114 -0
- package/build/implementations/http/doc-registry.js.map +1 -0
- package/build/implementations/http/doc-registry.test.d.ts +1 -0
- package/build/implementations/http/doc-registry.test.js +321 -0
- package/build/implementations/http/doc-registry.test.js.map +1 -0
- package/build/implementations/types.d.ts +31 -0
- package/package.json +5 -2
- package/src/errors.test.ts +0 -163
- package/src/errors.ts +0 -107
- package/src/exports.ts +0 -7
- package/src/implementations/http/README.md +0 -260
- package/src/implementations/http/express-rpc/README.md +0 -281
- package/src/implementations/http/express-rpc/index.test.ts +0 -957
- package/src/implementations/http/express-rpc/index.ts +0 -265
- package/src/implementations/http/express-rpc/types.ts +0 -16
- package/src/implementations/http/hono-api/index.test.ts +0 -1328
- package/src/implementations/http/hono-api/index.ts +0 -461
- package/src/implementations/http/hono-api/types.ts +0 -16
- package/src/implementations/http/hono-rpc/README.md +0 -358
- package/src/implementations/http/hono-rpc/index.test.ts +0 -1075
- package/src/implementations/http/hono-rpc/index.ts +0 -237
- package/src/implementations/http/hono-rpc/types.ts +0 -16
- package/src/implementations/http/hono-stream/README.md +0 -526
- package/src/implementations/http/hono-stream/index.test.ts +0 -1676
- package/src/implementations/http/hono-stream/index.ts +0 -435
- package/src/implementations/http/hono-stream/types.ts +0 -29
- package/src/implementations/types.ts +0 -127
- package/src/index.test.ts +0 -1194
- package/src/index.ts +0 -512
- package/src/schema/compute-schema.test.ts +0 -128
- package/src/schema/compute-schema.ts +0 -88
- package/src/schema/extract-json-schema.test.ts +0 -25
- package/src/schema/extract-json-schema.ts +0 -15
- package/src/schema/parser.test.ts +0 -182
- package/src/schema/parser.ts +0 -215
- package/src/schema/resolve-schema-lib.test.ts +0 -19
- package/src/schema/resolve-schema-lib.ts +0 -29
- package/src/schema/types.ts +0 -20
- package/src/stack-utils.test.ts +0 -94
- package/src/stack-utils.ts +0 -129
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { v } from 'suretype';
|
|
3
|
+
import { Procedures } from '../../index.js';
|
|
4
|
+
import { HonoRPCAppBuilder } from './hono-rpc/index.js';
|
|
5
|
+
import { DocRegistry } from './doc-registry.js';
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// Helpers — minimal doc fixtures
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
const rpcDoc = {
|
|
10
|
+
name: 'Echo',
|
|
11
|
+
path: '/echo/1',
|
|
12
|
+
method: 'post',
|
|
13
|
+
scope: 'echo',
|
|
14
|
+
version: 1,
|
|
15
|
+
jsonSchema: { body: { type: 'object' } },
|
|
16
|
+
};
|
|
17
|
+
const apiDoc = {
|
|
18
|
+
name: 'GetUser',
|
|
19
|
+
path: '/users/:id',
|
|
20
|
+
method: 'get',
|
|
21
|
+
fullPath: '/api/users/:id',
|
|
22
|
+
jsonSchema: { pathParams: { type: 'object' } },
|
|
23
|
+
};
|
|
24
|
+
const streamDoc = {
|
|
25
|
+
name: 'Feed',
|
|
26
|
+
path: '/feed/1',
|
|
27
|
+
methods: ['get'],
|
|
28
|
+
streamMode: 'sse',
|
|
29
|
+
scope: 'feed',
|
|
30
|
+
version: 1,
|
|
31
|
+
jsonSchema: { yieldType: { type: 'object' } },
|
|
32
|
+
};
|
|
33
|
+
function makeSource(docs) {
|
|
34
|
+
return { docs };
|
|
35
|
+
}
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// Tests
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
describe('DocRegistry', () => {
|
|
40
|
+
// --------------------------------------------------------------------------
|
|
41
|
+
// Constructor
|
|
42
|
+
// --------------------------------------------------------------------------
|
|
43
|
+
describe('constructor', () => {
|
|
44
|
+
test('uses defaults when no config provided', () => {
|
|
45
|
+
const registry = new DocRegistry();
|
|
46
|
+
const out = registry.toJSON();
|
|
47
|
+
expect(out.basePath).toBe('');
|
|
48
|
+
expect(out.headers).toEqual([]);
|
|
49
|
+
expect(out.errors).toEqual([]);
|
|
50
|
+
});
|
|
51
|
+
test('accepts partial config', () => {
|
|
52
|
+
const registry = new DocRegistry({ basePath: '/v1' });
|
|
53
|
+
const out = registry.toJSON();
|
|
54
|
+
expect(out.basePath).toBe('/v1');
|
|
55
|
+
expect(out.headers).toEqual([]);
|
|
56
|
+
expect(out.errors).toEqual([]);
|
|
57
|
+
});
|
|
58
|
+
test('accepts full config', () => {
|
|
59
|
+
const headers = [{ name: 'Authorization', description: 'Bearer token', required: true }];
|
|
60
|
+
const errors = [{ name: 'Unauthorized', statusCode: 401, description: 'Missing token' }];
|
|
61
|
+
const registry = new DocRegistry({ basePath: '/api', headers, errors });
|
|
62
|
+
const out = registry.toJSON();
|
|
63
|
+
expect(out.basePath).toBe('/api');
|
|
64
|
+
expect(out.headers).toEqual(headers);
|
|
65
|
+
expect(out.errors).toEqual(errors);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
// --------------------------------------------------------------------------
|
|
69
|
+
// from()
|
|
70
|
+
// --------------------------------------------------------------------------
|
|
71
|
+
describe('from()', () => {
|
|
72
|
+
test('returns this for chaining', () => {
|
|
73
|
+
const registry = new DocRegistry();
|
|
74
|
+
const result = registry.from(makeSource([rpcDoc]));
|
|
75
|
+
expect(result).toBe(registry);
|
|
76
|
+
});
|
|
77
|
+
test('accepts RPC builder source', () => {
|
|
78
|
+
const registry = new DocRegistry().from(makeSource([rpcDoc]));
|
|
79
|
+
expect(registry.toJSON().routes).toEqual([rpcDoc]);
|
|
80
|
+
});
|
|
81
|
+
test('accepts API builder source', () => {
|
|
82
|
+
const registry = new DocRegistry().from(makeSource([apiDoc]));
|
|
83
|
+
expect(registry.toJSON().routes).toEqual([apiDoc]);
|
|
84
|
+
});
|
|
85
|
+
test('accepts Stream builder source', () => {
|
|
86
|
+
const registry = new DocRegistry().from(makeSource([streamDoc]));
|
|
87
|
+
expect(registry.toJSON().routes).toEqual([streamDoc]);
|
|
88
|
+
});
|
|
89
|
+
test('accepts plain { docs } object', () => {
|
|
90
|
+
const plain = { docs: [rpcDoc, apiDoc] };
|
|
91
|
+
const registry = new DocRegistry().from(plain);
|
|
92
|
+
expect(registry.toJSON().routes).toHaveLength(2);
|
|
93
|
+
});
|
|
94
|
+
test('builder not yet built returns empty routes', () => {
|
|
95
|
+
const emptySource = makeSource([]);
|
|
96
|
+
const registry = new DocRegistry().from(emptySource);
|
|
97
|
+
expect(registry.toJSON().routes).toEqual([]);
|
|
98
|
+
});
|
|
99
|
+
test('same builder twice duplicates routes', () => {
|
|
100
|
+
const source = makeSource([rpcDoc]);
|
|
101
|
+
const registry = new DocRegistry().from(source).from(source);
|
|
102
|
+
expect(registry.toJSON().routes).toHaveLength(2);
|
|
103
|
+
expect(registry.toJSON().routes[0]).toEqual(registry.toJSON().routes[1]);
|
|
104
|
+
});
|
|
105
|
+
test('reads docs lazily at toJSON() time', () => {
|
|
106
|
+
const mutableDocs = [];
|
|
107
|
+
const source = { get docs() { return mutableDocs; } };
|
|
108
|
+
const registry = new DocRegistry().from(source);
|
|
109
|
+
expect(registry.toJSON().routes).toHaveLength(0);
|
|
110
|
+
mutableDocs.push(rpcDoc);
|
|
111
|
+
expect(registry.toJSON().routes).toHaveLength(1);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
// --------------------------------------------------------------------------
|
|
115
|
+
// toJSON()
|
|
116
|
+
// --------------------------------------------------------------------------
|
|
117
|
+
describe('toJSON()', () => {
|
|
118
|
+
test('returns correct DocEnvelope shape', () => {
|
|
119
|
+
const registry = new DocRegistry({ basePath: '/api' });
|
|
120
|
+
const out = registry.toJSON();
|
|
121
|
+
expect(out).toHaveProperty('basePath');
|
|
122
|
+
expect(out).toHaveProperty('headers');
|
|
123
|
+
expect(out).toHaveProperty('errors');
|
|
124
|
+
expect(out).toHaveProperty('routes');
|
|
125
|
+
});
|
|
126
|
+
test('collects routes from all sources', () => {
|
|
127
|
+
const registry = new DocRegistry()
|
|
128
|
+
.from(makeSource([rpcDoc]))
|
|
129
|
+
.from(makeSource([apiDoc]))
|
|
130
|
+
.from(makeSource([streamDoc]));
|
|
131
|
+
const out = registry.toJSON();
|
|
132
|
+
expect(out.routes).toHaveLength(3);
|
|
133
|
+
expect(out.routes).toEqual([rpcDoc, apiDoc, streamDoc]);
|
|
134
|
+
});
|
|
135
|
+
test('empty when no sources', () => {
|
|
136
|
+
const out = new DocRegistry().toJSON();
|
|
137
|
+
expect(out.routes).toEqual([]);
|
|
138
|
+
});
|
|
139
|
+
test('headers and errors are copies', () => {
|
|
140
|
+
const headers = [{ name: 'X-Custom' }];
|
|
141
|
+
const errors = [{ name: 'E', statusCode: 500, description: 'd' }];
|
|
142
|
+
const registry = new DocRegistry({ headers, errors });
|
|
143
|
+
const out = registry.toJSON();
|
|
144
|
+
expect(out.headers).toEqual(headers);
|
|
145
|
+
expect(out.headers).not.toBe(headers);
|
|
146
|
+
expect(out.errors).toEqual(errors);
|
|
147
|
+
expect(out.errors).not.toBe(errors);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
// --------------------------------------------------------------------------
|
|
151
|
+
// toJSON() filter
|
|
152
|
+
// --------------------------------------------------------------------------
|
|
153
|
+
describe('toJSON() filter', () => {
|
|
154
|
+
test('excludes routes by name', () => {
|
|
155
|
+
const registry = new DocRegistry()
|
|
156
|
+
.from(makeSource([rpcDoc]))
|
|
157
|
+
.from(makeSource([apiDoc]));
|
|
158
|
+
const out = registry.toJSON({ filter: (r) => r.name !== 'Echo' });
|
|
159
|
+
expect(out.routes).toHaveLength(1);
|
|
160
|
+
expect(out.routes[0].name).toBe('GetUser');
|
|
161
|
+
});
|
|
162
|
+
test('excludes routes by type field', () => {
|
|
163
|
+
const registry = new DocRegistry()
|
|
164
|
+
.from(makeSource([rpcDoc]))
|
|
165
|
+
.from(makeSource([apiDoc]));
|
|
166
|
+
const out = registry.toJSON({
|
|
167
|
+
filter: (r) => 'method' in r && r.method === 'post' && 'scope' in r,
|
|
168
|
+
});
|
|
169
|
+
expect(out.routes).toHaveLength(1);
|
|
170
|
+
expect(out.routes[0].name).toBe('Echo');
|
|
171
|
+
});
|
|
172
|
+
test('all filtered returns empty routes array', () => {
|
|
173
|
+
const registry = new DocRegistry().from(makeSource([rpcDoc]));
|
|
174
|
+
const out = registry.toJSON({ filter: () => false });
|
|
175
|
+
expect(out.routes).toEqual([]);
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
// --------------------------------------------------------------------------
|
|
179
|
+
// toJSON() transform
|
|
180
|
+
// --------------------------------------------------------------------------
|
|
181
|
+
describe('toJSON() transform', () => {
|
|
182
|
+
test('adds fields', () => {
|
|
183
|
+
const registry = new DocRegistry({ basePath: '/api' }).from(makeSource([rpcDoc]));
|
|
184
|
+
const out = registry.toJSON({
|
|
185
|
+
transform: (envelope) => ({ ...envelope, version: '2.0' }),
|
|
186
|
+
});
|
|
187
|
+
expect(out.version).toBe('2.0');
|
|
188
|
+
expect(out.basePath).toBe('/api');
|
|
189
|
+
});
|
|
190
|
+
test('reshapes envelope', () => {
|
|
191
|
+
const registry = new DocRegistry().from(makeSource([rpcDoc]));
|
|
192
|
+
const out = registry.toJSON({
|
|
193
|
+
transform: (envelope) => ({ count: envelope.routes.length }),
|
|
194
|
+
});
|
|
195
|
+
expect(out).toEqual({ count: 1 });
|
|
196
|
+
});
|
|
197
|
+
test('runs after filter', () => {
|
|
198
|
+
const registry = new DocRegistry()
|
|
199
|
+
.from(makeSource([rpcDoc]))
|
|
200
|
+
.from(makeSource([apiDoc]));
|
|
201
|
+
const out = registry.toJSON({
|
|
202
|
+
filter: (r) => r.name === 'Echo',
|
|
203
|
+
transform: (envelope) => ({ ...envelope, filteredCount: envelope.routes.length }),
|
|
204
|
+
});
|
|
205
|
+
expect(out.filteredCount).toBe(1);
|
|
206
|
+
expect(out.routes).toHaveLength(1);
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
// --------------------------------------------------------------------------
|
|
210
|
+
// defaultErrors()
|
|
211
|
+
// --------------------------------------------------------------------------
|
|
212
|
+
describe('defaultErrors()', () => {
|
|
213
|
+
test('returns 4 entries', () => {
|
|
214
|
+
const errors = DocRegistry.defaultErrors();
|
|
215
|
+
expect(errors).toHaveLength(4);
|
|
216
|
+
});
|
|
217
|
+
test('has correct error names', () => {
|
|
218
|
+
const names = DocRegistry.defaultErrors().map((e) => e.name);
|
|
219
|
+
expect(names).toEqual([
|
|
220
|
+
'ProcedureError',
|
|
221
|
+
'ProcedureValidationError',
|
|
222
|
+
'ProcedureYieldValidationError',
|
|
223
|
+
'ProcedureRegistrationError',
|
|
224
|
+
]);
|
|
225
|
+
});
|
|
226
|
+
test('has correct status codes', () => {
|
|
227
|
+
const errors = DocRegistry.defaultErrors();
|
|
228
|
+
expect(errors[0].statusCode).toBe(500); // ProcedureError
|
|
229
|
+
expect(errors[1].statusCode).toBe(400); // ProcedureValidationError
|
|
230
|
+
expect(errors[2].statusCode).toBe(500); // ProcedureYieldValidationError
|
|
231
|
+
expect(errors[3].statusCode).toBe(500); // ProcedureRegistrationError
|
|
232
|
+
});
|
|
233
|
+
test('each entry has schema', () => {
|
|
234
|
+
for (const err of DocRegistry.defaultErrors()) {
|
|
235
|
+
expect(err.schema).toBeDefined();
|
|
236
|
+
expect(err.schema.type).toBe('object');
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
test('returns a new array each call', () => {
|
|
240
|
+
const a = DocRegistry.defaultErrors();
|
|
241
|
+
const b = DocRegistry.defaultErrors();
|
|
242
|
+
expect(a).not.toBe(b);
|
|
243
|
+
expect(a).toEqual(b);
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
// --------------------------------------------------------------------------
|
|
247
|
+
// Integration
|
|
248
|
+
// --------------------------------------------------------------------------
|
|
249
|
+
describe('integration', () => {
|
|
250
|
+
test('multiple builder types composed', () => {
|
|
251
|
+
const registry = new DocRegistry({
|
|
252
|
+
basePath: '/api',
|
|
253
|
+
headers: [{ name: 'Authorization', description: 'Bearer token', required: false }],
|
|
254
|
+
errors: DocRegistry.defaultErrors(),
|
|
255
|
+
})
|
|
256
|
+
.from(makeSource([rpcDoc]))
|
|
257
|
+
.from(makeSource([apiDoc]))
|
|
258
|
+
.from(makeSource([streamDoc]));
|
|
259
|
+
const out = registry.toJSON();
|
|
260
|
+
expect(out.basePath).toBe('/api');
|
|
261
|
+
expect(out.headers).toHaveLength(1);
|
|
262
|
+
expect(out.errors).toHaveLength(4);
|
|
263
|
+
expect(out.routes).toHaveLength(3);
|
|
264
|
+
});
|
|
265
|
+
test('filter + transform combined', () => {
|
|
266
|
+
const registry = new DocRegistry({
|
|
267
|
+
basePath: '/api',
|
|
268
|
+
errors: DocRegistry.defaultErrors(),
|
|
269
|
+
})
|
|
270
|
+
.from(makeSource([rpcDoc]))
|
|
271
|
+
.from(makeSource([apiDoc]))
|
|
272
|
+
.from(makeSource([streamDoc]));
|
|
273
|
+
const out = registry.toJSON({
|
|
274
|
+
filter: (r) => r.name !== 'Feed',
|
|
275
|
+
transform: (envelope) => ({
|
|
276
|
+
...envelope,
|
|
277
|
+
generatedAt: '2026-01-01',
|
|
278
|
+
}),
|
|
279
|
+
});
|
|
280
|
+
expect(out.routes).toHaveLength(2);
|
|
281
|
+
expect(out.routes.map((r) => r.name)).toEqual(['Echo', 'GetUser']);
|
|
282
|
+
expect(out.generatedAt).toBe('2026-01-01');
|
|
283
|
+
});
|
|
284
|
+
test('output is JSON.stringify-safe', () => {
|
|
285
|
+
const registry = new DocRegistry({
|
|
286
|
+
basePath: '/api',
|
|
287
|
+
headers: [{ name: 'X-Request-Id', example: 'abc-123' }],
|
|
288
|
+
errors: DocRegistry.defaultErrors(),
|
|
289
|
+
})
|
|
290
|
+
.from(makeSource([rpcDoc]))
|
|
291
|
+
.from(makeSource([apiDoc]));
|
|
292
|
+
const out = registry.toJSON();
|
|
293
|
+
const str = JSON.stringify(out);
|
|
294
|
+
expect(() => JSON.parse(str)).not.toThrow();
|
|
295
|
+
expect(JSON.parse(str)).toEqual(out);
|
|
296
|
+
});
|
|
297
|
+
test('JSON.stringify(registry) produces default envelope', () => {
|
|
298
|
+
const registry = new DocRegistry({ basePath: '/api' })
|
|
299
|
+
.from(makeSource([rpcDoc]));
|
|
300
|
+
const str = JSON.stringify(registry);
|
|
301
|
+
const parsed = JSON.parse(str);
|
|
302
|
+
expect(parsed.basePath).toBe('/api');
|
|
303
|
+
expect(parsed.routes).toHaveLength(1);
|
|
304
|
+
expect(parsed.routes[0].name).toBe('Echo');
|
|
305
|
+
});
|
|
306
|
+
test('accepts a real HonoRPCAppBuilder as source', () => {
|
|
307
|
+
const RPC = Procedures();
|
|
308
|
+
RPC.Create('Ping', { scope: 'ping', version: 1, schema: { params: v.object({ msg: v.string() }) } }, async (_ctx, params) => params);
|
|
309
|
+
const builder = new HonoRPCAppBuilder();
|
|
310
|
+
builder.register(RPC, () => ({ userId: '123' }));
|
|
311
|
+
builder.build();
|
|
312
|
+
const registry = new DocRegistry({ basePath: '/rpc' }).from(builder);
|
|
313
|
+
const out = registry.toJSON();
|
|
314
|
+
expect(out.basePath).toBe('/rpc');
|
|
315
|
+
expect(out.routes).toHaveLength(1);
|
|
316
|
+
expect(out.routes[0].name).toBe('Ping');
|
|
317
|
+
expect(out.routes[0]).toHaveProperty('jsonSchema');
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
});
|
|
321
|
+
//# sourceMappingURL=doc-registry.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doc-registry.test.js","sourceRoot":"","sources":["../../../src/implementations/http/doc-registry.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -104,3 +104,34 @@ export type ProceduresFactory = {
|
|
|
104
104
|
Create: (...args: any[]) => any;
|
|
105
105
|
CreateStream?: (...args: any[]) => any;
|
|
106
106
|
};
|
|
107
|
+
export type AnyHttpRouteDoc = RPCHttpRouteDoc | APIHttpRouteDoc | StreamHttpRouteDoc;
|
|
108
|
+
export interface DocSource<T = AnyHttpRouteDoc> {
|
|
109
|
+
readonly docs: T[];
|
|
110
|
+
}
|
|
111
|
+
export interface HeaderDoc {
|
|
112
|
+
name: string;
|
|
113
|
+
description?: string;
|
|
114
|
+
required?: boolean;
|
|
115
|
+
example?: string;
|
|
116
|
+
}
|
|
117
|
+
export interface ErrorDoc {
|
|
118
|
+
name: string;
|
|
119
|
+
statusCode: number;
|
|
120
|
+
description: string;
|
|
121
|
+
schema?: Record<string, unknown>;
|
|
122
|
+
}
|
|
123
|
+
export interface DocRegistryConfig {
|
|
124
|
+
basePath?: string;
|
|
125
|
+
headers?: HeaderDoc[];
|
|
126
|
+
errors?: ErrorDoc[];
|
|
127
|
+
}
|
|
128
|
+
export interface DocRegistryOutputOptions<TEnvelope = DocEnvelope> {
|
|
129
|
+
filter?: (route: AnyHttpRouteDoc) => boolean;
|
|
130
|
+
transform?: (envelope: DocEnvelope) => TEnvelope;
|
|
131
|
+
}
|
|
132
|
+
export interface DocEnvelope {
|
|
133
|
+
basePath: string;
|
|
134
|
+
headers: HeaderDoc[];
|
|
135
|
+
errors: ErrorDoc[];
|
|
136
|
+
routes: AnyHttpRouteDoc[];
|
|
137
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-procedures",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.5.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",
|
|
@@ -39,6 +39,10 @@
|
|
|
39
39
|
"./hono-api": {
|
|
40
40
|
"types": "./build/implementations/http/hono-api/index.d.ts",
|
|
41
41
|
"import": "./build/implementations/http/hono-api/index.js"
|
|
42
|
+
},
|
|
43
|
+
"./http-docs": {
|
|
44
|
+
"types": "./build/implementations/http/doc-registry.d.ts",
|
|
45
|
+
"import": "./build/implementations/http/doc-registry.js"
|
|
42
46
|
}
|
|
43
47
|
},
|
|
44
48
|
"author": "coryrobinson42@gmail.com",
|
|
@@ -46,7 +50,6 @@
|
|
|
46
50
|
"files": [
|
|
47
51
|
"assets",
|
|
48
52
|
"build",
|
|
49
|
-
"src",
|
|
50
53
|
"agent_config"
|
|
51
54
|
],
|
|
52
55
|
"keywords": [
|
package/src/errors.test.ts
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from 'vitest'
|
|
2
|
-
import {
|
|
3
|
-
ProcedureError,
|
|
4
|
-
ProcedureValidationError,
|
|
5
|
-
ProcedureRegistrationError,
|
|
6
|
-
} from './errors.js'
|
|
7
|
-
import { DefinitionInfo } from './stack-utils.js'
|
|
8
|
-
|
|
9
|
-
describe('Error Classes', () => {
|
|
10
|
-
test('ProcedureError has correct properties', () => {
|
|
11
|
-
const err = new ProcedureError('TestProc', 'Something failed', { code: 123 })
|
|
12
|
-
|
|
13
|
-
expect(err.name).toBe('ProcedureError')
|
|
14
|
-
expect(err.procedureName).toBe('TestProc')
|
|
15
|
-
expect(err.message).toBe('Something failed')
|
|
16
|
-
expect(err.meta).toEqual({ code: 123 })
|
|
17
|
-
expect(err instanceof Error).toBe(true)
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
test('ProcedureValidationError extends ProcedureError', () => {
|
|
21
|
-
const err = new ProcedureValidationError('TestProc', 'Validation failed', [])
|
|
22
|
-
|
|
23
|
-
expect(err instanceof ProcedureError).toBe(true)
|
|
24
|
-
expect(err instanceof Error).toBe(true)
|
|
25
|
-
expect(err.name).toBe('ProcedureValidationError')
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
test('ProcedureRegistrationError extends ProcedureError', () => {
|
|
29
|
-
const err = new ProcedureRegistrationError('TestProc', 'Registration failed')
|
|
30
|
-
|
|
31
|
-
expect(err instanceof ProcedureError).toBe(true)
|
|
32
|
-
expect(err instanceof Error).toBe(true)
|
|
33
|
-
expect(err.name).toBe('ProcedureRegistrationError')
|
|
34
|
-
expect(err.procedureName).toBe('TestProc')
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
test('ProcedureError supports cause property', () => {
|
|
38
|
-
const cause = new Error('Original error')
|
|
39
|
-
const err = new ProcedureError('TestProc', 'Wrapped error')
|
|
40
|
-
err.cause = cause
|
|
41
|
-
|
|
42
|
-
expect(err.cause).toBe(cause)
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
test('All error types have consistent procedureName property', () => {
|
|
46
|
-
const baseErr = new ProcedureError('Proc1', 'message')
|
|
47
|
-
const validationErr = new ProcedureValidationError('Proc2', 'message', [])
|
|
48
|
-
const registrationErr = new ProcedureRegistrationError('Proc3', 'message')
|
|
49
|
-
|
|
50
|
-
expect(baseErr.procedureName).toBe('Proc1')
|
|
51
|
-
expect(validationErr.procedureName).toBe('Proc2')
|
|
52
|
-
expect(registrationErr.procedureName).toBe('Proc3')
|
|
53
|
-
})
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
describe('Error Classes - Definition Info', () => {
|
|
57
|
-
const mockDefinitionInfo: DefinitionInfo = {
|
|
58
|
-
definedAt: {
|
|
59
|
-
file: '/app/procedures/user.ts',
|
|
60
|
-
line: 25,
|
|
61
|
-
column: 3,
|
|
62
|
-
raw: 'at Object.<anonymous> (/app/procedures/user.ts:25:3)',
|
|
63
|
-
},
|
|
64
|
-
definitionStack: 'Error\n at Object.<anonymous> (/app/procedures/user.ts:25:3)',
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
test('ProcedureError includes definedAt when provided', () => {
|
|
68
|
-
const err = new ProcedureError('TestProc', 'Something failed', undefined, mockDefinitionInfo)
|
|
69
|
-
|
|
70
|
-
expect(err.definedAt).toBeDefined()
|
|
71
|
-
expect(err.definedAt?.file).toBe('/app/procedures/user.ts')
|
|
72
|
-
expect(err.definedAt?.line).toBe(25)
|
|
73
|
-
expect(err.definedAt?.column).toBe(3)
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
test('ProcedureError includes definitionStack when provided', () => {
|
|
77
|
-
const err = new ProcedureError('TestProc', 'Something failed', undefined, mockDefinitionInfo)
|
|
78
|
-
|
|
79
|
-
expect(err.definitionStack).toBeDefined()
|
|
80
|
-
expect(err.definitionStack).toContain('/app/procedures/user.ts')
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
test('ProcedureError works without definitionInfo (backward compat)', () => {
|
|
84
|
-
const err = new ProcedureError('TestProc', 'Something failed', { code: 123 })
|
|
85
|
-
|
|
86
|
-
expect(err.definedAt).toBeUndefined()
|
|
87
|
-
expect(err.definitionStack).toBeUndefined()
|
|
88
|
-
expect(err.procedureName).toBe('TestProc')
|
|
89
|
-
expect(err.message).toBe('Something failed')
|
|
90
|
-
expect(err.meta).toEqual({ code: 123 })
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
test('ProcedureValidationError includes definedAt when provided', () => {
|
|
94
|
-
const err = new ProcedureValidationError('TestProc', 'Validation failed', [], mockDefinitionInfo)
|
|
95
|
-
|
|
96
|
-
expect(err.definedAt).toBeDefined()
|
|
97
|
-
expect(err.definedAt?.file).toBe('/app/procedures/user.ts')
|
|
98
|
-
expect(err.definedAt?.line).toBe(25)
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
test('ProcedureValidationError works without definitionInfo (backward compat)', () => {
|
|
102
|
-
const err = new ProcedureValidationError('TestProc', 'Validation failed', [])
|
|
103
|
-
|
|
104
|
-
expect(err.definedAt).toBeUndefined()
|
|
105
|
-
expect(err.definitionStack).toBeUndefined()
|
|
106
|
-
expect(err.name).toBe('ProcedureValidationError')
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
test('ProcedureRegistrationError includes definedAt when provided', () => {
|
|
110
|
-
const err = new ProcedureRegistrationError('TestProc', 'Registration failed', mockDefinitionInfo)
|
|
111
|
-
|
|
112
|
-
expect(err.definedAt).toBeDefined()
|
|
113
|
-
expect(err.definedAt?.file).toBe('/app/procedures/user.ts')
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
test('ProcedureRegistrationError works without definitionInfo (backward compat)', () => {
|
|
117
|
-
const err = new ProcedureRegistrationError('TestProc', 'Registration failed')
|
|
118
|
-
|
|
119
|
-
expect(err.definedAt).toBeUndefined()
|
|
120
|
-
expect(err.definitionStack).toBeUndefined()
|
|
121
|
-
expect(err.name).toBe('ProcedureRegistrationError')
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
test('getDefinitionLocation returns formatted location string', () => {
|
|
125
|
-
const err = new ProcedureError('TestProc', 'Something failed', undefined, mockDefinitionInfo)
|
|
126
|
-
|
|
127
|
-
const location = err.getDefinitionLocation()
|
|
128
|
-
|
|
129
|
-
expect(location).toBe('/app/procedures/user.ts:25:3')
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
test('getDefinitionLocation returns undefined when no definedAt', () => {
|
|
133
|
-
const err = new ProcedureError('TestProc', 'Something failed')
|
|
134
|
-
|
|
135
|
-
const location = err.getDefinitionLocation()
|
|
136
|
-
|
|
137
|
-
expect(location).toBeUndefined()
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
test('enhanced stack contains definition location', () => {
|
|
141
|
-
const err = new ProcedureError('TestProc', 'Something failed', undefined, mockDefinitionInfo)
|
|
142
|
-
|
|
143
|
-
expect(err.stack).toContain('--- Procedure "TestProc" defined at ---')
|
|
144
|
-
expect(err.stack).toContain('/app/procedures/user.ts:25:3')
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
test('stack is not modified when no definitionInfo', () => {
|
|
148
|
-
const err = new ProcedureError('TestProc', 'Something failed')
|
|
149
|
-
|
|
150
|
-
expect(err.stack).toBeDefined()
|
|
151
|
-
expect(err.stack).not.toContain('--- Procedure')
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
test('all error types enhance stack with definition location', () => {
|
|
155
|
-
const baseErr = new ProcedureError('Proc1', 'message', undefined, mockDefinitionInfo)
|
|
156
|
-
const validationErr = new ProcedureValidationError('Proc2', 'message', [], mockDefinitionInfo)
|
|
157
|
-
const registrationErr = new ProcedureRegistrationError('Proc3', 'message', mockDefinitionInfo)
|
|
158
|
-
|
|
159
|
-
expect(baseErr.stack).toContain('--- Procedure "Proc1" defined at ---')
|
|
160
|
-
expect(validationErr.stack).toContain('--- Procedure "Proc2" defined at ---')
|
|
161
|
-
expect(registrationErr.stack).toContain('--- Procedure "Proc3" defined at ---')
|
|
162
|
-
})
|
|
163
|
-
})
|