@agentuity/frontend 0.0.110 → 0.0.111
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/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +93 -15
- package/dist/client/index.js.map +1 -1
- package/dist/client/types.d.ts +51 -5
- package/dist/client/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/client/index.ts +109 -15
- package/src/client/types.ts +104 -17
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AA4DrD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,GAAE,aAAkB,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,CAoK1F;AAGD,YAAY,EACX,aAAa,EACb,MAAM,EACN,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,YAAY,GACZ,MAAM,SAAS,CAAC"}
|
package/dist/client/index.js
CHANGED
|
@@ -17,6 +17,37 @@ function resolveBaseUrl(baseUrl) {
|
|
|
17
17
|
function resolveHeaders(headers) {
|
|
18
18
|
return typeof headers === 'function' ? headers() : headers;
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Escape special regex characters in a string.
|
|
22
|
+
*/
|
|
23
|
+
function escapeRegExp(str) {
|
|
24
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Substitute path parameters in a URL path template.
|
|
28
|
+
* E.g., '/api/users/:id' with { id: '123' } becomes '/api/users/123'
|
|
29
|
+
*/
|
|
30
|
+
function substitutePathParams(pathTemplate, pathParams) {
|
|
31
|
+
if (!pathParams)
|
|
32
|
+
return pathTemplate;
|
|
33
|
+
let result = pathTemplate;
|
|
34
|
+
for (const [key, value] of Object.entries(pathParams)) {
|
|
35
|
+
const escapedKey = escapeRegExp(key);
|
|
36
|
+
result = result.replace(new RegExp(`:${escapedKey}\\??`, 'g'), encodeURIComponent(value));
|
|
37
|
+
result = result.replace(new RegExp(`\\*${escapedKey}`, 'g'), encodeURIComponent(value));
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Build URL with query params.
|
|
43
|
+
*/
|
|
44
|
+
function buildUrlWithQuery(baseUrl, path, query) {
|
|
45
|
+
const url = `${baseUrl}${path}`;
|
|
46
|
+
if (!query || Object.keys(query).length === 0)
|
|
47
|
+
return url;
|
|
48
|
+
const params = new URLSearchParams(query);
|
|
49
|
+
return `${url}?${params.toString()}`;
|
|
50
|
+
}
|
|
20
51
|
/**
|
|
21
52
|
* Create a type-safe API client from a RouteRegistry.
|
|
22
53
|
*
|
|
@@ -65,9 +96,11 @@ export function createClient(options = {}, metadata) {
|
|
|
65
96
|
if (isTerminalMethod && currentPath.length >= 1) {
|
|
66
97
|
const method = prop;
|
|
67
98
|
const pathSegments = currentPath;
|
|
68
|
-
|
|
69
|
-
// Determine route type
|
|
99
|
+
// Look up route metadata
|
|
70
100
|
let routeType = 'api';
|
|
101
|
+
let routePath;
|
|
102
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
103
|
+
let metaNode = metadata;
|
|
71
104
|
if (isStreamMethod) {
|
|
72
105
|
// Stream methods directly specify the route type
|
|
73
106
|
if (method === 'websocket')
|
|
@@ -77,26 +110,71 @@ export function createClient(options = {}, metadata) {
|
|
|
77
110
|
else if (method === 'stream')
|
|
78
111
|
routeType = 'stream';
|
|
79
112
|
}
|
|
80
|
-
|
|
81
|
-
// Look up route type from metadata for HTTP methods
|
|
82
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
83
|
-
let metaNode = metadata;
|
|
113
|
+
if (metadata) {
|
|
84
114
|
for (const segment of pathSegments) {
|
|
85
115
|
if (metaNode && typeof metaNode === 'object') {
|
|
86
116
|
metaNode = metaNode[segment];
|
|
87
117
|
}
|
|
88
118
|
}
|
|
89
|
-
if (metaNode && typeof metaNode === 'object' && metaNode[method]
|
|
90
|
-
|
|
119
|
+
if (metaNode && typeof metaNode === 'object' && metaNode[method]) {
|
|
120
|
+
if (metaNode[method].type) {
|
|
121
|
+
routeType = metaNode[method].type;
|
|
122
|
+
}
|
|
123
|
+
if (metaNode[method].path) {
|
|
124
|
+
routePath = metaNode[method].path;
|
|
125
|
+
}
|
|
91
126
|
}
|
|
92
127
|
}
|
|
93
|
-
|
|
128
|
+
// Fallback URL path if no metadata
|
|
129
|
+
const fallbackPath = '/api/' + pathSegments.join('/');
|
|
130
|
+
return (...args) => {
|
|
94
131
|
const resolvedBaseUrl = resolveBaseUrl(baseUrl);
|
|
95
132
|
const resolvedHeaders = resolveHeaders(defaultHeaders);
|
|
133
|
+
// Get path param names from metadata if available
|
|
134
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
135
|
+
const pathParamNames = metaNode?.[method]?.pathParams;
|
|
136
|
+
const hasPathParams = pathParamNames && pathParamNames.length > 0;
|
|
137
|
+
let pathParams;
|
|
138
|
+
let input;
|
|
139
|
+
let query;
|
|
140
|
+
if (hasPathParams) {
|
|
141
|
+
// Route has path params - positional arguments API
|
|
142
|
+
// Args are: param1, param2, ..., [options?]
|
|
143
|
+
// Example: client.user.get('123', 12) or client.user.get('123', 12, { query: {...} })
|
|
144
|
+
pathParams = {};
|
|
145
|
+
for (let i = 0; i < pathParamNames.length; i++) {
|
|
146
|
+
const arg = args[i];
|
|
147
|
+
if (arg === undefined || arg === null) {
|
|
148
|
+
throw new Error(`Missing required path parameter '${pathParamNames[i]}' at position ${i + 1}. ` +
|
|
149
|
+
`Expected ${pathParamNames.length} path parameter(s): ${pathParamNames.join(', ')}`);
|
|
150
|
+
}
|
|
151
|
+
pathParams[pathParamNames[i]] = String(arg);
|
|
152
|
+
}
|
|
153
|
+
// Check if there's an options object after the path params
|
|
154
|
+
const optionsArg = args[pathParamNames.length];
|
|
155
|
+
if (optionsArg && typeof optionsArg === 'object') {
|
|
156
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
157
|
+
const opts = optionsArg;
|
|
158
|
+
input = opts.input;
|
|
159
|
+
query = opts.query;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
// No path params - use existing behavior
|
|
164
|
+
const options = args[0];
|
|
165
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
166
|
+
const opts = options;
|
|
167
|
+
const isOptionsObject = opts && typeof opts === 'object' && ('input' in opts || 'query' in opts);
|
|
168
|
+
input = isOptionsObject ? opts.input : options;
|
|
169
|
+
query = isOptionsObject ? opts.query : undefined;
|
|
170
|
+
}
|
|
171
|
+
// Substitute path params in the route path
|
|
172
|
+
const basePath = routePath || fallbackPath;
|
|
173
|
+
const urlPath = substitutePathParams(basePath, pathParams);
|
|
96
174
|
// WebSocket endpoint
|
|
97
175
|
if (routeType === 'websocket') {
|
|
98
176
|
const wsBaseUrl = resolvedBaseUrl.replace(/^http/, 'ws');
|
|
99
|
-
const wsUrl =
|
|
177
|
+
const wsUrl = buildUrlWithQuery(wsBaseUrl, urlPath, query);
|
|
100
178
|
const ws = createWebSocketClient(wsUrl);
|
|
101
179
|
if (input) {
|
|
102
180
|
ws.on('open', () => ws.send(input));
|
|
@@ -105,16 +183,15 @@ export function createClient(options = {}, metadata) {
|
|
|
105
183
|
}
|
|
106
184
|
// SSE endpoint
|
|
107
185
|
if (routeType === 'sse') {
|
|
108
|
-
const sseUrl =
|
|
109
|
-
// Note: Native EventSource doesn't support custom headers
|
|
110
|
-
// For auth, use withCredentials or consider fetch-based alternatives like @microsoft/fetch-event-source
|
|
186
|
+
const sseUrl = buildUrlWithQuery(resolvedBaseUrl, urlPath, query);
|
|
111
187
|
return createEventStreamClient(sseUrl, {
|
|
112
188
|
withCredentials: Object.keys(resolvedHeaders).length > 0,
|
|
113
189
|
});
|
|
114
190
|
}
|
|
115
191
|
// Stream endpoint
|
|
116
192
|
if (routeType === 'stream') {
|
|
117
|
-
|
|
193
|
+
const streamUrl = buildUrlWithQuery(resolvedBaseUrl, urlPath, query);
|
|
194
|
+
return fetch(streamUrl, {
|
|
118
195
|
method: method.toUpperCase(),
|
|
119
196
|
headers: { 'Content-Type': contentType, ...resolvedHeaders },
|
|
120
197
|
body: input ? JSON.stringify(input) : undefined,
|
|
@@ -126,7 +203,8 @@ export function createClient(options = {}, metadata) {
|
|
|
126
203
|
});
|
|
127
204
|
}
|
|
128
205
|
// Regular API endpoint
|
|
129
|
-
|
|
206
|
+
const apiUrl = buildUrlWithQuery(resolvedBaseUrl, urlPath, query);
|
|
207
|
+
return fetch(apiUrl, {
|
|
130
208
|
method: method.toUpperCase(),
|
|
131
209
|
headers: { 'Content-Type': contentType, ...resolvedHeaders },
|
|
132
210
|
body: method.toUpperCase() !== 'GET' && input ? JSON.stringify(input) : undefined,
|
package/dist/client/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE9C;;GAEG;AACH,MAAM,cAAc,GAAG,EAAE,CAAC;AAE1B;;GAEG;AACH,SAAS,cAAc,CAAC,OAAgC;IACvD,OAAO,OAAO,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;AAC5D,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CACtB,OAAgE;IAEhE,OAAO,OAAO,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;AAC5D,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,UAAU,YAAY,CAAI,UAAyB,EAAE,EAAE,QAAkB;IAC9E,MAAM,EAAE,OAAO,GAAG,cAAc,EAAE,OAAO,EAAE,WAAW,GAAG,kBAAkB,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAEhG,kDAAkD;IAClD,MAAM,cAAc,GAAG,OAAO,IAAI,EAAE,CAAC;IAErC,MAAM,OAAO,GAAwD;QACpE,GAAG,CAAC,MAAM,EAAE,IAAY;YACvB,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC;YAClC,MAAM,OAAO,GAAG,CAAC,GAAG,WAAW,EAAE,IAAI,CAAC,CAAC;YAEvC,qCAAqC;YACrC,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;YACjF,MAAM,aAAa,GAAG,CAAC,WAAW,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;YAC7D,MAAM,YAAY,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAChD,MAAM,cAAc,GAAG,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YACpD,MAAM,gBAAgB,GAAG,YAAY,IAAI,cAAc,CAAC;YAExD,gEAAgE;YAChE,sFAAsF;YACtF,IAAI,gBAAgB,IAAI,WAAW,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;gBACjD,MAAM,MAAM,GAAG,IAAI,CAAC;gBACpB,MAAM,YAAY,GAAG,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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"}
|
package/dist/client/types.d.ts
CHANGED
|
@@ -86,26 +86,61 @@ export interface StreamClient {
|
|
|
86
86
|
*/
|
|
87
87
|
cancel(): Promise<void>;
|
|
88
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Options object for endpoints without path params (optional query support).
|
|
91
|
+
*/
|
|
92
|
+
export interface EndpointOptionsWithQuery<Input = unknown, Query = Record<string, string>> {
|
|
93
|
+
input?: Input;
|
|
94
|
+
query?: Query;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Additional options that can be passed after positional path params.
|
|
98
|
+
*/
|
|
99
|
+
export interface EndpointExtraOptions<Input = unknown, Query = Record<string, string>> {
|
|
100
|
+
input?: Input;
|
|
101
|
+
query?: Query;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Convert a path params object to a tuple of its value types.
|
|
105
|
+
* Used for positional argument typing.
|
|
106
|
+
* Note: For proper ordering, we rely on the generated PathParamsTuple type.
|
|
107
|
+
*/
|
|
108
|
+
export type PathParamsToTuple<P> = P extends readonly [infer First, ...infer Rest] ? [First, ...PathParamsToTuple<Rest>] : P extends readonly [] ? [] : string[];
|
|
89
109
|
/**
|
|
90
110
|
* API endpoint - callable function for regular HTTP calls.
|
|
111
|
+
* - Without path params: accepts input directly OR options object with query
|
|
112
|
+
* - With path params: accepts positional arguments followed by optional options object
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* // No path params
|
|
116
|
+
* client.hello.post({ name: 'World' })
|
|
117
|
+
*
|
|
118
|
+
* // Single path param
|
|
119
|
+
* client.users.userId.get('123')
|
|
120
|
+
*
|
|
121
|
+
* // Multiple path params
|
|
122
|
+
* client.orgs.orgId.members.memberId.get('org-1', 'user-2')
|
|
123
|
+
*
|
|
124
|
+
* // With additional options
|
|
125
|
+
* client.users.userId.get('123', { query: { include: 'posts' } })
|
|
91
126
|
*/
|
|
92
|
-
export type APIEndpoint<Input = unknown, Output = unknown> = (
|
|
127
|
+
export type APIEndpoint<Input = unknown, Output = unknown, PathParams = never, PathParamsTuple extends unknown[] = string[]> = [PathParams] extends [never] ? (inputOrOptions?: Input | EndpointOptionsWithQuery<Input>) => Promise<Output> : (...args: [...PathParamsTuple, options?: EndpointExtraOptions<Input>]) => Promise<Output>;
|
|
93
128
|
/**
|
|
94
129
|
* WebSocket endpoint - callable function that returns WebSocket client.
|
|
95
130
|
*/
|
|
96
|
-
export type WebSocketEndpoint<Input = unknown, _Output = unknown> = (
|
|
131
|
+
export type WebSocketEndpoint<Input = unknown, _Output = unknown, PathParams = never, PathParamsTuple extends unknown[] = string[]> = [PathParams] extends [never] ? (inputOrOptions?: Input | EndpointOptionsWithQuery<Input>) => WebSocketClient : (...args: [...PathParamsTuple, options?: EndpointExtraOptions<Input>]) => WebSocketClient;
|
|
97
132
|
/**
|
|
98
133
|
* Server-Sent Events endpoint - callable function that returns EventStream client.
|
|
99
134
|
*/
|
|
100
|
-
export type SSEEndpoint<Input = unknown, _Output = unknown> = (
|
|
135
|
+
export type SSEEndpoint<Input = unknown, _Output = unknown, PathParams = never, PathParamsTuple extends unknown[] = string[]> = [PathParams] extends [never] ? (inputOrOptions?: Input | EndpointOptionsWithQuery<Input>) => EventStreamClient : (...args: [...PathParamsTuple, options?: EndpointExtraOptions<Input>]) => EventStreamClient;
|
|
101
136
|
/**
|
|
102
137
|
* Streaming endpoint - callable function that returns Stream client.
|
|
103
138
|
*/
|
|
104
|
-
export type StreamEndpoint<Input = unknown, _Output = unknown> = (
|
|
139
|
+
export type StreamEndpoint<Input = unknown, _Output = unknown, PathParams = never, PathParamsTuple extends unknown[] = string[]> = [PathParams] extends [never] ? (inputOrOptions?: Input | EndpointOptionsWithQuery<Input>) => StreamClient : (...args: [...PathParamsTuple, options?: EndpointExtraOptions<Input>]) => StreamClient;
|
|
105
140
|
/**
|
|
106
141
|
* Route endpoint - discriminated union based on route type.
|
|
107
142
|
*/
|
|
108
|
-
export type RouteEndpoint<Input = unknown, Output = unknown, Type extends string = 'api'> = Type extends 'websocket' ? WebSocketEndpoint<Input, Output> : Type extends 'sse' ? SSEEndpoint<Input, Output> : Type extends 'stream' ? StreamEndpoint<Input, Output> : APIEndpoint<Input, Output>;
|
|
143
|
+
export type RouteEndpoint<Input = unknown, Output = unknown, Type extends string = 'api', PathParams = never, PathParamsTuple extends unknown[] = []> = Type extends 'websocket' ? WebSocketEndpoint<Input, Output, PathParams, PathParamsTuple> : Type extends 'sse' ? SSEEndpoint<Input, Output, PathParams, PathParamsTuple> : Type extends 'stream' ? StreamEndpoint<Input, Output, PathParams, PathParamsTuple> : APIEndpoint<Input, Output, PathParams, PathParamsTuple>;
|
|
109
144
|
/**
|
|
110
145
|
* Recursively build the client proxy type from a RouteRegistry.
|
|
111
146
|
*/
|
|
@@ -114,6 +149,17 @@ export type Client<R> = {
|
|
|
114
149
|
input: infer I;
|
|
115
150
|
output: infer O;
|
|
116
151
|
type: infer T;
|
|
152
|
+
params: infer P;
|
|
153
|
+
paramsTuple: infer PT;
|
|
154
|
+
} ? PT extends unknown[] ? RouteEndpoint<I, O, T extends string ? T : 'api', P, PT> : RouteEndpoint<I, O, T extends string ? T : 'api', P> : R[K] extends {
|
|
155
|
+
input: infer I;
|
|
156
|
+
output: infer O;
|
|
157
|
+
type: infer T;
|
|
158
|
+
params: infer P;
|
|
159
|
+
} ? RouteEndpoint<I, O, T extends string ? T : 'api', P> : R[K] extends {
|
|
160
|
+
input: infer I;
|
|
161
|
+
output: infer O;
|
|
162
|
+
type: infer T;
|
|
117
163
|
} ? RouteEndpoint<I, O, T extends string ? T : 'api'> : R[K] extends {
|
|
118
164
|
input: infer I;
|
|
119
165
|
output: infer O;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/client/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,CAAC;IAElC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAElE;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,GAAG,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B;;OAEG;IACH,EAAE,EAAE;QACH,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;QACzD,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;QACpD,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;QAC1D,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;KACrD,CAAC;IAEF;;OAEG;IACH,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IAE1B;;OAEG;IACH,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IACjC;;OAEG;IACH,EAAE,EAAE;QACH,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC;QAC9D,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;QACpD,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;KACrD,CAAC;IAEF;;OAEG;IACH,KAAK,IAAI,IAAI,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B;;OAEG;IACH,EAAE,EAAE;QACH,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;QAC1D,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QACpD,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;KACrD,CAAC;IAEF;;OAEG;IACH,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/client/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentuity/frontend",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.111",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"author": "Agentuity employees and contributors",
|
|
6
6
|
"type": "module",
|
|
@@ -26,10 +26,10 @@
|
|
|
26
26
|
"prepublishOnly": "bun run clean && bun run build"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@agentuity/core": "0.0.
|
|
29
|
+
"@agentuity/core": "0.0.111"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@agentuity/test-utils": "0.0.
|
|
32
|
+
"@agentuity/test-utils": "0.0.111",
|
|
33
33
|
"@types/bun": "latest",
|
|
34
34
|
"bun-types": "latest",
|
|
35
35
|
"typescript": "^5.9.0"
|
package/src/client/index.ts
CHANGED
|
@@ -24,6 +24,40 @@ function resolveHeaders(
|
|
|
24
24
|
return typeof headers === 'function' ? headers() : headers;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Escape special regex characters in a string.
|
|
29
|
+
*/
|
|
30
|
+
function escapeRegExp(str: string): string {
|
|
31
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Substitute path parameters in a URL path template.
|
|
36
|
+
* E.g., '/api/users/:id' with { id: '123' } becomes '/api/users/123'
|
|
37
|
+
*/
|
|
38
|
+
function substitutePathParams(pathTemplate: string, pathParams?: Record<string, string>): string {
|
|
39
|
+
if (!pathParams) return pathTemplate;
|
|
40
|
+
|
|
41
|
+
let result = pathTemplate;
|
|
42
|
+
for (const [key, value] of Object.entries(pathParams)) {
|
|
43
|
+
const escapedKey = escapeRegExp(key);
|
|
44
|
+
result = result.replace(new RegExp(`:${escapedKey}\\??`, 'g'), encodeURIComponent(value));
|
|
45
|
+
result = result.replace(new RegExp(`\\*${escapedKey}`, 'g'), encodeURIComponent(value));
|
|
46
|
+
}
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Build URL with query params.
|
|
52
|
+
*/
|
|
53
|
+
function buildUrlWithQuery(baseUrl: string, path: string, query?: Record<string, string>): string {
|
|
54
|
+
const url = `${baseUrl}${path}`;
|
|
55
|
+
if (!query || Object.keys(query).length === 0) return url;
|
|
56
|
+
|
|
57
|
+
const params = new URLSearchParams(query);
|
|
58
|
+
return `${url}?${params.toString()}`;
|
|
59
|
+
}
|
|
60
|
+
|
|
27
61
|
/**
|
|
28
62
|
* Create a type-safe API client from a RouteRegistry.
|
|
29
63
|
*
|
|
@@ -76,37 +110,97 @@ export function createClient<R>(options: ClientOptions = {}, metadata?: unknown)
|
|
|
76
110
|
if (isTerminalMethod && currentPath.length >= 1) {
|
|
77
111
|
const method = prop;
|
|
78
112
|
const pathSegments = currentPath;
|
|
79
|
-
const urlPath = '/api/' + pathSegments.join('/');
|
|
80
113
|
|
|
81
|
-
//
|
|
114
|
+
// Look up route metadata
|
|
82
115
|
let routeType = 'api';
|
|
116
|
+
let routePath: string | undefined;
|
|
117
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
118
|
+
let metaNode: any = metadata;
|
|
119
|
+
|
|
83
120
|
if (isStreamMethod) {
|
|
84
121
|
// Stream methods directly specify the route type
|
|
85
122
|
if (method === 'websocket') routeType = 'websocket';
|
|
86
123
|
else if (method === 'eventstream') routeType = 'sse';
|
|
87
124
|
else if (method === 'stream') routeType = 'stream';
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
let metaNode: any = metadata;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (metadata) {
|
|
92
128
|
for (const segment of pathSegments) {
|
|
93
129
|
if (metaNode && typeof metaNode === 'object') {
|
|
94
130
|
metaNode = metaNode[segment];
|
|
95
131
|
}
|
|
96
132
|
}
|
|
97
|
-
if (metaNode && typeof metaNode === 'object' && metaNode[method]
|
|
98
|
-
|
|
133
|
+
if (metaNode && typeof metaNode === 'object' && metaNode[method]) {
|
|
134
|
+
if (metaNode[method].type) {
|
|
135
|
+
routeType = metaNode[method].type;
|
|
136
|
+
}
|
|
137
|
+
if (metaNode[method].path) {
|
|
138
|
+
routePath = metaNode[method].path;
|
|
139
|
+
}
|
|
99
140
|
}
|
|
100
141
|
}
|
|
101
142
|
|
|
102
|
-
|
|
143
|
+
// Fallback URL path if no metadata
|
|
144
|
+
const fallbackPath = '/api/' + pathSegments.join('/');
|
|
145
|
+
|
|
146
|
+
return (...args: unknown[]) => {
|
|
103
147
|
const resolvedBaseUrl = resolveBaseUrl(baseUrl);
|
|
104
148
|
const resolvedHeaders = resolveHeaders(defaultHeaders);
|
|
105
149
|
|
|
150
|
+
// Get path param names from metadata if available
|
|
151
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
152
|
+
const pathParamNames: string[] | undefined = (metaNode as any)?.[method]?.pathParams;
|
|
153
|
+
const hasPathParams = pathParamNames && pathParamNames.length > 0;
|
|
154
|
+
|
|
155
|
+
let pathParams: Record<string, string> | undefined;
|
|
156
|
+
let input: unknown;
|
|
157
|
+
let query: Record<string, string> | undefined;
|
|
158
|
+
|
|
159
|
+
if (hasPathParams) {
|
|
160
|
+
// Route has path params - positional arguments API
|
|
161
|
+
// Args are: param1, param2, ..., [options?]
|
|
162
|
+
// Example: client.user.get('123', 12) or client.user.get('123', 12, { query: {...} })
|
|
163
|
+
pathParams = {};
|
|
164
|
+
|
|
165
|
+
for (let i = 0; i < pathParamNames.length; i++) {
|
|
166
|
+
const arg = args[i];
|
|
167
|
+
if (arg === undefined || arg === null) {
|
|
168
|
+
throw new Error(
|
|
169
|
+
`Missing required path parameter '${pathParamNames[i]}' at position ${i + 1}. ` +
|
|
170
|
+
`Expected ${pathParamNames.length} path parameter(s): ${pathParamNames.join(', ')}`
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
pathParams[pathParamNames[i]] = String(arg);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Check if there's an options object after the path params
|
|
177
|
+
const optionsArg = args[pathParamNames.length];
|
|
178
|
+
if (optionsArg && typeof optionsArg === 'object') {
|
|
179
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
180
|
+
const opts = optionsArg as any;
|
|
181
|
+
input = opts.input;
|
|
182
|
+
query = opts.query;
|
|
183
|
+
}
|
|
184
|
+
} else {
|
|
185
|
+
// No path params - use existing behavior
|
|
186
|
+
const options = args[0];
|
|
187
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
188
|
+
const opts = options as any;
|
|
189
|
+
const isOptionsObject =
|
|
190
|
+
opts && typeof opts === 'object' && ('input' in opts || 'query' in opts);
|
|
191
|
+
|
|
192
|
+
input = isOptionsObject ? opts.input : options;
|
|
193
|
+
query = isOptionsObject ? opts.query : undefined;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Substitute path params in the route path
|
|
197
|
+
const basePath = routePath || fallbackPath;
|
|
198
|
+
const urlPath = substitutePathParams(basePath, pathParams);
|
|
199
|
+
|
|
106
200
|
// WebSocket endpoint
|
|
107
201
|
if (routeType === 'websocket') {
|
|
108
202
|
const wsBaseUrl = resolvedBaseUrl.replace(/^http/, 'ws');
|
|
109
|
-
const wsUrl =
|
|
203
|
+
const wsUrl = buildUrlWithQuery(wsBaseUrl, urlPath, query);
|
|
110
204
|
const ws = createWebSocketClient(wsUrl);
|
|
111
205
|
if (input) {
|
|
112
206
|
ws.on('open', () => ws.send(input));
|
|
@@ -116,9 +210,7 @@ export function createClient<R>(options: ClientOptions = {}, metadata?: unknown)
|
|
|
116
210
|
|
|
117
211
|
// SSE endpoint
|
|
118
212
|
if (routeType === 'sse') {
|
|
119
|
-
const sseUrl =
|
|
120
|
-
// Note: Native EventSource doesn't support custom headers
|
|
121
|
-
// For auth, use withCredentials or consider fetch-based alternatives like @microsoft/fetch-event-source
|
|
213
|
+
const sseUrl = buildUrlWithQuery(resolvedBaseUrl, urlPath, query);
|
|
122
214
|
return createEventStreamClient(sseUrl, {
|
|
123
215
|
withCredentials: Object.keys(resolvedHeaders).length > 0,
|
|
124
216
|
});
|
|
@@ -126,7 +218,8 @@ export function createClient<R>(options: ClientOptions = {}, metadata?: unknown)
|
|
|
126
218
|
|
|
127
219
|
// Stream endpoint
|
|
128
220
|
if (routeType === 'stream') {
|
|
129
|
-
|
|
221
|
+
const streamUrl = buildUrlWithQuery(resolvedBaseUrl, urlPath, query);
|
|
222
|
+
return fetch(streamUrl, {
|
|
130
223
|
method: method.toUpperCase(),
|
|
131
224
|
headers: { 'Content-Type': contentType, ...resolvedHeaders },
|
|
132
225
|
body: input ? JSON.stringify(input) : undefined,
|
|
@@ -138,7 +231,8 @@ export function createClient<R>(options: ClientOptions = {}, metadata?: unknown)
|
|
|
138
231
|
}
|
|
139
232
|
|
|
140
233
|
// Regular API endpoint
|
|
141
|
-
|
|
234
|
+
const apiUrl = buildUrlWithQuery(resolvedBaseUrl, urlPath, query);
|
|
235
|
+
return fetch(apiUrl, {
|
|
142
236
|
method: method.toUpperCase(),
|
|
143
237
|
headers: { 'Content-Type': contentType, ...resolvedHeaders },
|
|
144
238
|
body: method.toUpperCase() !== 'GET' && input ? JSON.stringify(input) : undefined,
|
package/src/client/types.ts
CHANGED
|
@@ -99,27 +99,95 @@ export interface StreamClient {
|
|
|
99
99
|
cancel(): Promise<void>;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Options object for endpoints without path params (optional query support).
|
|
104
|
+
*/
|
|
105
|
+
export interface EndpointOptionsWithQuery<Input = unknown, Query = Record<string, string>> {
|
|
106
|
+
input?: Input;
|
|
107
|
+
query?: Query;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Additional options that can be passed after positional path params.
|
|
112
|
+
*/
|
|
113
|
+
export interface EndpointExtraOptions<Input = unknown, Query = Record<string, string>> {
|
|
114
|
+
input?: Input;
|
|
115
|
+
query?: Query;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Convert a path params object to a tuple of its value types.
|
|
120
|
+
* Used for positional argument typing.
|
|
121
|
+
* Note: For proper ordering, we rely on the generated PathParamsTuple type.
|
|
122
|
+
*/
|
|
123
|
+
export type PathParamsToTuple<P> = P extends readonly [infer First, ...infer Rest]
|
|
124
|
+
? [First, ...PathParamsToTuple<Rest>]
|
|
125
|
+
: P extends readonly []
|
|
126
|
+
? []
|
|
127
|
+
: string[];
|
|
128
|
+
|
|
102
129
|
/**
|
|
103
130
|
* API endpoint - callable function for regular HTTP calls.
|
|
131
|
+
* - Without path params: accepts input directly OR options object with query
|
|
132
|
+
* - With path params: accepts positional arguments followed by optional options object
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* // No path params
|
|
136
|
+
* client.hello.post({ name: 'World' })
|
|
137
|
+
*
|
|
138
|
+
* // Single path param
|
|
139
|
+
* client.users.userId.get('123')
|
|
140
|
+
*
|
|
141
|
+
* // Multiple path params
|
|
142
|
+
* client.orgs.orgId.members.memberId.get('org-1', 'user-2')
|
|
143
|
+
*
|
|
144
|
+
* // With additional options
|
|
145
|
+
* client.users.userId.get('123', { query: { include: 'posts' } })
|
|
104
146
|
*/
|
|
105
|
-
export type APIEndpoint<
|
|
147
|
+
export type APIEndpoint<
|
|
148
|
+
Input = unknown,
|
|
149
|
+
Output = unknown,
|
|
150
|
+
PathParams = never,
|
|
151
|
+
PathParamsTuple extends unknown[] = string[],
|
|
152
|
+
> = [PathParams] extends [never]
|
|
153
|
+
? (inputOrOptions?: Input | EndpointOptionsWithQuery<Input>) => Promise<Output>
|
|
154
|
+
: (...args: [...PathParamsTuple, options?: EndpointExtraOptions<Input>]) => Promise<Output>;
|
|
106
155
|
|
|
107
156
|
/**
|
|
108
157
|
* WebSocket endpoint - callable function that returns WebSocket client.
|
|
109
158
|
*/
|
|
110
|
-
export type WebSocketEndpoint<
|
|
111
|
-
|
|
112
|
-
|
|
159
|
+
export type WebSocketEndpoint<
|
|
160
|
+
Input = unknown,
|
|
161
|
+
_Output = unknown,
|
|
162
|
+
PathParams = never,
|
|
163
|
+
PathParamsTuple extends unknown[] = string[],
|
|
164
|
+
> = [PathParams] extends [never]
|
|
165
|
+
? (inputOrOptions?: Input | EndpointOptionsWithQuery<Input>) => WebSocketClient
|
|
166
|
+
: (...args: [...PathParamsTuple, options?: EndpointExtraOptions<Input>]) => WebSocketClient;
|
|
113
167
|
|
|
114
168
|
/**
|
|
115
169
|
* Server-Sent Events endpoint - callable function that returns EventStream client.
|
|
116
170
|
*/
|
|
117
|
-
export type SSEEndpoint<
|
|
171
|
+
export type SSEEndpoint<
|
|
172
|
+
Input = unknown,
|
|
173
|
+
_Output = unknown,
|
|
174
|
+
PathParams = never,
|
|
175
|
+
PathParamsTuple extends unknown[] = string[],
|
|
176
|
+
> = [PathParams] extends [never]
|
|
177
|
+
? (inputOrOptions?: Input | EndpointOptionsWithQuery<Input>) => EventStreamClient
|
|
178
|
+
: (...args: [...PathParamsTuple, options?: EndpointExtraOptions<Input>]) => EventStreamClient;
|
|
118
179
|
|
|
119
180
|
/**
|
|
120
181
|
* Streaming endpoint - callable function that returns Stream client.
|
|
121
182
|
*/
|
|
122
|
-
export type StreamEndpoint<
|
|
183
|
+
export type StreamEndpoint<
|
|
184
|
+
Input = unknown,
|
|
185
|
+
_Output = unknown,
|
|
186
|
+
PathParams = never,
|
|
187
|
+
PathParamsTuple extends unknown[] = string[],
|
|
188
|
+
> = [PathParams] extends [never]
|
|
189
|
+
? (inputOrOptions?: Input | EndpointOptionsWithQuery<Input>) => StreamClient
|
|
190
|
+
: (...args: [...PathParamsTuple, options?: EndpointExtraOptions<Input>]) => StreamClient;
|
|
123
191
|
|
|
124
192
|
/**
|
|
125
193
|
* Route endpoint - discriminated union based on route type.
|
|
@@ -128,23 +196,42 @@ export type RouteEndpoint<
|
|
|
128
196
|
Input = unknown,
|
|
129
197
|
Output = unknown,
|
|
130
198
|
Type extends string = 'api',
|
|
199
|
+
PathParams = never,
|
|
200
|
+
PathParamsTuple extends unknown[] = [],
|
|
131
201
|
> = Type extends 'websocket'
|
|
132
|
-
? WebSocketEndpoint<Input, Output>
|
|
202
|
+
? WebSocketEndpoint<Input, Output, PathParams, PathParamsTuple>
|
|
133
203
|
: Type extends 'sse'
|
|
134
|
-
? SSEEndpoint<Input, Output>
|
|
204
|
+
? SSEEndpoint<Input, Output, PathParams, PathParamsTuple>
|
|
135
205
|
: Type extends 'stream'
|
|
136
|
-
? StreamEndpoint<Input, Output>
|
|
137
|
-
: APIEndpoint<Input, Output>;
|
|
206
|
+
? StreamEndpoint<Input, Output, PathParams, PathParamsTuple>
|
|
207
|
+
: APIEndpoint<Input, Output, PathParams, PathParamsTuple>;
|
|
138
208
|
|
|
139
209
|
/**
|
|
140
210
|
* Recursively build the client proxy type from a RouteRegistry.
|
|
141
211
|
*/
|
|
142
212
|
export type Client<R> = {
|
|
143
|
-
[K in keyof R]: R[K] extends {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
213
|
+
[K in keyof R]: R[K] extends {
|
|
214
|
+
input: infer I;
|
|
215
|
+
output: infer O;
|
|
216
|
+
type: infer T;
|
|
217
|
+
params: infer P;
|
|
218
|
+
paramsTuple: infer PT;
|
|
219
|
+
}
|
|
220
|
+
? PT extends unknown[]
|
|
221
|
+
? RouteEndpoint<I, O, T extends string ? T : 'api', P, PT>
|
|
222
|
+
: RouteEndpoint<I, O, T extends string ? T : 'api', P>
|
|
223
|
+
: R[K] extends {
|
|
224
|
+
input: infer I;
|
|
225
|
+
output: infer O;
|
|
226
|
+
type: infer T;
|
|
227
|
+
params: infer P;
|
|
228
|
+
}
|
|
229
|
+
? RouteEndpoint<I, O, T extends string ? T : 'api', P>
|
|
230
|
+
: R[K] extends { input: infer I; output: infer O; type: infer T }
|
|
231
|
+
? RouteEndpoint<I, O, T extends string ? T : 'api'>
|
|
232
|
+
: R[K] extends { input: infer I; output: infer O }
|
|
233
|
+
? RouteEndpoint<I, O, 'api'>
|
|
234
|
+
: R[K] extends object
|
|
235
|
+
? Client<R[K]>
|
|
236
|
+
: never;
|
|
150
237
|
};
|