@forgebase/sdk 0.0.1 → 0.0.3

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/README.md CHANGED
@@ -1,64 +1,27 @@
1
1
  # ForgeBase TypeScript SDK
2
2
 
3
- A powerful, type-safe TypeScript SDK for interacting with ForgeBase services, providing comprehensive database operations, real-time features, and advanced query capabilities.
3
+ A powerful, type-safe TypeScript SDK for interacting with ForgeBase services, providing comprehensive database operations, advanced query capabilities, and type safety.
4
4
 
5
5
  ## Core Features
6
6
 
7
7
  - **Type-Safe Query Builder**:
8
8
  - Fluent API design
9
- - Advanced filtering
9
+ - Advanced filtering (`where`, `whereIn`, `whereExists`, etc.)
10
10
  - Complex joins and relations
11
- - Aggregations and window functions
12
- - Transaction support
13
- - Raw query support
14
- - Query optimization
11
+ - Aggregations (`count`, `sum`, `avg`, `min`, `max`)
12
+ - Window functions (`rowNumber`, `rank`, `lag`, `lead`)
13
+ - Recursive CTEs
14
+ - Result transformations (`pivot`, `compute`)
15
15
 
16
16
  - **Database Operations**:
17
- - CRUD operations
17
+ - CRUD operations (`create`, `update`, `delete`)
18
18
  - Batch operations
19
- - Pagination
20
- - Sorting
21
- - Custom queries
22
- - Schema validation
23
- - Error handling
24
-
25
- - **Security Features**:
26
-
27
- <!-- - JWKS support
28
- - Token validation
29
- - Request signing -->
30
- - Input sanitization
31
- - Type validation
32
- - Error boundaries
33
- <!-- - Rate limiting -->
34
-
35
- - **Advanced Querying**:
36
- - Window functions
37
- - Common Table Expressions (CTEs)
38
- - Recursive queries
39
- - Complex filtering
40
- - Advanced joins
41
- - Subqueries
42
- - Aggregations
43
-
44
- <!-- - **Real-time Features**:
45
-
46
- - Live queries
47
- - Change notifications
48
- - WebSocket integration
49
- - Presence tracking
50
- - Subscription management
51
- - Connection handling
52
- - Event buffering -->
53
-
54
- <!-- - **Performance Features**:
55
- - Query caching
56
- - Connection pooling
57
- - Batch operations
58
- - Lazy loading
59
- - Query optimization
60
- - Result transformation
61
- - Memory management -->
19
+ - Pagination (`limit`, `offset`)
20
+ - Sorting (`orderBy`)
21
+
22
+ - **Security & Validation**:
23
+ - Input validation
24
+ - Type inference from your interfaces
62
25
 
63
26
  ## Installation
64
27
 
@@ -72,35 +35,59 @@ pnpm add @forgebase/sdk
72
35
 
73
36
  ## Basic Usage
74
37
 
75
- ### Database Operations
38
+ ### Initialization
39
+
40
+ First, define your database schema and initialize the SDK. This provides automatic type safety across your entire application.
76
41
 
77
42
  ```typescript
78
43
  import { DatabaseSDK } from '@forgebase/sdk/client';
79
44
 
80
- // Initialize with your API URL
81
- const db = new DatabaseSDK('http://localhost:3000', {
82
- credentials: 'include',
83
- headers: {
84
- 'Content-Type': 'application/json',
45
+ // 1. Define your entity types
46
+ interface User {
47
+ id: number;
48
+ name: string;
49
+ email: string;
50
+ role: 'admin' | 'user';
51
+ status: 'active' | 'inactive';
52
+ }
53
+
54
+ interface Order {
55
+ id: number;
56
+ user_id: number;
57
+ amount: number;
58
+ status: 'pending' | 'completed';
59
+ }
60
+
61
+ // 2. Define your Database Schema
62
+ interface Schema {
63
+ users: User;
64
+ orders: Order;
65
+ }
66
+
67
+ // 3. Initialize the SDK with your Schema
68
+ const db = new DatabaseSDK<Schema>({
69
+ baseUrl: 'http://localhost:3000',
70
+ axiosConfig: {
71
+ withCredentials: true,
72
+ headers: { 'Content-Type': 'application/json' },
85
73
  },
86
74
  });
75
+ ```
87
76
 
