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