@forgebase/sdk 0.0.1

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.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +390 -0
  3. package/dist/cjs/database/client/client.d.ts +470 -0
  4. package/dist/cjs/database/client/client.d.ts.map +1 -0
  5. package/dist/cjs/database/client/client.js +812 -0
  6. package/dist/cjs/database/client/client.js.map +1 -0
  7. package/dist/cjs/database/client/index.d.ts +2 -0
  8. package/dist/cjs/database/client/index.d.ts.map +1 -0
  9. package/dist/cjs/database/client/index.js +18 -0
  10. package/dist/cjs/database/client/index.js.map +1 -0
  11. package/dist/cjs/database/examples.d.ts +70 -0
  12. package/dist/cjs/database/examples.d.ts.map +1 -0
  13. package/dist/cjs/database/examples.js +239 -0
  14. package/dist/cjs/database/examples.js.map +1 -0
  15. package/dist/cjs/database/server/index.d.ts +2 -0
  16. package/dist/cjs/database/server/index.d.ts.map +1 -0
  17. package/dist/cjs/database/server/index.js +18 -0
  18. package/dist/cjs/database/server/index.js.map +1 -0
  19. package/dist/cjs/database/server/server.d.ts +2 -0
  20. package/dist/cjs/database/server/server.d.ts.map +1 -0
  21. package/dist/cjs/database/server/server.js +6 -0
  22. package/dist/cjs/database/server/server.js.map +1 -0
  23. package/dist/cjs/index.d.ts +3 -0
  24. package/dist/cjs/index.d.ts.map +1 -0
  25. package/dist/cjs/index.js +19 -0
  26. package/dist/cjs/index.js.map +1 -0
  27. package/dist/esm/database/client/client.d.ts +470 -0
  28. package/dist/esm/database/client/client.d.ts.map +1 -0
  29. package/dist/esm/database/client/client.js +805 -0
  30. package/dist/esm/database/client/client.js.map +1 -0
  31. package/dist/esm/database/client/index.d.ts +2 -0
  32. package/dist/esm/database/client/index.d.ts.map +1 -0
  33. package/dist/esm/database/client/index.js +2 -0
  34. package/dist/esm/database/client/index.js.map +1 -0
  35. package/dist/esm/database/examples.d.ts +70 -0
  36. package/dist/esm/database/examples.d.ts.map +1 -0
  37. package/dist/esm/database/examples.js +236 -0
  38. package/dist/esm/database/examples.js.map +1 -0
  39. package/dist/esm/database/server/index.d.ts +2 -0
  40. package/dist/esm/database/server/index.d.ts.map +1 -0
  41. package/dist/esm/database/server/index.js +2 -0
  42. package/dist/esm/database/server/index.js.map +1 -0
  43. package/dist/esm/database/server/server.d.ts +2 -0
  44. package/dist/esm/database/server/server.d.ts.map +1 -0
  45. package/dist/esm/database/server/server.js +2 -0
  46. package/dist/esm/database/server/server.js.map +1 -0
  47. package/dist/esm/index.d.ts +3 -0
  48. package/dist/esm/index.d.ts.map +1 -0
  49. package/dist/esm/index.js +3 -0
  50. package/dist/esm/index.js.map +1 -0
  51. package/package.json +71 -0
