ts-procedures 5.10.0 → 5.10.2
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/agent_config/bin/postinstall.mjs +3 -3
- package/agent_config/bin/setup.mjs +22 -11
- package/agent_config/claude-code/agents/ts-procedures-architect.md +2 -2
- package/agent_config/claude-code/skills/{guide → ts-procedures}/SKILL.md +1 -1
- package/agent_config/claude-code/skills/{review → ts-procedures-review}/SKILL.md +3 -3
- package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/SKILL.md +2 -2
- package/agent_config/lib/install-claude.mjs +35 -87
- package/build/src/client/call.d.ts +14 -0
- package/build/src/client/call.js +47 -0
- package/build/src/client/call.js.map +1 -0
- package/build/src/client/call.test.d.ts +1 -0
- package/build/src/client/call.test.js +124 -0
- package/build/src/client/call.test.js.map +1 -0
- package/build/src/client/errors.d.ts +25 -0
- package/build/src/client/errors.js +33 -0
- package/build/src/client/errors.js.map +1 -0
- package/build/src/client/errors.test.d.ts +1 -0
- package/build/src/client/errors.test.js +41 -0
- package/build/src/client/errors.test.js.map +1 -0
- package/build/src/client/fetch-adapter.d.ts +12 -0
- package/build/src/client/fetch-adapter.js +156 -0
- package/build/src/client/fetch-adapter.js.map +1 -0
- package/build/src/client/fetch-adapter.test.d.ts +1 -0
- package/build/src/client/fetch-adapter.test.js +271 -0
- package/build/src/client/fetch-adapter.test.js.map +1 -0
- package/build/src/client/hooks.d.ts +17 -0
- package/build/src/client/hooks.js +40 -0
- package/build/src/client/hooks.js.map +1 -0
- package/build/src/client/hooks.test.d.ts +1 -0
- package/build/src/client/hooks.test.js +163 -0
- package/build/src/client/hooks.test.js.map +1 -0
- package/build/src/client/index.d.ts +22 -0
- package/build/src/client/index.js +67 -0
- package/build/src/client/index.js.map +1 -0
- package/build/src/client/index.test.d.ts +1 -0
- package/build/src/client/index.test.js +231 -0
- package/build/src/client/index.test.js.map +1 -0
- package/build/src/client/request-builder.d.ts +13 -0
- package/build/src/client/request-builder.js +53 -0
- package/build/src/client/request-builder.js.map +1 -0
- package/build/src/client/request-builder.test.d.ts +1 -0
- package/build/src/client/request-builder.test.js +160 -0
- package/build/src/client/request-builder.test.js.map +1 -0
- package/build/src/client/stream.d.ts +27 -0
- package/build/src/client/stream.js +118 -0
- package/build/src/client/stream.js.map +1 -0
- package/build/src/client/stream.test.d.ts +1 -0
- package/build/src/client/stream.test.js +228 -0
- package/build/src/client/stream.test.js.map +1 -0
- package/build/src/client/types.d.ts +78 -0
- package/build/src/client/types.js +3 -0
- package/build/src/client/types.js.map +1 -0
- package/build/src/codegen/bin/cli.d.ts +45 -0
- package/build/src/codegen/bin/cli.js +246 -0
- package/build/src/codegen/bin/cli.js.map +1 -0
- package/build/src/codegen/bin/cli.test.d.ts +1 -0
- package/build/src/codegen/bin/cli.test.js +220 -0
- package/build/src/codegen/bin/cli.test.js.map +1 -0
- package/build/src/codegen/constants.d.ts +1 -0
- package/build/src/codegen/constants.js +2 -0
- package/build/src/codegen/constants.js.map +1 -0
- package/build/src/codegen/e2e.test.d.ts +1 -0
- package/build/src/codegen/e2e.test.js +464 -0
- package/build/src/codegen/e2e.test.js.map +1 -0
- package/build/src/codegen/emit-client-runtime.d.ts +9 -0
- package/build/src/codegen/emit-client-runtime.js +99 -0
- package/build/src/codegen/emit-client-runtime.js.map +1 -0
- package/build/src/codegen/emit-client-runtime.test.d.ts +1 -0
- package/build/src/codegen/emit-client-runtime.test.js +78 -0
- package/build/src/codegen/emit-client-runtime.test.js.map +1 -0
- package/build/src/codegen/emit-client-types.d.ts +8 -0
- package/build/src/codegen/emit-client-types.js +25 -0
- package/build/src/codegen/emit-client-types.js.map +1 -0
- package/build/src/codegen/emit-client-types.test.d.ts +1 -0
- package/build/src/codegen/emit-client-types.test.js +33 -0
- package/build/src/codegen/emit-client-types.test.js.map +1 -0
- package/build/src/codegen/emit-errors.d.ts +19 -0
- package/build/src/codegen/emit-errors.js +59 -0
- package/build/src/codegen/emit-errors.js.map +1 -0
- package/build/src/codegen/emit-errors.test.d.ts +1 -0
- package/build/src/codegen/emit-errors.test.js +175 -0
- package/build/src/codegen/emit-errors.test.js.map +1 -0
- package/build/src/codegen/emit-index.d.ts +12 -0
- package/build/src/codegen/emit-index.js +41 -0
- package/build/src/codegen/emit-index.js.map +1 -0
- package/build/src/codegen/emit-index.test.d.ts +1 -0
- package/build/src/codegen/emit-index.test.js +106 -0
- package/build/src/codegen/emit-index.test.js.map +1 -0
- package/build/src/codegen/emit-scope.d.ts +15 -0
- package/build/src/codegen/emit-scope.js +299 -0
- package/build/src/codegen/emit-scope.js.map +1 -0
- package/build/src/codegen/emit-scope.test.d.ts +1 -0
- package/build/src/codegen/emit-scope.test.js +559 -0
- package/build/src/codegen/emit-scope.test.js.map +1 -0
- package/build/src/codegen/emit-types.d.ts +43 -0
- package/build/src/codegen/emit-types.js +111 -0
- package/build/src/codegen/emit-types.js.map +1 -0
- package/build/src/codegen/emit-types.test.d.ts +1 -0
- package/build/src/codegen/emit-types.test.js +184 -0
- package/build/src/codegen/emit-types.test.js.map +1 -0
- package/build/src/codegen/group-routes.d.ts +23 -0
- package/build/src/codegen/group-routes.js +46 -0
- package/build/src/codegen/group-routes.js.map +1 -0
- package/build/src/codegen/group-routes.test.d.ts +1 -0
- package/build/src/codegen/group-routes.test.js +131 -0
- package/build/src/codegen/group-routes.test.js.map +1 -0
- package/build/src/codegen/index.d.ts +15 -0
- package/build/src/codegen/index.js +16 -0
- package/build/src/codegen/index.js.map +1 -0
- package/build/src/codegen/naming.d.ts +7 -0
- package/build/src/codegen/naming.js +21 -0
- package/build/src/codegen/naming.js.map +1 -0
- package/build/src/codegen/naming.test.d.ts +1 -0
- package/build/src/codegen/naming.test.js +40 -0
- package/build/src/codegen/naming.test.js.map +1 -0
- package/build/src/codegen/pipeline.d.ts +17 -0
- package/build/src/codegen/pipeline.js +78 -0
- package/build/src/codegen/pipeline.js.map +1 -0
- package/build/src/codegen/pipeline.test.d.ts +1 -0
- package/build/src/codegen/pipeline.test.js +269 -0
- package/build/src/codegen/pipeline.test.js.map +1 -0
- package/build/src/codegen/resolve-envelope.d.ts +7 -0
- package/build/src/codegen/resolve-envelope.js +46 -0
- package/build/src/codegen/resolve-envelope.js.map +1 -0
- package/build/src/codegen/resolve-envelope.test.d.ts +1 -0
- package/build/src/codegen/resolve-envelope.test.js +69 -0
- package/build/src/codegen/resolve-envelope.test.js.map +1 -0
- package/build/src/errors.d.ts +33 -0
- package/build/src/errors.js +91 -0
- package/build/src/errors.js.map +1 -0
- package/build/src/errors.test.d.ts +1 -0
- package/build/src/errors.test.js +122 -0
- package/build/src/errors.test.js.map +1 -0
- package/build/src/exports.d.ts +7 -0
- package/build/src/exports.js +8 -0
- package/build/src/exports.js.map +1 -0
- package/build/src/implementations/http/doc-registry.d.ts +12 -0
- package/build/src/implementations/http/doc-registry.js +114 -0
- package/build/src/implementations/http/doc-registry.js.map +1 -0
- package/build/src/implementations/http/doc-registry.test.d.ts +1 -0
- package/build/src/implementations/http/doc-registry.test.js +347 -0
- package/build/src/implementations/http/doc-registry.test.js.map +1 -0
- package/build/src/implementations/http/express-rpc/index.d.ts +94 -0
- package/build/src/implementations/http/express-rpc/index.js +185 -0
- package/build/src/implementations/http/express-rpc/index.js.map +1 -0
- package/build/src/implementations/http/express-rpc/index.test.d.ts +1 -0
- package/build/src/implementations/http/express-rpc/index.test.js +684 -0
- package/build/src/implementations/http/express-rpc/index.test.js.map +1 -0
- package/build/src/implementations/http/express-rpc/types.d.ts +11 -0
- package/build/src/implementations/http/express-rpc/types.js +2 -0
- package/build/src/implementations/http/express-rpc/types.js.map +1 -0
- package/build/src/implementations/http/hono-api/index.d.ts +102 -0
- package/build/src/implementations/http/hono-api/index.js +341 -0
- package/build/src/implementations/http/hono-api/index.js.map +1 -0
- package/build/src/implementations/http/hono-api/index.test.d.ts +1 -0
- package/build/src/implementations/http/hono-api/index.test.js +992 -0
- package/build/src/implementations/http/hono-api/index.test.js.map +1 -0
- package/build/src/implementations/http/hono-api/types.d.ts +13 -0
- package/build/src/implementations/http/hono-api/types.js +2 -0
- package/build/src/implementations/http/hono-api/types.js.map +1 -0
- package/build/src/implementations/http/hono-rpc/index.d.ts +92 -0
- package/build/src/implementations/http/hono-rpc/index.js +161 -0
- package/build/src/implementations/http/hono-rpc/index.js.map +1 -0
- package/build/src/implementations/http/hono-rpc/index.test.d.ts +1 -0
- package/build/src/implementations/http/hono-rpc/index.test.js +803 -0
- package/build/src/implementations/http/hono-rpc/index.test.js.map +1 -0
- package/build/src/implementations/http/hono-rpc/types.d.ts +11 -0
- package/build/src/implementations/http/hono-rpc/types.js +2 -0
- package/build/src/implementations/http/hono-rpc/types.js.map +1 -0
- package/build/src/implementations/http/hono-stream/index.d.ts +120 -0
- package/build/src/implementations/http/hono-stream/index.js +309 -0
- package/build/src/implementations/http/hono-stream/index.js.map +1 -0
- package/build/src/implementations/http/hono-stream/index.test.d.ts +1 -0
- package/build/src/implementations/http/hono-stream/index.test.js +1356 -0
- package/build/src/implementations/http/hono-stream/index.test.js.map +1 -0
- package/build/src/implementations/http/hono-stream/types.d.ts +15 -0
- package/build/src/implementations/http/hono-stream/types.js +2 -0
- package/build/src/implementations/http/hono-stream/types.js.map +1 -0
- package/build/src/implementations/types.d.ts +142 -0
- package/build/src/implementations/types.js +2 -0
- package/build/src/implementations/types.js.map +1 -0
- package/build/src/index.d.ts +165 -0
- package/build/src/index.js +253 -0
- package/build/src/index.js.map +1 -0
- package/build/src/index.test.d.ts +1 -0
- package/build/src/index.test.js +890 -0
- package/build/src/index.test.js.map +1 -0
- package/build/src/schema/compute-schema.d.ts +35 -0
- package/build/src/schema/compute-schema.js +41 -0
- package/build/src/schema/compute-schema.js.map +1 -0
- package/build/src/schema/compute-schema.test.d.ts +1 -0
- package/build/src/schema/compute-schema.test.js +107 -0
- package/build/src/schema/compute-schema.test.js.map +1 -0
- package/build/src/schema/extract-json-schema.d.ts +2 -0
- package/build/src/schema/extract-json-schema.js +12 -0
- package/build/src/schema/extract-json-schema.js.map +1 -0
- package/build/src/schema/extract-json-schema.test.d.ts +1 -0
- package/build/src/schema/extract-json-schema.test.js +23 -0
- package/build/src/schema/extract-json-schema.test.js.map +1 -0
- package/build/src/schema/parser.d.ts +28 -0
- package/build/src/schema/parser.js +170 -0
- package/build/src/schema/parser.js.map +1 -0
- package/build/src/schema/parser.test.d.ts +1 -0
- package/build/src/schema/parser.test.js +120 -0
- package/build/src/schema/parser.test.js.map +1 -0
- package/build/src/schema/resolve-schema-lib.d.ts +12 -0
- package/build/src/schema/resolve-schema-lib.js +11 -0
- package/build/src/schema/resolve-schema-lib.js.map +1 -0
- package/build/src/schema/resolve-schema-lib.test.d.ts +1 -0
- package/build/src/schema/resolve-schema-lib.test.js +17 -0
- package/build/src/schema/resolve-schema-lib.test.js.map +1 -0
- package/build/src/schema/types.d.ts +8 -0
- package/build/src/schema/types.js +2 -0
- package/build/src/schema/types.js.map +1 -0
- package/build/src/stack-utils.d.ts +25 -0
- package/build/src/stack-utils.js +95 -0
- package/build/src/stack-utils.js.map +1 -0
- package/build/src/stack-utils.test.d.ts +1 -0
- package/build/src/stack-utils.test.js +80 -0
- package/build/src/stack-utils.test.js.map +1 -0
- package/docs/ai-agent-setup.md +7 -6
- package/package.json +1 -1
- /package/agent_config/claude-code/skills/{guide → ts-procedures}/anti-patterns.md +0 -0
- /package/agent_config/claude-code/skills/{guide → ts-procedures}/api-reference.md +0 -0
- /package/agent_config/claude-code/skills/{guide → ts-procedures}/patterns.md +0 -0
- /package/agent_config/claude-code/skills/{review → ts-procedures-review}/checklist.md +0 -0
- /package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/client.md +0 -0
- /package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/express-rpc.md +0 -0
- /package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/hono-api.md +0 -0
- /package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/hono-rpc.md +0 -0
- /package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/hono-stream.md +0 -0
- /package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/procedure.md +0 -0
- /package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/stream-procedure.md +0 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { interpolatePath, buildAdapterRequest } from './request-builder.js';
|
|
3
|
+
import { ClientPathParamError } from './errors.js';
|
|
4
|
+
// ── interpolatePath ───────────────────────────────────────
|
|
5
|
+
describe('interpolatePath', () => {
|
|
6
|
+
it('returns path unchanged when no params are present', () => {
|
|
7
|
+
expect(interpolatePath('/users', {}, 'GetUsers')).toBe('/users');
|
|
8
|
+
});
|
|
9
|
+
it('replaces a single :param with the provided value', () => {
|
|
10
|
+
expect(interpolatePath('/users/:id', { id: '42' }, 'GetUser')).toBe('/users/42');
|
|
11
|
+
});
|
|
12
|
+
it('replaces multiple :params in one path', () => {
|
|
13
|
+
expect(interpolatePath('/orgs/:orgId/users/:userId', { orgId: 'acme', userId: '7' }, 'GetUser')).toBe('/orgs/acme/users/7');
|
|
14
|
+
});
|
|
15
|
+
it('URI-encodes param values', () => {
|
|
16
|
+
expect(interpolatePath('/users/:name', { name: 'hello world' }, 'GetUser')).toBe('/users/hello%20world');
|
|
17
|
+
});
|
|
18
|
+
it('throws ClientPathParamError when a required param is missing', () => {
|
|
19
|
+
expect(() => interpolatePath('/users/:id', {}, 'GetUser')).toThrow(ClientPathParamError);
|
|
20
|
+
});
|
|
21
|
+
it('throws with descriptive message containing the param name and path', () => {
|
|
22
|
+
expect(() => interpolatePath('/users/:id', {}, 'GetUser')).toThrow(/id/);
|
|
23
|
+
expect(() => interpolatePath('/users/:id', {}, 'GetUser')).toThrow(/\/users\/:id/);
|
|
24
|
+
});
|
|
25
|
+
it('is a no-op when path has no :params', () => {
|
|
26
|
+
expect(interpolatePath('/static/path', {}, 'Foo')).toBe('/static/path');
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
// ── buildAdapterRequest ───────────────────────────────────
|
|
30
|
+
describe('buildAdapterRequest', () => {
|
|
31
|
+
const base = {
|
|
32
|
+
name: 'GetUser',
|
|
33
|
+
scope: 'users',
|
|
34
|
+
path: '/users/:id',
|
|
35
|
+
method: 'GET',
|
|
36
|
+
};
|
|
37
|
+
it('RPC: sends flat params as JSON body', () => {
|
|
38
|
+
const descriptor = {
|
|
39
|
+
...base,
|
|
40
|
+
path: '/rpc/GetUser',
|
|
41
|
+
kind: 'rpc',
|
|
42
|
+
params: { userId: '42', extra: true },
|
|
43
|
+
};
|
|
44
|
+
const req = buildAdapterRequest(descriptor, 'https://api.example.com');
|
|
45
|
+
expect(req.url).toBe('https://api.example.com/rpc/GetUser');
|
|
46
|
+
expect(req.method).toBe('GET');
|
|
47
|
+
expect(req.body).toEqual({ userId: '42', extra: true });
|
|
48
|
+
expect(req.headers).toBeUndefined();
|
|
49
|
+
});
|
|
50
|
+
it('stream: sends flat params as JSON body (same as RPC)', () => {
|
|
51
|
+
const descriptor = {
|
|
52
|
+
...base,
|
|
53
|
+
path: '/stream/Updates',
|
|
54
|
+
kind: 'stream',
|
|
55
|
+
params: { filter: 'active' },
|
|
56
|
+
};
|
|
57
|
+
const req = buildAdapterRequest(descriptor, 'https://api.example.com');
|
|
58
|
+
expect(req.url).toBe('https://api.example.com/stream/Updates');
|
|
59
|
+
expect(req.body).toEqual({ filter: 'active' });
|
|
60
|
+
});
|
|
61
|
+
it('API: interpolates pathParams into URL', () => {
|
|
62
|
+
const descriptor = {
|
|
63
|
+
...base,
|
|
64
|
+
path: '/users/:id',
|
|
65
|
+
kind: 'api',
|
|
66
|
+
params: { pathParams: { id: '99' } },
|
|
67
|
+
};
|
|
68
|
+
const req = buildAdapterRequest(descriptor, 'https://api.example.com');
|
|
69
|
+
expect(req.url).toBe('https://api.example.com/users/99');
|
|
70
|
+
expect(req.body).toBeUndefined();
|
|
71
|
+
});
|
|
72
|
+
it('API: appends query params to the URL', () => {
|
|
73
|
+
const descriptor = {
|
|
74
|
+
...base,
|
|
75
|
+
path: '/users',
|
|
76
|
+
kind: 'api',
|
|
77
|
+
params: { query: { role: 'admin', active: 'true' } },
|
|
78
|
+
};
|
|
79
|
+
const req = buildAdapterRequest(descriptor, 'https://api.example.com');
|
|
80
|
+
expect(req.url).toContain('role=admin');
|
|
81
|
+
expect(req.url).toContain('active=true');
|
|
82
|
+
});
|
|
83
|
+
it('API: sets body from body channel', () => {
|
|
84
|
+
const descriptor = {
|
|
85
|
+
...base,
|
|
86
|
+
path: '/users',
|
|
87
|
+
method: 'POST',
|
|
88
|
+
kind: 'api',
|
|
89
|
+
params: { body: { name: 'Alice', age: 30 } },
|
|
90
|
+
};
|
|
91
|
+
const req = buildAdapterRequest(descriptor, 'https://api.example.com');
|
|
92
|
+
expect(req.body).toEqual({ name: 'Alice', age: 30 });
|
|
93
|
+
});
|
|
94
|
+
it('API: merges headers channel into request headers', () => {
|
|
95
|
+
const descriptor = {
|
|
96
|
+
...base,
|
|
97
|
+
path: '/users',
|
|
98
|
+
kind: 'api',
|
|
99
|
+
params: { headers: { 'x-tenant-id': 'tenant-123' } },
|
|
100
|
+
};
|
|
101
|
+
const req = buildAdapterRequest(descriptor, 'https://api.example.com');
|
|
102
|
+
expect(req.headers?.['x-tenant-id']).toBe('tenant-123');
|
|
103
|
+
});
|
|
104
|
+
it('API GET with query only — no body', () => {
|
|
105
|
+
const descriptor = {
|
|
106
|
+
...base,
|
|
107
|
+
path: '/search',
|
|
108
|
+
method: 'GET',
|
|
109
|
+
kind: 'api',
|
|
110
|
+
params: { query: { q: 'typescript' } },
|
|
111
|
+
};
|
|
112
|
+
const req = buildAdapterRequest(descriptor, 'https://api.example.com');
|
|
113
|
+
expect(req.url).toContain('q=typescript');
|
|
114
|
+
expect(req.body).toBeUndefined();
|
|
115
|
+
});
|
|
116
|
+
it('API: combines pathParams, query, body, and headers together', () => {
|
|
117
|
+
const descriptor = {
|
|
118
|
+
...base,
|
|
119
|
+
path: '/orgs/:orgId/users/:userId',
|
|
120
|
+
method: 'PUT',
|
|
121
|
+
kind: 'api',
|
|
122
|
+
params: {
|
|
123
|
+
pathParams: { orgId: 'acme', userId: '7' },
|
|
124
|
+
query: { version: '2' },
|
|
125
|
+
body: { name: 'Bob' },
|
|
126
|
+
headers: { 'x-request-id': 'req-xyz' },
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
const req = buildAdapterRequest(descriptor, 'https://api.example.com');
|
|
130
|
+
expect(req.url).toContain('/orgs/acme/users/7');
|
|
131
|
+
expect(req.url).toContain('version=2');
|
|
132
|
+
expect(req.body).toEqual({ name: 'Bob' });
|
|
133
|
+
expect(req.headers?.['x-request-id']).toBe('req-xyz');
|
|
134
|
+
});
|
|
135
|
+
it('RPC with keys named "body" and "query" is treated as flat — NOT structured', () => {
|
|
136
|
+
const descriptor = {
|
|
137
|
+
...base,
|
|
138
|
+
path: '/rpc/DoThing',
|
|
139
|
+
kind: 'rpc',
|
|
140
|
+
params: { body: 'literal-body-value', query: 'literal-query-value' },
|
|
141
|
+
};
|
|
142
|
+
const req = buildAdapterRequest(descriptor, 'https://api.example.com');
|
|
143
|
+
// The entire params object goes to body — no query string appended
|
|
144
|
+
expect(req.body).toEqual({ body: 'literal-body-value', query: 'literal-query-value' });
|
|
145
|
+
expect(req.url).toBe('https://api.example.com/rpc/DoThing');
|
|
146
|
+
// Should NOT have a query string derived from params.query
|
|
147
|
+
expect(req.url).not.toContain('?');
|
|
148
|
+
});
|
|
149
|
+
it('prepends basePath to the URL', () => {
|
|
150
|
+
const descriptor = {
|
|
151
|
+
...base,
|
|
152
|
+
path: '/users',
|
|
153
|
+
kind: 'rpc',
|
|
154
|
+
params: {},
|
|
155
|
+
};
|
|
156
|
+
const req = buildAdapterRequest(descriptor, 'https://api.example.com/v1');
|
|
157
|
+
expect(req.url).toBe('https://api.example.com/v1/users');
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
//# sourceMappingURL=request-builder.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-builder.test.js","sourceRoot":"","sources":["../../../src/client/request-builder.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ClientAdapter, ClientHooks, StreamDescriptor, TypedStream } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Wraps an AsyncIterable into a TypedStream.
|
|
4
|
+
*
|
|
5
|
+
* SSE mode: each item is `{ data, event?, id? }`.
|
|
6
|
+
* - If `event === 'return'`, the data resolves `.result` and is NOT yielded.
|
|
7
|
+
* - Otherwise, `data` is yielded.
|
|
8
|
+
*
|
|
9
|
+
* Text mode: each item is yielded as-is.
|
|
10
|
+
* - `.result` resolves to `void` on completion.
|
|
11
|
+
*
|
|
12
|
+
* On error: `.result` rejects and the error is re-thrown from the async iterator.
|
|
13
|
+
*/
|
|
14
|
+
export declare function createTypedStream<TYield, TReturn = void>(source: AsyncIterable<unknown>, streamMode: 'sse' | 'text'): TypedStream<TYield, TReturn>;
|
|
15
|
+
/**
|
|
16
|
+
* Executes a streaming procedure call through the adapter.
|
|
17
|
+
*
|
|
18
|
+
* Flow:
|
|
19
|
+
* 1. Build AdapterRequest from descriptor
|
|
20
|
+
* 2. Run onBeforeRequest hooks
|
|
21
|
+
* 3. Call adapter.stream()
|
|
22
|
+
* 4. On adapter error: run onError hooks, re-throw
|
|
23
|
+
* 5. Run onAfterResponse immediately (before iteration), body is null
|
|
24
|
+
* 6. If non-2xx: throw ClientRequestError
|
|
25
|
+
* 7. Return createTypedStream(streamResponse.body, descriptor.streamMode)
|
|
26
|
+
*/
|
|
27
|
+
export declare function executeStream<TYield, TReturn = void>(descriptor: StreamDescriptor, basePath: string, adapter: ClientAdapter, globalHooks: ClientHooks, localHooks: ClientHooks | undefined): Promise<TypedStream<TYield, TReturn>>;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { buildAdapterRequest } from './request-builder.js';
|
|
2
|
+
import { runBeforeRequest, runAfterResponse, runOnError } from './hooks.js';
|
|
3
|
+
import { ClientRequestError } from './errors.js';
|
|
4
|
+
// ── createTypedStream ─────────────────────────────────────
|
|
5
|
+
/**
|
|
6
|
+
* Wraps an AsyncIterable into a TypedStream.
|
|
7
|
+
*
|
|
8
|
+
* SSE mode: each item is `{ data, event?, id? }`.
|
|
9
|
+
* - If `event === 'return'`, the data resolves `.result` and is NOT yielded.
|
|
10
|
+
* - Otherwise, `data` is yielded.
|
|
11
|
+
*
|
|
12
|
+
* Text mode: each item is yielded as-is.
|
|
13
|
+
* - `.result` resolves to `void` on completion.
|
|
14
|
+
*
|
|
15
|
+
* On error: `.result` rejects and the error is re-thrown from the async iterator.
|
|
16
|
+
*/
|
|
17
|
+
export function createTypedStream(source, streamMode) {
|
|
18
|
+
let resolveResult;
|
|
19
|
+
let rejectResult;
|
|
20
|
+
const resultPromise = new Promise((resolve, reject) => {
|
|
21
|
+
resolveResult = resolve;
|
|
22
|
+
rejectResult = reject;
|
|
23
|
+
});
|
|
24
|
+
async function* generate() {
|
|
25
|
+
try {
|
|
26
|
+
if (streamMode === 'sse') {
|
|
27
|
+
let returnValue;
|
|
28
|
+
let hasReturn = false;
|
|
29
|
+
for await (const item of source) {
|
|
30
|
+
const sseItem = item;
|
|
31
|
+
if (sseItem.event === 'return') {
|
|
32
|
+
returnValue = sseItem.data;
|
|
33
|
+
hasReturn = true;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
yield sseItem.data;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Resolve result after iteration completes
|
|
40
|
+
if (hasReturn) {
|
|
41
|
+
resolveResult(returnValue);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
resolveResult(undefined);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
// text mode: yield each item as-is
|
|
49
|
+
for await (const item of source) {
|
|
50
|
+
yield item;
|
|
51
|
+
}
|
|
52
|
+
resolveResult(undefined);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
rejectResult(err);
|
|
57
|
+
throw err;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const iterator = generate();
|
|
61
|
+
return {
|
|
62
|
+
[Symbol.asyncIterator]() {
|
|
63
|
+
return iterator;
|
|
64
|
+
},
|
|
65
|
+
result: resultPromise,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
// ── executeStream ─────────────────────────────────────────
|
|
69
|
+
/**
|
|
70
|
+
* Executes a streaming procedure call through the adapter.
|
|
71
|
+
*
|
|
72
|
+
* Flow:
|
|
73
|
+
* 1. Build AdapterRequest from descriptor
|
|
74
|
+
* 2. Run onBeforeRequest hooks
|
|
75
|
+
* 3. Call adapter.stream()
|
|
76
|
+
* 4. On adapter error: run onError hooks, re-throw
|
|
77
|
+
* 5. Run onAfterResponse immediately (before iteration), body is null
|
|
78
|
+
* 6. If non-2xx: throw ClientRequestError
|
|
79
|
+
* 7. Return createTypedStream(streamResponse.body, descriptor.streamMode)
|
|
80
|
+
*/
|
|
81
|
+
export async function executeStream(descriptor, basePath, adapter, globalHooks, localHooks) {
|
|
82
|
+
// 1. Build the initial request
|
|
83
|
+
let request = buildAdapterRequest(descriptor, basePath);
|
|
84
|
+
// 2. Run before-request hooks
|
|
85
|
+
const beforeCtx = await runBeforeRequest({ procedureName: descriptor.name, scope: descriptor.scope, request }, globalHooks, localHooks);
|
|
86
|
+
request = beforeCtx.request;
|
|
87
|
+
// 3. Call the adapter
|
|
88
|
+
let streamResponse;
|
|
89
|
+
try {
|
|
90
|
+
streamResponse = await adapter.stream(request);
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
// 4. On adapter error: run error hooks, re-throw
|
|
94
|
+
await runOnError({ procedureName: descriptor.name, scope: descriptor.scope, request, error: err }, globalHooks, localHooks);
|
|
95
|
+
throw err;
|
|
96
|
+
}
|
|
97
|
+
// Build an AdapterResponse shape for the hooks (body is null for streams at this point)
|
|
98
|
+
const responseForHooks = {
|
|
99
|
+
status: streamResponse.status,
|
|
100
|
+
headers: streamResponse.headers,
|
|
101
|
+
body: null,
|
|
102
|
+
};
|
|
103
|
+
// 5. Run after-response hooks immediately (before iteration)
|
|
104
|
+
await runAfterResponse({ procedureName: descriptor.name, scope: descriptor.scope, request, response: responseForHooks }, globalHooks, localHooks);
|
|
105
|
+
// 6. Check status after hooks (hooks may mutate responseForHooks.status)
|
|
106
|
+
if (responseForHooks.status < 200 || responseForHooks.status >= 300) {
|
|
107
|
+
throw new ClientRequestError({
|
|
108
|
+
status: responseForHooks.status,
|
|
109
|
+
headers: responseForHooks.headers,
|
|
110
|
+
body: responseForHooks.body,
|
|
111
|
+
procedureName: descriptor.name,
|
|
112
|
+
scope: descriptor.scope,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
// 7. Return the typed stream
|
|
116
|
+
return createTypedStream(streamResponse.body, descriptor.streamMode);
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../../../src/client/stream.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { createTypedStream, executeStream } from './stream.js';
|
|
3
|
+
import { ClientRequestError } from './errors.js';
|
|
4
|
+
// ── helpers ───────────────────────────────────────────────
|
|
5
|
+
function makeDescriptor(overrides) {
|
|
6
|
+
return {
|
|
7
|
+
name: 'WatchUpdates',
|
|
8
|
+
scope: 'updates',
|
|
9
|
+
path: '/stream/updates',
|
|
10
|
+
method: 'POST',
|
|
11
|
+
kind: 'stream',
|
|
12
|
+
streamMode: 'sse',
|
|
13
|
+
params: {},
|
|
14
|
+
...overrides,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
async function* makeAsyncIterable(items) {
|
|
18
|
+
for (const item of items) {
|
|
19
|
+
yield item;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function makeStreamAdapter(response, items) {
|
|
23
|
+
return {
|
|
24
|
+
request: vi.fn(async () => {
|
|
25
|
+
throw new Error('request not expected in stream tests');
|
|
26
|
+
}),
|
|
27
|
+
stream: vi.fn(async (_req) => ({
|
|
28
|
+
status: 200,
|
|
29
|
+
headers: {},
|
|
30
|
+
body: makeAsyncIterable(items ?? []),
|
|
31
|
+
...response,
|
|
32
|
+
})),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
// ── createTypedStream — SSE mode ──────────────────────────
|
|
36
|
+
describe('createTypedStream — SSE mode', () => {
|
|
37
|
+
it('yields data payloads for normal events', async () => {
|
|
38
|
+
const sseItems = [
|
|
39
|
+
{ data: { count: 1 }, event: 'update' },
|
|
40
|
+
{ data: { count: 2 }, event: 'update' },
|
|
41
|
+
];
|
|
42
|
+
const stream = createTypedStream(makeAsyncIterable(sseItems), 'sse');
|
|
43
|
+
const received = [];
|
|
44
|
+
for await (const item of stream) {
|
|
45
|
+
received.push(item);
|
|
46
|
+
}
|
|
47
|
+
expect(received).toEqual([{ count: 1 }, { count: 2 }]);
|
|
48
|
+
});
|
|
49
|
+
it('captures return event data in .result instead of yielding', async () => {
|
|
50
|
+
const sseItems = [
|
|
51
|
+
{ data: { count: 1 }, event: 'update' },
|
|
52
|
+
{ data: { total: 99 }, event: 'return' },
|
|
53
|
+
];
|
|
54
|
+
const stream = createTypedStream(makeAsyncIterable(sseItems), 'sse');
|
|
55
|
+
const yielded = [];
|
|
56
|
+
for await (const item of stream) {
|
|
57
|
+
yielded.push(item);
|
|
58
|
+
}
|
|
59
|
+
// Only the 'update' event is yielded
|
|
60
|
+
expect(yielded).toEqual([{ count: 1 }]);
|
|
61
|
+
// The 'return' event resolves .result
|
|
62
|
+
const result = await stream.result;
|
|
63
|
+
expect(result).toEqual({ total: 99 });
|
|
64
|
+
});
|
|
65
|
+
it('resolves .result with undefined when no return event', async () => {
|
|
66
|
+
const sseItems = [
|
|
67
|
+
{ data: 'hello', event: 'message' },
|
|
68
|
+
];
|
|
69
|
+
const stream = createTypedStream(makeAsyncIterable(sseItems), 'sse');
|
|
70
|
+
for await (const _ of stream) { /* drain */ }
|
|
71
|
+
const result = await stream.result;
|
|
72
|
+
expect(result).toBeUndefined();
|
|
73
|
+
});
|
|
74
|
+
it('rejects .result and re-throws on error', async () => {
|
|
75
|
+
async function* errorIterable() {
|
|
76
|
+
yield { data: 'first', event: 'message' };
|
|
77
|
+
throw new Error('stream broke');
|
|
78
|
+
}
|
|
79
|
+
const stream = createTypedStream(errorIterable(), 'sse');
|
|
80
|
+
// Consuming the stream should throw
|
|
81
|
+
await expect(async () => {
|
|
82
|
+
for await (const _ of stream) { /* drain */ }
|
|
83
|
+
}).rejects.toThrow('stream broke');
|
|
84
|
+
// .result should also reject
|
|
85
|
+
await expect(stream.result).rejects.toThrow('stream broke');
|
|
86
|
+
});
|
|
87
|
+
it('handles SSE items without event field (defaults to yielding data)', async () => {
|
|
88
|
+
const sseItems = [
|
|
89
|
+
{ data: 'a' },
|
|
90
|
+
{ data: 'b' },
|
|
91
|
+
];
|
|
92
|
+
const stream = createTypedStream(makeAsyncIterable(sseItems), 'sse');
|
|
93
|
+
const yielded = [];
|
|
94
|
+
for await (const item of stream) {
|
|
95
|
+
yielded.push(item);
|
|
96
|
+
}
|
|
97
|
+
expect(yielded).toEqual(['a', 'b']);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
// ── createTypedStream — text mode ────────────────────────
|
|
101
|
+
describe('createTypedStream — text mode', () => {
|
|
102
|
+
it('yields each chunk as-is', async () => {
|
|
103
|
+
const chunks = ['chunk1', 'chunk2', 'chunk3'];
|
|
104
|
+
const stream = createTypedStream(makeAsyncIterable(chunks), 'text');
|
|
105
|
+
const received = [];
|
|
106
|
+
for await (const chunk of stream) {
|
|
107
|
+
received.push(chunk);
|
|
108
|
+
}
|
|
109
|
+
expect(received).toEqual(chunks);
|
|
110
|
+
});
|
|
111
|
+
it('.result resolves to void on normal completion', async () => {
|
|
112
|
+
const stream = createTypedStream(makeAsyncIterable(['a', 'b']), 'text');
|
|
113
|
+
for await (const _ of stream) { /* drain */ }
|
|
114
|
+
const result = await stream.result;
|
|
115
|
+
expect(result).toBeUndefined();
|
|
116
|
+
});
|
|
117
|
+
it('rejects .result and re-throws on error', async () => {
|
|
118
|
+
async function* errorIterable() {
|
|
119
|
+
yield 'before error';
|
|
120
|
+
throw new Error('text stream error');
|
|
121
|
+
}
|
|
122
|
+
const stream = createTypedStream(errorIterable(), 'text');
|
|
123
|
+
await expect(async () => {
|
|
124
|
+
for await (const _ of stream) { /* drain */ }
|
|
125
|
+
}).rejects.toThrow('text stream error');
|
|
126
|
+
await expect(stream.result).rejects.toThrow('text stream error');
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
// ── executeStream ─────────────────────────────────────────
|
|
130
|
+
describe('executeStream', () => {
|
|
131
|
+
it('calls adapter.stream and returns a TypedStream', async () => {
|
|
132
|
+
const items = [{ data: 'hello', event: 'msg' }];
|
|
133
|
+
const adapter = makeStreamAdapter({}, items);
|
|
134
|
+
const stream = await executeStream(makeDescriptor(), 'https://api.example.com', adapter, {}, undefined);
|
|
135
|
+
expect(adapter.stream).toHaveBeenCalledOnce();
|
|
136
|
+
const received = [];
|
|
137
|
+
for await (const item of stream) {
|
|
138
|
+
received.push(item);
|
|
139
|
+
}
|
|
140
|
+
expect(received).toEqual(['hello']);
|
|
141
|
+
});
|
|
142
|
+
it('runs onBeforeRequest before calling adapter', async () => {
|
|
143
|
+
const capturedHeaders = [];
|
|
144
|
+
const adapter = {
|
|
145
|
+
request: vi.fn(async () => { throw new Error('not expected'); }),
|
|
146
|
+
stream: vi.fn(async (req) => {
|
|
147
|
+
capturedHeaders.push(req.headers ?? {});
|
|
148
|
+
return { status: 200, headers: {}, body: makeAsyncIterable([]) };
|
|
149
|
+
}),
|
|
150
|
+
};
|
|
151
|
+
const globalHooks = {
|
|
152
|
+
onBeforeRequest: (ctx) => ({
|
|
153
|
+
...ctx,
|
|
154
|
+
request: { ...ctx.request, headers: { 'x-stream-auth': 'stream-token' } },
|
|
155
|
+
}),
|
|
156
|
+
};
|
|
157
|
+
const stream = await executeStream(makeDescriptor(), 'https://api.example.com', adapter, globalHooks, undefined);
|
|
158
|
+
// Drain
|
|
159
|
+
for await (const _ of stream) { /* noop */ }
|
|
160
|
+
expect(capturedHeaders[0]?.['x-stream-auth']).toBe('stream-token');
|
|
161
|
+
});
|
|
162
|
+
it('runs onAfterResponse immediately (before iteration)', async () => {
|
|
163
|
+
const order = [];
|
|
164
|
+
const adapter = {
|
|
165
|
+
request: vi.fn(async () => { throw new Error('not expected'); }),
|
|
166
|
+
stream: vi.fn(async () => {
|
|
167
|
+
order.push('adapter');
|
|
168
|
+
return { status: 200, headers: {}, body: makeAsyncIterable([]) };
|
|
169
|
+
}),
|
|
170
|
+
};
|
|
171
|
+
const globalHooks = {
|
|
172
|
+
onAfterResponse: () => { order.push('afterResponse'); },
|
|
173
|
+
};
|
|
174
|
+
await executeStream(makeDescriptor(), 'https://api.example.com', adapter, globalHooks, undefined);
|
|
175
|
+
// After executeStream returns (before iteration), afterResponse should have fired
|
|
176
|
+
expect(order).toEqual(['adapter', 'afterResponse']);
|
|
177
|
+
});
|
|
178
|
+
it('throws ClientRequestError on non-2xx status', async () => {
|
|
179
|
+
const adapter = {
|
|
180
|
+
request: vi.fn(async () => { throw new Error('not expected'); }),
|
|
181
|
+
stream: vi.fn(async () => ({
|
|
182
|
+
status: 403,
|
|
183
|
+
headers: {},
|
|
184
|
+
body: makeAsyncIterable([]),
|
|
185
|
+
})),
|
|
186
|
+
};
|
|
187
|
+
await expect(executeStream(makeDescriptor(), 'https://api.example.com', adapter, {}, undefined)).rejects.toThrow(ClientRequestError);
|
|
188
|
+
});
|
|
189
|
+
it('runs onError on adapter failure and re-throws', async () => {
|
|
190
|
+
const adapterError = new Error('stream connection failed');
|
|
191
|
+
const adapter = {
|
|
192
|
+
request: vi.fn(async () => { throw new Error('not expected'); }),
|
|
193
|
+
stream: vi.fn(async () => { throw adapterError; }),
|
|
194
|
+
};
|
|
195
|
+
const receivedErrors = [];
|
|
196
|
+
const globalHooks = {
|
|
197
|
+
onError: (ctx) => { receivedErrors.push(ctx.error); },
|
|
198
|
+
};
|
|
199
|
+
await expect(executeStream(makeDescriptor(), 'https://api.example.com', adapter, globalHooks, undefined)).rejects.toThrow('stream connection failed');
|
|
200
|
+
expect(receivedErrors[0]).toBe(adapterError);
|
|
201
|
+
});
|
|
202
|
+
it('returns TypedStream with working .result for SSE return event', async () => {
|
|
203
|
+
const sseItems = [
|
|
204
|
+
{ data: { n: 1 }, event: 'tick' },
|
|
205
|
+
{ data: { final: true }, event: 'return' },
|
|
206
|
+
];
|
|
207
|
+
const adapter = makeStreamAdapter({}, sseItems);
|
|
208
|
+
const stream = await executeStream(makeDescriptor({ streamMode: 'sse' }), 'https://api.example.com', adapter, {}, undefined);
|
|
209
|
+
const yielded = [];
|
|
210
|
+
for await (const item of stream) {
|
|
211
|
+
yielded.push(item);
|
|
212
|
+
}
|
|
213
|
+
expect(yielded).toEqual([{ n: 1 }]);
|
|
214
|
+
await expect(stream.result).resolves.toEqual({ final: true });
|
|
215
|
+
});
|
|
216
|
+
it('returns TypedStream for text mode', async () => {
|
|
217
|
+
const chunks = ['line1', 'line2'];
|
|
218
|
+
const adapter = makeStreamAdapter({}, chunks);
|
|
219
|
+
const stream = await executeStream(makeDescriptor({ streamMode: 'text' }), 'https://api.example.com', adapter, {}, undefined);
|
|
220
|
+
const received = [];
|
|
221
|
+
for await (const chunk of stream) {
|
|
222
|
+
received.push(chunk);
|
|
223
|
+
}
|
|
224
|
+
expect(received).toEqual(chunks);
|
|
225
|
+
await expect(stream.result).resolves.toBeUndefined();
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
//# sourceMappingURL=stream.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.test.js","sourceRoot":"","sources":["../../../src/client/stream.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export interface ClientAdapter {
|
|
2
|
+
request(config: AdapterRequest): Promise<AdapterResponse>;
|
|
3
|
+
stream(config: AdapterRequest): Promise<AdapterStreamResponse>;
|
|
4
|
+
}
|
|
5
|
+
export interface AdapterRequest {
|
|
6
|
+
url: string;
|
|
7
|
+
method: string;
|
|
8
|
+
headers?: Record<string, string>;
|
|
9
|
+
body?: unknown;
|
|
10
|
+
signal?: AbortSignal;
|
|
11
|
+
}
|
|
12
|
+
export interface AdapterResponse {
|
|
13
|
+
status: number;
|
|
14
|
+
headers: Record<string, string>;
|
|
15
|
+
body: unknown;
|
|
16
|
+
}
|
|
17
|
+
export interface AdapterStreamResponse {
|
|
18
|
+
status: number;
|
|
19
|
+
headers: Record<string, string>;
|
|
20
|
+
body: AsyncIterable<unknown>;
|
|
21
|
+
}
|
|
22
|
+
export interface ClientHooks {
|
|
23
|
+
onBeforeRequest?(context: BeforeRequestContext): BeforeRequestContext | Promise<BeforeRequestContext>;
|
|
24
|
+
onAfterResponse?(context: AfterResponseContext): void | Promise<void>;
|
|
25
|
+
onError?(context: ErrorContext): void | Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
export interface BeforeRequestContext {
|
|
28
|
+
procedureName: string;
|
|
29
|
+
scope: string;
|
|
30
|
+
request: AdapterRequest;
|
|
31
|
+
}
|
|
32
|
+
export interface AfterResponseContext {
|
|
33
|
+
procedureName: string;
|
|
34
|
+
scope: string;
|
|
35
|
+
request: AdapterRequest;
|
|
36
|
+
response: AdapterResponse;
|
|
37
|
+
}
|
|
38
|
+
export interface ErrorContext {
|
|
39
|
+
procedureName: string;
|
|
40
|
+
scope: string;
|
|
41
|
+
request: AdapterRequest;
|
|
42
|
+
error: unknown;
|
|
43
|
+
}
|
|
44
|
+
export interface CallDescriptor {
|
|
45
|
+
name: string;
|
|
46
|
+
scope: string;
|
|
47
|
+
path: string;
|
|
48
|
+
method: string;
|
|
49
|
+
kind: 'rpc' | 'api' | 'stream';
|
|
50
|
+
params: unknown;
|
|
51
|
+
}
|
|
52
|
+
export interface StreamDescriptor extends CallDescriptor {
|
|
53
|
+
kind: 'stream';
|
|
54
|
+
streamMode: 'sse' | 'text';
|
|
55
|
+
}
|
|
56
|
+
export interface TypedStream<TYield, TReturn = void> extends AsyncIterable<TYield> {
|
|
57
|
+
/**
|
|
58
|
+
* Resolves when the stream completes with the final return value.
|
|
59
|
+
* Rejects if the stream errors before completing.
|
|
60
|
+
* Note: iteration must begin (via for-await) for this promise to settle,
|
|
61
|
+
* since resolution depends on the async generator running to completion.
|
|
62
|
+
*/
|
|
63
|
+
result: Promise<TReturn>;
|
|
64
|
+
}
|
|
65
|
+
export type ProcedureCallOptions = ClientHooks;
|
|
66
|
+
export interface ClientInstance {
|
|
67
|
+
basePath: string;
|
|
68
|
+
adapter: ClientAdapter;
|
|
69
|
+
hooks: ClientHooks;
|
|
70
|
+
call<TResponse>(descriptor: CallDescriptor, options?: ProcedureCallOptions): Promise<TResponse>;
|
|
71
|
+
stream<TYield, TReturn>(descriptor: StreamDescriptor, options?: ProcedureCallOptions): TypedStream<TYield, TReturn>;
|
|
72
|
+
}
|
|
73
|
+
export interface CreateClientConfig<TScopes> {
|
|
74
|
+
adapter: ClientAdapter;
|
|
75
|
+
basePath: string;
|
|
76
|
+
scopes: (client: ClientInstance) => TScopes;
|
|
77
|
+
hooks?: ClientHooks;
|
|
78
|
+
}
|