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