@ragbits/api-client 1.4.0-dev.202512090236 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30,23 +30,12 @@ export declare const MessageRole: {
30
30
  readonly System: "system";
31
31
  };
32
32
  export type MessageRole = TypeFrom<typeof MessageRole>;
33
- /**
34
- * Represents the TaskStatus enum
35
- */
36
- export declare const TaskStatus: {
37
- readonly Pending: "pending";
38
- readonly InProgress: "in_progress";
39
- readonly Completed: "completed";
40
- readonly Failed: "failed";
41
- readonly Cancelled: "cancelled";
42
- readonly Retrying: "retrying";
43
- };
44
- export type TaskStatus = TypeFrom<typeof TaskStatus>;
45
33
  /**
46
34
  * Represents the AuthType enum
47
35
  */
48
36
  export declare const AuthType: {
49
37
  readonly Credentials: "credentials";
38
+ readonly Oauth2: "oauth2";
50
39
  };
51
40
  export type AuthType = TypeFrom<typeof AuthType>;
52
41
  /**
@@ -61,11 +50,9 @@ export interface ChatContext {
61
50
  user: User | null;
62
51
  session_id: string | null;
63
52
  /**
64
- * List of confirmed/declined tools from the frontend
53
+ * User's timezone in IANA format (e.g., 'Europe/Warsaw', 'America/New_York')
65
54
  */
66
- confirmed_tools: {
67
- [k: string]: unknown;
68
- }[] | null;
55
+ timezone: string | null;
69
56
  [k: string]: unknown;
70
57
  }
71
58
  /**
@@ -154,33 +141,6 @@ export interface MessageUsage {
154
141
  completion_tokens: number;
155
142
  total_tokens: number;
156
143
  }
157
- /**
158
- * Simple task representation.
159
- */
160
- export interface Task {
161
- id: string;
162
- description: string;
163
- /**
164
- * Task status options.
165
- */
166
- status: 'pending' | 'in_progress' | 'completed' | 'failed' | 'cancelled' | 'retrying';
167
- order: number;
168
- summary: string | null;
169
- parent_id: string | null;
170
- full_response: string | null;
171
- dependencies: string[];
172
- }
173
- /**
174
- * Represents a tool confirmation request sent to the user.
175
- */
176
- export interface ConfirmationRequest {
177
- confirmation_id: string;
178
- tool_name: string;
179
- tool_description: string;
180
- arguments: {
181
- [k: string]: unknown;
182
- };
183
- }
184
144
  /**
185
145
  * Text content wrapper.
186
146
  */
@@ -219,18 +179,6 @@ export interface UsageContent {
219
179
  [k: string]: MessageUsage;
220
180
  };
221
181
  }
222
- /**
223
- * Todo item content wrapper.
224
- */
225
- export interface TodoItemContent {
226
- task: Task;
227
- }
228
- /**
229
- * Confirmation request content wrapper.
230
- */
231
- export interface ConfirmationRequestContent {
232
- confirmation_request: ConfirmationRequest;
233
- }
234
182
  /**
235
183
  * Error content wrapper for displaying error messages to users.
236
184
  */