88
- // Basic CRUD Operations
89
- const users = await db
90
- .table('users')
91
- .select('id', 'name', 'email')
92
- .where('status', 'active')
93
- .execute({
94
- headers: {
95
- 'some-stuff': 'true',
96
- },
97
- });
77
+ ### Database Operations
98
78
 
99
- // Create a new record
79
+ The SDK automatically infers types based on your Schema.
80
+
81
+ ```typescript
82
+ // Query users (Type is inferred as User[])
83
+ const users = await db.table('users').select('id', 'name', 'email').where('status', 'active').query();
84
+
85
+ // Create a new record (Type checking ensures payload matches User)
100
86
  const newUser = await db.table('users').create({
101
87
  name: 'John Doe',
102
88
  email: 'john@example.com',
103
89
  role: 'user',
90
+ status: 'active',
104
91
  });
105
92
 
106
93
  // Update a record
@@ -115,74 +102,33 @@ await db.table('users').delete(1);
115
102
  ### Advanced Queries
116
103
 
117
104
  ```typescript
118
- // Complex filtering with type safety
119
- interface User {
120
- id: number;
121
- name: string;
122
- email: string;
123
- role: string;
124
- department: string;
125
- salary: number;
126
- }
127
-
105
+ // Complex filtering
128
106
  const results = await db
129
- .table<User>('users')
107
+ .table('users') // Type inferred automatically
130
108
  .where('status', 'active')
131
109
  .andWhere((query) => {
132
- query.where('role', 'manager').where('department', 'IT').orWhere('salary', '>', 100000);
110
+ query.where('role', 'admin').orWhere('email', 'like', '%@company.com');
133
111
  })
134
112
  .orderBy('name', 'asc')
135
113
  .limit(10)
136
- .execute();
114
+ .query();
137
115
 
138
116
  // Aggregations
139
- const stats = await db.table<User>('users').groupBy('department').select('department').count('id', 'total_users').avg('salary', 'avg_salary').having('total_users', '>', 5).execute();
117
+ const stats = await db.table('orders').groupBy('status').sum('amount', 'total_amount').count('id', 'order_count').having('total_amount', '>', 5000).query();
118
+
119
+ // Result type is narrowed:
120
+ // stats.data -> { status: string, total_amount: number, order_count: number }[]
140
121
 
141
122
  // Window Functions
142
123
  const rankedUsers = await db
143
- .table<User>('users')
124
+ .table('users')
144
125
  .select('name', 'department', 'salary')
145
- .window('rank', 'salary_rank', {
146
- partitionBy: ['department'],
147
- orderBy: [{ field: 'salary', direction: 'desc' }],
148
- })
149
- .execute();
150
-
151
- // Advanced Window Functions
152
- const analysis = await db
153
- .table<User>('users')
154
- .windowAdvanced('sum', 'running_total', {
155
- field: 'salary',
156
- over: {
157
- partitionBy: ['department'],
158
- orderBy: [{ field: 'hire_date', direction: 'asc' }],
159
- frame: {
160
- type: 'ROWS',
161
- start: 'UNBOUNDED PRECEDING',
162
- end: 'CURRENT ROW',
163
- },
164
- },
165
- })
166
- .execute();
167
- ```
168
-
169
- ### CTEs and Recursive Queries
170
-
171
- ```typescript
172
- // Simple CTE
173
- const highPaidUsers = db.table<User>('users').where('salary', '>', 100000);
174
-
175
- const result = await db.table<User>('users').with('high_paid', highPaidUsers).execute();
176
-
177
- // Recursive CTE
178
- interface Category {
179
- id: number;
180
- parent_id: number | null;
181
- name: string;
182
- }
126
+ .rank('salary_rank', ['department'], [{ field: 'salary', direction: 'desc' }])
127
+ .query();
183
128
 
129
+ // Recursive CTEs (e.g., for hierarchical data)
184
130
  const categories = await db
185
- .table<Category>('categories')
131
+ .table('categories')
186
132
  .withRecursive(
187
133
  'category_tree',
188
134
  // Initial query
@@ -191,199 +137,42 @@ const categories = await db
191
137
  db.table('categories').join('category_tree', 'parent_id', 'id'),
192
138
  { unionAll: true },
193
139
  )
