@ragbits/api-client 1.4.0-dev.202512050236 → 1.4.0-dev.202602190302
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/autogen.types.d.ts +78 -45
- package/dist/index.cjs +32 -8
- package/dist/index.d.ts +4 -7
- package/dist/index.js +32 -8
- package/dist/types.d.ts +25 -25
- package/package.json +1 -1
package/dist/autogen.types.d.ts
CHANGED
|
@@ -47,6 +47,7 @@ export type TaskStatus = TypeFrom<typeof TaskStatus>;
|
|
|
47
47
|
*/
|
|
48
48
|
export declare const AuthType: {
|
|
49
49
|
readonly Credentials: "credentials";
|
|
50
|
+
readonly Oauth2: "oauth2";
|
|
50
51
|
};
|
|
51
52
|
export type AuthType = TypeFrom<typeof AuthType>;
|
|
52
53
|
/**
|
|
@@ -66,6 +67,10 @@ export interface ChatContext {
|
|
|
66
67
|
confirmed_tools: {
|
|
67
68
|
[k: string]: unknown;
|
|
68
69
|
}[] | null;
|
|
70
|
+
/**
|
|
71
|
+
* User's timezone in IANA format (e.g., 'Europe/Warsaw', 'America/New_York')
|
|
72
|
+
*/
|
|
73
|
+
timezone: string | null;
|
|
69
74
|
[k: string]: unknown;
|
|
70
75
|
}
|
|
71
76
|
/**
|
|
@@ -220,9 +225,9 @@ export interface UsageContent {
|
|
|
220
225
|
};
|
|
221
226
|
}
|
|
222
227
|
/**
|
|
223
|
-
*
|
|
228
|
+
* Plan item content wrapper.
|
|
224
229
|
*/
|
|
225
|
-
export interface
|
|
230
|
+
export interface PlanItemContent {
|
|
226
231
|
task: Task;
|
|
227
232
|
}
|
|
228
233
|
/**
|
|
@@ -231,6 +236,12 @@ export interface TodoItemContent {
|
|
|
231
236
|
export interface ConfirmationRequestContent {
|
|
232
237
|
confirmation_request: ConfirmationRequest;
|
|
233
238
|
}
|
|
239
|
+
/**
|
|
240
|
+
* Error content wrapper for displaying error messages to users.
|
|
241
|
+
*/
|
|
242
|
+
export interface ErrorContent {
|
|
243
|
+
message: string;
|
|
244
|
+
}
|
|
234
245
|
/**
|
|
235
246
|
* Customization for the header section of the UI.
|
|
236
247
|
*/
|
|
@@ -304,6 +315,10 @@ export interface ConfigResponse {
|
|
|
304
315
|
*/
|
|
305
316
|
customization: UICustomization | null;
|
|
306
317
|
user_settings: UserSettings;
|
|
318
|
+
/**
|
|
319
|
+
* Flag indicating whether API supports file upload
|
|
320
|
+
*/
|
|
321
|
+
supports_upload: boolean;
|
|
307
322
|
/**
|
|
308
323
|
* Debug mode flag
|
|
309
324
|
*/
|
|
@@ -327,6 +342,48 @@ export interface FeedbackResponse {
|
|
|
327
342
|
*/
|
|
328
343
|
status: string;
|
|
329
344
|
}
|
|
345
|
+
/**
|
|
346
|
+
* Response for OAuth2 authorization URL request
|
|
347
|
+
*/
|
|
348
|
+
export interface OAuth2AuthorizeResponse {
|
|
349
|
+
/**
|
|
350
|
+
* URL to redirect user to for OAuth2 authorization
|
|
351
|
+
*/
|
|
352
|
+
authorize_url: string;
|
|
353
|
+
/**
|
|
354
|
+
* State parameter for CSRF protection
|
|
355
|
+
*/
|
|
356
|
+
state: string;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Configuration for an OAuth2 provider including visual configuration.
|
|
360
|
+
*/
|
|
361
|
+
export interface OAuth2ProviderConfig {
|
|
362
|
+
/**
|
|
363
|
+
* Provider name (e.g., 'discord')
|
|
364
|
+
*/
|
|
365
|
+
name: string;
|
|
366
|
+
/**
|
|
367
|
+
* Display name for the provider (e.g., 'Discord')
|
|
368
|
+
*/
|
|
369
|
+
display_name: string | null;
|
|
370
|
+
/**
|
|
371
|
+
* Brand color for the provider (e.g., '#5865F2')
|
|
372
|
+
*/
|
|
373
|
+
color: string | null;
|
|
374
|
+
/**
|
|
375
|
+
* Button background color (defaults to color)
|
|
376
|
+
*/
|
|
377
|
+
button_color: string | null;
|
|
378
|
+
/**
|
|
379
|
+
* Button text color (defaults to white)
|
|
380
|
+
*/
|
|
381
|
+
text_color: string | null;
|
|
382
|
+
/**
|
|
383
|
+
* SVG icon as string
|
|
384
|
+
*/
|
|
385
|
+
icon_svg: string | null;
|
|
386
|
+
}
|
|
330
387
|
/**
|
|
331
388
|
* Client-side chat request interface.
|
|
332
389
|
*/
|
|
@@ -377,45 +434,30 @@ export interface AuthenticationConfig {
|
|
|
377
434
|
* List of available authentication types
|
|
378
435
|
*/
|
|
379
436
|
auth_types: AuthType[];
|
|
380
|
-
}
|
|
381
|
-
/**
|
|
382
|
-
* Request body for user login
|
|
383
|
-
*/
|
|
384
|
-
export interface CredentialsLoginRequest {
|
|
385
437
|
/**
|
|
386
|
-
*
|
|
438
|
+
* List of available OAuth2 providers
|
|
387
439
|
*/
|
|
388
|
-
|
|
389
|
-
/**
|
|
390
|
-
* Password
|
|
391
|
-
*/
|
|
392
|
-
password: string;
|
|
440
|
+
oauth2_providers: OAuth2ProviderConfig[];
|
|
393
441
|
}
|
|
394
442
|
/**
|
|
395
|
-
* Represents
|
|
443
|
+
* Represents user login credentials.
|
|
396
444
|
*/
|
|
397
|
-
export interface
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
expires_in: number;
|
|
401
|
-
refresh_token: string | null;
|
|
402
|
-
user: User;
|
|
445
|
+
export interface UserCredentials {
|
|
446
|
+
username: string;
|
|
447
|
+
password: string;
|
|
403
448
|
}
|
|
404
449
|
/**
|
|
405
|
-
*
|
|
450
|
+
* Represents user login credentials.
|
|
406
451
|
*/
|
|
407
452
|
export interface LoginRequest {
|
|
408
|
-
/**
|
|
409
|
-
* Username
|
|
410
|
-
*/
|
|
411
453
|
username: string;
|
|
412
|
-
/**
|
|
413
|
-
* Password
|
|
414
|
-
*/
|
|
415
454
|
password: string;
|
|
416
455
|
}
|
|
417
456
|
/**
|
|
418
|
-
* Response body for
|
|
457
|
+
* Response body for login with session-based authentication.
|
|
458
|
+
*
|
|
459
|
+
* The session ID is set as an HTTP-only cookie by the backend.
|
|
460
|
+
* Frontend only receives user information.
|
|
419
461
|
*/
|
|
420
462
|
export interface LoginResponse {
|
|
421
463
|
/**
|
|
@@ -430,19 +472,6 @@ export interface LoginResponse {
|
|
|
430
472
|
* Error message if login failed
|
|
431
473
|
*/
|
|
432
474
|
error_message: string | null;
|
|
433
|
-
/**
|
|
434
|
-
* Access jwt_token
|
|
435
|
-
*/
|
|
436
|
-
jwt_token: JWTToken | null;
|
|
437
|
-
}
|
|
438
|
-
/**
|
|
439
|
-
* Request body for user logout
|
|
440
|
-
*/
|
|
441
|
-
export interface LogoutRequest {
|
|
442
|
-
/**
|
|
443
|
-
* Session ID to logout
|
|
444
|
-
*/
|
|
445
|
-
token: string;
|
|
446
475
|
}
|
|
447
476
|
/**
|
|
448
477
|
* Represents an authenticated user.
|
|
@@ -500,9 +529,9 @@ export interface ClearMessageChatResponse {
|
|
|
500
529
|
type: 'clear_message';
|
|
501
530
|
content: unknown;
|
|
502
531
|
}
|
|
503
|
-
export interface
|
|
504
|
-
type: '
|
|
505
|
-
content:
|
|
532
|
+
export interface PlanItemChatResponse {
|
|
533
|
+
type: 'plan_item';
|
|
534
|
+
content: PlanItemContent;
|
|
506
535
|
}
|
|
507
536
|
export interface ConversationSummaryResponse {
|
|
508
537
|
type: 'conversation_summary';
|
|
@@ -512,6 +541,10 @@ export interface ConfirmationRequestChatResponse {
|
|
|
512
541
|
type: 'confirmation_request';
|
|
513
542
|
content: ConfirmationRequestContent;
|
|
514
543
|
}
|
|
544
|
+
export interface ErrorChatResponse {
|
|
545
|
+
type: 'error';
|
|
546
|
+
content: ErrorContent;
|
|
547
|
+
}
|
|
515
548
|
export interface ChunkedChatResponse {
|
|
516
549
|
type: 'chunked_content';
|
|
517
550
|
content: ChunkedContent;
|
|
@@ -519,4 +552,4 @@ export interface ChunkedChatResponse {
|
|
|
519
552
|
/**
|
|
520
553
|
* Typed chat response union
|
|
521
554
|
*/
|
|
522
|
-
export type ChatResponse = TextChatResponse | ReferenceChatResponse | MessageIdChatResponse | ConversationIdChatResponse | StateUpdateChatResponse | LiveUpdateChatResponse | FollowupMessagesChatResponse | ImageChatResponse | MessageUsageChatResponse | ClearMessageChatResponse |
|
|
555
|
+
export type ChatResponse = TextChatResponse | ReferenceChatResponse | MessageIdChatResponse | ConversationIdChatResponse | StateUpdateChatResponse | LiveUpdateChatResponse | FollowupMessagesChatResponse | ImageChatResponse | MessageUsageChatResponse | ClearMessageChatResponse | PlanItemChatResponse | ConversationSummaryResponse | ConfirmationRequestChatResponse | ErrorChatResponse;
|
package/dist/index.cjs
CHANGED
|
@@ -52,7 +52,8 @@ var TaskStatus = {
|
|
|
52
52
|
Retrying: "retrying"
|
|
53
53
|
};
|
|
54
54
|
var AuthType = {
|
|
55
|
-
Credentials: "credentials"
|
|
55
|
+
Credentials: "credentials",
|
|
56
|
+
Oauth2: "oauth2"
|
|
56
57
|
};
|
|
57
58
|
|
|
58
59
|
// src/index.ts
|
|
@@ -99,6 +100,9 @@ var RagbitsClient = class {
|
|
|
99
100
|
const defaultHeaders = {
|
|
100
101
|
"Content-Type": "application/json"
|
|
101
102
|
};
|
|
103
|
+
if (options.body instanceof FormData) {
|
|
104
|
+
delete defaultHeaders["Content-Type"];
|
|
105
|
+
}
|
|
102
106
|
const headers = {
|
|
103
107
|
...defaultHeaders,
|
|
104
108
|
...this.normalizeHeaders(options.headers)
|
|
@@ -106,7 +110,11 @@ var RagbitsClient = class {
|
|
|
106
110
|
if (this.auth?.getToken) {
|
|
107
111
|
headers["Authorization"] = `Bearer ${this.auth.getToken()}`;
|
|
108
112
|
}
|
|
109
|
-
const response = await fetch(url, {
|
|
113
|
+
const response = await fetch(url, {
|
|
114
|
+
...options,
|
|
115
|
+
headers,
|
|
116
|
+
...this.auth?.credentials ? { credentials: this.auth?.credentials } : {}
|
|
117
|
+
});
|
|
110
118
|
if (response.status === 401) {
|
|
111
119
|
this.auth?.onUnauthorized?.();
|
|
112
120
|
}
|
|
@@ -136,10 +144,17 @@ var RagbitsClient = class {
|
|
|
136
144
|
...restOptions
|
|
137
145
|
};
|
|
138
146
|
if (body && method !== "GET") {
|
|
139
|
-
|
|
147
|
+
if (body instanceof FormData) {
|
|
148
|
+
requestOptions.body = body;
|
|
149
|
+
if (requestOptions.headers && "Content-Type" in requestOptions.headers) {
|
|
150
|
+
delete requestOptions.headers["Content-Type"];
|
|
151
|
+
}
|
|
152
|
+
} else {
|
|
153
|
+
requestOptions.body = typeof body === "string" ? body : JSON.stringify(body);
|
|
154
|
+
}
|
|
140
155
|
}
|
|
141
156
|
let url = endpoint.toString();
|
|
142
|
-
if (pathParams) {
|
|
157
|
+
if (pathParams && typeof pathParams === "object") {
|
|
143
158
|
url = url.replace(/:([^/]+)/g, (_, paramName) => {
|
|
144
159
|
if (paramName in pathParams) {
|
|
145
160
|
const value = pathParams[paramName];
|
|
@@ -191,9 +206,14 @@ var RagbitsClient = class {
|
|
|
191
206
|
if (!line.startsWith("data: ")) continue;
|
|
192
207
|
try {
|
|
193
208
|
const jsonString = line.replace("data: ", "").trim();
|
|
194
|
-
const parsedData = JSON.parse(
|
|
195
|
-
|
|
196
|
-
|
|
209
|
+
const parsedData = JSON.parse(jsonString);
|
|
210
|
+
if (!this.isChatResponse(parsedData)) {
|
|
211
|
+
console.warn(
|
|
212
|
+
"Received response that isn't ChatResponse, skipping.",
|
|
213
|
+
parsedData
|
|
214
|
+
);
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
197
217
|
if (parsedData.type === "chunked_content") {
|
|
198
218
|
this.handleChunkedContent(parsedData, callbacks);
|
|
199
219
|
continue;
|
|
@@ -238,7 +258,8 @@ var RagbitsClient = class {
|
|
|
238
258
|
method: "POST",
|
|
239
259
|
headers,
|
|
240
260
|
body: JSON.stringify(data),
|
|
241
|
-
signal
|
|
261
|
+
signal,
|
|
262
|
+
...this.auth?.credentials ? { credentials: this.auth?.credentials } : {}
|
|
242
263
|
}
|
|
243
264
|
);
|
|
244
265
|
if (response.status === 401) {
|
|
@@ -267,6 +288,9 @@ var RagbitsClient = class {
|
|
|
267
288
|
isCancelled = true;
|
|
268
289
|
};
|
|
269
290
|
}
|
|
291
|
+
isChatResponse(response) {
|
|
292
|
+
return response !== null && typeof response === "object" && "type" in response && "content" in response;
|
|
293
|
+
}
|
|
270
294
|
normalizeHeaders(init) {
|
|
271
295
|
if (!init) return {};
|
|
272
296
|
if (init instanceof Headers) {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ClientConfig, StreamCallbacks, BaseApiEndpoints,
|
|
1
|
+
import type { ClientConfig, StreamCallbacks, BaseApiEndpoints, EndpointResponse, BaseStreamingEndpoints, EndpointRequest, MakeRequestOptions, AnyEndpoints } from './types';
|
|
2
2
|
/**
|
|
3
3
|
* Client for communicating with the Ragbits API
|
|
4
4
|
*/
|
|
@@ -29,9 +29,7 @@ export declare class RagbitsClient {
|
|
|
29
29
|
* @param endpoint - API endpoint path
|
|
30
30
|
* @param options - Typed request options for the specific endpoint
|
|
31
31
|
*/
|
|
32
|
-
makeRequest<Endpoints extends
|
|
33
|
-
[K in keyof Endpoints]: EndpointDefinition<any, any, any, any>;
|
|
34
|
-
} = BaseApiEndpoints, URL extends keyof Endpoints = keyof Endpoints>(endpoint: URL, ...args: MakeRequestOptions<URL, Endpoints>): Promise<EndpointResponse<URL, Endpoints>>;
|
|
32
|
+
makeRequest<Endpoints extends AnyEndpoints<Endpoints> = BaseApiEndpoints, URL extends keyof Endpoints = keyof Endpoints>(endpoint: URL, ...args: MakeRequestOptions<URL, Endpoints>): Promise<EndpointResponse<URL, Endpoints>>;
|
|
35
33
|
/**
|
|
36
34
|
* Method for streaming requests to known endpoints only
|
|
37
35
|
* @param endpoint - Streaming endpoint path
|
|
@@ -39,9 +37,8 @@ export declare class RagbitsClient {
|
|
|
39
37
|
* @param callbacks - Stream callbacks
|
|
40
38
|
* @param signal - Optional AbortSignal for cancelling the request
|
|
41
39
|
*/
|
|
42
|
-
makeStreamRequest<Endpoints extends
|
|
43
|
-
|
|
44
|
-
} = BaseStreamingEndpoints, URL extends keyof Endpoints = keyof Endpoints>(endpoint: URL, data: EndpointRequest<URL, Endpoints>, callbacks: StreamCallbacks<EndpointResponse<URL, Endpoints>>, signal?: AbortSignal, customHeaders?: Record<string, string>): () => void;
|
|
40
|
+
makeStreamRequest<Endpoints extends AnyEndpoints<Endpoints> = BaseStreamingEndpoints, URL extends keyof Endpoints = keyof Endpoints>(endpoint: URL, data: EndpointRequest<URL, Endpoints>, callbacks: StreamCallbacks<EndpointResponse<URL, Endpoints>>, signal?: AbortSignal, customHeaders?: Record<string, string>): () => void;
|
|
41
|
+
private isChatResponse;
|
|
45
42
|
private normalizeHeaders;
|
|
46
43
|
private handleChunkedContent;
|
|
47
44
|
}
|
package/dist/index.js
CHANGED
|
@@ -21,7 +21,8 @@ var TaskStatus = {
|
|
|
21
21
|
Retrying: "retrying"
|
|
22
22
|
};
|
|
23
23
|
var AuthType = {
|
|
24
|
-
Credentials: "credentials"
|
|
24
|
+
Credentials: "credentials",
|
|
25
|
+
Oauth2: "oauth2"
|
|
25
26
|
};
|
|
26
27
|
|
|
27
28
|
// src/index.ts
|
|
@@ -68,6 +69,9 @@ var RagbitsClient = class {
|
|
|
68
69
|
const defaultHeaders = {
|
|
69
70
|
"Content-Type": "application/json"
|
|
70
71
|
};
|
|
72
|
+
if (options.body instanceof FormData) {
|
|
73
|
+
delete defaultHeaders["Content-Type"];
|
|
74
|
+
}
|
|
71
75
|
const headers = {
|
|
72
76
|
...defaultHeaders,
|
|
73
77
|
...this.normalizeHeaders(options.headers)
|
|
@@ -75,7 +79,11 @@ var RagbitsClient = class {
|
|
|
75
79
|
if (this.auth?.getToken) {
|
|
76
80
|
headers["Authorization"] = `Bearer ${this.auth.getToken()}`;
|
|
77
81
|
}
|
|
78
|
-
const response = await fetch(url, {
|
|
82
|
+
const response = await fetch(url, {
|
|
83
|
+
...options,
|
|
84
|
+
headers,
|
|
85
|
+
...this.auth?.credentials ? { credentials: this.auth?.credentials } : {}
|
|
86
|
+
});
|
|
79
87
|
if (response.status === 401) {
|
|
80
88
|
this.auth?.onUnauthorized?.();
|
|
81
89
|
}
|
|
@@ -105,10 +113,17 @@ var RagbitsClient = class {
|
|
|
105
113
|
...restOptions
|
|
106
114
|
};
|
|
107
115
|
if (body && method !== "GET") {
|
|
108
|
-
|
|
116
|
+
if (body instanceof FormData) {
|
|
117
|
+
requestOptions.body = body;
|
|
118
|
+
if (requestOptions.headers && "Content-Type" in requestOptions.headers) {
|
|
119
|
+
delete requestOptions.headers["Content-Type"];
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
requestOptions.body = typeof body === "string" ? body : JSON.stringify(body);
|
|
123
|
+
}
|
|
109
124
|
}
|
|
110
125
|
let url = endpoint.toString();
|
|
111
|
-
if (pathParams) {
|
|
126
|
+
if (pathParams && typeof pathParams === "object") {
|
|
112
127
|
url = url.replace(/:([^/]+)/g, (_, paramName) => {
|
|
113
128
|
if (paramName in pathParams) {
|
|
114
129
|
const value = pathParams[paramName];
|
|
@@ -160,9 +175,14 @@ var RagbitsClient = class {
|
|
|
160
175
|
if (!line.startsWith("data: ")) continue;
|
|
161
176
|
try {
|
|
162
177
|
const jsonString = line.replace("data: ", "").trim();
|
|
163
|
-
const parsedData = JSON.parse(
|
|
164
|
-
|
|
165
|
-
|
|
178
|
+
const parsedData = JSON.parse(jsonString);
|
|
179
|
+
if (!this.isChatResponse(parsedData)) {
|
|
180
|
+
console.warn(
|
|
181
|
+
"Received response that isn't ChatResponse, skipping.",
|
|
182
|
+
parsedData
|
|
183
|
+
);
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
166
186
|
if (parsedData.type === "chunked_content") {
|
|
167
187
|
this.handleChunkedContent(parsedData, callbacks);
|
|
168
188
|
continue;
|
|
@@ -207,7 +227,8 @@ var RagbitsClient = class {
|
|
|
207
227
|
method: "POST",
|
|
208
228
|
headers,
|
|
209
229
|
body: JSON.stringify(data),
|
|
210
|
-
signal
|
|
230
|
+
signal,
|
|
231
|
+
...this.auth?.credentials ? { credentials: this.auth?.credentials } : {}
|
|
211
232
|
}
|
|
212
233
|
);
|
|
213
234
|
if (response.status === 401) {
|
|
@@ -236,6 +257,9 @@ var RagbitsClient = class {
|
|
|
236
257
|
isCancelled = true;
|
|
237
258
|
};
|
|
238
259
|
}
|
|
260
|
+
isChatResponse(response) {
|
|
261
|
+
return response !== null && typeof response === "object" && "type" in response && "content" in response;
|
|
262
|
+
}
|
|
239
263
|
normalizeHeaders(init) {
|
|
240
264
|
if (!init) return {};
|
|
241
265
|
if (init instanceof Headers) {
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ConfigResponse, FeedbackRequest, FeedbackResponse, ChatRequest, ChatResponse,
|
|
1
|
+
import { ConfigResponse, FeedbackRequest, FeedbackResponse, ChatRequest, ChatResponse, LoginRequest, LoginResponse, User, OAuth2AuthorizeResponse } from './autogen.types';
|
|
2
2
|
export interface GenericResponse {
|
|
3
3
|
success: boolean;
|
|
4
4
|
}
|
|
@@ -10,6 +10,7 @@ export interface ClientConfig {
|
|
|
10
10
|
auth?: {
|
|
11
11
|
getToken?: () => string;
|
|
12
12
|
onUnauthorized?: () => Promise<void> | void;
|
|
13
|
+
credentials?: RequestCredentials;
|
|
13
14
|
};
|
|
14
15
|
}
|
|
15
16
|
/**
|
|
@@ -20,7 +21,7 @@ export interface StreamCallbacks<T, E = Error> {
|
|
|
20
21
|
onError: (error: E) => void | Promise<void>;
|
|
21
22
|
onClose?: () => void | Promise<void>;
|
|
22
23
|
}
|
|
23
|
-
export interface EndpointDefinition<Req =
|
|
24
|
+
export interface EndpointDefinition<Req = unknown, Res = unknown, PathParams = never, QueryParams = never> {
|
|
24
25
|
method: string;
|
|
25
26
|
request: Req;
|
|
26
27
|
response: Res;
|
|
@@ -34,8 +35,16 @@ export interface BaseApiEndpoints {
|
|
|
34
35
|
'/api/config': EndpointDefinition<never, ConfigResponse>;
|
|
35
36
|
'/api/feedback': EndpointDefinition<FeedbackRequest, FeedbackResponse>;
|
|
36
37
|
'/api/auth/login': EndpointDefinition<LoginRequest, LoginResponse>;
|
|
37
|
-
'/api/auth/logout': EndpointDefinition<
|
|
38
|
+
'/api/auth/logout': EndpointDefinition<never, GenericResponse>;
|
|
39
|
+
'/api/auth/authorize/:provider': EndpointDefinition<never, OAuth2AuthorizeResponse, {
|
|
40
|
+
provider: string;
|
|
41
|
+
}>;
|
|
42
|
+
'/api/user': EndpointDefinition<never, User>;
|
|
38
43
|
'/api/theme': EndpointDefinition<never, string>;
|
|
44
|
+
'/api/upload': EndpointDefinition<FormData, {
|
|
45
|
+
status: string;
|
|
46
|
+
filename: string;
|
|
47
|
+
}>;
|
|
39
48
|
}
|
|
40
49
|
/**
|
|
41
50
|
* Streaming API endpoint definitions with their request/stream response types
|
|
@@ -43,36 +52,32 @@ export interface BaseApiEndpoints {
|
|
|
43
52
|
export interface BaseStreamingEndpoints {
|
|
44
53
|
'/api/chat': EndpointDefinition<ChatRequest, ChatResponse>;
|
|
45
54
|
}
|
|
55
|
+
type AnyEndpointDefinition = EndpointDefinition<unknown, unknown, unknown, unknown>;
|
|
56
|
+
export type AnyEndpoints<T> = {
|
|
57
|
+
[K in keyof T]: AnyEndpointDefinition;
|
|
58
|
+
};
|
|
46
59
|
/**
|
|
47
60
|
* Extract endpoint paths as a union type
|
|
48
61
|
*/
|
|
49
|
-
export type EndpointPath<Endpoints extends
|
|
50
|
-
[K in keyof Endpoints]: EndpointDefinition<any, any, any, any>;
|
|
51
|
-
}> = keyof Endpoints;
|
|
62
|
+
export type EndpointPath<Endpoints extends AnyEndpoints<Endpoints>> = keyof Endpoints;
|
|
52
63
|
/**
|
|
53
64
|
* Extract request type for a specific API endpoint
|
|
54
65
|
*/
|
|
55
|
-
export type EndpointRequest<URL extends keyof Endpoints, Endpoints extends
|
|
56
|
-
[K in keyof Endpoints]: EndpointDefinition<any, any, any, any>;
|
|
57
|
-
}> = Endpoints[URL]['request'];
|
|
66
|
+
export type EndpointRequest<URL extends keyof Endpoints, Endpoints extends AnyEndpoints<Endpoints>> = Endpoints[URL]['request'];
|
|
58
67
|
/**
|
|
59
68
|
* Extract response type for a specific API endpoint
|
|
60
69
|
*/
|
|
61
|
-
export type EndpointResponse<URL extends keyof Endpoints, Endpoints extends
|
|
62
|
-
[K in keyof Endpoints]: EndpointDefinition<any, any, any, any>;
|
|
63
|
-
}> = Endpoints[URL]['response'];
|
|
70
|
+
export type EndpointResponse<URL extends keyof Endpoints, Endpoints extends AnyEndpoints<Endpoints>> = Endpoints[URL]['response'];
|
|
64
71
|
/**
|
|
65
72
|
* Extract HTTP method for a specific API endpoint
|
|
66
73
|
*/
|
|
67
|
-
export type EndpointMethod<URL extends keyof Endpoints, Endpoints extends
|
|
68
|
-
[K in keyof Endpoints]: EndpointDefinition<any, any, any, any>;
|
|
69
|
-
}> = Endpoints[URL]['method'];
|
|
74
|
+
export type EndpointMethod<URL extends keyof Endpoints, Endpoints extends AnyEndpoints<Endpoints>> = Endpoints[URL]['method'];
|
|
70
75
|
/**
|
|
71
76
|
* Check if an object type has any required properties
|
|
72
77
|
* - {} extends T means all properties are optional → false
|
|
73
78
|
* - {} doesn't extend T means at least one property is required → true
|
|
74
79
|
*/
|
|
75
|
-
export type HasRequiredKeys<T> = [T] extends [never] ? false :
|
|
80
|
+
export type HasRequiredKeys<T> = [T] extends [never] ? false : NonNullable<unknown> extends T ? false : true;
|
|
76
81
|
/**
|
|
77
82
|
* Generic request options for API endpoints with typed methods, path params, query params, and body
|
|
78
83
|
* - pathParams is REQUIRED when PathParams is not never
|
|
@@ -81,9 +86,7 @@ export type HasRequiredKeys<T> = [T] extends [never] ? false : {} extends T ? fa
|
|
|
81
86
|
* - body is REQUIRED when it's a specific type (not never, not undefined)
|
|
82
87
|
* - body is OPTIONAL when it's never or undefined
|
|
83
88
|
*/
|
|
84
|
-
export type RequestOptions<URL extends keyof Endpoints, Endpoints extends {
|
|
85
|
-
[K in keyof Endpoints]: EndpointDefinition<any, any, any, any>;
|
|
86
|
-
}> = {
|
|
89
|
+
export type RequestOptions<URL extends keyof Endpoints, Endpoints extends AnyEndpoints<Endpoints>> = {
|
|
87
90
|
method?: Endpoints[URL]['method'];
|
|
88
91
|
headers?: Record<string, string>;
|
|
89
92
|
signal?: AbortSignal;
|
|
@@ -116,9 +119,7 @@ export type IsRequired<T> = [T] extends [never] ? false : T extends undefined ?
|
|
|
116
119
|
* - queryParams has any required keys inside, OR
|
|
117
120
|
* - body/request is required (not never, not undefined)
|
|
118
121
|
*/
|
|
119
|
-
export type HasRequiredParams<URL extends keyof Endpoints, Endpoints extends
|
|
120
|
-
[K in keyof Endpoints]: EndpointDefinition<any, any, any, any>;
|
|
121
|
-
}> = Endpoints[URL]['pathParams'] extends never ? HasRequiredKeys<Endpoints[URL]['queryParams']> extends true ? true : IsRequired<Endpoints[URL]['request']> : true;
|
|
122
|
+
export type HasRequiredParams<URL extends keyof Endpoints, Endpoints extends AnyEndpoints<Endpoints>> = Endpoints[URL]['pathParams'] extends never ? HasRequiredKeys<Endpoints[URL]['queryParams']> extends true ? true : IsRequired<Endpoints[URL]['request']> : true;
|
|
122
123
|
/**
|
|
123
124
|
* Conditional options parameter for makeRequest
|
|
124
125
|
* - Required if endpoint has:
|
|
@@ -127,6 +128,5 @@ export type HasRequiredParams<URL extends keyof Endpoints, Endpoints extends {
|
|
|
127
128
|
* - body with specific type (not undefined)
|
|
128
129
|
* - Optional otherwise
|
|
129
130
|
*/
|
|
130
|
-
export type MakeRequestOptions<URL extends keyof Endpoints, Endpoints extends
|
|
131
|
-
|
|
132
|
-
}> = HasRequiredParams<URL, Endpoints> extends true ? [options: RequestOptions<URL, Endpoints>] : [options?: RequestOptions<URL, Endpoints>];
|
|
131
|
+
export type MakeRequestOptions<URL extends keyof Endpoints, Endpoints extends AnyEndpoints<Endpoints>> = HasRequiredParams<URL, Endpoints> extends true ? [options: RequestOptions<URL, Endpoints>] : [options?: RequestOptions<URL, Endpoints>];
|
|
132
|
+
export {};
|