@@ -310,6 +258,10 @@ export interface ConfigResponse {
310
258
  */
311
259
  customization: UICustomization | null;
312
260
  user_settings: UserSettings;
261
+ /**
262
+ * Flag indicating whether API supports file upload
263
+ */
264
+ supports_upload: boolean;
313
265
  /**
314
266
  * Debug mode flag
315
267
  */
@@ -333,6 +285,48 @@ export interface FeedbackResponse {
333
285
  */
334
286
  status: string;
335
287
  }
288
+ /**
289
+ * Response for OAuth2 authorization URL request
290
+ */
291
+ export interface OAuth2AuthorizeResponse {
292
+ /**
293
+ * URL to redirect user to for OAuth2 authorization
294
+ */
295
+ authorize_url: string;
296
+ /**
297
+ * State parameter for CSRF protection
298
+ */
299
+ state: string;
300
+ }
301
+ /**
302
+ * Configuration for an OAuth2 provider including visual configuration.
303
+ */
304
+ export interface OAuth2ProviderConfig {
305
+ /**
306
+ * Provider name (e.g., 'discord')
307
+ */
308
+ name: string;
309
+ /**
310
+ * Display name for the provider (e.g., 'Discord')
311
+ */
312
+ display_name: string | null;
313
+ /**
314
+ * Brand color for the provider (e.g., '#5865F2')
315
+ */
316
+ color: string | null;
317
+ /**
318
+ * Button background color (defaults to color)
319
+ */
320
+ button_color: string | null;
321
+ /**
322
+ * Button text color (defaults to white)
323
+ */
324
+ text_color: string | null;
325
+ /**
326
+ * SVG icon as string
327
+ */
328
+ icon_svg: string | null;
329
+ }
336
330
  /**
337
331
  * Client-side chat request interface.
338
332
  */
@@ -383,45 +377,30 @@ export interface AuthenticationConfig {
383
377
  * List of available authentication types
384
378
  */
385
379
  auth_types: AuthType[];
386
- }
387
- /**
388
- * Request body for user login
389
- */
390
- export interface CredentialsLoginRequest {
391
- /**
392
- * Username
393
- */
394
- username: string;
395
380
  /**
396
- * Password
381
+ * List of available OAuth2 providers
397
382
  */
398
- password: string;
383
+ oauth2_providers: OAuth2ProviderConfig[];
399
384
  }
400
385
  /**
401
- * Represents a JWT authentication jwt_token.
386
+ * Represents user login credentials.
402
387
  */
403
- export interface JWTToken {
404
- access_token: string;
405
- token_type: string;
406
- expires_in: number;
407
- refresh_token: string | null;
408
- user: User;
388
+ export interface UserCredentials {
389
+ username: string;
390
+ password: string;
409
391
  }
410
392
  /**
411
- * Request body for user login
393
+ * Represents user login credentials.
412
394
  */
413
395
  export interface LoginRequest {
414
- /**
415
- * Username
416
- */
417
396
  username: string;
418
- /**
419
- * Password
420
- */
421
397
  password: string;
422
398
  }
423
399
  /**
424
- * Response body for successful login
400
+ * Response body for login with session-based authentication.
401
+ *
402
+ * The session ID is set as an HTTP-only cookie by the backend.
403
+ * Frontend only receives user information.
425
404
  */
426
405
  export interface LoginResponse {
427
406
  /**
@@ -436,19 +415,6 @@ export interface LoginResponse {
436
415
  * Error message if login failed
437
416
  */
438
417
  error_message: string | null;
439
- /**
440
- * Access jwt_token
441
- */
442
- jwt_token: JWTToken | null;
443
- }
444
- /**
445
- * Request body for user logout
446
- */
447
- export interface LogoutRequest {
448
- /**
449
- * Session ID to logout
450
- */
451
- token: string;
452
418
  }
453
419
  /**
454
420
  * Represents an authenticated user.
@@ -506,18 +472,10 @@ export interface ClearMessageChatResponse {
506
472
  type: 'clear_message';
507
473
  content: unknown;
508
474
  }
509
- export interface TodoItemChatResonse {
510
- type: 'todo_item';
511
- content: TodoItemContent;
512
- }
513
475
  export interface ConversationSummaryResponse {
514
476
  type: 'conversation_summary';
515
477
  content: ConversationSummaryContent;
516
478
  }
517
- export interface ConfirmationRequestChatResponse {
518
- type: 'confirmation_request';
519
- content: ConfirmationRequestContent;
520
- }
521
479
  export interface ErrorChatResponse {
522
480
  type: 'error';
523
481
  content: ErrorContent;
@@ -529,4 +487,4 @@ export interface ChunkedChatResponse {
529
487
  /**
530
488
  * Typed chat response union
531
489
  */
532
- export type ChatResponse = TextChatResponse | ReferenceChatResponse | MessageIdChatResponse | ConversationIdChatResponse | StateUpdateChatResponse | LiveUpdateChatResponse | FollowupMessagesChatResponse | ImageChatResponse | MessageUsageChatResponse | ClearMessageChatResponse | TodoItemChatResonse | ConversationSummaryResponse | ConfirmationRequestChatResponse | ErrorChatResponse;
490
+ export type ChatResponse = TextChatResponse | ReferenceChatResponse | MessageIdChatResponse | ConversationIdChatResponse | StateUpdateChatResponse | LiveUpdateChatResponse | FollowupMessagesChatResponse | ImageChatResponse | MessageUsageChatResponse | ClearMessageChatResponse | ConversationSummaryResponse | ErrorChatResponse;
package/dist/index.cjs CHANGED
@@ -24,8 +24,7 @@ __export(index_exports, {
24
24
  FeedbackType: () => FeedbackType,
25
25
  LiveUpdateType: () => LiveUpdateType,
26
26
  MessageRole: () => MessageRole,
27
- RagbitsClient: () => RagbitsClient,
28
- TaskStatus: () => TaskStatus
27
+ RagbitsClient: () => RagbitsClient
29
28
  });
30
29
  module.exports = __toCommonJS(index_exports);
31
30
 
@@ -43,16 +42,9 @@ var MessageRole = {
43
42
  Assistant: "assistant",
44
43
  System: "system"
45
44
  };
46
- var TaskStatus = {
47
- Pending: "pending",
48
- InProgress: "in_progress",
49
- Completed: "completed",
50
- Failed: "failed",
51
- Cancelled: "cancelled",
52
- Retrying: "retrying"
53
- };
54
45
  var AuthType = {
55
- Credentials: "credentials"
46
+ Credentials: "credentials",
47
+ Oauth2: "oauth2"
56
48
  };
57
49
 
58
50
  // src/index.ts
@@ -99,6 +91,9 @@ var RagbitsClient = class {
99
91
  const defaultHeaders = {
100
92
  "Content-Type": "application/json"
101
93
  };
94
+ if (options.body instanceof FormData) {
95
+ delete defaultHeaders["Content-Type"];
96
+ }
102
97
  const headers = {
103
98
  ...defaultHeaders,
104
99
  ...this.normalizeHeaders(options.headers)
@@ -106,7 +101,11 @@ var RagbitsClient = class {
106
101
  if (this.auth?.getToken) {
107
102
  headers["Authorization"] = `Bearer ${this.auth.getToken()}`;
108
103
  }
109
- const response = await fetch(url, { ...options, headers });
104
+ const response = await fetch(url, {
105
+ ...options,
106
+ headers,
107
+ ...this.auth?.credentials ? { credentials: this.auth?.credentials } : {}
108
+ });
110
109
  if (response.status === 401) {
111
110
  this.auth?.onUnauthorized?.();
112
111
  }
@@ -136,10 +135,17 @@ var RagbitsClient = class {
136
135
  ...restOptions
137
136
  };
138
137
  if (body && method !== "GET") {
139
- requestOptions.body = typeof body === "string" ? body : JSON.stringify(body);
138
+ if (body instanceof FormData) {
139
+ requestOptions.body = body;
140
+ if (requestOptions.headers && "Content-Type" in requestOptions.headers) {
141
+ delete requestOptions.headers["Content-Type"];
142
+ }
143
+ } else {
144
+ requestOptions.body = typeof body === "string" ? body : JSON.stringify(body);
145
+ }
140
146
  }
141
147
  let url = endpoint.toString();
142
- if (pathParams) {
148
+ if (pathParams && typeof pathParams === "object") {
143
149
  url = url.replace(/:([^/]+)/g, (_, paramName) => {
144
150
  if (paramName in pathParams) {
145
151
  const value = pathParams[paramName];
@@ -191,17 +197,19 @@ var RagbitsClient = class {
191
197
  if (!line.startsWith("data: ")) continue;
192
198
  try {
193
199
  const jsonString = line.replace("data: ", "").trim();
194
- const parsedData = JSON.parse(
195
- jsonString
196
- );
200
+ const parsedData = JSON.parse(jsonString);
201
+ if (!this.isChatResponse(parsedData)) {
202
+ console.warn(
203
+ "Received response that isn't ChatResponse, skipping.",
204
+ parsedData
205
+ );
206
+ continue;
207
+ }
197
208
  if (parsedData.type === "chunked_content") {
198
209
  this.handleChunkedContent(parsedData, callbacks);
199
210
  continue;
200
211
  }
201
212
  await callbacks.onMessage(parsedData);
202
- await new Promise(
203
- (resolve) => setTimeout(resolve, 0)
204
- );
205
213
  } catch (parseError) {
206
214
  console.error("Error parsing JSON:", parseError);
207
215
  await callbacks.onError(
@@ -238,7 +246,8 @@ var RagbitsClient = class {
238
246
  method: "POST",
239
247
  headers,
240
248
  body: JSON.stringify(data),
241
- signal
249
+ signal,
250
+ ...this.auth?.credentials ? { credentials: this.auth?.credentials } : {}
242
251
  }
243
252
  );
244
253
  if (response.status === 401) {
@@ -267,6 +276,9 @@ var RagbitsClient = class {
267
276
  isCancelled = true;
268
277
  };
269
278
  }
279
+ isChatResponse(response) {
280
+ return response !== null && typeof response === "object" && "type" in response && "content" in response;
281
+ }
270
282
  normalizeHeaders(init) {
271
283
  if (!init) return {};
272
284
  if (init instanceof Headers) {
@@ -329,6 +341,5 @@ var RagbitsClient = class {
329
341
  FeedbackType,
330
342
  LiveUpdateType,
331
343
  MessageRole,
332
- RagbitsClient,
333
- TaskStatus
344
+ RagbitsClient
334
345
  });
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ClientConfig, StreamCallbacks, BaseApiEndpoints, EndpointDefinition, EndpointResponse, BaseStreamingEndpoints, EndpointRequest, MakeRequestOptions } from './types';
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
- [K in keyof Endpoints]: EndpointDefinition<any, any, any, any>;
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
@@ -12,16 +12,9 @@ var MessageRole = {
12
12
  Assistant: "assistant",
13
13
  System: "system"
14
14
  };
15
- var TaskStatus = {
16
- Pending: "pending",
17
- InProgress: "in_progress",
18
- Completed: "completed",
19
- Failed: "failed",
20
- Cancelled: "cancelled",
21
- Retrying: "retrying"
22
- };
23
15
  var AuthType = {
24
- Credentials: "credentials"
16
+ Credentials: "credentials",
17
+ Oauth2: "oauth2"
25
18
  };
26
19
 
27
20
  // src/index.ts
@@ -68,6 +61,9 @@ var RagbitsClient = class {
68
61
  const defaultHeaders = {
69
62
  "Content-Type": "application/json"
70
63
  };
64
+ if (options.body instanceof FormData) {
65
+ delete defaultHeaders["Content-Type"];
66
+ }
71
67
  const headers = {
72
68
  ...defaultHeaders,
73
69
  ...this.normalizeHeaders(options.headers)
@@ -75,7 +71,11 @@ var RagbitsClient = class {
75
71
  if (this.auth?.getToken) {
76
72
  headers["Authorization"] = `Bearer ${this.auth.getToken()}`;
77
73
  }
78
- const response = await fetch(url, { ...options, headers });
74
+ const response = await fetch(url, {
75
+ ...options,
76
+ headers,
77
+ ...this.auth?.credentials ? { credentials: this.auth?.credentials } : {}
78
+ });
79
79
  if (response.status === 401) {
80
80
  this.auth?.onUnauthorized?.();
81
81
  }
@@ -105,10 +105,17 @@ var RagbitsClient = class {
105
105
  ...restOptions
106
106
  };
107
107
  if (body && method !== "GET") {
108
- requestOptions.body = typeof body === "string" ? body : JSON.stringify(body);
108
+ if (body instanceof FormData) {
109
+ requestOptions.body = body;
110
+ if (requestOptions.headers && "Content-Type" in requestOptions.headers) {
111
+ delete requestOptions.headers["Content-Type"];
112
+ }
113
+ } else {
114
+ requestOptions.body = typeof body === "string" ? body : JSON.stringify(body);
115
+ }
109
116
  }
110
117
  let url = endpoint.toString();
111
- if (pathParams) {
118
+ if (pathParams && typeof pathParams === "object") {
112
119
  url = url.replace(/:([^/]+)/g, (_, paramName) => {
113
120
  if (paramName in pathParams) {
114
121
  const value = pathParams[paramName];
@@ -160,17 +167,19 @@ var RagbitsClient = class {
160
167
  if (!line.startsWith("data: ")) continue;
161
168
  try {
162
169
  const jsonString = line.replace("data: ", "").trim();
163
- const parsedData = JSON.parse(
164
- jsonString
165
- );
170
+ const parsedData = JSON.parse(jsonString);
171
+ if (!this.isChatResponse(parsedData)) {
172
+ console.warn(
173
+ "Received response that isn't ChatResponse, skipping.",
174
+ parsedData
175
+ );
176
+ continue;
177
+ }
166
178
  if (parsedData.type === "chunked_content") {
167
179
  this.handleChunkedContent(parsedData, callbacks);
168
180
  continue;
169
181
  }
170
182
  await callbacks.onMessage(parsedData);
171
- await new Promise(
172
- (resolve) => setTimeout(resolve, 0)
173
- );
174
183
  } catch (parseError) {
175
184
  console.error("Error parsing JSON:", parseError);
176
185
  await callbacks.onError(
@@ -207,7 +216,8 @@ var RagbitsClient = class {
207
216
  method: "POST",
208
217
  headers,
209
218
  body: JSON.stringify(data),
210
- signal
219
+ signal,
220
+ ...this.auth?.credentials ? { credentials: this.auth?.credentials } : {}
211
221
  }
212
222
  );
213
223
  if (response.status === 401) {
@@ -236,6 +246,9 @@ var RagbitsClient = class {
236
246
  isCancelled = true;
237
247
  };
238
248
  }
249
+ isChatResponse(response) {
250
+ return response !== null && typeof response === "object" && "type" in response && "content" in response;
251
+ }
239
252
  normalizeHeaders(init) {
240
253
  if (!init) return {};
241
254
  if (init instanceof Headers) {
@@ -297,6 +310,5 @@ export {
297
310
  FeedbackType,
298
311
  LiveUpdateType,
299
312
  MessageRole,
300
- RagbitsClient,
301
- TaskStatus
313
+ RagbitsClient
302
314
  };
package/dist/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ConfigResponse, FeedbackRequest, FeedbackResponse, ChatRequest, ChatResponse, LogoutRequest, LoginRequest, LoginResponse } from './autogen.types';
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 = any, Res = any, PathParams = never, QueryParams = never> {
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<LogoutRequest, GenericResponse>;
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 : {} extends T ? false : true;
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
- [K in keyof Endpoints]: EndpointDefinition<any, any, any, any>;
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 {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ragbits/api-client",
3
- "version": "1.4.0-dev.202512090236",
3
+ "version": "1.4.0",
4
4
  "description": "JavaScript client for the Ragbits API",
5
5
  "repository": {
6
6
  "type": "git",