194
- .execute();
140
+ .query();
195
141
  ```
196
142
 
197
- <!-- ### Real-time Subscriptions
143
+ ### Transformations
198
144
 
199
- ```typescript
200
- // Subscribe to changes
201
- const unsubscribe = await db
202
- .table<User>('users')
203
- .where('department', 'IT')
204
- .subscribe({
205
- onAdd: (user) => console.log('New user:', user),
206
- onChange: (user) => console.log('User updated:', user),
207
- onDelete: (id) => console.log('User deleted:', id),
208
- });
209
-
210
- // Later: cleanup subscription
211
- unsubscribe();
212
- ``` -->
213
-
214
- <!-- ### Security Features
145
+ You can transform the result set on the client side using `pivot` or `compute`.
215
146
 
216
147
  ```typescript
217
- // JWKS Configuration
218
- const db = new DatabaseSDK('http://localhost:3000', {
219
- auth: {
220
- jwksUrl: '/.well-known/jwks.json',
221
- audience: 'your-api',
222
- issuer: 'your-auth-server',
223
- },
224
- });
225
-
226
- // Request Signing
227
- const db = new DatabaseSDK('http://localhost:3000', {
228
- security: {
229
- signRequests: true,
230
- privateKey: 'your-private-key',
231
- keyId: 'your-key-id',
232
- },
233
- });
234
-
235
- // Rate Limiting
236
- const db = new DatabaseSDK('http://localhost:3000', {
237
- rateLimit: {
238
- maxRequests: 100,
239
- windowMs: 60000, // 1 minute
240
- },
241
- });
242
- ``` -->
148
+ // Pivot data
149
+ const pivoted = await db.table('sales').pivot('month', ['Jan', 'Feb', 'Mar'], { type: 'sum', field: 'amount' }).query();
150
+
151
+ // Compute new fields
152
+ const computed = await db
153
+ .table('employees')
154
+ .compute({
155
+ fullName: (row) => `${row.firstName} ${row.lastName}`,
156
+ tax: (row) => row.salary * 0.2,
157
+ })
158
+ .query();
159
+ ```
243
160
 
244
161
  ## Error Handling
245
162
 
163
+ The SDK throws standard errors that you can catch and handle.
164
+
246
165
  ```typescript
247
166
  try {
248
- const result = await db.table('users').where('id', 1).execute();
167
+ await db.table('users').create(data);
249
168
  } catch (error) {
250
- if (error instanceof QueryError) {
251
- // Handle query-related errors
252
- console.error('Query Error:', error.message);
253
- } else if (error instanceof ValidationError) {
254
- // Handle validation errors
255
- console.error('Validation Error:', error.details);
256
- } else if (error instanceof AuthorizationError) {
257
- // Handle authorization errors
258
- console.error('Authorization Error:', error.message);
259
- } else {
260
- // Handle other errors
261
- console.error('Unknown Error:', error);
262
- }
169
+ console.error('Failed to create user:', error.message);
263
170
  }
264
171
  ```
265
172
 
266
- <!--
267
- ## Advanced Configuration
268
-
269
- ```typescript
270
- const db = new DatabaseSDK('http://localhost:3000', {
271
- // Authentication
272
- credentials: 'include',
273
- headers: {
274
- Authorization: 'Bearer your-token',
275
- },
276
-
277
- // Query Options
278
- queryConfig: {
279
- maxLimit: 1000,
280
- defaultLimit: 50,
281
- maxComplexity: 10,
282
- },
283
-
284
- // Cache Configuration
285
- cache: {
286
- enabled: true,
287
- ttl: 300, // 5 minutes
288
- maxSize: 100, // Maximum number of cached queries
289
- },
290
-
291
- // Real-time Configuration
292
- realtime: {
293
- enabled: true,
294
- reconnectDelay: 1000,
295
- maxRetries: 5,
296
- },
297
-
298
- // Performance Tuning
299
- performance: {
300
- batchSize: 1000,
301
- poolSize: 10,
302
- timeout: 5000,
303
- },
304
- });
305
- ``` -->
306
-
307
- ## Type Safety
308
-
309
- The SDK provides full TypeScript support with generic types:
173
+ ## Real-time Updates
310
174
 
