@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.
@@ -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;AA0BrD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,GAAE,aAAkB,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,CAwG1F;AAGD,YAAY,EACX,aAAa,EACb,MAAM,EACN,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,YAAY,GACZ,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"}
@@ -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
- const urlPath = '/api/' + pathSegments.join('/');
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
- else if (metadata) {
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]?.type) {
90
- routeType = metaNode[method].type;
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
- return (input) => {
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 = `${wsBaseUrl}${urlPath}`;
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 = `${resolvedBaseUrl}${urlPath}`;
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
- return fetch(`${resolvedBaseUrl}${urlPath}`, {
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
- return fetch(`${resolvedBaseUrl}${urlPath}`, {
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,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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"}
@@ -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> = (input?: Input) => Promise<Output>;
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> = (input?: Input) => WebSocketClient;
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> = (input?: Input) => EventStreamClient;
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> = (input?: Input) => StreamClient;
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":"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"}
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.110",
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.110"
29
+ "@agentuity/core": "0.0.111"
30
30
  },
31
31
  "devDependencies": {
32
- "@agentuity/test-utils": "0.0.110",
32
+ "@agentuity/test-utils": "0.0.111",
33
33
  "@types/bun": "latest",
34
34
  "bun-types": "latest",
35
35
  "typescript": "^5.9.0"
@@ -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
- // Determine route type
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
- } else if (metadata) {
89
- // Look up route type from metadata for HTTP methods
90
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
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]?.type) {
98
- routeType = metaNode[method].type;
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
- return (input?: unknown) => {
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 = `${wsBaseUrl}${urlPath}`;
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 = `${resolvedBaseUrl}${urlPath}`;
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
- return fetch(`${resolvedBaseUrl}${urlPath}`, {
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
- return fetch(`${resolvedBaseUrl}${urlPath}`, {
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,
@@ -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<Input = unknown, Output = unknown> = (input?: Input) => Promise<Output>;
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<Input = unknown, _Output = unknown> = (
111
- input?: Input
112
- ) => WebSocketClient;
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<Input = unknown, _Output = unknown> = (input?: Input) => EventStreamClient;
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<Input = unknown, _Output = unknown> = (input?: Input) => StreamClient;
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 { input: infer I; output: infer O; type: infer T }
144
- ? RouteEndpoint<I, O, T extends string ? T : 'api'>
145
- : R[K] extends { input: infer I; output: infer O }
146
- ? RouteEndpoint<I, O, 'api'>
147
- : R[K] extends object
148
- ? Client<R[K]>
149
- : never;
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
  };