@carbonorm/carbonnode 3.5.7 → 3.5.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -1,11 +1,10 @@
1
1
  import axios from 'axios';
2
2
  import Qs from 'qs';
3
- import { __assign, __awaiter, __generator, __extends, __spreadArray } from 'tslib';
4
3
  import { toast } from 'react-toastify';
5
4
  import namedPlaceholders from 'named-placeholders';
6
5
  import { Buffer as Buffer$1 } from 'buffer';
7
6
 
8
- var C6Constants = {
7
+ const C6Constants = {
9
8
  // try to 1=1 match the Rest abstract class
10
9
  ADDDATE: 'ADDDATE',
11
10
  ADDTIME: 'ADDTIME',
@@ -163,7 +162,7 @@ var C6Constants = {
163
162
  FINISH: 'FINISH',
164
163
  VALIDATE_C6_ENTITY_ID_REGEX: '#^([a-fA-F0-9]{20,35})$#',
165
164
  };
166
- var C6C = C6Constants;
165
+ const C6C = C6Constants;
167
166
 
168
167
  // @link https://www.npmjs.com/package/axios-cache-adapter
169
168
  // updating these values
@@ -268,22 +267,20 @@ var axiosInstance = (axios.create({
268
267
  */
269
268
  }));
270
269
 
271
- function convertForRequestBody (restfulObject, tableName, C6, regexErrorHandler) {
272
- if (regexErrorHandler === void 0) { regexErrorHandler = alert; }
273
- var payload = {};
274
- var tableNames = Array.isArray(tableName) ? tableName : [tableName];
275
- var tableDefinitions = tableNames.map(function (name) {
276
- var tableDefinition = Object.values(C6.TABLES).find(function (t) { return t.TABLE_NAME === name; });
270
+ function convertForRequestBody (restfulObject, tableName, C6, regexErrorHandler = alert) {
271
+ const payload = {};
272
+ const tableNames = Array.isArray(tableName) ? tableName : [tableName];
273
+ const tableDefinitions = tableNames.map((name) => {
274
+ const tableDefinition = Object.values(C6.TABLES).find((t) => t.TABLE_NAME === name);
277
275
  if (!tableDefinition) {
278
- console.error("Table name (".concat(name, ") is not found in the C6.TABLES object."), C6.TABLES);
279
- throw new Error("Table name (".concat(name, ") is not found in the C6.TABLES object."));
276
+ console.error(`Table name (${name}) is not found in the C6.TABLES object.`, C6.TABLES);
277
+ throw new Error(`Table name (${name}) is not found in the C6.TABLES object.`);
280
278
  }
281
279
  return tableDefinition;
282
280
  });
283
- for (var _i = 0, tableDefinitions_1 = tableDefinitions; _i < tableDefinitions_1.length; _i++) {
284
- var tableDefinition = tableDefinitions_1[_i];
285
- var _loop_1 = function (value) {
286
- var shortReference = value.toUpperCase();
281
+ for (const tableDefinition of tableDefinitions) {
282
+ for (const value of Object.keys(restfulObject)) {
283
+ const shortReference = value.toUpperCase();
287
284
  if ([
288
285
  C6Constants.GET,
289
286
  C6Constants.POST,
@@ -294,61 +291,72 @@ function convertForRequestBody (restfulObject, tableName, C6, regexErrorHandler)
294
291
  C6Constants.JOIN,
295
292
  C6Constants.PAGINATION
296
293
  ].includes(value)) {
297
- var val_1 = restfulObject[value];
298
- if (Array.isArray(val_1)) {
299
- payload[value] = val_1.sort();
294
+ const val = restfulObject[value];
295
+ if (Array.isArray(val)) {
296
+ payload[value] = val.sort();
300
297
  }
301
- else if (typeof val_1 === 'object' && val_1 !== null) {
302
- payload[value] = Object.keys(val_1)
298
+ else if (typeof val === 'object' && val !== null) {
299
+ payload[value] = Object.keys(val)
303
300
  .sort()
304
- .reduce(function (acc, key) {
305
- var _a;
306
- return (__assign(__assign({}, acc), (_a = {}, _a[key] = val_1[key], _a)));
307
- }, {});
301
+ .reduce((acc, key) => ({ ...acc, [key]: val[key] }), {});
308
302
  }
309
- return "continue";
303
+ continue;
310
304
  }
311
305
  if (shortReference in tableDefinition) {
312
- var longName = tableDefinition[shortReference];
313
- var columnValue = restfulObject[value];
306
+ const longName = tableDefinition[shortReference];
307
+ const columnValue = restfulObject[value];
314
308
  payload[longName] = columnValue;
315
- var regexValidations = tableDefinition.REGEX_VALIDATION[longName];
309
+ const regexValidations = tableDefinition.REGEX_VALIDATION[longName];
316
310
  if (regexValidations instanceof RegExp) {
317
311
  if (!regexValidations.test(columnValue)) {
318
- regexErrorHandler("Failed to match regex (".concat(regexValidations, ") for column (").concat(longName, ")"));
319
- throw new Error("Failed to match regex (".concat(regexValidations, ") for column (").concat(longName, ")"));
312
+ regexErrorHandler(`Failed to match regex (${regexValidations}) for column (${longName})`);
313
+ throw new Error(`Failed to match regex (${regexValidations}) for column (${longName})`);
320
314
  }
321
315
  }
322
316
  else if (typeof regexValidations === 'object' && regexValidations !== null) {
323
- for (var errorMessage in regexValidations) {
324
- var regex = regexValidations[errorMessage];
317
+ for (const errorMessage in regexValidations) {
318
+ const regex = regexValidations[errorMessage];
325
319
  if (!regex.test(columnValue)) {
326
- var devErrorMessage = "Failed to match regex (".concat(regex, ") for column (").concat(longName, ")");
320
+ const devErrorMessage = `Failed to match regex (${regex}) for column (${longName})`;
321
+ regexErrorHandler(errorMessage || devErrorMessage);
322
+ throw new Error(devErrorMessage);
323
+ }
324
+ }
325
+ }
326
+ }
327
+ else if (Object.values(tableDefinition.COLUMNS).includes(value)) {
328
+ // Already a fully qualified column name
329
+ const columnValue = restfulObject[value];
330
+ payload[value] = columnValue;
331
+ const regexValidations = tableDefinition.REGEX_VALIDATION[value];
332
+ if (regexValidations instanceof RegExp) {
333
+ if (!regexValidations.test(columnValue)) {
334
+ regexErrorHandler(`Failed to match regex (${regexValidations}) for column (${value})`);
335
+ throw new Error(`Failed to match regex (${regexValidations}) for column (${value})`);
336
+ }
337
+ }
338
+ else if (typeof regexValidations === 'object' && regexValidations !== null) {
339
+ for (const errorMessage in regexValidations) {
340
+ const regex = regexValidations[errorMessage];
341
+ if (!regex.test(columnValue)) {
342
+ const devErrorMessage = `Failed to match regex (${regex}) for column (${value})`;
327
343
  regexErrorHandler(errorMessage || devErrorMessage);
328
344
  throw new Error(devErrorMessage);
329
345
  }
330
346
  }
331
347
  }
332
348
  }
333
- };
334
- for (var _a = 0, _b = Object.keys(restfulObject); _a < _b.length; _a++) {
335
- var value = _b[_a];
336
- _loop_1(value);
337
349
  }
338
350
  }
339
351
  return Object.keys(payload)
340
352
  .sort()
341
- .reduce(function (acc, key) {
342
- var _a;
343
- return (__assign(__assign({}, acc), (_a = {}, _a[key] = payload[key], _a)));
344
- }, {});
353
+ .reduce((acc, key) => ({ ...acc, [key]: payload[key] }), {});
345
354
  }
346
355
 
347
- var isNode = function () {
348
- var _a;
356
+ const isNode = () => {
349
357
  console.log('Checking if running in Node.js environment...');
350
- var isNodeEnv = typeof process !== 'undefined' && !!((_a = process.versions) === null || _a === void 0 ? void 0 : _a.node);
351
- console.log("Is Node.js environment: ".concat(isNodeEnv));
358
+ const isNodeEnv = typeof process !== 'undefined' && !!process.versions?.node;
359
+ console.log(`Is Node.js environment: ${isNodeEnv}`);
352
360
  return isNodeEnv;
353
361
  };
354
362
 
@@ -356,112 +364,94 @@ var isNode = function () {
356
364
  * Facade: routes API calls to SQL or HTTP executors based on runtime context.
357
365
  */
358
366
  function restRequest(configX) {
359
- var _this = this;
360
- return function (request) { return __awaiter(_this, void 0, void 0, function () {
361
- var config, SqlExecutor, executor, HttpExecutor, http;
362
- var _a;
363
- return __generator(this, function (_b) {
364
- switch (_b.label) {
365
- case 0:
366
- config = typeof configX === "function" ? configX() : configX;
367
- (_a = config.verbose) !== null && _a !== void 0 ? _a : (config.verbose = true); // Default to verbose logging if not set
368
- if (!(isNode() && config.mysqlPool)) return [3 /*break*/, 2];
369
- return [4 /*yield*/, Promise.resolve().then(function () { return SqlExecutor$1; })];
370
- case 1:
371
- SqlExecutor = (_b.sent()).SqlExecutor;
372
- executor = new SqlExecutor(config, request);
373
- return [2 /*return*/, executor.execute()];
374
- case 2: return [4 /*yield*/, Promise.resolve().then(function () { return HttpExecutor$1; })];
375
- case 3:
376
- HttpExecutor = (_b.sent()).HttpExecutor;
377
- http = new HttpExecutor(config, request);
378
- return [2 /*return*/, http.execute()];
379
- }
380
- });
381
- }); };
367
+ return async (request) => {
368
+ const config = typeof configX === "function" ? configX() : configX;
369
+ config.verbose ??= true; // Default to verbose logging if not set
370
+ // SQL path if on Node with a provided pool
371
+ if (isNode() && config.mysqlPool) {
372
+ const { SqlExecutor } = await Promise.resolve().then(function () { return SqlExecutor$1; });
373
+ const executor = new SqlExecutor(config, request);
374
+ return executor.execute();
375
+ }
376
+ // HTTP path fallback
377
+ const { HttpExecutor } = await Promise.resolve().then(function () { return HttpExecutor$1; });
378
+ const http = new HttpExecutor(config, request);
379
+ return http.execute();
380
+ };
382
381
  }
383
382
 
384
383
  function restOrm(configFn) {
385
384
  return {
386
- Get: restRequest(function () { return (__assign(__assign({}, configFn()), { requestMethod: "GET" })); }),
387
- Put: restRequest(function () { return (__assign(__assign({}, configFn()), { requestMethod: "PUT" })); }),
388
- Post: restRequest(function () { return (__assign(__assign({}, configFn()), { requestMethod: "POST" })); }),
389
- Delete: restRequest(function () { return (__assign(__assign({}, configFn()), { requestMethod: "DELETE" })); })
385
+ Get: restRequest(() => ({
386
+ ...configFn(),
387
+ requestMethod: "GET"
388
+ })),
389
+ Put: restRequest(() => ({
390
+ ...configFn(),
391
+ requestMethod: "PUT"
392
+ })),
393
+ Post: restRequest(() => ({
394
+ ...configFn(),
395
+ requestMethod: "POST"
396
+ })),
397
+ Delete: restRequest(() => ({
398
+ ...configFn(),
399
+ requestMethod: "DELETE"
400
+ }))
390
401
  };
391
402
  }
392
403
 
393
- function timeout(shouldContinueAfterTimeout, cb, timeoutMs) {
394
- if (timeoutMs === void 0) { timeoutMs = 3000; }
395
- var timer = function () { return setTimeout(function () {
404
+ function timeout(shouldContinueAfterTimeout, cb, timeoutMs = 3000) {
405
+ const timer = () => setTimeout(() => {
396
406
  if (false === shouldContinueAfterTimeout()) {
397
407
  return;
398
408
  }
399
409
  cb();
400
- }, timeoutMs); };
401
- var timerId = timer();
402
- return function () {
410
+ }, timeoutMs);
411
+ const timerId = timer();
412
+ return () => {
403
413
  clearTimeout(timerId);
404
414
  };
405
415
  }
406
416
 
407
- var Executor = /** @class */ (function () {
408
- function Executor(config, request, useNamedParams) {
409
- if (useNamedParams === void 0) { useNamedParams = false; }
417
+ class Executor {
418
+ config;
419
+ request;
420
+ useNamedParams;
421
+ constructor(config, request, useNamedParams = false) {
410
422
  this.config = config;
411
423
  this.request = request;
412
424
  this.useNamedParams = useNamedParams;
413
425
  }
414
- Executor.prototype.runLifecycleHooks = function (phase, args) {
415
- return __awaiter(this, void 0, void 0, function () {
416
- var lifecycleGroup, _i, _a, _b, key, fn, err_1;
417
- var _c;
418
- return __generator(this, function (_d) {
419
- switch (_d.label) {
420
- case 0:
421
- lifecycleGroup = (_c = this.config.restModel.LIFECYCLE_HOOKS[this.config.requestMethod]) === null || _c === void 0 ? void 0 : _c[phase];
422
- if (!lifecycleGroup)
423
- return [2 /*return*/];
424
- _i = 0, _a = Object.entries(lifecycleGroup);
425
- _d.label = 1;
426
- case 1:
427
- if (!(_i < _a.length)) return [3 /*break*/, 6];
428
- _b = _a[_i], key = _b[0], fn = _b[1];
429
- if (!(typeof fn === "function")) return [3 /*break*/, 5];
430
- if (this.config.verbose || args.request.debug) {
431
- console.groupCollapsed("[LIFECYCLE] ".concat(this.config.requestMethod, ".").concat(String(phase), ":").concat(key));
432
- console.log("config:", args.config);
433
- console.log("request:", args.request);
434
- if ("response" in args) {
435
- console.log("response:", args.response);
436
- }
437
- console.groupEnd();
438
- }
439
- _d.label = 2;
440
- case 2:
441
- _d.trys.push([2, 4, , 5]);
442
- // todo - this
443
- return [4 /*yield*/, fn(args)];
444
- case 3:
445
- // todo - this
446
- _d.sent();
447
- return [3 /*break*/, 5];
448
- case 4:
449
- err_1 = _d.sent();
450
- console.error("[LIFECYCLE ERROR] ".concat(this.config.requestMethod, ".").concat(String(phase), ":").concat(key), err_1);
451
- throw err_1;
452
- case 5:
453
- _i++;
454
- return [3 /*break*/, 1];
455
- case 6: return [2 /*return*/];
426
+ async runLifecycleHooks(phase, args) {
427
+ const lifecycleGroup = this.config.restModel.LIFECYCLE_HOOKS[this.config.requestMethod]?.[phase];
428
+ if (!lifecycleGroup)
429
+ return;
430
+ for (const [key, fn] of Object.entries(lifecycleGroup)) {
431
+ if (typeof fn === "function") {
432
+ if (this.config.verbose || args.request.debug) {
433
+ console.groupCollapsed(`[LIFECYCLE] ${this.config.requestMethod}.${String(phase)}:${key}`);
434
+ console.log("config:", args.config);
435
+ console.log("request:", args.request);
436
+ if ("response" in args) {
437
+ console.log("response:", args.response);
438
+ }
439
+ console.groupEnd();
456
440
  }
457
- });
458
- });
459
- };
460
- return Executor;
461
- }());
441
+ try {
442
+ // todo - this
443
+ await fn(args);
444
+ }
445
+ catch (err) {
446
+ console.error(`[LIFECYCLE ERROR] ${this.config.requestMethod}.${String(phase)}:${key}`, err);
447
+ throw err;
448
+ }
449
+ }
450
+ }
451
+ }
452
+ }
462
453
 
463
- function getEnvVar(key, fallback) {
464
- if (fallback === void 0) { fallback = ''; }
454
+ function getEnvVar(key, fallback = '') {
465
455
  // Vite-style injection
466
456
  // @ts-ignore
467
457
  if (typeof import.meta !== 'undefined' && import.meta.env && key in import.meta.env) {
@@ -498,12 +488,12 @@ var eFetchDependencies;
498
488
  })(eFetchDependencies || (eFetchDependencies = {}));
499
489
 
500
490
  // Refined TypeScript types for CarbonORM
501
- var POST = 'POST';
502
- var PUT = 'PUT';
503
- var GET = 'GET';
504
- var DELETE = 'DELETE';
491
+ const POST = 'POST';
492
+ const PUT = 'PUT';
493
+ const GET = 'GET';
494
+ const DELETE = 'DELETE';
505
495
 
506
- var toastOptions = {
496
+ const toastOptions = {
507
497
  position: "bottom-left",
508
498
  autoClose: 10000,
509
499
  hideProgressBar: false,
@@ -512,7 +502,7 @@ var toastOptions = {
512
502
  draggable: true,
513
503
  theme: "dark",
514
504
  };
515
- var toastOptionsDevs = {
505
+ const toastOptionsDevs = {
516
506
  position: "bottom-right",
517
507
  autoClose: 3000,
518
508
  hideProgressBar: false,
@@ -524,20 +514,19 @@ var toastOptionsDevs = {
524
514
 
525
515
  // When we capture DropExceptions and display them as a custom page, this will change.
526
516
  function TestRestfulResponse(response, success, error) {
527
- var _a, _b, _c, _d, _e, _f, _g, _h;
528
- if (undefined === ((_a = response.data) === null || _a === void 0 ? void 0 : _a['ERROR TYPE'])
529
- && (undefined !== ((_b = response === null || response === void 0 ? void 0 : response.data) === null || _b === void 0 ? void 0 : _b.rest)
530
- || undefined !== ((_c = response.data) === null || _c === void 0 ? void 0 : _c.created)
531
- || undefined !== ((_d = response.data) === null || _d === void 0 ? void 0 : _d.updated)
532
- || undefined !== ((_e = response.data) === null || _e === void 0 ? void 0 : _e.deleted))) {
533
- var successReturn = 'function' === typeof success ? success === null || success === void 0 ? void 0 : success(response) : success;
517
+ if (undefined === response.data?.['ERROR TYPE']
518
+ && (undefined !== response?.data?.rest
519
+ || undefined !== response.data?.created
520
+ || undefined !== response.data?.updated
521
+ || undefined !== response.data?.deleted)) {
522
+ let successReturn = 'function' === typeof success ? success?.(response) : success;
534
523
  if (typeof successReturn === 'string') {
535
524
  toast.success(successReturn, toastOptions);
536
525
  }
537
526
  // this could end up with bad results for deleting id's === 0
538
- return (_h = (_g = (_f = response.data.created) !== null && _f !== void 0 ? _f : response.data.updated) !== null && _g !== void 0 ? _g : response.data.deleted) !== null && _h !== void 0 ? _h : true;
527
+ return response.data.created ?? response.data.updated ?? response.data.deleted ?? true;
539
528
  }
540
- var errorReturn = 'function' === typeof error ? error === null || error === void 0 ? void 0 : error(response) : error;
529
+ let errorReturn = 'function' === typeof error ? error?.(response) : error;
541
530
  if (typeof errorReturn === 'string') {
542
531
  toast.error(errorReturn, toastOptions);
543
532
  }
@@ -550,15 +539,15 @@ function removePrefixIfExists(tableName, prefix) {
550
539
  return tableName;
551
540
  }
552
541
  function removeInvalidKeys(request, c6Tables) {
553
- var intersection = {};
554
- var restfulObjectKeys = [];
555
- var tableList = Object.values(c6Tables);
556
- tableList.forEach(function (table) { return Object.values(table.COLUMNS).forEach(function (column) {
542
+ let intersection = {};
543
+ let restfulObjectKeys = [];
544
+ const tableList = Object.values(c6Tables);
545
+ tableList.forEach(table => Object.values(table.COLUMNS).forEach(column => {
557
546
  if (false === restfulObjectKeys.includes(column)) {
558
547
  restfulObjectKeys.push(column);
559
548
  }
560
- }); });
561
- Object.keys(request).forEach(function (key) {
549
+ }));
550
+ Object.keys(request).forEach(key => {
562
551
  if (restfulObjectKeys.includes(key)) {
563
552
  intersection[key] = request[key];
564
553
  }
@@ -569,13 +558,13 @@ function removeInvalidKeys(request, c6Tables) {
569
558
 
570
559
  // do not remove entries from this array. It is used to track the progress of API requests.
571
560
  // position in array is important. Do not sort. To not add to begging.
572
- var apiRequestCache = [];
573
- var userCustomClearCache = [];
561
+ let apiRequestCache = [];
562
+ let userCustomClearCache = [];
574
563
  function clearCache(props) {
575
- if (false === (props === null || props === void 0 ? void 0 : props.ignoreWarning)) {
564
+ if (false === props?.ignoreWarning) {
576
565
  console.warn('The rest api clearCache should only be used with extreme care! Avoid using this in favor of using `cacheResults : boolean`.');
577
566
  }
578
- userCustomClearCache.map(function (f) { return 'function' === typeof f && f(); });
567
+ userCustomClearCache.map((f) => 'function' === typeof f && f());
579
568
  userCustomClearCache = apiRequestCache = [];
580
569
  }
581
570
  function checkCache(cacheResult, requestMethod, tableName, request) {
@@ -590,601 +579,551 @@ function checkCache(cacheResult, requestMethod, tableName, request) {
590
579
  }
591
580
 
592
581
  function sortAndSerializeQueryObject(tables, query) {
593
- var orderedQuery = Object.keys(query).sort().reduce(function (obj, key) {
582
+ const orderedQuery = Object.keys(query).sort().reduce((obj, key) => {
594
583
  obj[key] = query[key];
595
584
  return obj;
596
585
  }, {});
597
586
  return tables + ' ' + JSON.stringify(orderedQuery);
598
587
  }
599
588
 
600
- var HttpExecutor = /** @class */ (function (_super) {
601
- __extends(HttpExecutor, _super);
602
- function HttpExecutor() {
603
- return _super !== null && _super.apply(this, arguments) || this;
604
- }
605
- HttpExecutor.prototype.putState = function (response, request, callback) {
606
- var _a, _b;
607
- (_a = this.config.reactBootstrap) === null || _a === void 0 ? void 0 : _a.updateRestfulObjectArrays({
608
- callback: callback,
589
+ class HttpExecutor extends Executor {
590
+ putState(response, request, callback) {
591
+ this.config.reactBootstrap?.updateRestfulObjectArrays({
592
+ callback,
609
593
  dataOrCallback: [
610
- removeInvalidKeys(__assign(__assign({}, request), (_b = response === null || response === void 0 ? void 0 : response.data) === null || _b === void 0 ? void 0 : _b.rest), this.config.C6.TABLES)
594
+ removeInvalidKeys({
595
+ ...request,
596
+ ...response?.data?.rest,
597
+ }, this.config.C6.TABLES)
611
598
  ],
612
599
  stateKey: this.config.restModel.TABLE_NAME,
613
600
  uniqueObjectId: this.config.restModel.PRIMARY_SHORT
614
601
  });
615
- };
616
- HttpExecutor.prototype.postState = function (response, request, callback) {
617
- var _this = this;
618
- var _a, _b, _c;
602
+ }
603
+ postState(response, request, callback) {
619
604
  if (1 !== this.config.restModel.PRIMARY_SHORT.length) {
620
605
  console.error("C6 received unexpected result's given the primary key length");
621
606
  }
622
607
  else {
623
- var pk = this.config.restModel.PRIMARY_SHORT[0];
608
+ const pk = this.config.restModel.PRIMARY_SHORT[0];
624
609
  // TODO - should overrides be handled differently? Why override: (react/php), driver missmatches, aux data..
625
610
  // @ts-ignore - this is technically a correct error, but we allow it anyway...
626
- request[pk] = (_a = response.data) === null || _a === void 0 ? void 0 : _a.created;
611
+ request[pk] = response.data?.created;
627
612
  }
628
- (_b = this.config.reactBootstrap) === null || _b === void 0 ? void 0 : _b.updateRestfulObjectArrays({
629
- callback: callback,
613
+ this.config.reactBootstrap?.updateRestfulObjectArrays({
614
+ callback,
630
615
  dataOrCallback: undefined !== request.dataInsertMultipleRows
631
- ? request.dataInsertMultipleRows.map(function (request, index) {
632
- var _a;
633
- return removeInvalidKeys(__assign(__assign({}, request), (index === 0 ? (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.rest : {})), _this.config.C6.TABLES);
616
+ ? request.dataInsertMultipleRows.map((request, index) => {
617
+ return removeInvalidKeys({
618
+ ...request,
619
+ ...(index === 0 ? response?.data?.rest : {}),
620
+ }, this.config.C6.TABLES);
634
621
  })
635
622
  : [
636
- removeInvalidKeys(__assign(__assign({}, request), (_c = response === null || response === void 0 ? void 0 : response.data) === null || _c === void 0 ? void 0 : _c.rest), this.config.C6.TABLES)
623
+ removeInvalidKeys({
624
+ ...request,
625
+ ...response?.data?.rest,
626
+ }, this.config.C6.TABLES)
637
627
  ],
638
628
  stateKey: this.config.restModel.TABLE_NAME,
639
629
  uniqueObjectId: this.config.restModel.PRIMARY_SHORT
640
630
  });
641
- };
642
- HttpExecutor.prototype.deleteState = function (_response, request, callback) {
643
- var _a;
644
- (_a = this.config.reactBootstrap) === null || _a === void 0 ? void 0 : _a.deleteRestfulObjectArrays({
645
- callback: callback,
631
+ }
632
+ deleteState(_response, request, callback) {
633
+ this.config.reactBootstrap?.deleteRestfulObjectArrays({
634
+ callback,
646
635
  dataOrCallback: [
647
636
  request,
648
637
  ],
649
638
  stateKey: this.config.restModel.TABLE_NAME,
650
639
  uniqueObjectId: this.config.restModel.PRIMARY_SHORT
651
640
  });
652
- };
653
- HttpExecutor.prototype.execute = function () {
654
- return __awaiter(this, void 0, void 0, function () {
655
- var _a, C6, axios, restURL, withCredentials, restModel, reactBootstrap, requestMethod, skipPrimaryCheck, clearCache, tableName, fullTableList, operatingTableFullName, operatingTable, tables, query, apiRequest;
656
- var _this = this;
657
- return __generator(this, function (_b) {
658
- switch (_b.label) {
659
- case 0:
660
- _a = this.config, C6 = _a.C6, axios = _a.axios, restURL = _a.restURL, withCredentials = _a.withCredentials, restModel = _a.restModel, reactBootstrap = _a.reactBootstrap, requestMethod = _a.requestMethod, skipPrimaryCheck = _a.skipPrimaryCheck, clearCache = _a.clearCache;
661
- console.log('this.config', this.config);
662
- return [4 /*yield*/, this.runLifecycleHooks("beforeProcessing", {
663
- config: this.config,
664
- request: this.request,
665
- })];
666
- case 1:
667
- _b.sent();
668
- tableName = restModel.TABLE_NAME;
669
- fullTableList = Array.isArray(tableName) ? tableName : [tableName];
670
- operatingTableFullName = fullTableList[0];
671
- operatingTable = removePrefixIfExists(operatingTableFullName, C6.PREFIX);
672
- tables = fullTableList.join(',');
641
+ }
642
+ async execute() {
643
+ const { C6, axios, restURL, withCredentials, restModel, reactBootstrap, requestMethod, skipPrimaryCheck, clearCache, } = this.config;
644
+ console.log('this.config', this.config);
645
+ await this.runLifecycleHooks("beforeProcessing", {
646
+ config: this.config,
647
+ request: this.request,
648
+ });
649
+ const tableName = restModel.TABLE_NAME;
650
+ const fullTableList = Array.isArray(tableName) ? tableName : [tableName];
651
+ const operatingTableFullName = fullTableList[0];
652
+ const operatingTable = removePrefixIfExists(operatingTableFullName, C6.PREFIX);
653
+ const tables = fullTableList.join(',');
654
+ switch (requestMethod) {
655
+ case GET:
656
+ case POST:
657
+ case PUT:
658
+ case DELETE:
659
+ break;
660
+ default:
661
+ throw Error('Bad request method passed to getApi');
662
+ }
663
+ if (null !== clearCache || undefined !== clearCache) {
664
+ userCustomClearCache[tables + requestMethod] = clearCache;
665
+ }
666
+ console.groupCollapsed('%c API: (' + requestMethod + ') Request for (' + tableName + ')', 'color: #0c0');
667
+ console.log('request', this.request);
668
+ console.groupEnd();
669
+ // an undefined query would indicate queryCallback returned undefined,
670
+ // thus the request shouldn't fire as is in custom cache
671
+ if (undefined === this.request || null === this.request) {
672
+ console.groupCollapsed('%c API: (' + requestMethod + ') Request Query for (' + tableName + ') undefined, returning null (will not fire)!', 'color: #c00');
673
+ console.log('request', this.request);
674
+ console.log('%c Returning (undefined|null) for a query would indicate a custom cache hit (outside API.tsx), thus the request should not fire.', 'color: #c00');
675
+ console.trace();
676
+ console.groupEnd();
677
+ return null;
678
+ }
679
+ let query = this.request;
680
+ if (C6.GET === requestMethod) {
681
+ if (undefined === query[C6.PAGINATION]) {
682
+ query[C6.PAGINATION] = {};
683
+ }
684
+ query[C6.PAGINATION][C6.PAGE] = query[C6.PAGINATION][C6.PAGE] || 1;
685
+ query[C6.PAGINATION][C6.LIMIT] = query[C6.PAGINATION][C6.LIMIT] || 100;
686
+ }
687
+ // this is parameterless and could return itself with a new page number, or undefined if the end is reached
688
+ const apiRequest = async () => {
689
+ const { debug, cacheResults = (C6.GET === requestMethod), dataInsertMultipleRows, success, fetchDependencies = eFetchDependencies.NONE, error = "An unexpected API error occurred!" } = this.request;
690
+ if (C6.GET === requestMethod
691
+ && undefined !== query?.[C6.PAGINATION]?.[C6.PAGE]
692
+ && 1 !== query[C6.PAGINATION][C6.PAGE]) {
693
+ console.groupCollapsed('Request on table (' + tableName + ') is firing for page (' + query[C6.PAGINATION][C6.PAGE] + '), please wait!');
694
+ console.log('Request Data (note you may see the success and/or error prompt):', this.request);
695
+ console.trace();
696
+ console.groupEnd();
697
+ }
698
+ // The problem with creating cache keys with a stringified object is the order of keys matters and it's possible for the same query to be stringified differently.
699
+ // Here we ensure the key order will be identical between two of the same requests. https://stackoverflow.com/questions/5467129/sort-javascript-object-by-key
700
+ // literally impossible for query to be undefined or null here but the editor is too busy licking windows to understand that
701
+ let querySerialized = sortAndSerializeQueryObject(tables, query ?? {});
702
+ let cacheResult = apiRequestCache.find(cache => cache.requestArgumentsSerialized === querySerialized);
703
+ let cachingConfirmed = false;
704
+ // determine if we need to paginate.
705
+ if (requestMethod === C6.GET) {
706
+ if (undefined === query?.[C6.PAGINATION]) {
707
+ if (undefined === query || null === query) {
708
+ query = {};
709
+ }
710
+ query[C6.PAGINATION] = {};
711
+ }
712
+ query[C6.PAGINATION][C6.PAGE] = query[C6.PAGINATION][C6.PAGE] || 1;
713
+ query[C6.PAGINATION][C6.LIMIT] = query[C6.PAGINATION][C6.LIMIT] || 100;
714
+ // this will evaluate true most the time
715
+ if (true === cacheResults) {
716
+ // just find the next, non-fetched, page and return a function to request it
717
+ if (undefined !== cacheResult) { // we will return in this loop
718
+ do {
719
+ const cacheCheck = checkCache(cacheResult, requestMethod, tableName, this.request);
720
+ if (false !== cacheCheck) {
721
+ return (await cacheCheck).data;
722
+ }
723
+ // this line incrementing page is why we return recursively
724
+ ++query[C6.PAGINATION][C6.PAGE];
725
+ // this json stringify is to capture the new page number
726
+ querySerialized = sortAndSerializeQueryObject(tables, query ?? {});
727
+ cacheResult = apiRequestCache.find(cache => cache.requestArgumentsSerialized === querySerialized);
728
+ } while (undefined !== cacheResult);
729
+ if (debug && isLocal()) {
730
+ toast.warning("DEVS: Request in cache. (" + apiRequestCache.findIndex(cache => cache.requestArgumentsSerialized === querySerialized) + "). Returning function to request page (" + query[C6.PAGINATION][C6.PAGE] + ")", toastOptionsDevs);
731
+ }
732
+ // @ts-ignore - this is an incorrect warning on TS, it's well typed
733
+ return apiRequest;
734
+ }
735
+ cachingConfirmed = true;
736
+ }
737
+ else {
738
+ if (debug && isLocal()) {
739
+ toast.info("DEVS: Ignore cache was set to true.", toastOptionsDevs);
740
+ }
741
+ }
742
+ if (debug && isLocal()) {
743
+ toast.success("DEVS: Request not in cache." + (requestMethod === C6.GET ? "Page (" + query[C6.PAGINATION][C6.PAGE] + ")." : '') + " Logging cache 2 console.", toastOptionsDevs);
744
+ }
745
+ }
746
+ else if (cacheResults) { // if we are not getting, we are updating, deleting, or inserting
747
+ if (cacheResult) {
748
+ const cacheCheck = checkCache(cacheResult, requestMethod, tableName, this.request);
749
+ if (false !== cacheCheck) {
750
+ return (await cacheCheck).data;
751
+ }
752
+ }
753
+ cachingConfirmed = true;
754
+ // push to cache so we do not repeat the request
755
+ }
756
+ let addBackPK;
757
+ let apiResponse;
758
+ let returnGetNextPageFunction = false;
759
+ let restRequestUri = restURL + operatingTable + '/';
760
+ const needsConditionOrPrimaryCheck = (PUT === requestMethod || DELETE === requestMethod)
761
+ && false === skipPrimaryCheck;
762
+ const TABLES = C6.TABLES;
763
+ // todo - aggregate primary key check with condition check
764
+ // check if PK exists in query, clone so pop does not affect the real data
765
+ const primaryKey = structuredClone(TABLES[operatingTable]?.PRIMARY)?.pop()?.split('.')?.pop();
766
+ if (needsConditionOrPrimaryCheck) {
767
+ if (undefined === primaryKey) {
768
+ if (null === query
769
+ || undefined === query
770
+ || undefined === query?.[C6.WHERE]
771
+ || (true === Array.isArray(query[C6.WHERE])
772
+ || query[C6.WHERE].length === 0)
773
+ || (Object.keys(query?.[C6.WHERE]).length === 0)) {
774
+ console.error(query);
775
+ throw Error('Failed to parse primary key information. Query: (' + JSON.stringify(query) + ') Primary Key: (' + JSON.stringify(primaryKey) + ') TABLES[operatingTable]?.PRIMARY: (' + JSON.stringify(TABLES[operatingTable]?.PRIMARY) + ') for operatingTable (' + operatingTable + ').');
776
+ }
777
+ }
778
+ else {
779
+ if (undefined === query
780
+ || null === query
781
+ || false === primaryKey in query) {
782
+ if (true === debug && isLocal()) {
783
+ toast.error('DEVS: The primary key (' + primaryKey + ') was not provided!!');
784
+ }
785
+ throw Error('You must provide the primary key (' + primaryKey + ') for table (' + operatingTable + '). Request (' + JSON.stringify(this.request, undefined, 4) + ') Query (' + JSON.stringify(query) + ')');
786
+ }
787
+ if (undefined === query?.[primaryKey]
788
+ || null === query?.[primaryKey]) {
789
+ toast.error('The primary key (' + primaryKey + ') provided is undefined or null explicitly!!');
790
+ throw Error('The primary key (' + primaryKey + ') provided in the request was exactly equal to undefined.');
791
+ }
792
+ }
793
+ }
794
+ // A part of me exists that wants to remove this, but it's a good feature
795
+ // this allows developers the ability to cache requests based on primary key
796
+ // for tables like `photos` this can be a huge performance boost
797
+ if (undefined !== query
798
+ && null !== query
799
+ && undefined !== primaryKey
800
+ && primaryKey in query) {
801
+ restRequestUri += query[primaryKey] + '/';
802
+ const removedPkValue = query[primaryKey];
803
+ addBackPK = () => {
804
+ query ??= {};
805
+ query[primaryKey] = removedPkValue;
806
+ };
807
+ delete query[primaryKey];
808
+ console.log('query', query, 'primaryKey', primaryKey, 'removedPkValue', removedPkValue);
809
+ }
810
+ else {
811
+ console.log('query', query);
812
+ }
813
+ try {
814
+ console.groupCollapsed('%c API: (' + requestMethod + ') Request Query for (' + operatingTable + ') is about to fire, will return with promise!', 'color: #A020F0');
815
+ console.log(this.request);
816
+ console.log('%c If this is the first request for this datatype; thus the value being set is currently undefined, please remember to update the state to null.', 'color: #A020F0');
817
+ console.log('%c Remember undefined indicated the request has not fired, null indicates the request is firing, an empty array would signal no data was returned for the sql stmt.', 'color: #A020F0');
818
+ console.trace();
819
+ console.groupEnd();
820
+ this.runLifecycleHooks("beforeExecution", {
821
+ config: this.config,
822
+ request: this.request
823
+ });
824
+ const axiosActiveRequest = axios[requestMethod.toLowerCase()](restRequestUri, ...(() => {
825
+ const convert = (data) => convertForRequestBody(data, fullTableList, C6, (message) => toast.error(message, toastOptions));
826
+ const baseConfig = {
827
+ withCredentials: withCredentials,
828
+ };
829
+ switch (requestMethod) {
830
+ case GET:
831
+ return [{
832
+ ...baseConfig,
833
+ params: query
834
+ }];
835
+ case POST:
836
+ if (dataInsertMultipleRows !== undefined) {
837
+ return [
838
+ dataInsertMultipleRows.map(convert),
839
+ baseConfig
840
+ ];
841
+ }
842
+ return [convert(query), baseConfig];
843
+ case PUT:
844
+ return [convert(query), baseConfig];
845
+ case DELETE:
846
+ return [{
847
+ ...baseConfig,
848
+ data: convert(query)
849
+ }];
850
+ default:
851
+ throw new Error(`The request method (${requestMethod}) was not recognized.`);
852
+ }
853
+ })());
854
+ if (cachingConfirmed) {
855
+ // push to cache so we do not repeat the request
856
+ apiRequestCache.push({
857
+ requestArgumentsSerialized: querySerialized,
858
+ request: axiosActiveRequest
859
+ });
860
+ }
861
+ // todo - wip verify this works
862
+ // we had removed the value from the request to add to the URI.
863
+ addBackPK?.(); // adding back so post-processing methods work
864
+ // returning the promise with this then is important for tests. todo - we could make that optional.
865
+ // https://rapidapi.com/guides/axios-async-await
866
+ return axiosActiveRequest.then(async (response) => {
867
+ // noinspection SuspiciousTypeOfGuard
868
+ if (typeof response.data === 'string') {
869
+ if (isTest()) {
870
+ console.trace();
871
+ throw new Error('The response data was a string this typically indicated html was sent. Make sure all cookies (' + JSON.stringify(response.config.headers) + ') needed are present! (' + response.data + ')');
872
+ }
873
+ return Promise.reject(response);
874
+ }
875
+ if (cachingConfirmed) {
876
+ const cacheIndex = apiRequestCache.findIndex(cache => cache.requestArgumentsSerialized === querySerialized);
877
+ // TODO - currently nonthing is setting this correctly
878
+ apiRequestCache[cacheIndex].final = false === returnGetNextPageFunction;
879
+ // only cache get method requests
880
+ apiRequestCache[cacheIndex].response = response;
881
+ }
882
+ this.runLifecycleHooks("afterExecution", {
883
+ config: this.config,
884
+ request: this.request,
885
+ response
886
+ });
887
+ // todo - this feels dumb now, but i digress
888
+ apiResponse = TestRestfulResponse(response, success, error);
889
+ if (false === apiResponse) {
890
+ if (debug && isLocal()) {
891
+ toast.warning("DEVS: TestRestfulResponse returned false for (" + operatingTable + ").", toastOptionsDevs);
892
+ }
893
+ return response;
894
+ }
895
+ const callback = () => this.runLifecycleHooks("afterCommit", {
896
+ config: this.config,
897
+ request: this.request,
898
+ response
899
+ });
900
+ if (undefined !== reactBootstrap && response) {
673
901
  switch (requestMethod) {
674
902
  case GET:
903
+ response.data && reactBootstrap.updateRestfulObjectArrays({
904
+ dataOrCallback: Array.isArray(response.data.rest) ? response.data.rest : [response.data.rest],
905
+ stateKey: this.config.restModel.TABLE_NAME,
906
+ uniqueObjectId: this.config.restModel.PRIMARY_SHORT,
907
+ callback
908
+ });
909
+ break;
675
910
  case POST:
911
+ this.postState(response, this.request, callback);
912
+ break;
676
913
  case PUT:
914
+ this.putState(response, this.request, callback);
915
+ break;
677
916
  case DELETE:
917
+ this.deleteState(response, this.request, callback);
678
918
  break;
679
- default:
680
- throw Error('Bad request method passed to getApi');
681
919
  }
682
- if (null !== clearCache || undefined !== clearCache) {
683
- userCustomClearCache[tables + requestMethod] = clearCache;
684
- }
685
- console.groupCollapsed('%c API: (' + requestMethod + ') Request for (' + tableName + ')', 'color: #0c0');
686
- console.log('request', this.request);
687
- console.groupEnd();
688
- // an undefined query would indicate queryCallback returned undefined,
689
- // thus the request shouldn't fire as is in custom cache
690
- if (undefined === this.request || null === this.request) {
691
- console.groupCollapsed('%c API: (' + requestMethod + ') Request Query for (' + tableName + ') undefined, returning null (will not fire)!', 'color: #c00');
692
- console.log('request', this.request);
693
- console.log('%c Returning (undefined|null) for a query would indicate a custom cache hit (outside API.tsx), thus the request should not fire.', 'color: #c00');
920
+ }
921
+ else {
922
+ callback();
923
+ }
924
+ if (C6.GET === requestMethod) {
925
+ const responseData = response.data;
926
+ returnGetNextPageFunction = 1 !== query?.[C6.PAGINATION]?.[C6.LIMIT] &&
927
+ query?.[C6.PAGINATION]?.[C6.LIMIT] === responseData.rest.length;
928
+ if (false === isTest() || this.config.verbose) {
929
+ console.groupCollapsed('%c API: Response (' + requestMethod + ' ' + tableName + ') returned length (' + responseData.rest?.length + ') of possible (' + query?.[C6.PAGINATION]?.[C6.LIMIT] + ') limit!', 'color: #0c0');
930
+ console.log('%c ' + requestMethod + ' ' + tableName, 'color: #0c0');
931
+ console.log('%c Request Data (note you may see the success and/or error prompt):', 'color: #0c0', this.request);
932
+ console.log('%c Response Data:', 'color: #0c0', responseData.rest);
933
+ console.log('%c Will return get next page function:' + (returnGetNextPageFunction ? '' : ' (Will not return with explicit limit 1 set)'), 'color: #0c0', true === returnGetNextPageFunction);
694
934
  console.trace();
695
935
  console.groupEnd();
696
- return [2 /*return*/, null];
697
936
  }
698
- query = this.request;
699
- if (C6.GET === requestMethod) {
700
- if (undefined === query[C6.PAGINATION]) {
701
- query[C6.PAGINATION] = {};
937
+ if (false === returnGetNextPageFunction) {
938
+ responseData.next = apiRequest;
939
+ }
940
+ else {
941
+ responseData.next = undefined;
942
+ if (true === debug
943
+ && isLocal()) {
944
+ toast.success("DEVS: Response returned length (" + responseData.rest?.length + ") less than limit (" + query?.[C6.PAGINATION]?.[C6.LIMIT] + ").", toastOptionsDevs);
702
945
  }
703
- query[C6.PAGINATION][C6.PAGE] = query[C6.PAGINATION][C6.PAGE] || 1;
704
- query[C6.PAGINATION][C6.LIMIT] = query[C6.PAGINATION][C6.LIMIT] || 100;
705
946
  }
706
- apiRequest = function () { return __awaiter(_this, void 0, void 0, function () {
707
- var _a, debug, _b, cacheResults, dataInsertMultipleRows, success, _c, fetchDependencies, _d, error, querySerialized, cacheResult, cachingConfirmed, cacheCheck, cacheCheck, addBackPK, apiResponse, returnGetNextPageFunction, restRequestUri, needsConditionOrPrimaryCheck, TABLES, primaryKey, removedPkValue_1, axiosActiveRequest;
708
- var _e;
709
- var _this = this;
710
- var _f, _g, _h, _j, _k, _l;
711
- return __generator(this, function (_m) {
712
- switch (_m.label) {
713
- case 0:
714
- _a = this.request, debug = _a.debug, _b = _a.cacheResults, cacheResults = _b === void 0 ? (C6.GET === requestMethod) : _b, dataInsertMultipleRows = _a.dataInsertMultipleRows, success = _a.success, _c = _a.fetchDependencies, fetchDependencies = _c === void 0 ? eFetchDependencies.NONE : _c, _d = _a.error, error = _d === void 0 ? "An unexpected API error occurred!" : _d;
715
- if (C6.GET === requestMethod
716
- && undefined !== ((_f = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _f === void 0 ? void 0 : _f[C6.PAGE])
717
- && 1 !== query[C6.PAGINATION][C6.PAGE]) {
718
- console.groupCollapsed('Request on table (' + tableName + ') is firing for page (' + query[C6.PAGINATION][C6.PAGE] + '), please wait!');
719
- console.log('Request Data (note you may see the success and/or error prompt):', this.request);
720
- console.trace();
721
- console.groupEnd();
722
- }
723
- querySerialized = sortAndSerializeQueryObject(tables, query !== null && query !== void 0 ? query : {});
724
- cacheResult = apiRequestCache.find(function (cache) { return cache.requestArgumentsSerialized === querySerialized; });
725
- cachingConfirmed = false;
726
- if (!(requestMethod === C6.GET)) return [3 /*break*/, 9];
727
- if (undefined === (query === null || query === void 0 ? void 0 : query[C6.PAGINATION])) {
728
- if (undefined === query || null === query) {
729
- query = {};
730
- }
731
- query[C6.PAGINATION] = {};
732
- }
733
- query[C6.PAGINATION][C6.PAGE] = query[C6.PAGINATION][C6.PAGE] || 1;
734
- query[C6.PAGINATION][C6.LIMIT] = query[C6.PAGINATION][C6.LIMIT] || 100;
735
- if (!(true === cacheResults)) return [3 /*break*/, 7];
736
- if (!(undefined !== cacheResult)) return [3 /*break*/, 6];
737
- _m.label = 1;
738
- case 1:
739
- cacheCheck = checkCache(cacheResult, requestMethod, tableName, this.request);
740
- if (!(false !== cacheCheck)) return [3 /*break*/, 3];
741
- return [4 /*yield*/, cacheCheck];
742
- case 2: return [2 /*return*/, (_m.sent()).data];
743
- case 3:
744
- // this line incrementing page is why we return recursively
745
- ++query[C6.PAGINATION][C6.PAGE];
746
- // this json stringify is to capture the new page number
747
- querySerialized = sortAndSerializeQueryObject(tables, query !== null && query !== void 0 ? query : {});
748
- cacheResult = apiRequestCache.find(function (cache) { return cache.requestArgumentsSerialized === querySerialized; });
749
- _m.label = 4;
750
- case 4:
751
- if (undefined !== cacheResult) return [3 /*break*/, 1];
752
- _m.label = 5;
753
- case 5:
754
- if (debug && isLocal()) {
755
- toast.warning("DEVS: Request in cache. (" + apiRequestCache.findIndex(function (cache) { return cache.requestArgumentsSerialized === querySerialized; }) + "). Returning function to request page (" + query[C6.PAGINATION][C6.PAGE] + ")", toastOptionsDevs);
756
- }
757
- // @ts-ignore - this is an incorrect warning on TS, it's well typed
758
- return [2 /*return*/, apiRequest];
759
- case 6:
760
- cachingConfirmed = true;
761
- return [3 /*break*/, 8];
762
- case 7:
763
- if (debug && isLocal()) {
764
- toast.info("DEVS: Ignore cache was set to true.", toastOptionsDevs);
765
- }
766
- _m.label = 8;
767
- case 8:
768
- if (debug && isLocal()) {
769
- toast.success("DEVS: Request not in cache." + (requestMethod === C6.GET ? "Page (" + query[C6.PAGINATION][C6.PAGE] + ")." : '') + " Logging cache 2 console.", toastOptionsDevs);
770
- }
771
- return [3 /*break*/, 12];
772
- case 9:
773
- if (!cacheResults) return [3 /*break*/, 12];
774
- if (!cacheResult) return [3 /*break*/, 11];
775
- cacheCheck = checkCache(cacheResult, requestMethod, tableName, this.request);
776
- if (!(false !== cacheCheck)) return [3 /*break*/, 11];
777
- return [4 /*yield*/, cacheCheck];
778
- case 10: return [2 /*return*/, (_m.sent()).data];
779
- case 11:
780
- cachingConfirmed = true;
781
- _m.label = 12;
782
- case 12:
783
- returnGetNextPageFunction = false;
784
- restRequestUri = restURL + operatingTable + '/';
785
- needsConditionOrPrimaryCheck = (PUT === requestMethod || DELETE === requestMethod)
786
- && false === skipPrimaryCheck;
787
- TABLES = C6.TABLES;
788
- primaryKey = (_k = (_j = (_h = structuredClone((_g = TABLES[operatingTable]) === null || _g === void 0 ? void 0 : _g.PRIMARY)) === null || _h === void 0 ? void 0 : _h.pop()) === null || _j === void 0 ? void 0 : _j.split('.')) === null || _k === void 0 ? void 0 : _k.pop();
789
- if (needsConditionOrPrimaryCheck) {
790
- if (undefined === primaryKey) {
791
- if (null === query
792
- || undefined === query
793
- || undefined === (query === null || query === void 0 ? void 0 : query[C6.WHERE])
794
- || (true === Array.isArray(query[C6.WHERE])
795
- || query[C6.WHERE].length === 0)
796
- || (Object.keys(query === null || query === void 0 ? void 0 : query[C6.WHERE]).length === 0)) {
797
- console.error(query);
798
- throw Error('Failed to parse primary key information. Query: (' + JSON.stringify(query) + ') Primary Key: (' + JSON.stringify(primaryKey) + ') TABLES[operatingTable]?.PRIMARY: (' + JSON.stringify((_l = TABLES[operatingTable]) === null || _l === void 0 ? void 0 : _l.PRIMARY) + ') for operatingTable (' + operatingTable + ').');
799
- }
800
- }
801
- else {
802
- if (undefined === query
803
- || null === query
804
- || false === primaryKey in query) {
805
- if (true === debug && isLocal()) {
806
- toast.error('DEVS: The primary key (' + primaryKey + ') was not provided!!');
807
- }
808
- throw Error('You must provide the primary key (' + primaryKey + ') for table (' + operatingTable + '). Request (' + JSON.stringify(this.request, undefined, 4) + ') Query (' + JSON.stringify(query) + ')');
809
- }
810
- if (undefined === (query === null || query === void 0 ? void 0 : query[primaryKey])
811
- || null === (query === null || query === void 0 ? void 0 : query[primaryKey])) {
812
- toast.error('The primary key (' + primaryKey + ') provided is undefined or null explicitly!!');
813
- throw Error('The primary key (' + primaryKey + ') provided in the request was exactly equal to undefined.');
947
+ if (fetchDependencies
948
+ && 'number' === typeof fetchDependencies
949
+ && responseData.rest.length > 0) {
950
+ console.groupCollapsed('%c API: Fetch Dependencies segment (' + requestMethod + ' ' + tableName + ')'
951
+ + (fetchDependencies & eFetchDependencies.CHILDREN ? ' | (CHILDREN|REFERENCED) ' : '')
952
+ + (fetchDependencies & eFetchDependencies.PARENTS ? ' | (PARENTS|REFERENCED_BY)' : '')
953
+ + (fetchDependencies & eFetchDependencies.C6ENTITY ? ' | (C6ENTITY)' : '')
954
+ + (fetchDependencies & eFetchDependencies.RECURSIVE ? ' | (RECURSIVE)' : ''), 'color: #33ccff');
955
+ console.groupCollapsed('Collapsed JS Trace');
956
+ console.trace(); // hidden in collapsed group
957
+ console.groupEnd();
958
+ // noinspection JSBitwiseOperatorUsage
959
+ let dependencies = {};
960
+ // Remember this is a binary bitwise operation, so we can check for multiple dependencies at once
961
+ if (fetchDependencies & eFetchDependencies.C6ENTITY) {
962
+ dependencies = operatingTable.endsWith("carbon_carbons")
963
+ ? {
964
+ // the context of the entity system is a bit different
965
+ ...fetchDependencies & eFetchDependencies.CHILDREN // REFERENCED === CHILDREN
966
+ ? C6.TABLES[operatingTable].TABLE_REFERENCED_BY
967
+ : {},
968
+ ...fetchDependencies & eFetchDependencies.PARENTS // REFERENCES === PARENTS
969
+ ? C6.TABLES[operatingTable].TABLE_REFERENCES
970
+ : {}
971
+ } : {
972
+ // the context of the entity system is a bit different
973
+ ...fetchDependencies & eFetchDependencies.CHILDREN // REFERENCED === CHILDREN
974
+ ? {
975
+ ...Object.keys(C6.TABLES[operatingTable].TABLE_REFERENCES).reduce((accumulator, columnName) => {
976
+ if (!C6.TABLES[operatingTable].PRIMARY_SHORT.includes(columnName)) {
977
+ accumulator[columnName] = C6.TABLES[operatingTable].TABLE_REFERENCES[columnName];
814
978
  }
815
- }
816
- }
817
- // A part of me exists that wants to remove this, but it's a good feature
818
- // this allows developers the ability to cache requests based on primary key
819
- // for tables like `photos` this can be a huge performance boost
820
- if (undefined !== query
821
- && null !== query
822
- && undefined !== primaryKey
823
- && primaryKey in query) {
824
- restRequestUri += query[primaryKey] + '/';
825
- removedPkValue_1 = query[primaryKey];
826
- addBackPK = function () {
827
- query !== null && query !== void 0 ? query : (query = {});
828
- query[primaryKey] = removedPkValue_1;
829
- };
830
- delete query[primaryKey];
831
- console.log('query', query, 'primaryKey', primaryKey, 'removedPkValue', removedPkValue_1);
832
- }
833
- else {
834
- console.log('query', query);
979
+ return accumulator;
980
+ }, {}),
981
+ ...C6.TABLES[operatingTable].TABLE_REFERENCED_BY // it is unlikely that a C6 table will have any TABLE_REFERENCED_BY
835
982
  }
836
- try {
837
- console.groupCollapsed('%c API: (' + requestMethod + ') Request Query for (' + operatingTable + ') is about to fire, will return with promise!', 'color: #A020F0');
838
- console.log(this.request);
839
- console.log('%c If this is the first request for this datatype; thus the value being set is currently undefined, please remember to update the state to null.', 'color: #A020F0');
840
- console.log('%c Remember undefined indicated the request has not fired, null indicates the request is firing, an empty array would signal no data was returned for the sql stmt.', 'color: #A020F0');
841
- console.trace();
842
- console.groupEnd();
843
- this.runLifecycleHooks("beforeExecution", {
844
- config: this.config,
845
- request: this.request
846
- });
847
- axiosActiveRequest = (_e = axios)[requestMethod.toLowerCase()].apply(_e, __spreadArray([restRequestUri], (function () {
848
- var convert = function (data) {
849
- return convertForRequestBody(data, fullTableList, C6, function (message) { return toast.error(message, toastOptions); });
850
- };
851
- var baseConfig = {
852
- withCredentials: withCredentials,
853
- };
854
- switch (requestMethod) {
855
- case GET:
856
- return [__assign(__assign({}, baseConfig), { params: query })];
857
- case POST:
858
- if (dataInsertMultipleRows !== undefined) {
859
- return [
860
- dataInsertMultipleRows.map(convert),
861
- baseConfig
862
- ];
863
- }
864
- return [convert(query), baseConfig];
865
- case PUT:
866
- return [convert(query), baseConfig];
867
- case DELETE:
868
- return [__assign(__assign({}, baseConfig), { data: convert(query) })];
869
- default:
870
- throw new Error("The request method (".concat(requestMethod, ") was not recognized."));
871
- }
872
- })(), false));
873
- if (cachingConfirmed) {
874
- // push to cache so we do not repeat the request
875
- apiRequestCache.push({
876
- requestArgumentsSerialized: querySerialized,
877
- request: axiosActiveRequest
878
- });
983
+ : {},
984
+ ...fetchDependencies & eFetchDependencies.PARENTS // REFERENCES === PARENTS
985
+ ? C6.TABLES[operatingTable].PRIMARY_SHORT.reduce((accumulator, primaryKey) => {
986
+ if (primaryKey in C6.TABLES[operatingTable].TABLE_REFERENCES) {
987
+ accumulator[primaryKey] = C6.TABLES[operatingTable].TABLE_REFERENCES[primaryKey];
879
988
  }
880
- // todo - wip verify this works
881
- // we had removed the value from the request to add to the URI.
882
- addBackPK === null || addBackPK === void 0 ? void 0 : addBackPK(); // adding back so post-processing methods work
883
- // returning the promise with this then is important for tests. todo - we could make that optional.
884
- // https://rapidapi.com/guides/axios-async-await
885
- return [2 /*return*/, axiosActiveRequest.then(function (response) { return __awaiter(_this, void 0, void 0, function () {
886
- var cacheIndex, callback, responseData_1, dependencies_1, fetchReferences_1, apiRequestPromises, _loop_1, _a, _b, _c, _i, tableToFetch;
887
- var _this = this;
888
- var _d, _e, _f, _g, _h, _j;
889
- return __generator(this, function (_k) {
890
- switch (_k.label) {
891
- case 0:
892
- // noinspection SuspiciousTypeOfGuard
893
- if (typeof response.data === 'string') {
894
- if (isTest()) {
895
- console.trace();
896
- throw new Error('The response data was a string this typically indicated html was sent. Make sure all cookies (' + JSON.stringify(response.config.headers) + ') needed are present! (' + response.data + ')');
897
- }
898
- return [2 /*return*/, Promise.reject(response)];
899
- }
900
- if (cachingConfirmed) {
901
- cacheIndex = apiRequestCache.findIndex(function (cache) { return cache.requestArgumentsSerialized === querySerialized; });
902
- // TODO - currently nonthing is setting this correctly
903
- apiRequestCache[cacheIndex].final = false === returnGetNextPageFunction;
904
- // only cache get method requests
905
- apiRequestCache[cacheIndex].response = response;
906
- }
907
- this.runLifecycleHooks("afterExecution", {
908
- config: this.config,
909
- request: this.request,
910
- response: response
911
- });
912
- // todo - this feels dumb now, but i digress
913
- apiResponse = TestRestfulResponse(response, success, error);
914
- if (false === apiResponse) {
915
- if (debug && isLocal()) {
916
- toast.warning("DEVS: TestRestfulResponse returned false for (" + operatingTable + ").", toastOptionsDevs);
917
- }
918
- return [2 /*return*/, response];
919
- }
920
- callback = function () { return _this.runLifecycleHooks("afterCommit", {
921
- config: _this.config,
922
- request: _this.request,
923
- response: response
924
- }); };
925
- if (undefined !== reactBootstrap && response) {
926
- switch (requestMethod) {
927
- case GET:
928
- response.data && reactBootstrap.updateRestfulObjectArrays({
929
- dataOrCallback: Array.isArray(response.data.rest) ? response.data.rest : [response.data.rest],
930
- stateKey: this.config.restModel.TABLE_NAME,
931
- uniqueObjectId: this.config.restModel.PRIMARY_SHORT,
932
- callback: callback
933
- });
934
- break;
935
- case POST:
936
- this.postState(response, this.request, callback);
937
- break;
938
- case PUT:
939
- this.putState(response, this.request, callback);
940
- break;
941
- case DELETE:
942
- this.deleteState(response, this.request, callback);
943
- break;
944
- }
945
- }
946
- else {
947
- callback();
948
- }
949
- if (!(C6.GET === requestMethod)) return [3 /*break*/, 6];
950
- responseData_1 = response.data;
951
- returnGetNextPageFunction = 1 !== ((_d = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _d === void 0 ? void 0 : _d[C6.LIMIT]) &&
952
- ((_e = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _e === void 0 ? void 0 : _e[C6.LIMIT]) === responseData_1.rest.length;
953
- if (false === isTest() || this.config.verbose) {
954
- console.groupCollapsed('%c API: Response (' + requestMethod + ' ' + tableName + ') returned length (' + ((_f = responseData_1.rest) === null || _f === void 0 ? void 0 : _f.length) + ') of possible (' + ((_g = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _g === void 0 ? void 0 : _g[C6.LIMIT]) + ') limit!', 'color: #0c0');
955
- console.log('%c ' + requestMethod + ' ' + tableName, 'color: #0c0');
956
- console.log('%c Request Data (note you may see the success and/or error prompt):', 'color: #0c0', this.request);
957
- console.log('%c Response Data:', 'color: #0c0', responseData_1.rest);
958
- console.log('%c Will return get next page function:' + (returnGetNextPageFunction ? '' : ' (Will not return with explicit limit 1 set)'), 'color: #0c0', true === returnGetNextPageFunction);
959
- console.trace();
960
- console.groupEnd();
961
- }
962
- if (false === returnGetNextPageFunction) {
963
- responseData_1.next = apiRequest;
964
- }
965
- else {
966
- responseData_1.next = undefined;
967
- if (true === debug
968
- && isLocal()) {
969
- toast.success("DEVS: Response returned length (" + ((_h = responseData_1.rest) === null || _h === void 0 ? void 0 : _h.length) + ") less than limit (" + ((_j = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _j === void 0 ? void 0 : _j[C6.LIMIT]) + ").", toastOptionsDevs);
970
- }
971
- }
972
- if (!(fetchDependencies
973
- && 'number' === typeof fetchDependencies
974
- && responseData_1.rest.length > 0)) return [3 /*break*/, 6];
975
- console.groupCollapsed('%c API: Fetch Dependencies segment (' + requestMethod + ' ' + tableName + ')'
976
- + (fetchDependencies & eFetchDependencies.CHILDREN ? ' | (CHILDREN|REFERENCED) ' : '')
977
- + (fetchDependencies & eFetchDependencies.PARENTS ? ' | (PARENTS|REFERENCED_BY)' : '')
978
- + (fetchDependencies & eFetchDependencies.C6ENTITY ? ' | (C6ENTITY)' : '')
979
- + (fetchDependencies & eFetchDependencies.RECURSIVE ? ' | (RECURSIVE)' : ''), 'color: #33ccff');
980
- console.groupCollapsed('Collapsed JS Trace');
981
- console.trace(); // hidden in collapsed group
982
- console.groupEnd();
983
- dependencies_1 = {};
984
- // Remember this is a binary bitwise operation, so we can check for multiple dependencies at once
985
- if (fetchDependencies & eFetchDependencies.C6ENTITY) {
986
- dependencies_1 = operatingTable.endsWith("carbon_carbons")
987
- ? __assign(__assign({}, fetchDependencies & eFetchDependencies.CHILDREN // REFERENCED === CHILDREN
988
- ? C6.TABLES[operatingTable].TABLE_REFERENCED_BY
989
- : {}), fetchDependencies & eFetchDependencies.PARENTS // REFERENCES === PARENTS
990
- ? C6.TABLES[operatingTable].TABLE_REFERENCES
991
- : {}) : __assign(__assign({}, fetchDependencies & eFetchDependencies.CHILDREN // REFERENCED === CHILDREN
992
- ? __assign(__assign({}, Object.keys(C6.TABLES[operatingTable].TABLE_REFERENCES).reduce(function (accumulator, columnName) {
993
- if (!C6.TABLES[operatingTable].PRIMARY_SHORT.includes(columnName)) {
994
- accumulator[columnName] = C6.TABLES[operatingTable].TABLE_REFERENCES[columnName];
995
- }
996
- return accumulator;
997
- }, {})), C6.TABLES[operatingTable].TABLE_REFERENCED_BY // it is unlikely that a C6 table will have any TABLE_REFERENCED_BY
998
- ) : {}), fetchDependencies & eFetchDependencies.PARENTS // REFERENCES === PARENTS
999
- ? C6.TABLES[operatingTable].PRIMARY_SHORT.reduce(function (accumulator, primaryKey) {
1000
- if (primaryKey in C6.TABLES[operatingTable].TABLE_REFERENCES) {
1001
- accumulator[primaryKey] = C6.TABLES[operatingTable].TABLE_REFERENCES[primaryKey];
1002
- }
1003
- return accumulator;
1004
- }, {})
1005
- : {});
1006
- }
1007
- else {
1008
- // this is the natural mysql context
1009
- dependencies_1 = __assign(__assign({}, fetchDependencies & eFetchDependencies.REFERENCED // REFERENCED === CHILDREN
1010
- ? C6.TABLES[operatingTable].TABLE_REFERENCED_BY
1011
- : {}), fetchDependencies & eFetchDependencies.REFERENCES // REFERENCES === PARENTS
1012
- ? C6.TABLES[operatingTable].TABLE_REFERENCES
1013
- : {});
1014
- }
1015
- fetchReferences_1 = {};
1016
- apiRequestPromises = [];
1017
- console.log('%c Dependencies', 'color: #005555', dependencies_1);
1018
- Object.keys(dependencies_1)
1019
- .forEach(function (column) { return dependencies_1[column]
1020
- .forEach(function (constraint) {
1021
- var _a, _b, _c, _d;
1022
- var _e, _f, _g;
1023
- var columnValues = (_b = (_a = responseData_1.rest[column]) !== null && _a !== void 0 ? _a : responseData_1.rest.map(function (row) {
1024
- if (operatingTable.endsWith("carbons")
1025
- && 'entity_tag' in row
1026
- && !constraint.TABLE.endsWith(row['entity_tag'].split('\\').pop().toLowerCase())) {
1027
- return false; // map
1028
- }
1029
- if (!(column in row)) {
1030
- return false;
1031
- }
1032
- // todo - row[column] is a FK value, we should optionally remove values that are already in state
1033
- // this could be any column in the table constraint.TABLE, not just the primary key
1034
- return row[column];
1035
- }).filter(function (n) { return n; })) !== null && _b !== void 0 ? _b : [];
1036
- if (columnValues.length === 0) {
1037
- return; // forEach
1038
- }
1039
- (_c = fetchReferences_1[_e = constraint.TABLE]) !== null && _c !== void 0 ? _c : (fetchReferences_1[_e] = {});
1040
- (_d = (_f = fetchReferences_1[constraint.TABLE])[_g = constraint.COLUMN]) !== null && _d !== void 0 ? _d : (_f[_g] = []);
1041
- fetchReferences_1[constraint.TABLE][constraint.COLUMN].push(columnValues);
1042
- }); });
1043
- console.log('fetchReferences', fetchReferences_1);
1044
- _loop_1 = function (tableToFetch) {
1045
- var referencesTables, shouldContinue, fetchTable, RestApi, nextFetchDependencies;
1046
- var _l;
1047
- return __generator(this, function (_m) {
1048
- switch (_m.label) {
1049
- case 0:
1050
- if (fetchDependencies & eFetchDependencies.C6ENTITY
1051
- && 'string' === typeof tableName
1052
- && tableName.endsWith("carbon_carbons")) {
1053
- referencesTables = responseData_1.rest.reduce(function (accumulator, row) {
1054
- if ('entity_tag' in row && !accumulator.includes(row['entity_tag'])) {
1055
- accumulator.push(row['entity_tag']);
1056
- }
1057
- return accumulator;
1058
- }, []).map(function (entityTag) { return entityTag.split('\\').pop().toLowerCase(); });
1059
- shouldContinue = referencesTables.find(function (referencesTable) { return tableToFetch.endsWith(referencesTable); });
1060
- if (!shouldContinue) {
1061
- console.log('%c C6ENTITY: The constraintTableName (' + tableToFetch + ') did not end with any value in referencesTables', 'color: #c00', referencesTables);
1062
- return [2 /*return*/, "continue"];
1063
- }
1064
- console.log('%c C6ENTITY: The constraintTableName (' + tableToFetch + ') will be fetched.', 'color: #0c0');
1065
- }
1066
- return [4 /*yield*/, C6.IMPORT(tableToFetch)];
1067
- case 1:
1068
- fetchTable = _m.sent();
1069
- RestApi = fetchTable.default;
1070
- console.log('%c Fetch Dependencies will select (' + tableToFetch + ') using GET request', 'color: #33ccff');
1071
- nextFetchDependencies = eFetchDependencies.NONE;
1072
- if (fetchDependencies & eFetchDependencies.RECURSIVE) {
1073
- if (fetchDependencies & eFetchDependencies.ALL) {
1074
- throw Error('Recursive fetch dependencies with both PARENT and CHILD reference will result in an infin1ite loop. As there is not real ending condition, this is not supported.');
1075
- }
1076
- nextFetchDependencies = fetchDependencies;
1077
- }
1078
- else if (fetchDependencies & eFetchDependencies.C6ENTITY) {
1079
- if (tableToFetch === "carbon_carbons") {
1080
- nextFetchDependencies = fetchDependencies;
1081
- }
1082
- else {
1083
- nextFetchDependencies = fetchDependencies ^ eFetchDependencies.C6ENTITY;
1084
- }
1085
- }
1086
- console.log('fetchReferences', fetchReferences_1[tableToFetch], "Current fetchDependencies for (" + operatingTable + "):", fetchDependencies, "New fetchDependencies for (" + tableToFetch + "): ", nextFetchDependencies);
1087
- // todo - filter out ids that exist in state?!? note - remember that this does not necessarily mean the pk, but only known is its an FK to somewhere
1088
- // it not certain that they are using carbons' entities either
1089
- // this is a dynamic call to the rest api, any generated table may resolve with (RestApi)
1090
- // todo - using value to avoid joins.... but. maybe this should be a parameterizable option -- think race conditions; its safer to join
1091
- apiRequestPromises.push(RestApi.Get((_l = {},
1092
- _l[C6.WHERE] = {
1093
- 0: Object.keys(fetchReferences_1[tableToFetch]).reduce(function (sum, column) {
1094
- fetchReferences_1[tableToFetch][column] = fetchReferences_1[tableToFetch][column].flat(Infinity);
1095
- if (0 === fetchReferences_1[tableToFetch][column].length) {
1096
- console.warn('The column (' + column + ') was not found in the response data. We will not fetch.', responseData_1);
1097
- return false;
1098
- }
1099
- sum[column] = fetchReferences_1[tableToFetch][column].length === 1
1100
- ? fetchReferences_1[tableToFetch][column][0]
1101
- : [
1102
- C6.IN, fetchReferences_1[tableToFetch][column]
1103
- ];
1104
- return sum;
1105
- }, {})
1106
- },
1107
- _l.fetchDependencies = nextFetchDependencies,
1108
- _l)));
1109
- return [2 /*return*/];
1110
- }
1111
- });
1112
- };
1113
- _a = fetchReferences_1;
1114
- _b = [];
1115
- for (_c in _a)
1116
- _b.push(_c);
1117
- _i = 0;
1118
- _k.label = 1;
1119
- case 1:
1120
- if (!(_i < _b.length)) return [3 /*break*/, 4];
1121
- _c = _b[_i];
1122
- if (!(_c in _a)) return [3 /*break*/, 3];
1123
- tableToFetch = _c;
1124
- return [5 /*yield**/, _loop_1(tableToFetch)];
1125
- case 2:
1126
- _k.sent();
1127
- _k.label = 3;
1128
- case 3:
1129
- _i++;
1130
- return [3 /*break*/, 1];
1131
- case 4:
1132
- console.groupEnd();
1133
- return [4 /*yield*/, Promise.all(apiRequestPromises)];
1134
- case 5:
1135
- _k.sent();
1136
- apiRequestPromises.map(function (promise) { return __awaiter(_this, void 0, void 0, function () {
1137
- var _a, _b;
1138
- return __generator(this, function (_c) {
1139
- switch (_c.label) {
1140
- case 0:
1141
- if (!Array.isArray(this.request.fetchDependencies)) {
1142
- // to reassign value we must ref the root
1143
- this.request.fetchDependencies = [];
1144
- }
1145
- _b = (_a = this.request.fetchDependencies).push;
1146
- return [4 /*yield*/, promise];
1147
- case 1:
1148
- _b.apply(_a, [_c.sent()]);
1149
- return [2 /*return*/];
1150
- }
1151
- });
1152
- }); });
1153
- _k.label = 6;
1154
- case 6:
1155
- if (debug && isLocal()) {
1156
- toast.success("DEVS: (" + requestMethod + ") request complete.", toastOptionsDevs);
1157
- }
1158
- // this is the literal axios return
1159
- return [2 /*return*/, response];
1160
- }
1161
- });
1162
- }); }).then(function (response) { return response.data; })]; // this escapes from axios context
989
+ return accumulator;
990
+ }, {})
991
+ : {}
992
+ };
993
+ }
994
+ else {
995
+ // this is the natural mysql context
996
+ dependencies = {
997
+ ...fetchDependencies & eFetchDependencies.REFERENCED // REFERENCED === CHILDREN
998
+ ? C6.TABLES[operatingTable].TABLE_REFERENCED_BY
999
+ : {},
1000
+ ...fetchDependencies & eFetchDependencies.REFERENCES // REFERENCES === PARENTS
1001
+ ? C6.TABLES[operatingTable].TABLE_REFERENCES
1002
+ : {}
1003
+ };
1004
+ }
1005
+ let fetchReferences = {};
1006
+ let apiRequestPromises = [];
1007
+ console.log('%c Dependencies', 'color: #005555', dependencies);
1008
+ Object.keys(dependencies)
1009
+ .forEach(column => dependencies[column]
1010
+ .forEach((constraint) => {
1011
+ const columnValues = responseData.rest[column] ?? responseData.rest.map((row) => {
1012
+ if (operatingTable.endsWith("carbons")
1013
+ && 'entity_tag' in row
1014
+ && !constraint.TABLE.endsWith(row['entity_tag'].split('\\').pop().toLowerCase())) {
1015
+ return false; // map
1016
+ }
1017
+ if (!(column in row)) {
1018
+ return false;
1019
+ }
1020
+ // todo - row[column] is a FK value, we should optionally remove values that are already in state
1021
+ // this could be any column in the table constraint.TABLE, not just the primary key
1022
+ return row[column];
1023
+ }).filter(n => n) ?? [];
1024
+ if (columnValues.length === 0) {
1025
+ return; // forEach
1026
+ }
1027
+ fetchReferences[constraint.TABLE] ??= {};
1028
+ fetchReferences[constraint.TABLE][constraint.COLUMN] ??= [];
1029
+ fetchReferences[constraint.TABLE][constraint.COLUMN].push(columnValues);
1030
+ }));
1031
+ console.log('fetchReferences', fetchReferences);
1032
+ for (const tableToFetch in fetchReferences) {
1033
+ if (fetchDependencies & eFetchDependencies.C6ENTITY
1034
+ && 'string' === typeof tableName
1035
+ && tableName.endsWith("carbon_carbons")) {
1036
+ // todo - rethink the table ref entity system - when tables are renamed? no hooks exist in mysql
1037
+ // since were already filtering on column, we can assume the first row constraint is the same as the rest
1038
+ const referencesTables = responseData.rest.reduce((accumulator, row) => {
1039
+ if ('entity_tag' in row && !accumulator.includes(row['entity_tag'])) {
1040
+ accumulator.push(row['entity_tag']);
1163
1041
  }
1164
- catch (throwableError) {
1165
- if (isTest()) {
1166
- throw new Error(JSON.stringify(throwableError));
1042
+ return accumulator;
1043
+ }, []).map((entityTag) => entityTag.split('\\').pop().toLowerCase());
1044
+ const shouldContinue = referencesTables.find((referencesTable) => tableToFetch.endsWith(referencesTable));
1045
+ if (!shouldContinue) {
1046
+ console.log('%c C6ENTITY: The constraintTableName (' + tableToFetch + ') did not end with any value in referencesTables', 'color: #c00', referencesTables);
1047
+ continue;
1048
+ }
1049
+ console.log('%c C6ENTITY: The constraintTableName (' + tableToFetch + ') will be fetched.', 'color: #0c0');
1050
+ }
1051
+ const fetchTable = await C6.IMPORT(tableToFetch);
1052
+ const RestApi = fetchTable.default;
1053
+ console.log('%c Fetch Dependencies will select (' + tableToFetch + ') using GET request', 'color: #33ccff');
1054
+ let nextFetchDependencies = eFetchDependencies.NONE;
1055
+ if (fetchDependencies & eFetchDependencies.RECURSIVE) {
1056
+ if (fetchDependencies & eFetchDependencies.ALL) {
1057
+ throw Error('Recursive fetch dependencies with both PARENT and CHILD reference will result in an infin1ite loop. As there is not real ending condition, this is not supported.');
1058
+ }
1059
+ nextFetchDependencies = fetchDependencies;
1060
+ }
1061
+ else if (fetchDependencies & eFetchDependencies.C6ENTITY) {
1062
+ if (tableToFetch === "carbon_carbons") {
1063
+ nextFetchDependencies = fetchDependencies;
1064
+ }
1065
+ else {
1066
+ nextFetchDependencies = fetchDependencies ^ eFetchDependencies.C6ENTITY;
1067
+ }
1068
+ }
1069
+ console.log('fetchReferences', fetchReferences[tableToFetch], "Current fetchDependencies for (" + operatingTable + "):", fetchDependencies, "New fetchDependencies for (" + tableToFetch + "): ", nextFetchDependencies);
1070
+ // todo - filter out ids that exist in state?!? note - remember that this does not necessarily mean the pk, but only known is its an FK to somewhere
1071
+ // it not certain that they are using carbons' entities either
1072
+ // this is a dynamic call to the rest api, any generated table may resolve with (RestApi)
1073
+ // todo - using value to avoid joins.... but. maybe this should be a parameterizable option -- think race conditions; its safer to join
1074
+ apiRequestPromises.push(RestApi.Get({
1075
+ [C6.WHERE]: {
1076
+ 0: Object.keys(fetchReferences[tableToFetch]).reduce((sum, column) => {
1077
+ fetchReferences[tableToFetch][column] = fetchReferences[tableToFetch][column].flat(Infinity);
1078
+ if (0 === fetchReferences[tableToFetch][column].length) {
1079
+ console.warn('The column (' + column + ') was not found in the response data. We will not fetch.', responseData);
1080
+ return false;
1167
1081
  }
1168
- console.groupCollapsed('%c API: An error occurred in the try catch block. returning null!', 'color: #ff0000');
1169
- console.log('%c ' + requestMethod + ' ' + tableName, 'color: #A020F0');
1170
- console.warn(throwableError);
1171
- console.trace();
1172
- console.groupEnd();
1173
- TestRestfulResponse(throwableError, success, error);
1174
- return [2 /*return*/, null];
1175
- }
1176
- return [2 /*return*/];
1082
+ sum[column] = fetchReferences[tableToFetch][column].length === 1
1083
+ ? fetchReferences[tableToFetch][column][0]
1084
+ : [
1085
+ C6.IN, fetchReferences[tableToFetch][column]
1086
+ ];
1087
+ return sum;
1088
+ }, {})
1089
+ },
1090
+ fetchDependencies: nextFetchDependencies
1091
+ }));
1092
+ }
1093
+ console.groupEnd();
1094
+ await Promise.all(apiRequestPromises);
1095
+ apiRequestPromises.map(async (promise) => {
1096
+ if (!Array.isArray(this.request.fetchDependencies)) {
1097
+ // to reassign value we must ref the root
1098
+ this.request.fetchDependencies = [];
1177
1099
  }
1100
+ this.request.fetchDependencies.push(await promise);
1178
1101
  });
1179
- }); };
1180
- return [4 /*yield*/, apiRequest()];
1181
- case 2: return [2 /*return*/, _b.sent()];
1102
+ }
1103
+ }
1104
+ if (debug && isLocal()) {
1105
+ toast.success("DEVS: (" + requestMethod + ") request complete.", toastOptionsDevs);
1106
+ }
1107
+ // this is the literal axios return
1108
+ return response;
1109
+ }).then(response => response.data); // this escapes from axios context
1110
+ }
1111
+ catch (throwableError) {
1112
+ if (isTest()) {
1113
+ throw new Error(JSON.stringify(throwableError));
1182
1114
  }
1183
- });
1184
- });
1185
- };
1186
- return HttpExecutor;
1187
- }(Executor));
1115
+ console.groupCollapsed('%c API: An error occurred in the try catch block. returning null!', 'color: #ff0000');
1116
+ console.log('%c ' + requestMethod + ' ' + tableName, 'color: #A020F0');
1117
+ console.warn(throwableError);
1118
+ console.trace();
1119
+ console.groupEnd();
1120
+ TestRestfulResponse(throwableError, success, error);
1121
+ return null;
1122
+ }
1123
+ };
1124
+ return await apiRequest();
1125
+ }
1126
+ }
1188
1127
 
1189
1128
  var HttpExecutor$1 = /*#__PURE__*/Object.freeze({
1190
1129
  __proto__: null,
@@ -1201,210 +1140,188 @@ function convertHexIfBinary(_col, val, columnDef) {
1201
1140
  return val;
1202
1141
  }
1203
1142
 
1204
- var AggregateBuilder = /** @class */ (function (_super) {
1205
- __extends(AggregateBuilder, _super);
1206
- function AggregateBuilder() {
1207
- return _super !== null && _super.apply(this, arguments) || this;
1208
- }
1209
- AggregateBuilder.prototype.buildAggregateField = function (field) {
1210
- var _this = this;
1143
+ class AggregateBuilder extends Executor {
1144
+ buildAggregateField(field) {
1211
1145
  if (typeof field === 'string') {
1212
1146
  return field;
1213
1147
  }
1214
1148
  if (!Array.isArray(field) || field.length === 0) {
1215
1149
  throw new Error('Invalid SELECT field entry');
1216
1150
  }
1217
- var fn = field[0], args = field.slice(1);
1218
- var alias;
1151
+ let [fn, ...args] = field;
1152
+ let alias;
1219
1153
  if (args.length >= 2 && String(args[args.length - 2]).toUpperCase() === 'AS') {
1220
1154
  alias = String(args.pop());
1221
1155
  args.pop();
1222
1156
  }
1223
- var F = String(fn).toUpperCase();
1224
- var argList = args.map(function (arg) {
1225
- return Array.isArray(arg) ? _this.buildAggregateField(arg) : arg;
1226
- }).join(', ');
1227
- var expr = "".concat(F, "(").concat(argList, ")");
1157
+ const F = String(fn).toUpperCase();
1158
+ const argList = args.map(arg => Array.isArray(arg) ? this.buildAggregateField(arg) : arg).join(', ');
1159
+ let expr = `${F}(${argList})`;
1228
1160
  if (alias) {
1229
- expr += " AS ".concat(alias);
1161
+ expr += ` AS ${alias}`;
1230
1162
  }
1231
- this.config.verbose && console.log("[SELECT] ".concat(expr));
1163
+ this.config.verbose && console.log(`[SELECT] ${expr}`);
1232
1164
  return expr;
1233
- };
1234
- return AggregateBuilder;
1235
- }(Executor));
1236
-
1237
- var ConditionBuilder = /** @class */ (function (_super) {
1238
- __extends(ConditionBuilder, _super);
1239
- function ConditionBuilder() {
1240
- var _this = _super !== null && _super.apply(this, arguments) || this;
1241
- _this.aliasMap = {};
1242
- _this.OPERATORS = new Set([
1243
- C6C.EQUAL, C6C.NOT_EQUAL, C6C.LESS_THAN, C6C.LESS_THAN_OR_EQUAL_TO,
1244
- C6C.GREATER_THAN, C6C.GREATER_THAN_OR_EQUAL_TO,
1245
- C6C.LIKE, C6C.NOT_LIKE,
1246
- C6C.IN, C6C.NOT_IN, 'NOT IN',
1247
- C6C.IS, C6C.IS_NOT,
1248
- C6C.BETWEEN, 'NOT BETWEEN',
1249
- C6C.MATCH_AGAINST,
1250
- C6C.ST_DISTANCE_SPHERE
1251
- ]);
1252
- return _this;
1253
1165
  }
1254
- ConditionBuilder.prototype.initAlias = function (baseTable, joins) {
1255
- var _a;
1256
- this.aliasMap = (_a = {}, _a[baseTable] = baseTable, _a);
1166
+ }
1167
+
1168
+ class ConditionBuilder extends AggregateBuilder {
1169
+ aliasMap = {};
1170
+ initAlias(baseTable, joins) {
1171
+ this.aliasMap = { [baseTable]: baseTable };
1257
1172
  if (!joins)
1258
1173
  return;
1259
- for (var joinType in joins) {
1260
- for (var raw in joins[joinType]) {
1261
- var _b = raw.split(' '), table = _b[0], alias = _b[1];
1174
+ for (const joinType in joins) {
1175
+ for (const raw in joins[joinType]) {
1176
+ const [table, alias] = raw.split(' ');
1262
1177
  this.aliasMap[alias || table] = table;
1263
1178
  }
1264
1179
  }
1265
- };
1266
- ConditionBuilder.prototype.isColumnRef = function (ref) {
1267
- var _a, _b;
1180
+ }
1181
+ isColumnRef(ref) {
1268
1182
  if (typeof ref !== 'string' || !ref.includes('.'))
1269
1183
  return false;
1270
- var _c = ref.split('.', 2), prefix = _c[0], column = _c[1];
1271
- var tableName = this.aliasMap[prefix] || prefix;
1272
- var table = (_b = (_a = this.config.C6) === null || _a === void 0 ? void 0 : _a.TABLES) === null || _b === void 0 ? void 0 : _b[tableName];
1184
+ const [prefix, column] = ref.split('.', 2);
1185
+ const tableName = this.aliasMap[prefix] || prefix;
1186
+ const table = this.config.C6?.TABLES?.[tableName];
1273
1187
  if (!table)
1274
1188
  return false;
1275
- var fullKey = "".concat(tableName, ".").concat(column);
1189
+ const fullKey = `${tableName}.${column}`;
1276
1190
  if (table.COLUMNS && (fullKey in table.COLUMNS))
1277
1191
  return true;
1278
1192
  if (table.COLUMNS && Object.values(table.COLUMNS).includes(ref))
1279
1193
  return true;
1280
- this.config.verbose && console.log("[COLUMN REF] ".concat(ref, " is not a valid column reference"));
1194
+ this.config.verbose && console.log(`[COLUMN REF] ${ref} is not a valid column reference`);
1281
1195
  return false;
1282
- };
1283
- ConditionBuilder.prototype.execute = function () {
1196
+ }
1197
+ execute() {
1284
1198
  throw new Error("Method not implemented.");
1285
- };
1286
- ConditionBuilder.prototype.validateOperator = function (op) {
1199
+ }
1200
+ OPERATORS = new Set([
1201
+ C6C.EQUAL, C6C.NOT_EQUAL, C6C.LESS_THAN, C6C.LESS_THAN_OR_EQUAL_TO,
1202
+ C6C.GREATER_THAN, C6C.GREATER_THAN_OR_EQUAL_TO,
1203
+ C6C.LIKE, C6C.NOT_LIKE,
1204
+ C6C.IN, C6C.NOT_IN, 'NOT IN',
1205
+ C6C.IS, C6C.IS_NOT,
1206
+ C6C.BETWEEN, 'NOT BETWEEN',
1207
+ C6C.MATCH_AGAINST,
1208
+ C6C.ST_DISTANCE_SPHERE
1209
+ ]);
1210
+ validateOperator(op) {
1287
1211
  if (!this.OPERATORS.has(op)) {
1288
- throw new Error("Invalid or unsupported SQL operator detected: '".concat(op, "'"));
1212
+ throw new Error(`Invalid or unsupported SQL operator detected: '${op}'`);
1289
1213
  }
1290
- };
1291
- ConditionBuilder.prototype.addParam = function (params, column, value) {
1292
- var _a, _b;
1293
- var columnDef = (_b = (_a = this.config.C6[column.split('.')[0]]) === null || _a === void 0 ? void 0 : _a.TYPE_VALIDATION) === null || _b === void 0 ? void 0 : _b[column];
1294
- var val = convertHexIfBinary(column, value, columnDef);
1214
+ }
1215
+ addParam(params, column, value) {
1216
+ const columnDef = this.config.C6[column.split('.')[0]]?.TYPE_VALIDATION?.[column];
1217
+ const val = convertHexIfBinary(column, value, columnDef);
1295
1218
  if (this.useNamedParams) {
1296
- var key = "param".concat(Object.keys(params).length);
1219
+ const key = `param${Object.keys(params).length}`;
1297
1220
  params[key] = val;
1298
- return ":".concat(key);
1221
+ return `:${key}`;
1299
1222
  }
1300
1223
  else {
1301
1224
  params.push(val);
1302
1225
  return '?';
1303
1226
  }
1304
- };
1305
- ConditionBuilder.prototype.buildBooleanJoinedConditions = function (set, andMode, params) {
1306
- var _this = this;
1307
- if (andMode === void 0) { andMode = true; }
1308
- if (params === void 0) { params = []; }
1309
- var booleanOperator = andMode ? 'AND' : 'OR';
1310
- var addCondition = function (column, op, value) {
1227
+ }
1228
+ buildBooleanJoinedConditions(set, andMode = true, params = []) {
1229
+ const booleanOperator = andMode ? 'AND' : 'OR';
1230
+ const addCondition = (column, op, value) => {
1311
1231
  // Support function-based expressions like [C6C.ST_DISTANCE_SPHERE, col1, col2]
1312
1232
  if (typeof column === 'string' &&
1313
- _this.OPERATORS.has(column) &&
1233
+ this.OPERATORS.has(column) &&
1314
1234
  Array.isArray(op)) {
1315
1235
  if (column === C6C.ST_DISTANCE_SPHERE) {
1316
- var col1 = op[0], col2 = op[1];
1317
- var threshold = Array.isArray(value) ? value[0] : value;
1318
- return "ST_Distance_Sphere(".concat(col1, ", ").concat(col2, ") < ").concat(_this.addParam(params, '', threshold));
1236
+ const [col1, col2] = op;
1237
+ const threshold = Array.isArray(value) ? value[0] : value;
1238
+ return `ST_Distance_Sphere(${col1}, ${col2}) < ${this.addParam(params, '', threshold)}`;
1319
1239
  }
1320
1240
  }
1321
- var leftIsCol = _this.isColumnRef(column);
1322
- var rightIsCol = typeof value === 'string' && _this.isColumnRef(value);
1241
+ const leftIsCol = this.isColumnRef(column);
1242
+ const rightIsCol = typeof value === 'string' && this.isColumnRef(value);
1323
1243
  if (!leftIsCol && !rightIsCol) {
1324
- throw new Error("Potential SQL injection detected: '".concat(column, " ").concat(op, " ").concat(value, "'"));
1244
+ throw new Error(`Potential SQL injection detected: '${column} ${op} ${value}'`);
1325
1245
  }
1326
- _this.validateOperator(op);
1246
+ this.validateOperator(op);
1327
1247
  if (op === C6C.MATCH_AGAINST && Array.isArray(value)) {
1328
- var search = value[0], mode = value[1];
1329
- var paramName = _this.useNamedParams ? "param".concat(Object.keys(params).length) : null;
1330
- if (_this.useNamedParams) {
1248
+ const [search, mode] = value;
1249
+ const paramName = this.useNamedParams ? `param${Object.keys(params).length}` : null;
1250
+ if (this.useNamedParams) {
1331
1251
  params[paramName] = search;
1332
1252
  }
1333
1253
  else {
1334
1254
  params.push(search);
1335
1255
  }
1336
- var againstClause = void 0;
1256
+ let againstClause;
1337
1257
  switch ((mode || '').toUpperCase()) {
1338
1258
  case 'BOOLEAN':
1339
- againstClause = _this.useNamedParams ? "AGAINST(:".concat(paramName, " IN BOOLEAN MODE)") : "AGAINST(? IN BOOLEAN MODE)";
1259
+ againstClause = this.useNamedParams ? `AGAINST(:${paramName} IN BOOLEAN MODE)` : `AGAINST(? IN BOOLEAN MODE)`;
1340
1260
  break;
1341
1261
  case 'WITH QUERY EXPANSION':
1342
- againstClause = _this.useNamedParams ? "AGAINST(:".concat(paramName, " WITH QUERY EXPANSION)") : "AGAINST(? WITH QUERY EXPANSION)";
1262
+ againstClause = this.useNamedParams ? `AGAINST(:${paramName} WITH QUERY EXPANSION)` : `AGAINST(? WITH QUERY EXPANSION)`;
1343
1263
  break;
1344
1264
  default: // NATURAL or undefined
1345
- againstClause = _this.useNamedParams ? "AGAINST(:".concat(paramName, ")") : "AGAINST(?)";
1265
+ againstClause = this.useNamedParams ? `AGAINST(:${paramName})` : `AGAINST(?)`;
1346
1266
  break;
1347
1267
  }
1348
1268
  if (!leftIsCol) {
1349
- throw new Error("MATCH_AGAINST requires a table reference as the left operand. Column '".concat(column, "' is not a valid table reference."));
1269
+ throw new Error(`MATCH_AGAINST requires a table reference as the left operand. Column '${column}' is not a valid table reference.`);
1350
1270
  }
1351
- var matchClause = "(MATCH(".concat(column, ") ").concat(againstClause, ")");
1352
- _this.config.verbose && console.log("[MATCH_AGAINST] ".concat(matchClause));
1271
+ const matchClause = `(MATCH(${column}) ${againstClause})`;
1272
+ this.config.verbose && console.log(`[MATCH_AGAINST] ${matchClause}`);
1353
1273
  return matchClause;
1354
1274
  }
1355
1275
  if ((op === C6C.IN || op === C6C.NOT_IN) && Array.isArray(value)) {
1356
- var placeholders = value.map(function (v) {
1357
- return _this.isColumnRef(v) ? v : _this.addParam(params, column, v);
1358
- }).join(', ');
1359
- var normalized = op.replace('_', ' ');
1276
+ const placeholders = value.map(v => this.isColumnRef(v) ? v : this.addParam(params, column, v)).join(', ');
1277
+ const normalized = op.replace('_', ' ');
1360
1278
  if (!leftIsCol) {
1361
- throw new Error("IN operator requires a table reference as the left operand. Column '".concat(column, "' is not a valid table reference."));
1279
+ throw new Error(`IN operator requires a table reference as the left operand. Column '${column}' is not a valid table reference.`);
1362
1280
  }
1363
- return "( ".concat(column, " ").concat(normalized, " (").concat(placeholders, ") )");
1281
+ return `( ${column} ${normalized} (${placeholders}) )`;
1364
1282
  }
1365
1283
  if (op === C6C.BETWEEN || op === 'NOT BETWEEN') {
1366
1284
  if (!Array.isArray(value) || value.length !== 2) {
1367
- throw new Error("BETWEEN operator requires an array of two values. Received: ".concat(JSON.stringify(value)));
1285
+ throw new Error(`BETWEEN operator requires an array of two values. Received: ${JSON.stringify(value)}`);
1368
1286
  }
1369
- var start = value[0], end = value[1];
1287
+ const [start, end] = value;
1370
1288
  if (!leftIsCol) {
1371
- throw new Error("BETWEEN operator requires a table reference as the left operand. Column '".concat(column, "' is not a valid table reference."));
1289
+ throw new Error(`BETWEEN operator requires a table reference as the left operand. Column '${column}' is not a valid table reference.`);
1372
1290
  }
1373
- return "(".concat(column, ") ").concat(op.replace('_', ' '), " ").concat(_this.addParam(params, column, start), " AND ").concat(_this.addParam(params, column, end));
1291
+ return `(${column}) ${op.replace('_', ' ')} ${this.addParam(params, column, start)} AND ${this.addParam(params, column, end)}`;
1374
1292
  }
1375
1293
  if (leftIsCol && rightIsCol) {
1376
- return "(".concat(column, ") ").concat(op, " ").concat(value);
1294
+ return `(${column}) ${op} ${value}`;
1377
1295
  }
1378
1296
  if (leftIsCol && !rightIsCol) {
1379
- return "(".concat(column, ") ").concat(op, " ").concat(_this.addParam(params, column, value));
1297
+ return `(${column}) ${op} ${this.addParam(params, column, value)}`;
1380
1298
  }
1381
1299
  if (rightIsCol) {
1382
- return "(".concat(_this.addParam(params, column, column), ") ").concat(op, " ").concat(value);
1300
+ return `(${this.addParam(params, column, column)}) ${op} ${value}`;
1383
1301
  }
1384
- throw new Error("Neither operand appears to be a table reference");
1302
+ throw new Error(`Neither operand appears to be a table reference`);
1385
1303
  };
1386
- var parts = [];
1387
- var buildFromObject = function (obj, mode) {
1388
- var subParts = [];
1389
- for (var _i = 0, _a = Object.entries(obj); _i < _a.length; _i++) {
1390
- var _b = _a[_i], k = _b[0], v = _b[1];
1304
+ const parts = [];
1305
+ const buildFromObject = (obj, mode) => {
1306
+ const subParts = [];
1307
+ for (const [k, v] of Object.entries(obj)) {
1391
1308
  // numeric keys represent nested OR groups
1392
1309
  if (!isNaN(Number(k))) {
1393
- var sub = _this.buildBooleanJoinedConditions(v, false, params);
1310
+ const sub = this.buildBooleanJoinedConditions(v, false, params);
1394
1311
  if (sub)
1395
1312
  subParts.push(sub);
1396
1313
  continue;
1397
1314
  }
1398
1315
  if (typeof v === 'object' && v !== null && Object.keys(v).length === 1) {
1399
- var _c = Object.entries(v)[0], op = _c[0], val = _c[1];
1316
+ const [op, val] = Object.entries(v)[0];
1400
1317
  subParts.push(addCondition(k, op, val));
1401
1318
  }
1402
1319
  else if (Array.isArray(v) && v.length >= 2 && typeof v[0] === 'string') {
1403
- var _d = v, op = _d[0], val = _d[1];
1320
+ const [op, val] = v;
1404
1321
  subParts.push(addCondition(k, op, val));
1405
1322
  }
1406
1323
  else if (typeof v === 'object' && v !== null) {
1407
- var sub = _this.buildBooleanJoinedConditions(v, mode, params);
1324
+ const sub = this.buildBooleanJoinedConditions(v, mode, params);
1408
1325
  if (sub)
1409
1326
  subParts.push(sub);
1410
1327
  }
@@ -1412,124 +1329,105 @@ var ConditionBuilder = /** @class */ (function (_super) {
1412
1329
  subParts.push(addCondition(k, '=', v));
1413
1330
  }
1414
1331
  }
1415
- return subParts.join(" ".concat(mode ? 'AND' : 'OR', " "));
1332
+ return subParts.join(` ${mode ? 'AND' : 'OR'} `);
1416
1333
  };
1417
1334
  if (Array.isArray(set)) {
1418
- for (var _i = 0, set_1 = set; _i < set_1.length; _i++) {
1419
- var item = set_1[_i];
1420
- var sub = this.buildBooleanJoinedConditions(item, false, params);
1335
+ for (const item of set) {
1336
+ const sub = this.buildBooleanJoinedConditions(item, false, params);
1421
1337
  if (sub)
1422
1338
  parts.push(sub);
1423
1339
  }
1424
1340
  }
1425
1341
  else if (typeof set === 'object' && set !== null) {
1426
- var sub = buildFromObject(set, andMode);
1342
+ const sub = buildFromObject(set, andMode);
1427
1343
  if (sub)
1428
1344
  parts.push(sub);
1429
1345
  }
1430
- var clause = parts.join(" ".concat(booleanOperator, " "));
1431
- return clause ? "(".concat(clause, ")") : '';
1432
- };
1433
- ConditionBuilder.prototype.buildWhereClause = function (whereArg, params) {
1434
- var clause = this.buildBooleanJoinedConditions(whereArg, true, params);
1346
+ const clause = parts.join(` ${booleanOperator} `);
1347
+ return clause ? `(${clause})` : '';
1348
+ }
1349
+ buildWhereClause(whereArg, params) {
1350
+ const clause = this.buildBooleanJoinedConditions(whereArg, true, params);
1435
1351
  if (!clause)
1436
1352
  return '';
1437
- var trimmed = clause.replace(/^\((.*)\)$/, '$1');
1438
- this.config.verbose && console.log("[WHERE] ".concat(trimmed));
1439
- return " WHERE ".concat(trimmed);
1440
- };
1441
- return ConditionBuilder;
1442
- }(AggregateBuilder));
1443
-
1444
- var JoinBuilder = /** @class */ (function (_super) {
1445
- __extends(JoinBuilder, _super);
1446
- function JoinBuilder() {
1447
- return _super !== null && _super.apply(this, arguments) || this;
1353
+ const trimmed = clause.replace(/^\((.*)\)$/, '$1');
1354
+ this.config.verbose && console.log(`[WHERE] ${trimmed}`);
1355
+ return ` WHERE ${trimmed}`;
1448
1356
  }
1449
- JoinBuilder.prototype.buildJoinClauses = function (joinArgs, params) {
1450
- var sql = '';
1451
- for (var joinType in joinArgs) {
1452
- var joinKind = joinType.replace('_', ' ').toUpperCase();
1453
- for (var raw in joinArgs[joinType]) {
1454
- var _a = raw.split(' '), table = _a[0], alias = _a[1];
1357
+ }
1358
+
1359
+ class JoinBuilder extends ConditionBuilder {
1360
+ buildJoinClauses(joinArgs, params) {
1361
+ let sql = '';
1362
+ for (const joinType in joinArgs) {
1363
+ const joinKind = joinType.replace('_', ' ').toUpperCase();
1364
+ for (const raw in joinArgs[joinType]) {
1365
+ const [table, alias] = raw.split(' ');
1455
1366
  this.aliasMap[alias || table] = table;
1456
- var onClause = this.buildBooleanJoinedConditions(joinArgs[joinType][raw], true, params);
1457
- var joinSql = alias ? "`".concat(table, "` AS `").concat(alias, "`") : "`".concat(table, "`");
1458
- sql += " ".concat(joinKind, " JOIN ").concat(joinSql, " ON ").concat(onClause);
1367
+ const onClause = this.buildBooleanJoinedConditions(joinArgs[joinType][raw], true, params);
1368
+ const joinSql = alias ? `\`${table}\` AS \`${alias}\`` : `\`${table}\``;
1369
+ sql += ` ${joinKind} JOIN ${joinSql} ON ${onClause}`;
1459
1370
  }
1460
1371
  }
1461
- this.config.verbose && console.log("[JOIN] ".concat(sql.trim()));
1372
+ this.config.verbose && console.log(`[JOIN] ${sql.trim()}`);
1462
1373
  return sql;
1463
- };
1464
- return JoinBuilder;
1465
- }(ConditionBuilder));
1466
-
1467
- var DeleteQueryBuilder = /** @class */ (function (_super) {
1468
- __extends(DeleteQueryBuilder, _super);
1469
- function DeleteQueryBuilder() {
1470
- return _super !== null && _super.apply(this, arguments) || this;
1471
1374
  }
1472
- DeleteQueryBuilder.prototype.build = function (table) {
1473
- var params = this.useNamedParams ? {} : [];
1375
+ }
1376
+
1377
+ class DeleteQueryBuilder extends JoinBuilder {
1378
+ build(table) {
1379
+ const params = this.useNamedParams ? {} : [];
1474
1380
  this.initAlias(table, this.request.JOIN);
1475
- var sql = "DELETE `".concat(table, "` FROM `").concat(table, "`");
1381
+ let sql = `DELETE \`${table}\` FROM \`${table}\``;
1476
1382
  if (this.request.JOIN) {
1477
1383
  sql += this.buildJoinClauses(this.request.JOIN, params);
1478
1384
  }
1479
1385
  if (this.request.WHERE) {
1480
1386
  sql += this.buildWhereClause(this.request.WHERE, params);
1481
1387
  }
1482
- return { sql: sql, params: params };
1483
- };
1484
- return DeleteQueryBuilder;
1485
- }(JoinBuilder));
1486
-
1487
- var PostQueryBuilder = /** @class */ (function (_super) {
1488
- __extends(PostQueryBuilder, _super);
1489
- function PostQueryBuilder() {
1490
- return _super !== null && _super.apply(this, arguments) || this;
1388
+ return { sql, params };
1491
1389
  }
1492
- PostQueryBuilder.prototype.trimTablePrefix = function (table, column) {
1390
+ }
1391
+
1392
+ class PostQueryBuilder extends ConditionBuilder {
1393
+ trimTablePrefix(table, column) {
1493
1394
  if (!column.includes('.'))
1494
1395
  return column;
1495
- var _a = column.split('.', 2), prefix = _a[0], col = _a[1];
1396
+ const [prefix, col] = column.split('.', 2);
1496
1397
  if (prefix !== table) {
1497
- throw new Error("Invalid prefixed column: '".concat(column, "'. Expected prefix '").concat(table, ".'"));
1398
+ throw new Error(`Invalid prefixed column: '${column}'. Expected prefix '${table}.'`);
1498
1399
  }
1499
1400
  return col;
1500
- };
1501
- PostQueryBuilder.prototype.build = function (table) {
1502
- var _this = this;
1503
- var verb = C6C.REPLACE in this.request ? C6C.REPLACE : C6C.INSERT;
1504
- var body = verb in this.request ? this.request[verb] : this.request;
1505
- var keys = Object.keys(body);
1506
- var params = [];
1507
- var placeholders = [];
1508
- for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
1509
- var key = keys_1[_i];
1510
- var value = body[key];
1511
- var placeholder = this.addParam(params, key, value);
1401
+ }
1402
+ build(table) {
1403
+ const verb = C6C.REPLACE in this.request ? C6C.REPLACE : C6C.INSERT;
1404
+ const body = verb in this.request ? this.request[verb] : this.request;
1405
+ const keys = Object.keys(body);
1406
+ const params = [];
1407
+ const placeholders = [];
1408
+ for (const key of keys) {
1409
+ const value = body[key];
1410
+ const placeholder = this.addParam(params, key, value);
1512
1411
  placeholders.push(placeholder);
1513
1412
  }
1514
- var sql = "".concat(verb, " INTO `").concat(table, "` (\n ").concat(keys.map(function (k) { return "`".concat(_this.trimTablePrefix(table, k), "`"); }).join(', '), "\n ) VALUES (\n ").concat(placeholders.join(', '), "\n )");
1413
+ let sql = `${verb} INTO \`${table}\` (
1414
+ ${keys.map(k => `\`${this.trimTablePrefix(table, k)}\``).join(', ')}
1415
+ ) VALUES (
1416
+ ${placeholders.join(', ')}
1417
+ )`;
1515
1418
  if (C6C.UPDATE in this.request) {
1516
- var updateData = this.request[C6C.UPDATE];
1419
+ const updateData = this.request[C6C.UPDATE];
1517
1420
  if (!Array.isArray(updateData)) {
1518
- throw new Error("Update data must be an array of keys to update, got: ".concat(JSON.stringify(updateData)));
1421
+ throw new Error(`Update data must be an array of keys to update, got: ${JSON.stringify(updateData)}`);
1519
1422
  }
1520
- var updateClause = updateData.map(function (k) { return "`".concat(k, "` = VALUES(`").concat(k, "`)"); }).join(', ');
1521
- sql += " ON DUPLICATE KEY UPDATE ".concat(updateClause);
1423
+ const updateClause = updateData.map(k => `\`${k}\` = VALUES(\`${k}\`)`).join(', ');
1424
+ sql += ` ON DUPLICATE KEY UPDATE ${updateClause}`;
1522
1425
  }
1523
- return { sql: sql, params: params };
1524
- };
1525
- return PostQueryBuilder;
1526
- }(ConditionBuilder));
1527
-
1528
- var PaginationBuilder = /** @class */ (function (_super) {
1529
- __extends(PaginationBuilder, _super);
1530
- function PaginationBuilder() {
1531
- return _super !== null && _super.apply(this, arguments) || this;
1426
+ return { sql, params };
1532
1427
  }
1428
+ }
1429
+
1430
+ class PaginationBuilder extends JoinBuilder {
1533
1431
  /**
1534
1432
  * MySQL ORDER/LIMIT/OFFSET generator.
1535
1433
  *
@@ -1543,60 +1441,49 @@ var PaginationBuilder = /** @class */ (function (_super) {
1543
1441
  * }
1544
1442
  * ```
1545
1443
  */
1546
- PaginationBuilder.prototype.buildPaginationClause = function (pagination) {
1547
- var _this = this;
1548
- var _a;
1549
- var sql = "";
1444
+ buildPaginationClause(pagination) {
1445
+ let sql = "";
1550
1446
  /* -------- ORDER BY -------- */
1551
- if (pagination === null || pagination === void 0 ? void 0 : pagination[C6Constants.ORDER]) {
1552
- var orderParts = [];
1553
- for (var _i = 0, _b = Object.entries(pagination[C6Constants.ORDER]); _i < _b.length; _i++) {
1554
- var _c = _b[_i], key = _c[0], val = _c[1];
1447
+ if (pagination?.[C6Constants.ORDER]) {
1448
+ const orderParts = [];
1449
+ for (const [key, val] of Object.entries(pagination[C6Constants.ORDER])) {
1555
1450
  // FUNCTION CALL: val is an array of args
1556
1451
  if (Array.isArray(val)) {
1557
- var args = val
1558
- .map(function (arg) { return Array.isArray(arg) ? _this.buildAggregateField(arg) : String(arg); })
1452
+ const args = val
1453
+ .map((arg) => Array.isArray(arg) ? this.buildAggregateField(arg) : String(arg))
1559
1454
  .join(", ");
1560
- orderParts.push("".concat(key, "(").concat(args, ")"));
1455
+ orderParts.push(`${key}(${args})`);
1561
1456
  }
1562
1457
  // SIMPLE COLUMN + DIR (ASC/DESC)
1563
1458
  else {
1564
- orderParts.push("".concat(key, " ").concat(String(val).toUpperCase()));
1459
+ orderParts.push(`${key} ${String(val).toUpperCase()}`);
1565
1460
  }
1566
1461
  }
1567
1462
  if (orderParts.length)
1568
- sql += " ORDER BY ".concat(orderParts.join(", "));
1463
+ sql += ` ORDER BY ${orderParts.join(", ")}`;
1569
1464
  }
1570
1465
  /* -------- LIMIT / OFFSET -------- */
1571
- if ((pagination === null || pagination === void 0 ? void 0 : pagination[C6Constants.LIMIT]) != null) {
1572
- var lim = parseInt(pagination[C6Constants.LIMIT], 10);
1573
- var page = parseInt((_a = pagination[C6Constants.PAGE]) !== null && _a !== void 0 ? _a : 1, 10);
1574
- var offset = (page - 1) * lim;
1575
- sql += " LIMIT ".concat(offset, ", ").concat(lim);
1466
+ if (pagination?.[C6Constants.LIMIT] != null) {
1467
+ const lim = parseInt(pagination[C6Constants.LIMIT], 10);
1468
+ const page = parseInt(pagination[C6Constants.PAGE] ?? 1, 10);
1469
+ const offset = (page - 1) * lim;
1470
+ sql += ` LIMIT ${offset}, ${lim}`;
1576
1471
  }
1577
- this.config.verbose && console.log("[PAGINATION] ".concat(sql.trim()));
1472
+ this.config.verbose && console.log(`[PAGINATION] ${sql.trim()}`);
1578
1473
  return sql;
1579
- };
1580
- return PaginationBuilder;
1581
- }(JoinBuilder));
1582
-
1583
- var SelectQueryBuilder = /** @class */ (function (_super) {
1584
- __extends(SelectQueryBuilder, _super);
1585
- function SelectQueryBuilder() {
1586
- return _super !== null && _super.apply(this, arguments) || this;
1587
1474
  }
1588
- SelectQueryBuilder.prototype.build = function (table, isSubSelect) {
1589
- var _this = this;
1590
- var _a;
1591
- if (isSubSelect === void 0) { isSubSelect = false; }
1592
- var args = this.request;
1475
+ }
1476
+
1477
+ class SelectQueryBuilder extends PaginationBuilder {
1478
+ build(table, isSubSelect = false) {
1479
+ const args = this.request;
1593
1480
  this.initAlias(table, args.JOIN);
1594
- var params = this.useNamedParams ? {} : [];
1595
- var selectList = (_a = args.SELECT) !== null && _a !== void 0 ? _a : ['*'];
1596
- var selectFields = selectList
1597
- .map(function (f) { return _this.buildAggregateField(f); })
1481
+ const params = this.useNamedParams ? {} : [];
1482
+ const selectList = args.SELECT ?? ['*'];
1483
+ const selectFields = selectList
1484
+ .map((f) => this.buildAggregateField(f))
1598
1485
  .join(', ');
1599
- var sql = "SELECT ".concat(selectFields, " FROM `").concat(table, "`");
1486
+ let sql = `SELECT ${selectFields} FROM \`${table}\``;
1600
1487
  if (args.JOIN) {
1601
1488
  sql += this.buildJoinClauses(args.JOIN, params);
1602
1489
  }
@@ -1604,227 +1491,165 @@ var SelectQueryBuilder = /** @class */ (function (_super) {
1604
1491
  sql += this.buildWhereClause(args.WHERE, params);
1605
1492
  }
1606
1493
  if (args.GROUP_BY) {
1607
- var groupBy = Array.isArray(args.GROUP_BY)
1494
+ const groupBy = Array.isArray(args.GROUP_BY)
1608
1495
  ? args.GROUP_BY.join(', ')
1609
1496
  : args.GROUP_BY;
1610
- sql += " GROUP BY ".concat(groupBy);
1497
+ sql += ` GROUP BY ${groupBy}`;
1611
1498
  }
1612
1499
  if (args.HAVING) {
1613
- sql += " HAVING ".concat(this.buildBooleanJoinedConditions(args.HAVING, true, params));
1500
+ sql += ` HAVING ${this.buildBooleanJoinedConditions(args.HAVING, true, params)}`;
1614
1501
  }
1615
1502
  if (args.PAGINATION) {
1616
1503
  sql += this.buildPaginationClause(args.PAGINATION);
1617
1504
  }
1618
1505
  else if (!isSubSelect) {
1619
- sql += " LIMIT 100";
1506
+ sql += ` LIMIT 100`;
1620
1507
  }
1621
- console.log("[SELECT] ".concat(sql.trim()));
1622
- return { sql: sql, params: params };
1623
- };
1624
- return SelectQueryBuilder;
1625
- }(PaginationBuilder));
1626
-
1627
- var UpdateQueryBuilder = /** @class */ (function (_super) {
1628
- __extends(UpdateQueryBuilder, _super);
1629
- function UpdateQueryBuilder() {
1630
- return _super !== null && _super.apply(this, arguments) || this;
1508
+ console.log(`[SELECT] ${sql.trim()}`);
1509
+ return { sql, params };
1631
1510
  }
1632
- UpdateQueryBuilder.prototype.build = function (table) {
1633
- var _this = this;
1634
- var args = this.request;
1635
- var params = this.useNamedParams ? {} : [];
1511
+ }
1512
+
1513
+ class UpdateQueryBuilder extends PaginationBuilder {
1514
+ build(table) {
1515
+ const args = this.request;
1516
+ const params = this.useNamedParams ? {} : [];
1636
1517
  this.initAlias(table, args.JOIN);
1637
- var sql = "UPDATE `".concat(table, "`");
1518
+ let sql = `UPDATE \`${table}\``;
1638
1519
  if (args.JOIN) {
1639
1520
  sql += this.buildJoinClauses(args.JOIN, params);
1640
1521
  }
1641
1522
  if (!(C6C.UPDATE in this.request)) {
1642
1523
  throw new Error("No update data provided in the request.");
1643
1524
  }
1644
- var setClauses = Object.entries(this.request[C6C.UPDATE]).map(function (_a) {
1645
- var col = _a[0], val = _a[1];
1646
- return _this.addParam(params, col, val);
1647
- });
1648
- sql += " SET ".concat(setClauses.join(', '));
1525
+ const setClauses = Object.entries(this.request[C6C.UPDATE]).map(([col, val]) => this.addParam(params, col, val));
1526
+ sql += ` SET ${setClauses.join(', ')}`;
1649
1527
  if (args.WHERE) {
1650
1528
  sql += this.buildWhereClause(args.WHERE, params);
1651
1529
  }
1652
1530
  if (args.PAGINATION) {
1653
1531
  sql += this.buildPaginationClause(args.PAGINATION);
1654
1532
  }
1655
- return { sql: sql, params: params };
1656
- };
1657
- return UpdateQueryBuilder;
1658
- }(PaginationBuilder));
1533
+ return { sql, params };
1534
+ }
1535
+ }
1659
1536
 
1660
- var SqlExecutor = /** @class */ (function (_super) {
1661
- __extends(SqlExecutor, _super);
1662
- function SqlExecutor() {
1663
- var _this = _super !== null && _super.apply(this, arguments) || this;
1664
- _this.serialize = function (row) { return Object.fromEntries(Object.entries(row).map(function (_a) {
1665
- var k = _a[0], v = _a[1];
1666
- return [k, Buffer$1.isBuffer(v) ? v.toString('hex').toUpperCase() : v];
1667
- })); };
1668
- return _this;
1537
+ class SqlExecutor extends Executor {
1538
+ async execute() {
1539
+ const { TABLE_NAME } = this.config.restModel;
1540
+ const method = this.config.requestMethod;
1541
+ this.config.verbose && console.log(`[SQL EXECUTOR] ▶️ Executing ${method} on table "${TABLE_NAME}"`);
1542
+ this.config.verbose && console.log(`[SQL EXECUTOR] 🧩 Request:`, JSON.stringify(this.request, undefined, 2));
1543
+ switch (method) {
1544
+ case 'GET': {
1545
+ const rest = await this.runQuery();
1546
+ return rest;
1547
+ }
1548
+ case 'POST': {
1549
+ const result = await this.runQuery();
1550
+ return result;
1551
+ }
1552
+ case 'PUT': {
1553
+ const result = await this.runQuery();
1554
+ return result;
1555
+ }
1556
+ case 'DELETE': {
1557
+ const result = await this.runQuery();
1558
+ return result;
1559
+ }
1560
+ default:
1561
+ throw new Error(`Unsupported request method: ${method}`);
1562
+ }
1669
1563
  }
1670
- SqlExecutor.prototype.execute = function () {
1671
- return __awaiter(this, void 0, void 0, function () {
1672
- var TABLE_NAME, method, _a, rest, result, result, result;
1673
- return __generator(this, function (_b) {
1674
- switch (_b.label) {
1675
- case 0:
1676
- TABLE_NAME = this.config.restModel.TABLE_NAME;
1677
- method = this.config.requestMethod;
1678
- this.config.verbose && console.log("[SQL EXECUTOR] \u25B6\uFE0F Executing ".concat(method, " on table \"").concat(TABLE_NAME, "\""));
1679
- this.config.verbose && console.log("[SQL EXECUTOR] \uD83E\uDDE9 Request:", JSON.stringify(this.request, undefined, 2));
1680
- _a = method;
1681
- switch (_a) {
1682
- case 'GET': return [3 /*break*/, 1];
1683
- case 'POST': return [3 /*break*/, 3];
1684
- case 'PUT': return [3 /*break*/, 5];
1685
- case 'DELETE': return [3 /*break*/, 7];
1686
- }
1687
- return [3 /*break*/, 9];
1688
- case 1: return [4 /*yield*/, this.runQuery()];
1689
- case 2:
1690
- rest = _b.sent();
1691
- return [2 /*return*/, rest];
1692
- case 3: return [4 /*yield*/, this.runQuery()];
1693
- case 4:
1694
- result = _b.sent();
1695
- return [2 /*return*/, result];
1696
- case 5: return [4 /*yield*/, this.runQuery()];
1697
- case 6:
1698
- result = _b.sent();
1699
- return [2 /*return*/, result];
1700
- case 7: return [4 /*yield*/, this.runQuery()];
1701
- case 8:
1702
- result = _b.sent();
1703
- return [2 /*return*/, result];
1704
- case 9: throw new Error("Unsupported request method: ".concat(method));
1705
- }
1706
- });
1707
- });
1708
- };
1709
- SqlExecutor.prototype.withConnection = function (cb) {
1710
- return __awaiter(this, void 0, void 0, function () {
1711
- var conn;
1712
- return __generator(this, function (_a) {
1713
- switch (_a.label) {
1714
- case 0:
1715
- console.log("[SQL EXECUTOR] \uD83D\uDCE1 Getting DB connection");
1716
- return [4 /*yield*/, this.config.mysqlPool.getConnection()];
1717
- case 1:
1718
- conn = _a.sent();
1719
- _a.label = 2;
1720
- case 2:
1721
- _a.trys.push([2, , 4, 5]);
1722
- this.config.verbose && console.log("[SQL EXECUTOR] \u2705 Connection acquired");
1723
- return [4 /*yield*/, cb(conn)];
1724
- case 3: return [2 /*return*/, _a.sent()];
1725
- case 4:
1726
- this.config.verbose && console.log("[SQL EXECUTOR] \uD83D\uDD0C Releasing DB connection");
1727
- conn.release();
1728
- return [7 /*endfinally*/];
1729
- case 5: return [2 /*return*/];
1730
- }
1731
- });
1732
- });
1733
- };
1734
- SqlExecutor.prototype.formatSQLWithParams = function (sql, params) {
1735
- var _this = this;
1564
+ async withConnection(cb) {
1565
+ console.log(`[SQL EXECUTOR] 📡 Getting DB connection`);
1566
+ const conn = await this.config.mysqlPool.getConnection();
1567
+ try {
1568
+ this.config.verbose && console.log(`[SQL EXECUTOR] ✅ Connection acquired`);
1569
+ return await cb(conn);
1570
+ }
1571
+ finally {
1572
+ this.config.verbose && console.log(`[SQL EXECUTOR] 🔌 Releasing DB connection`);
1573
+ conn.release();
1574
+ }
1575
+ }
1576
+ serialize = (row) => Object.fromEntries(Object.entries(row).map(([k, v]) => [k, Buffer$1.isBuffer(v) ? v.toString('hex').toUpperCase() : v]));
1577
+ formatSQLWithParams(sql, params) {
1736
1578
  if (Array.isArray(params)) {
1737
- var index_1 = 0;
1738
- return sql.replace(/\?/g, function () {
1739
- if (index_1 >= params.length)
1579
+ let index = 0;
1580
+ return sql.replace(/\?/g, () => {
1581
+ if (index >= params.length)
1740
1582
  return '?';
1741
- var val = params[index_1++];
1742
- return _this.formatValue(val);
1583
+ const val = params[index++];
1584
+ return this.formatValue(val);
1743
1585
  });
1744
1586
  }
1745
1587
  else {
1746
- return sql.replace(/:([a-zA-Z0-9_]+)/g, function (_, key) {
1747
- var val = params[key];
1748
- return _this.formatValue(val);
1588
+ return sql.replace(/:([a-zA-Z0-9_]+)/g, (_, key) => {
1589
+ const val = params[key];
1590
+ return this.formatValue(val);
1749
1591
  });
1750
1592
  }
1751
- };
1752
- SqlExecutor.prototype.formatValue = function (val) {
1593
+ }
1594
+ formatValue(val) {
1753
1595
  if (val === null || val === undefined)
1754
1596
  return 'NULL';
1755
1597
  if (Buffer$1.isBuffer(val))
1756
- return "UNHEX('".concat(val.toString('hex'), "')");
1598
+ return `UNHEX('${val.toString('hex')}')`;
1757
1599
  if (typeof val === 'string')
1758
- return "'".concat(val.replace(/'/g, "''"), "'");
1600
+ return `'${val.replace(/'/g, "''")}'`;
1759
1601
  if (typeof val === 'number')
1760
1602
  return val.toString();
1761
1603
  if (val instanceof Date)
1762
- return "'".concat(val.toISOString().slice(0, 19).replace('T', ' '), "'");
1763
- return "'".concat(JSON.stringify(val), "'");
1764
- };
1765
- SqlExecutor.prototype.runQuery = function () {
1766
- return __awaiter(this, void 0, void 0, function () {
1767
- var TABLE_NAME, method, builder, QueryResult, formatted, toUnnamed, _a, sql, values;
1768
- var _this = this;
1769
- return __generator(this, function (_b) {
1770
- switch (_b.label) {
1771
- case 0:
1772
- TABLE_NAME = this.config.restModel.TABLE_NAME;
1773
- method = this.config.requestMethod;
1774
- switch (method) {
1775
- case 'GET':
1776
- builder = new SelectQueryBuilder(this.config, this.request);
1777
- break;
1778
- case 'PUT':
1779
- builder = new UpdateQueryBuilder(this.config, this.request);
1780
- break;
1781
- case 'DELETE':
1782
- builder = new DeleteQueryBuilder(this.config, this.request);
1783
- break;
1784
- case 'POST':
1785
- builder = new PostQueryBuilder(this.config, this.request);
1786
- break;
1787
- default:
1788
- throw new Error("Unsupported query method: ".concat(method));
1789
- }
1790
- QueryResult = builder.build(TABLE_NAME);
1791
- this.config.verbose && console.log("[SQL EXECUTOR] \uD83E\uDDE0 Generated ".concat(method.toUpperCase(), " SQL:"), QueryResult);
1792
- formatted = this.formatSQLWithParams(QueryResult.sql, QueryResult.params);
1793
- this.config.verbose && console.log("[SQL EXECUTOR] \uD83E\uDDE0 Formatted ".concat(method.toUpperCase(), " SQL:"), formatted);
1794
- toUnnamed = namedPlaceholders();
1795
- _a = toUnnamed(QueryResult.sql, QueryResult.params), sql = _a[0], values = _a[1];
1796
- return [4 /*yield*/, this.withConnection(function (conn) { return __awaiter(_this, void 0, void 0, function () {
1797
- var result;
1798
- return __generator(this, function (_a) {
1799
- switch (_a.label) {
1800
- case 0: return [4 /*yield*/, conn.query(sql, values)];
1801
- case 1:
1802
- result = (_a.sent())[0];
1803
- if (method === 'GET') {
1804
- this.config.verbose && console.log("[SQL EXECUTOR] \uD83D\uDCE6 Rows fetched:", result);
1805
- return [2 /*return*/, {
1806
- rest: result.map(this.serialize),
1807
- sql: { sql: sql, values: values }
1808
- }];
1809
- }
1810
- else {
1811
- this.config.verbose && console.log("[SQL EXECUTOR] \u270F\uFE0F Rows affected:", result.affectedRows);
1812
- return [2 /*return*/, {
1813
- affected: result.affectedRows,
1814
- rest: [],
1815
- sql: { sql: sql, values: values }
1816
- }];
1817
- }
1818
- }
1819
- });
1820
- }); })];
1821
- case 1: return [2 /*return*/, _b.sent()];
1822
- }
1823
- });
1604
+ return `'${val.toISOString().slice(0, 19).replace('T', ' ')}'`;
1605
+ return `'${JSON.stringify(val)}'`;
1606
+ }
1607
+ async runQuery() {
1608
+ const { TABLE_NAME } = this.config.restModel;
1609
+ const method = this.config.requestMethod;
1610
+ let builder;
1611
+ switch (method) {
1612
+ case 'GET':
1613
+ builder = new SelectQueryBuilder(this.config, this.request);
1614
+ break;
1615
+ case 'PUT':
1616
+ builder = new UpdateQueryBuilder(this.config, this.request);
1617
+ break;
1618
+ case 'DELETE':
1619
+ builder = new DeleteQueryBuilder(this.config, this.request);
1620
+ break;
1621
+ case 'POST':
1622
+ builder = new PostQueryBuilder(this.config, this.request);
1623
+ break;
1624
+ default:
1625
+ throw new Error(`Unsupported query method: ${method}`);
1626
+ }
1627
+ const QueryResult = builder.build(TABLE_NAME);
1628
+ this.config.verbose && console.log(`[SQL EXECUTOR] 🧠 Generated ${method.toUpperCase()} SQL:`, QueryResult);
1629
+ const formatted = this.formatSQLWithParams(QueryResult.sql, QueryResult.params);
1630
+ this.config.verbose && console.log(`[SQL EXECUTOR] 🧠 Formatted ${method.toUpperCase()} SQL:`, formatted);
1631
+ const toUnnamed = namedPlaceholders();
1632
+ const [sql, values] = toUnnamed(QueryResult.sql, QueryResult.params);
1633
+ return await this.withConnection(async (conn) => {
1634
+ const [result] = await conn.query(sql, values);
1635
+ if (method === 'GET') {
1636
+ this.config.verbose && console.log(`[SQL EXECUTOR] 📦 Rows fetched:`, result);
1637
+ return {
1638
+ rest: result.map(this.serialize),
1639
+ sql: { sql, values }
1640
+ };
1641
+ }
1642
+ else {
1643
+ this.config.verbose && console.log(`[SQL EXECUTOR] ✏️ Rows affected:`, result.affectedRows);
1644
+ return {
1645
+ affected: result.affectedRows,
1646
+ rest: [],
1647
+ sql: { sql, values }
1648
+ };
1649
+ }
1824
1650
  });
1825
- };
1826
- return SqlExecutor;
1827
- }(Executor));
1651
+ }
1652
+ }
1828
1653
 
1829
1654
  var SqlExecutor$1 = /*#__PURE__*/Object.freeze({
1830
1655
  __proto__: null,
@@ -1833,101 +1658,80 @@ var SqlExecutor$1 = /*#__PURE__*/Object.freeze({
1833
1658
 
1834
1659
  // TODO - WE MUST make this a generic - optional, but helpful
1835
1660
  // note sure how it would help anyone actually...
1836
- function ExpressHandler(_a) {
1837
- var _this = this;
1838
- var C6 = _a.C6, mysqlPool = _a.mysqlPool;
1839
- return function (req, res, next) { return __awaiter(_this, void 0, void 0, function () {
1840
- var method, table, primary, payload, primaryKeys, primaryKeyName, response, err_1;
1841
- return __generator(this, function (_a) {
1842
- switch (_a.label) {
1843
- case 0:
1844
- _a.trys.push([0, 2, , 3]);
1845
- method = req.method.toUpperCase();
1846
- table = req.params.table;
1847
- primary = req.params.primary;
1848
- payload = method === 'GET' ? req.query : req.body;
1849
- if (!(table in C6.TABLES)) {
1850
- res.status(400).json({ error: "Invalid table: ".concat(table) });
1851
- return [2 /*return*/];
1661
+ function ExpressHandler({ C6, mysqlPool }) {
1662
+ return async (req, res, next) => {
1663
+ try {
1664
+ const method = req.method.toUpperCase();
1665
+ const table = req.params.table;
1666
+ const primary = req.params.primary;
1667
+ const payload = method === 'GET' ? req.query : req.body;
1668
+ if (!(table in C6.TABLES)) {
1669
+ res.status(400).json({ error: `Invalid table: ${table}` });
1670
+ return;
1671
+ }
1672
+ const primaryKeys = C6.TABLES[table].PRIMARY;
1673
+ if (primary && primaryKeys.length !== 1) {
1674
+ if (primaryKeys.length > 1) {
1675
+ res.status(400).json({ error: `Table ${table} has multiple primary keys. Cannot implicitly determine key.` });
1676
+ return;
1677
+ }
1678
+ res.status(400).json({
1679
+ error: `Table ${table} has no primary keys. Please specify one.`
1680
+ });
1681
+ return;
1682
+ }
1683
+ const primaryKeyName = primaryKeys[0];
1684
+ // 👇 Call restRequest for the resolved method
1685
+ // TODO - add primary conditionally based on method signature
1686
+ switch (method) {
1687
+ case 'GET':
1688
+ if (primary) {
1689
+ payload[C6C.WHERE][primaryKeyName] = primary;
1852
1690
  }
1853
- primaryKeys = C6.TABLES[table].PRIMARY;
1854
- if (primary && primaryKeys.length !== 1) {
1855
- if (primaryKeys.length > 1) {
1856
- res.status(400).json({ error: "Table ".concat(table, " has multiple primary keys. Cannot implicitly determine key.") });
1857
- return [2 /*return*/];
1858
- }
1859
- res.status(400).json({
1860
- error: "Table ".concat(table, " has no primary keys. Please specify one.")
1861
- });
1862
- return [2 /*return*/];
1691
+ break;
1692
+ case 'PUT':
1693
+ case 'DELETE':
1694
+ if (primary) {
1695
+ payload[C6C.WHERE][primaryKeyName] = primary;
1863
1696
  }
1864
- primaryKeyName = primaryKeys[0];
1865
- // 👇 Call restRequest for the resolved method
1866
- // TODO - add primary conditionally based on method signature
1867
- switch (method) {
1868
- case 'GET':
1869
- if (primary) {
1870
- payload[C6C.WHERE][primaryKeyName] = primary;
1871
- }
1872
- break;
1873
- case 'PUT':
1874
- case 'DELETE':
1875
- if (primary) {
1876
- payload[C6C.WHERE][primaryKeyName] = primary;
1877
- }
1878
- else {
1879
- res.status(400).json({ error: "Invalid request: ".concat(method, " requires a primary key.") });
1880
- }
1881
- break;
1882
- case 'POST':
1883
- break;
1884
- default:
1885
- res.status(405).json({ error: "Method ".concat(method, " not allowed") });
1886
- return [2 /*return*/];
1697
+ else {
1698
+ res.status(400).json({ error: `Invalid request: ${method} requires a primary key.` });
1887
1699
  }
1888
- return [4 /*yield*/, restRequest({
1889
- C6: C6,
1890
- mysqlPool: mysqlPool,
1891
- requestMethod: method,
1892
- restModel: C6.TABLES[table]
1893
- })(payload)];
1894
- case 1:
1895
- response = _a.sent();
1896
- res.status(200).json(__assign({ success: true }, response));
1897
- return [3 /*break*/, 3];
1898
- case 2:
1899
- err_1 = _a.sent();
1900
- res.status(500).json({ success: false, error: err_1 });
1901
- next(err_1);
1902
- return [3 /*break*/, 3];
1903
- case 3: return [2 /*return*/];
1700
+ break;
1701
+ case 'POST':
1702
+ break;
1703
+ default:
1704
+ res.status(405).json({ error: `Method ${method} not allowed` });
1705
+ return;
1904
1706
  }
1905
- });
1906
- }); };
1707
+ const response = await restRequest({
1708
+ C6,
1709
+ mysqlPool,
1710
+ requestMethod: method,
1711
+ restModel: C6.TABLES[table]
1712
+ })(payload);
1713
+ res.status(200).json({ success: true, ...response });
1714
+ }
1715
+ catch (err) {
1716
+ res.status(500).json({ success: false, error: err });
1717
+ next(err);
1718
+ }
1719
+ };
1907
1720
  }
1908
1721
 
1909
1722
  // Alias a table name with a given alias
1910
- var A = function (tableName, alias) {
1911
- return "".concat(tableName, " ").concat(alias);
1912
- };
1723
+ const A = (tableName, alias) => `${tableName} ${alias}`;
1913
1724
  // Qualify a column constant (e.g. 'property_units.parcel_id') to an alias
1914
- var F = function (qualifiedCol, alias) {
1915
- return "".concat(alias, ".").concat(qualifiedCol.split('.').pop());
1916
- };
1725
+ const F = (qualifiedCol, alias) => `${alias}.${qualifiedCol.split('.').pop()}`;
1917
1726
  // Equal join condition using full-qualified column constants
1918
- var fieldEq = function (leftCol, rightCol, leftAlias, rightAlias) {
1919
- var _a;
1920
- return (_a = {},
1921
- _a[F(leftCol, leftAlias)] = F(rightCol, rightAlias),
1922
- _a);
1923
- };
1727
+ const fieldEq = (leftCol, rightCol, leftAlias, rightAlias) => ({
1728
+ [F(leftCol, leftAlias)]: F(rightCol, rightAlias)
1729
+ });
1924
1730
  // ST_Distance_Sphere for aliased fields
1925
- var distSphere = function (fromCol, toCol, fromAlias, toAlias) {
1926
- return [C6C.ST_DISTANCE_SPHERE, F(fromCol, fromAlias), F(toCol, toAlias)];
1927
- };
1731
+ const distSphere = (fromCol, toCol, fromAlias, toAlias) => [C6C.ST_DISTANCE_SPHERE, F(fromCol, fromAlias), F(toCol, toAlias)];
1928
1732
 
1929
1733
  function determineRuntimeJsType(mysqlType) {
1930
- var base = mysqlType.toLowerCase().split('(')[0];
1734
+ const base = mysqlType.toLowerCase().split('(')[0];
1931
1735
  if ([
1932
1736
  'binary', 'varbinary', 'blob', 'tinyblob', 'mediumblob', 'longblob'
1933
1737
  ].includes(base))
@@ -1948,23 +1752,15 @@ function determineRuntimeJsType(mysqlType) {
1948
1752
  return 'string';
1949
1753
  }
1950
1754
  function getPrimaryKeyTypes(table) {
1951
- var _a;
1952
- var result = {};
1953
- var _loop_1 = function (key) {
1954
- var fullKey = (_a = Object.entries(table.COLUMNS).find(function (_a) {
1955
- _a[0]; var short = _a[1];
1956
- return short === key;
1957
- })) === null || _a === void 0 ? void 0 : _a[0];
1755
+ const result = {};
1756
+ for (const key of table.PRIMARY_SHORT) {
1757
+ const fullKey = Object.entries(table.COLUMNS).find(([_, short]) => short === key)?.[0];
1958
1758
  if (typeof fullKey === 'string') {
1959
- var validation = table.TYPE_VALIDATION[fullKey];
1759
+ const validation = table.TYPE_VALIDATION[fullKey];
1960
1760
  if (!validation)
1961
- return "continue";
1761
+ continue;
1962
1762
  result[key] = determineRuntimeJsType(validation.MYSQL_TYPE);
1963
1763
  }
1964
- };
1965
- for (var _i = 0, _b = table.PRIMARY_SHORT; _i < _b.length; _i++) {
1966
- var key = _b[_i];
1967
- _loop_1(key);
1968
1764
  }
1969
1765
  return result;
1970
1766
  }
@@ -1973,42 +1769,30 @@ function getPrimaryKeyTypes(table) {
1973
1769
  * Conditionally group a log if verbose.
1974
1770
  */
1975
1771
  function group(title, data) {
1976
- console.groupCollapsed("%c".concat(title), "color: #007acc");
1772
+ console.groupCollapsed(`%c${title}`, "color: #007acc");
1977
1773
  if (data !== undefined)
1978
1774
  console.log(data);
1979
1775
  console.groupEnd();
1980
1776
  }
1981
- function info(message) {
1982
- var optional = [];
1983
- for (var _i = 1; _i < arguments.length; _i++) {
1984
- optional[_i - 1] = arguments[_i];
1985
- }
1986
- console.info.apply(console, __spreadArray(["%cINFO: ".concat(message), "color: #0a0"], optional, false));
1777
+ function info(message, ...optional) {
1778
+ console.info(`%cINFO: ${message}`, "color: #0a0", ...optional);
1987
1779
  }
1988
- function warn(message) {
1989
- var optional = [];
1990
- for (var _i = 1; _i < arguments.length; _i++) {
1991
- optional[_i - 1] = arguments[_i];
1992
- }
1993
- console.warn.apply(console, __spreadArray(["%cWARN: ".concat(message), "color: #e90"], optional, false));
1780
+ function warn(message, ...optional) {
1781
+ console.warn(`%cWARN: ${message}`, "color: #e90", ...optional);
1994
1782
  }
1995
- function error(message) {
1996
- var optional = [];
1997
- for (var _i = 1; _i < arguments.length; _i++) {
1998
- optional[_i - 1] = arguments[_i];
1999
- }
2000
- console.error.apply(console, __spreadArray(["%cERROR: ".concat(message), "color: #c00"], optional, false));
1783
+ function error(message, ...optional) {
1784
+ console.error(`%cERROR: ${message}`, "color: #c00", ...optional);
2001
1785
  }
2002
1786
 
2003
1787
  function checkAllRequestsComplete() {
2004
- var stillRunning = apiRequestCache.filter(function (cache) { return undefined === cache.response; });
1788
+ const stillRunning = apiRequestCache.filter((cache) => undefined === cache.response);
2005
1789
  if (stillRunning.length !== 0) {
2006
1790
  if (document === null || document === undefined) {
2007
1791
  throw new Error('document is undefined while waiting for API requests to complete (' + JSON.stringify(apiRequestCache) + ')');
2008
1792
  }
2009
1793
  // when requests return emtpy sets in full renders, it may not be possible to track their progress.
2010
1794
  console.warn('stillRunning...', stillRunning);
2011
- return stillRunning.map(function (cache) { return cache.requestArgumentsSerialized; });
1795
+ return stillRunning.map((cache) => cache.requestArgumentsSerialized);
2012
1796
  }
2013
1797
  return true;
2014
1798
  }
@@ -2021,7 +1805,7 @@ function onError(message) {
2021
1805
  }
2022
1806
 
2023
1807
  function isVerbose () {
2024
- var envVerbose = getEnvVar('VERBOSE') || getEnvVar('REACT_APP_VERBOSE') || getEnvVar('VITE_VERBOSE') || '';
1808
+ const envVerbose = getEnvVar('VERBOSE') || getEnvVar('REACT_APP_VERBOSE') || getEnvVar('VITE_VERBOSE') || '';
2025
1809
  return ['true', '1', 'yes', 'on'].includes(envVerbose.toLowerCase());
2026
1810
  }
2027
1811