@carbonorm/carbonnode 3.5.7 → 3.5.9

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