311
- ```typescript
312
- interface User {
313
- id: number;
314
- name: string;
315
- email: string;
316
- role: string;
317
- }
318
-
319
- interface Order {
320
- id: number;
321
- userId: number;
322
- total: number;
323
- status: string;
324
- }
325
-
326
- // Type-safe queries
327
- const users = await db.table<User>('users').select('id', 'name', 'email').where('role', 'admin').execute();
328
-
329
- // Type-safe joins
330
- const orders = await db.table<Order>('orders').join<User>('users', 'userId', 'id').select('orders.id', 'users.name', 'orders.total').execute();
331
- ```
332
-
333
- ## Performance Optimization
334
-
335
- ### Query Optimization
336
-
337
- ```typescript
338
- // Use select to limit returned fields
339
- const users = await db.table('users').select('id', 'name').where('active', true).execute();
340
-
341
- // Use indexes effectively
342
- const result = await db
343
- .table('users')
344
- .where('email', 'user@example.com') // Assuming email is indexed
345
- .first()
346
- .execute();
347
-
348
- // Batch operations (WIP*)
349
- await db.table('users').createMany([
350
- { name: 'User 1', email: 'user1@example.com' },
351
- { name: 'User 2', email: 'user2@example.com' },
352
- ]);
353
- ```
354
-
355
- <!-- ### Caching
356
-
357
- ```typescript
358
- // Enable caching for specific queries
359
- const users = await db
360
- .table('users')
361
- .cache({
362
- ttl: 300, // 5 minutes
363
- tags: ['users'],
364
- })
365
- .execute();
366
-
367
- // Invalidate cache
368
- await db.invalidateCache('users');
369
- ``` -->
370
-
371
- ## Building
372
-
373
- Run `nx build sdk` to build the library.
374
-
375
- ## Running Tests
376
-
377
- ```bash
378
- # Run unit tests
379
- nx test sdk
380
-
381
- # Run integration tests
382
- nx test sdk --config=integration
383
-
384
- # Run tests with coverage
385
- nx test sdk --coverage
386
- ```
175
+ > ⚠️ **Note**: Real-time features (WebSockets/SSE) are currently experimental and under active development. They are not yet fully documented or recommended for production use.
387
176
 
388
177
  ## License
389
178
 
@@ -153,7 +153,7 @@ export interface AuthInterceptors {
153
153
  onRejected: (error: any) => Promise<any> | any;
154
154
  };
155
155
  }