@@ -0,0 +1,805 @@
1
+ /* eslint-disable prefer-const */
2
+ import axios from 'axios';
3
+ export class DatabaseSDK {
4
+ /**
5
+ * Create a new DatabaseSDK instance
6
+ * @param baseUrl The base URL for API requests
7
+ * @param axiosInstance Optional custom axios instance (e.g., from ForgebaseAuth)
8
+ * @param axiosConfig Optional axios configuration
9
+ * @param authInterceptors Optional auth interceptors to apply to the axios instance
10
+ */
11
+ constructor(options) {
12
+ let { baseUrl, axiosInstance, axiosConfig, authInterceptors } = options;
13
+ this.baseUrl = baseUrl.replace(/\/$/, ''); // Remove trailing slash if present
14
+ if (!axiosConfig) {
15
+ axiosConfig = {};
16
+ }
17
+ // Use the provided axios instance or create a new one
18
+ if (axiosInstance) {
19
+ this.axiosInstance = axiosInstance;
20
+ }
21
+ else {
22
+ this.axiosInstance = axios.create({
23
+ baseURL: this.baseUrl,
24
+ withCredentials: true,
25
+ ...axiosConfig,
26
+ });
27
+ // Apply auth interceptors if provided
28
+ if (authInterceptors) {
29
+ this.applyAuthInterceptors(authInterceptors);
30
+ }
31
+ }
32
+ }
33
+ /**
34
+ * Get the base URL used for API requests
35
+ * @returns The base URL string
36
+ */
37
+ getBaseUrl() {
38
+ return this.baseUrl;
39
+ }
40
+ /**
41
+ * Set a new base URL for API requests
42
+ * @param baseUrl The new base URL to use
43
+ */
44
+ setBaseUrl(baseUrl) {
45
+ this.baseUrl = baseUrl.replace(/\/$/, ''); // Remove trailing slash if present
46
+ // Update the axios instance baseURL if it was created by this class
47
+ if (this.axiosInstance.defaults.baseURL) {
48
+ this.axiosInstance.defaults.baseURL = this.baseUrl;
49
+ }
50
+ }
51
+ /**
52
+ * Get the axios instance used for API requests
53
+ * @returns The axios instance
54
+ */
55
+ getAxiosInstance() {
56
+ return this.axiosInstance;
57
+ }
58
+ /**
59
+ * Set a new axios instance for API requests
60
+ * @param axiosInstance The new axios instance to use
61
+ */
62
+ setAxiosInstance(axiosInstance) {
63
+ this.axiosInstance = axiosInstance;
64
+ }
65
+ /**
66
+ * Apply auth interceptors to the axios instance
67
+ * @param authInterceptors The auth interceptors to apply
68
+ */
69
+ applyAuthInterceptors(authInterceptors) {
70
+ // Add request interceptor
71
+ this.axiosInstance.interceptors.request.use(authInterceptors.request);
72
+ // Add response interceptors
73
+ this.axiosInstance.interceptors.response.use(authInterceptors.response.onFulfilled, authInterceptors.response.onRejected);
74
+ }
75
+ /**
76
+ * Fetches records from a specified table with filtering and pagination
77
+ * @param tableName The name of the table to query
78
+ * @param params Query parameters including filters and pagination
79
+ * @param options Query options
80
+ * @param axiosConfig Custom axios config for this specific request
81
+ * @returns Promise containing the fetched records
82
+ */
83
+ async getRecords(tableName, params = {}, options = { execute: true }, axiosConfig = {}) {
84
+ // If execute is false, return only the parameters
85
+ if (!options.execute) {
86
+ return { params: params };
87
+ }
88
+ const url = `/query/${tableName}`;
89
+ try {
90
+ const response = await this.axiosInstance.post(url, { query: params }, axiosConfig);
91
+ return {
92
+ records: response.data,
93
+ params: params,
94
+ message: 'Records fetched successfully',
95
+ error: undefined,
96
+ };
97
+ }
98
+ catch (error) {
99
+ if (axios.isAxiosError(error)) {
100
+ throw new Error(error.response?.data?.error || error.message);
101
+ }
102
+ throw error;
103
+ }
104
+ }
105
+ // private serializeQueryParams<T extends Record<string, any>>(
106
+ // params: QueryParams<T>
107
+ // ): Record<string, string> {
108
+ // const serialized: Record<string, string> = {};
109
+ // // any param that is type of object should be serialized to JSON
110
+ // Object.entries(params).forEach(([key, value]) => {
111
+ // if (typeof value === 'object') {
112
+ // serialized[key] = JSON.stringify(value);
113
+ // } else {
114
+ // serialized[key] = value.toString();
115
+ // }
116
+ // });
117
+ // return serialized;
118
+ // }
119
+ /**
120
+ * Creates a new record in the specified table
121
+ * @param tableName The name of the table to create the record in
122
+ * @param data The data to create the record with
123
+ * @param axiosConfig Custom axios config for this specific request
124
+ * @returns Promise containing the created record
125
+ */
126
+ async createRecord(tableName, data, axiosConfig = {}) {
127
+ this.validateData(data);
128
+ try {
129
+ const response = await this.axiosInstance.post(`/create/${tableName}`, { data }, axiosConfig);
130
+ return {
131
+ records: [response.data],
132
+ message: 'Record created successfully',
133
+ error: undefined,
134
+ };
135
+ }
136
+ catch (error) {
137
+ if (axios.isAxiosError(error)) {
138
+ throw new Error(error.response?.data?.error || error.message);
139
+ }
140
+ throw error;
141
+ }
142
+ }
143
+ /**
144
+ * Updates a record by ID in the specified table
145
+ * @param tableName The name of the table containing the record to update
146
+ * @param id The ID of the record to update
147
+ * @param data The data to update the record with
148
+ * @param axiosConfig Custom axios config for this specific request
149
+ * @returns Promise containing the updated record
150
+ */
151
+ async updateRecord(tableName, id, data, axiosConfig = {}) {
152
+ this.validateData(data);
153
+ try {
154
+ const response = await this.axiosInstance.put(`/update/${tableName}/${id}`, { data }, axiosConfig);
155
+ return {
156
+ records: [response.data],
157
+ message: 'Record updated successfully',
158
+ error: undefined,
159
+ };
160
+ }
161
+ catch (error) {
162
+ if (axios.isAxiosError(error)) {
163
+ throw new Error(error.response?.data?.error || error.message);
164
+ }
165
+ throw error;
166
+ }
167
+ }
168
+ /**
169
+ * Updates records by Complex Query from the specified table
170
+ * @param tableName The name of the table containing the record to delete
171
+ * @param params Query parameters including filters and pagination
172
+ * @param options Query options
173
+ * @param data The data to update the record with
174
+ * @param axiosConfig Custom axios config for this specific request
175
+ * @returns Promise containing the result of the deletion
176
+ */
177
+ async advanceUpdateRecord(tableName, data, params = {}, options = { execute: true }, axiosConfig = {}) {
178
+ try {
179
+ if (!options.execute) {
180
+ return { params: params };
181
+ }
182
+ const response = await this.axiosInstance.post(`/update/${tableName}`, { query: params, data }, axiosConfig);
183
+ return {
184
+ message: 'Records updated successfully',
185
+ error: undefined,
186
+ records: response.data,
187
+ };
188
+ }
189
+ catch (error) {
190
+ if (axios.isAxiosError(error)) {
191
+ throw new Error(error.response?.data?.error || error.message);
192
+ }
193
+ throw error;
194
+ }
195
+ }
196
+ /**
197
+ * Deletes a record by ID from the specified table
198
+ * @param tableName The name of the table containing the record to delete
199
+ * @param id The ID of the record to delete
200
+ * @param axiosConfig Custom axios config for this specific request
201
+ * @returns Promise containing the result of the deletion
202
+ */
203
+ async deleteRecord(tableName, id, axiosConfig = {}) {
204
+ try {
205
+ const response = await this.axiosInstance.post(`/del/${tableName}/${id}`, {}, axiosConfig);
206
+ return {
207
+ message: 'Record deleted successfully',
208
+ error: undefined,
209
+ records: response.data,
210
+ };
211
+ }
212
+ catch (error) {
213
+ if (axios.isAxiosError(error)) {
214
+ throw new Error(error.response?.data?.error || error.message);
215
+ }
216
+ throw error;
217
+ }
218
+ }
219
+ /**
220
+ * Deletes records by Complex Query from the specified table
221
+ * @param tableName The name of the table containing the record to delete
222
+ * @param params Query parameters including filters and pagination
223
+ * @param options Query options
224
+ * @param axiosConfig Custom axios config for this specific request
225
+ * @returns Promise containing the result of the deletion
226
+ */
227
+ async advanceDeleteRecord(tableName, params = {}, options = { execute: true }, axiosConfig = {}) {
228
+ try {
229
+ if (!options.execute) {
230
+ return { params: params };
231
+ }
232
+ const response = await this.axiosInstance.post(`/del/${tableName}`, { query: params }, axiosConfig);
233
+ return {
234
+ message: 'Record deleted successfully',
235
+ error: undefined,
236
+ records: response.data,
237
+ };
238
+ }
239
+ catch (error) {
240
+ if (axios.isAxiosError(error)) {
241
+ throw new Error(error.response?.data?.error || error.message);
242
+ }
243
+ throw error;
244
+ }
245
+ }
246
+ /**
247
+ * Helper method to create a query builder for fluent API usage
248
+ * @param tableName The name of the table to query
249
+ */
250
+ table(tableName) {
251
+ return new QueryBuilder(this, tableName);
252
+ }
253
+ /**
254
+ * Validates data object
255
+ */
256
+ validateData(data) {
257
+ if (typeof data !== 'object' || Object.keys(data).length === 0) {
258
+ throw new Error('Invalid data: must be a non-empty object');
259
+ }
260
+ }
261
+ }
262
+ /**
263
+ * Query builder class for more fluent API usage
264
+ */
265
+ class QueryBuilder {
266
+ constructor(sdk, tableName) {
267
+ this.sdk = sdk;
268
+ this.tableName = tableName;
269
+ this.params = {};
270
+ this.ctes = new Map();
271
+ }
272
+ /**
273
+ * Add a recursive CTE
274
+ */
275
+ withRecursive(name, initialQuery, recursiveQuery, options = {}) {
276
+ if (!this.params.recursiveCtes) {
277
+ this.params.recursiveCtes = [];
278
+ }
279
+ this.params.recursiveCtes.push({
280
+ name,
281
+ isRecursive: true,
282
+ initialQuery,
283
+ recursiveQuery,
284
+ unionAll: options.unionAll,
285
+ columns: options.columns,
286
+ query: initialQuery, // for compatibility with non-recursive CTEs
287
+ });
288
+ return this;
289
+ }
290
+ /**
291
+ * Advanced window function
292
+ */
293
+ windowAdvanced(type, alias, config) {
294
+ if (!this.params.advancedWindows) {
295
+ this.params.advancedWindows = [];
296
+ }
297
+ this.params.advancedWindows.push({
298
+ type,
299
+ alias,
300
+ ...config,
301
+ });
302
+ return this;
303
+ }
304
+ /**
305
+ * Add a window function
306
+ */
307
+ window(type, alias, config = {}) {
308
+ if (!this.params.windowFunctions) {
309
+ this.params.windowFunctions = [];
310
+ }
311
+ this.params.windowFunctions.push({
312
+ type,
313
+ alias,
314
+ field: config.field,
315
+ partitionBy: config.partitionBy,
316
+ orderBy: config.orderBy,
317
+ frameClause: config.frameClause,
318
+ });
319
+ return this;
320
+ }
321
+ /**
322
+ * Add common window functions
323
+ */
324
+ rowNumber(alias, partitionBy, orderBy) {
325
+ return this.window('row_number', alias, { partitionBy, orderBy });
326
+ }
327
+ rank(alias, partitionBy, orderBy) {
328
+ return this.window('rank', alias, { partitionBy, orderBy });
329
+ }
330
+ lag(field, alias, partitionBy, orderBy) {
331
+ return this.window('lag', alias, { field, partitionBy, orderBy });
332
+ }
333
+ lead(field, alias, partitionBy, orderBy) {
334
+ return this.window('lead', alias, { field, partitionBy, orderBy });
335
+ }
336
+ /**
337
+ * Add a CTE (WITH clause)
338
+ */
339
+ with(name, queryOrCallback, columns) {
340
+ let query;
341
+ if (typeof queryOrCallback === 'function') {
342
+ query = new QueryBuilder(this.sdk, this.tableName);
343
+ queryOrCallback(query);
344
+ }
345
+ else {
346
+ query = queryOrCallback;
347
+ }
348
+ this.ctes.set(name, {
349
+ name,
350
+ query,
351
+ columns: columns || [],
352
+ });
353
+ if (!this.params.ctes) {
354
+ this.params.ctes = [];
355
+ }
356
+ this.params.ctes.push({ name, query, columns: columns || [] });
357
+ return this;
358
+ }
359
+ /**
360
+ * Transform the result set
361
+ */
362
+ transform(config) {
363
+ this.params.transforms = {
364
+ ...this.params.transforms,
365
+ ...config,
366
+ };
367
+ return this;
368
+ }
369
+ /**
370
+ * Pivot the result set
371
+ */
372
+ pivot(column, values, aggregate) {
373
+ return this.transform({
374
+ pivot: {
375
+ column,
376
+ values,
377
+ aggregate,
378
+ },
379
+ });
380
+ }
381
+ /**
382
+ * Compute new fields from existing ones
383
+ */
384
+ compute(computations) {
385
+ return this.transform({
386
+ compute: computations,
387
+ });
388
+ }
389
+ where(fieldOrConditions, operatorOrValue, value) {
390
+ if (typeof fieldOrConditions === 'object') {
391
+ this.params.filter = {
392
+ ...this.params.filter,
393
+ ...fieldOrConditions,
394
+ };
395
+ }
396
+ else {
397
+ if (arguments.length === 2) {
398
+ this.params.filter = {
399
+ ...this.params.filter,
400
+ [fieldOrConditions]: operatorOrValue,
401
+ };
402
+ }
403
+ else {
404
+ if (!this.params.whereRaw) {
405
+ this.params.whereRaw = [];
406
+ }
407
+ this.params.whereRaw.push({
408
+ field: fieldOrConditions,
409
+ operator: operatorOrValue,
410
+ value,
411
+ });
412
+ }
413
+ }
414
+ return this;
415
+ }
416
+ // Where between
417
+ whereBetween(field, range) {
418
+ if (!this.params.whereBetween) {
419
+ this.params.whereBetween = [];
420
+ }
421
+ this.params.whereBetween.push({
422
+ field,
423
+ operator: 'between',
424
+ value: range,
425
+ });
426
+ return this;
427
+ }
428
+ // Where in
429
+ whereIn(field, values) {
430
+ if (!this.params.whereIn) {
431
+ this.params.whereIn = {};
432
+ }
433
+ this.params.whereIn[field] = values;
434
+ return this;
435
+ }
436
+ // Where not in
437
+ whereNotIn(field, values) {
438
+ if (!this.params.whereNotIn) {
439
+ this.params.whereNotIn = {};
440
+ }
441
+ this.params.whereNotIn[field] = values;
442
+ return this;
443
+ }
444
+ // Where null
445
+ whereNull(field) {
446
+ if (!this.params.whereNull) {
447
+ this.params.whereNull = [];
448
+ }
449
+ this.params.whereNull.push(field);
450
+ return this;
451
+ }
452
+ // Where not null
453
+ whereNotNull(field) {
454
+ if (!this.params.whereNotNull) {
455
+ this.params.whereNotNull = [];
456
+ }
457
+ this.params.whereNotNull.push(field);
458
+ return this;
459
+ }
460
+ orderBy(fieldOrOptions, direction, nulls) {
461
+ if (!this.params.orderBy) {
462
+ this.params.orderBy = [];
463
+ }
464
+ if (typeof fieldOrOptions === 'string') {
465
+ direction = direction || 'asc';
466
+ this.params.orderBy.push({
467
+ field: fieldOrOptions,
468
+ direction,
469
+ nulls,
470
+ });
471
+ }
472
+ else {
473
+ this.params.orderBy.push(fieldOrOptions);
474
+ }
475
+ return this;
476
+ }
477
+ limit(limit) {
478
+ this.params.limit = limit;
479
+ return this;
480
+ }
481
+ offset(offset) {
482
+ this.params.offset = offset;
483
+ return this;
484
+ }
485
+ /**
486
+ * Start an OR where group
487
+ */
488
+ orWhere(callback) {
489
+ return this.whereGroup('OR', callback);
490
+ }
491
+ /**
492
+ * Start an AND where group
493
+ */
494
+ andWhere(callback) {
495
+ return this.whereGroup('AND', callback);
496
+ }
497
+ /**
498
+ * Create a where group with the specified operator
499
+ */
500
+ whereGroup(operator, callback) {
501
+ // Create a new builder for the group to collect clauses
502
+ const groupBuilder = new QueryBuilder(this.sdk, this.tableName);
503
+ // Execute the callback with the group builder to collect clauses
504
+ callback(groupBuilder);
505
+ // Create the where group with the collected clauses
506
+ const group = {
507
+ type: operator,
508
+ clauses: [],
509
+ };
510
+ // Add all whereRaw clauses to the group
511
+ if (groupBuilder.params.whereRaw &&
512
+ groupBuilder.params.whereRaw.length > 0) {
513
+ group.clauses.push(...groupBuilder.params.whereRaw);
514
+ }
515
+ // Add all where groups from the builder to our group
516
+ if (groupBuilder.params.whereGroups &&
517
+ groupBuilder.params.whereGroups.length > 0) {
518
+ group.clauses.push(...groupBuilder.params.whereGroups);
519
+ }
520
+ // Initialize the whereGroups array if it doesn't exist
521
+ if (!this.params.whereGroups) {
522
+ this.params.whereGroups = [];
523
+ }
524
+ // Add the group to whereGroups array
525
+ this.params.whereGroups.push(group);
526
+ return this;
527
+ }
528
+ /**
529
+ * Add a where exists clause using a subquery
530
+ * @param subqueryBuilder A function that returns a configured query builder for the subquery
531
+ * @returns The query builder instance
532
+ * @example
533
+ * db.table<User>("users")
534
+ * .whereExists((subquery) =>
535
+ * subquery.table("orders")
536
+ * .where("orders.user_id", "=", "users.id")
537
+ * .where("total", ">", 1000)
538
+ * )
539
+ * .execute();
540
+ */
541
+ whereExists(subqueryBuilder) {
542
+ if (!this.params.whereExists) {
543
+ this.params.whereExists = [];
544
+ }
545
+ // Create a new SDK instance for the subquery
546
+ const subquerySdk = new DatabaseSDK({ baseUrl: this.sdk.getBaseUrl() });
547
+ // Get the subquery builder
548
+ const subquery = subqueryBuilder(subquerySdk);
549
+ // Extract the table name and parameters
550
+ this.params.whereExists.push({
551
+ tableName: subquery.getTableName(),
552
+ params: subquery.getParams(),
553
+ });
554
+ return this;
555
+ }
556
+ /**
557
+ * Add a where exists clause with join conditions
558
+ * @param tableName The table to check for existence
559
+ * @param leftField The field from the main table
560
+ * @param rightField The field from the subquery table
561
+ * @param additionalConditions Additional conditions for the subquery
562
+ * @returns The query builder instance
563
+ * @example
564
+ * db.table<User>("users")
565
+ * .whereExistsJoin("orders", "id", "user_id", (qb) =>
566
+ * qb.where("total", ">", 1000)
567
+ * )
568
+ * .execute();
569
+ */
570
+ whereExistsJoin(tableName, leftField, rightField, additionalConditions) {
571
+ if (!this.params.whereExists) {
572
+ this.params.whereExists = [];
573
+ }
574
+ // Create a new SDK instance for the subquery
575
+ const subquerySdk = new DatabaseSDK({ baseUrl: this.sdk.getBaseUrl() });
576
+ // Build the subquery
577
+ const subQueryBuilder = subquerySdk.table(tableName);
578
+ // Apply additional conditions if provided
579
+ if (additionalConditions) {
580
+ additionalConditions(subQueryBuilder);
581
+ }
582
+ // Add the join condition
583
+ this.params.whereExists.push({
584
+ tableName,
585
+ params: subQueryBuilder.getParams(),
586
+ joinCondition: {
587
+ leftField: leftField,
588
+ operator: '=',
589
+ rightField,
590
+ },
591
+ });
592
+ return this;
593
+ }
594
+ // Helper methods for the whereExists functions
595
+ getTableName() {
596
+ return this.tableName;
597
+ }
598
+ getParams() {
599
+ return this.params;
600
+ }
601
+ // rawExpression method removed for security reasons
602
+ /**
603
+ * Group by clause
604
+ */
605
+ groupBy(...fields) {
606
+ if (!this.params.groupBy) {
607
+ this.params.groupBy = [];
608
+ }
609
+ this.params.groupBy.push(...fields);
610
+ return this;
611
+ }
612
+ /**
613
+ * Having clause for grouped queries
614
+ */
615
+ having(field, operator, value) {
616
+ if (!this.params.having) {
617
+ this.params.having = [];
618
+ }
619
+ this.params.having.push({ field, operator, value });
620
+ return this;
621
+ }
622
+ /**
623
+ * Add an aggregate function
624
+ */
625
+ aggregate(type, field, alias) {
626
+ if (!this.params.aggregates) {
627
+ this.params.aggregates = [];
628
+ }
629
+ this.params.aggregates.push({ type, field, alias });
630
+ return this;
631
+ }
632
+ /**
633
+ * Shorthand for count aggregate
634
+ */
635
+ count(field = '*', alias) {
636
+ return this.aggregate('count', field, alias);
637
+ }
638
+ /**
639
+ * Shorthand for sum aggregate
640
+ */
641
+ sum(field, alias) {
642
+ return this.aggregate('sum', field, alias);
643
+ }
644
+ /**
645
+ * Shorthand for average aggregate
646
+ */
647
+ avg(field, alias) {
648
+ return this.aggregate('avg', field, alias);
649
+ }
650
+ /**
651
+ * Shorthand for minimum aggregate
652
+ */
653
+ min(field, alias) {
654
+ return this.aggregate('min', field, alias);
655
+ }
656
+ /**
657
+ * Shorthand for maximum aggregate
658
+ */
659
+ max(field, alias) {
660
+ return this.aggregate('max', field, alias);
661
+ }
662
+ // Get query parameters without executing
663
+ async toParams() {
664
+ const response = await this.sdk.getRecords(this.tableName, this.params, {
665
+ execute: false,
666
+ });
667
+ return response.params;
668
+ }
669
+ /**
670
+ * Execute with transformations
671
+ * @param axiosConfig Optional axios config to be used for this request
672
+ * @returns Promise with the query results
673
+ */
674
+ async query(axiosConfig = {}) {
675
+ const response = await this.sdk.getRecords(this.tableName, this.params, { execute: true }, axiosConfig);
676
+ if (this.params.transforms && response.records) {
677
+ return this.applyTransformations(response);
678
+ }
679
+ return response;
680
+ }
681
+ /**
682
+ * Create a record in the table
683
+ * @param data The data to create
684
+ * @param axiosConfig Optional axios config to be used for this request
685
+ * @returns Promise with the created record
686
+ */
687
+ async create(data, axiosConfig = {}) {
688
+ return this.sdk.createRecord(this.tableName, data, axiosConfig);
689
+ }
690
+ /**
691
+ * Update a record by ID
692
+ * @param id The ID of the record to update
693
+ * @param data The data to update
694
+ * @param axiosConfig Optional axios config to be used for this request
695
+ * @returns Promise with the updated record
696
+ */
697
+ async update(id, data, axiosConfig = {}) {
698
+ return this.sdk.updateRecord(this.tableName, id, data, axiosConfig);
699
+ }
700
+ /**
701
+ * Update records by Complex query
702
+ * @param data The data to update
703
+ * @param axiosConfig Optional axios config to be used for this request
704
+ * @returns Promise with the deletion result
705
+ */
706
+ async advanceUpdate(data, axiosConfig = {}) {
707
+ return this.sdk.advanceUpdateRecord(this.tableName, data, this.params, { execute: true }, axiosConfig);
708
+ }
709
+ /**
710
+ * Delete a record by ID
711
+ * @param id The ID of the record to delete
712
+ * @param axiosConfig Optional axios config to be used for this request
713
+ * @returns Promise with the deletion result
714
+ */
715
+ async delete(id, axiosConfig = {}) {
716
+ return this.sdk.deleteRecord(this.tableName, id, axiosConfig);
717
+ }
718
+ /**
719
+ * Delete records by Complex query
720
+ * @param axiosConfig Optional axios config to be used for this request
721
+ * @returns Promise with the deletion result
722
+ */
723
+ async advanceDelete(axiosConfig = {}) {
724
+ return this.sdk.advanceDeleteRecord(this.tableName, this.params, { execute: true }, axiosConfig);
725
+ }
726
+ applyTransformations(response) {
727
+ let transformed = [...(response.records || [])];
728
+ const transforms = this.params.transforms;
729
+ // Apply computations
730
+ if (transforms.compute) {
731
+ transformed = transformed.map((row) => ({
732
+ ...row,
733
+ ...Object.entries(transforms.compute).reduce((acc, [key, fn]) => ({
734
+ ...acc,
735
+ [key]: fn(row),
736
+ }), {}),
737
+ }));
738
+ }
739
+ // Apply grouping
740
+ if (transforms.groupBy) {
741
+ transformed = this.groupResults(transformed, transforms.groupBy);
742
+ }
743
+ // Apply pivoting
744
+ if (transforms.pivot) {
745
+ transformed = this.pivotResults(transformed, transforms.pivot);
746
+ }
747
+ return {
748
+ ...response,
749
+ records: transformed,
750
+ };
751
+ }
752
+ groupResults(records, groupBy) {
753
+ // Implementation of grouping logic
754
+ return records;
755
+ }
756
+ pivotResults(records, pivot) {
757
+ // Implementation of pivot logic
758
+ return records;
759
+ }
760
+ /**
761
+ * Select specific fields from the table
762
+ * @param fields Fields to select
763
+ * @example
764
+ * db.table("users")
765
+ * .select("id", "name", "email")
766
+ * .execute();
767
+ */
768
+ select(...fields) {
769
+ if (!this.params.select) {
770
+ this.params.select = [];
771
+ }
772
+ this.params.select.push(...fields);
773
+ return this;
774
+ }
775
+ }
776
+ // Example usage functions
777
+ // function demonstrateComplexQueries() {
778
+ // const db = new DatabaseSDK("https://api.example.com");
779
+ // // Complex grouped conditions
780
+ // db.table<User>("users")
781
+ // .where("status", "active")
782
+ // .andWhere((query) => {
783
+ // query.where("role", "admin").orWhere((subQuery) => {
784
+ // subQuery.where("role", "manager").where("department", "IT");
785
+ // });
786
+ // })
787
+ // .query();
788
+ // // Using exists with raw SQL
789
+ // db.table<Order>("orders")
790
+ // .whereExists(
791
+ // "SELECT 1 FROM order_items WHERE order_items.order_id = orders.id AND quantity > ?",
792
+ // [10]
793
+ // )
794
+ // .query();
795
+ // // Aggregations with grouping
796
+ // db.table<Order>("orders")
797
+ // .groupBy("customer_id", "status")
798
+ // .having("total_amount", ">", 1000)
799
+ // .sum("amount", "total_amount")
800
+ // .count("id", "order_count")
801
+ // .avg("amount", "average_amount")
802
+ // .query();
803
+ // // Raw expressions removed for security reasons
804
+ // }
805
+ //# sourceMappingURL=client.js.map