156
- export declare class DatabaseSDK {
156
+ export declare class DatabaseSDK<Schema extends Record<string, any> = any> {
157
157
  private baseUrl;
158
158
  private axiosInstance;
159
159
  /**
@@ -251,6 +251,7 @@ export declare class DatabaseSDK {
251
251
  * Helper method to create a query builder for fluent API usage
252
252
  * @param tableName The name of the table to query
253
253
  */
254
+ table<K extends keyof Schema>(tableName: K): QueryBuilder<Schema[K]>;
254
255
  table<T extends Record<string, any>>(tableName: string): QueryBuilder<T>;
255
256
  /**
256
257
  * Validates data object
@@ -260,7 +261,10 @@ export declare class DatabaseSDK {
260
261
  /**
261
262
  * Query builder class for more fluent API usage
262
263
  */
263
- declare class QueryBuilder<T extends Record<string, any>> {
264
+ /**
265
+ * Query builder class for more fluent API usage
266
+ */
267
+ declare class QueryBuilder<T extends Record<string, any>, Result extends Record<string, any> | undefined = undefined> {
264
268
  private sdk;
265
269
  private tableName;
266
270
  private params;
@@ -270,7 +274,7 @@ declare class QueryBuilder<T extends Record<string, any>> {
270
274
  /**
271
275
  * Add a recursive CTE
272
276
  */
273
- withRecursive(name: string, initialQuery: QueryBuilder<T>, recursiveQuery: QueryBuilder<T>, options?: {
277
+ withRecursive(name: string, initialQuery: QueryBuilder<T, any>, recursiveQuery: QueryBuilder<T, any>, options?: {
274
278
  unionAll?: boolean;
275
279
  columns?: string[];
276
280
  }): this;
@@ -285,14 +289,14 @@ declare class QueryBuilder<T extends Record<string, any>> {
285
289
  /**
286
290
  * Add common window functions
287
291
  */
288
- rowNumber(alias: string, partitionBy?: string[], orderBy?: OrderByClause<T>[]): this;
289
- rank(alias: string, partitionBy?: string[], orderBy?: OrderByClause<T>[]): this;
290
- lag(field: string, alias: string, partitionBy?: string[], orderBy?: OrderByClause<T>[]): this;
291
- lead(field: string, alias: string, partitionBy?: string[], orderBy?: OrderByClause<T>[]): this;
292
+ rowNumber(alias: string, partitionBy?: FieldKeys<T>[], orderBy?: OrderByClause<T>[]): this;
293
+ rank(alias: string, partitionBy?: FieldKeys<T>[], orderBy?: OrderByClause<T>[]): this;
294
+ lag(field: FieldKeys<T>, alias: string, partitionBy?: FieldKeys<T>[], orderBy?: OrderByClause<T>[]): this;
295
+ lead(field: FieldKeys<T>, alias: string, partitionBy?: FieldKeys<T>[], orderBy?: OrderByClause<T>[]): this;
292
296
  /**
293
297
  * Add a CTE (WITH clause)
294
298
  */
295
- with(name: string, queryOrCallback: QueryBuilder<T> | ((query: QueryBuilder<T>) => void), columns?: FieldKeys<T>[]): this;
299
+ with(name: string, queryOrCallback: QueryBuilder<T, any> | ((query: QueryBuilder<T, T>) => void), columns?: FieldKeys<T>[]): this;
296
300
  /**
297
301
  * Transform the result set
298
302
  */
@@ -311,18 +315,6 @@ declare class QueryBuilder<T extends Record<string, any>> {
311
315
  * @param operator The comparison operator
312
316
  * @param value The value to compare against
313
317
  * @returns The query builder instance
314
- * @example
315
- * db.table<User>("users").where("status", "active").execute();
316
- * db.table<User>("users").where("age", ">", 18).execute();
317
- * db.table<User>("users").where("role", "in", ["admin", "manager"]).execute();
318
- * db.table<User>("users").where("created_at", "is not null").execute();
319
- * db.table<User>("users").where("name", "like", "%doe%").execute();
320
- * db.table<User>("users").where("id", 1).execute();
321
- * db.table<User>("users").where({ status: "active", role: "admin" }).execute();
322
- * db.table<User>("users").where("age", ">=", 18).where("role", "manager").execute();
323
- * db.table<User>("users").where("age", ">=", 18).orWhere((query) => {
324
- * query.where("role", "manager").where("department", "IT");
325
- * }).execute();
326
318
  */
327
319
  where(field: FieldKeys<T>, operator: WhereOperator, value: any): this;
328
320
  where(field: FieldKeys<T>, value: any): this;
@@ -339,85 +331,88 @@ declare class QueryBuilder<T extends Record<string, any>> {
339
331
  /**
340
332
  * Start an OR where group
341
333
  */
342
- orWhere(callback: (query: QueryBuilder<T>) => void): this;
334
+ orWhere(callback: (query: QueryBuilder<T, Result>) => void): this;
343
335
  /**
344
336
  * Start an AND where group
345
337
  */
346
- andWhere(callback: (query: QueryBuilder<T>) => void): this;
338
+ andWhere(callback: (query: QueryBuilder<T, Result>) => void): this;
347
339
  /**
348
340
  * Create a where group with the specified operator
349
341
  */
350
342
  private whereGroup;
351
343
  /**
352
344
  * Add a where exists clause using a subquery
353
- * @param subqueryBuilder A function that returns a configured query builder for the subquery
354
- * @returns The query builder instance
355
- * @example
356
- * db.table<User>("users")
357
- * .whereExists((subquery) =>
358
- * subquery.table("orders")
359
- * .where("orders.user_id", "=", "users.id")
360
- * .where("total", ">", 1000)
361
- * )
362
- * .execute();
363
345
  */
364
- whereExists(subqueryBuilder: (qb: DatabaseSDK) => QueryBuilder<any>): this;
346
+ whereExists(subqueryBuilder: (qb: DatabaseSDK) => QueryBuilder<any, any>): this;
365
347
  /**
366
348
  * Add a where exists clause with join conditions
367
- * @param tableName The table to check for existence
368
- * @param leftField The field from the main table
369
- * @param rightField The field from the subquery table
370
- * @param additionalConditions Additional conditions for the subquery
371
- * @returns The query builder instance
372
- * @example
373
- * db.table<User>("users")
374
- * .whereExistsJoin("orders", "id", "user_id", (qb) =>
375
- * qb.where("total", ">", 1000)
376
- * )
377
- * .execute();
378
349
  */
379
- whereExistsJoin(tableName: string, leftField: FieldKeys<T>, rightField: string, additionalConditions?: (qb: QueryBuilder<any>) => void): this;
350
+ whereExistsJoin(tableName: string, leftField: FieldKeys<T>, rightField: string, additionalConditions?: (qb: QueryBuilder<any, any>) => void): this;
380
351
  getTableName(): string;
381
352
  getParams(): QueryParams<T>;
382
353
  /**
383
354
  * Group by clause
384
355
  */
385
- groupBy(...fields: string[]): this;
356
+ groupBy<K extends keyof T>(...fields: K[]): QueryBuilder<T, Result extends undefined ? Pick<T, K> : Result & Pick<T, K>>;
386
357
  /**
387
358
  * Having clause for grouped queries
388
359
  */
389
- having(field: string, operator: WhereOperator, value: any): this;
360
+ having(field: FieldKeys<T> | string, operator: WhereOperator, value: any): this;
390
361
  /**
391
362
  * Add an aggregate function
392
363
  */
393
- aggregate(type: AggregateOptions<T>['type'], field: FieldKeys<T>, alias?: string): this;
364
+ aggregate<Alias extends string>(type: AggregateOptions<T>['type'], field: FieldKeys<T>, alias?: Alias): QueryBuilder<T, Result extends undefined ? {
365
+ [P in Alias]: number;
366
+ } : Result & {
367
+ [P in Alias]: number;
368
+ }>;
394
369
  /**
395
370
  * Shorthand for count aggregate
396
371
  */
397
- count(field?: FieldKeys<T>, alias?: string): this;
372
+ count<Alias extends string = 'count'>(field?: FieldKeys<T>, alias?: Alias): QueryBuilder<T, Result extends undefined ? {
373
+ [P in Alias]: number;
374
+ } : Result & {
375
+ [P in Alias]: number;
376
+ }>;
398
377
  /**
399
378
  * Shorthand for sum aggregate
400
379
  */
401
- sum(field: FieldKeys<T>, alias?: string): this;
380
+ sum<Alias extends string>(field: FieldKeys<T>, alias: Alias): QueryBuilder<T, Result extends undefined ? {
381
+ [P in Alias]: number;
382
+ } : Result & {
383
+ [P in Alias]: number;
384
+ }>;
402
385
  /**
403
386
  * Shorthand for average aggregate
404
387
  */
405
- avg(field: FieldKeys<T>, alias?: string): this;
388
+ avg<Alias extends string>(field: FieldKeys<T>, alias: Alias): QueryBuilder<T, Result extends undefined ? {
389
+ [P in Alias]: number;
390
+ } : Result & {
391
+ [P in Alias]: number;
392
+ }>;
406
393
  /**
407
394
  * Shorthand for minimum aggregate
408
395
  */
409
- min(field: FieldKeys<T>, alias?: string): this;
396
+ min<Alias extends string>(field: FieldKeys<T>, alias: Alias): QueryBuilder<T, Result extends undefined ? {
397
+ [P in Alias]: number;
398
+ } : Result & {
399
+ [P in Alias]: number;
400
+ }>;
410
401
  /**
411
402
  * Shorthand for maximum aggregate
412
403
  */
413
- max(field: FieldKeys<T>, alias?: string): this;
404
+ max<Alias extends string>(field: FieldKeys<T>, alias: Alias): QueryBuilder<T, Result extends undefined ? {
405
+ [P in Alias]: number;
406
+ } : Result & {
407
+ [P in Alias]: number;
408
+ }>;
414
409
  toParams(): Promise<QueryParams<T>>;
415
410
  /**
416
411
  * Execute with transformations
417
412
  * @param axiosConfig Optional axios config to be used for this request
418
413
  * @returns Promise with the query results
419
414
  */
420
- query(axiosConfig?: AxiosRequestConfig): Promise<ApiResponse<T>>;
415
+ query(axiosConfig?: AxiosRequestConfig): Promise<ApiResponse<Result extends undefined ? T : Result>>;
421
416
  /**
422
417
  * Create a record in the table
423
418
  * @param data The data to create
@@ -464,7 +459,7 @@ declare class QueryBuilder<T extends Record<string, any>> {
464
459
  * .select("id", "name", "email")
465
460
  * .execute();
466
461
  */
467
- select(...fields: string[]): this;
462
+ select<K extends keyof T>(...fields: K[]): QueryBuilder<T, Result extends undefined ? Pick<T, K> : Result & Pick<T, K>>;
468
463
  }
469
464
  export {};
470
465
  //# sourceMappingURL=client.d.ts.map