@carbonorm/carbonnode 2.0.34 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/dist/api/builders/sqlBuilder.d.ts +3 -0
  2. package/dist/api/carbonSqlExecutor.d.ts +17 -0
  3. package/dist/api/convertForRequestBody.d.ts +1 -1
  4. package/dist/api/executors/Executor.d.ts +18 -0
  5. package/dist/api/executors/HttpExecutor.d.ts +15 -0
  6. package/dist/api/executors/SqlExecutor.d.ts +11 -0
  7. package/dist/api/interfaces/ormInterfaces.d.ts +22 -1
  8. package/dist/api/rest/Blog_Categories.d.ts +37 -0
  9. package/dist/api/rest/Blog_Categories.test.d.ts +11 -0
  10. package/dist/api/rest/Blog_Images.d.ts +37 -0
  11. package/dist/api/rest/Blog_Images.test.d.ts +15 -0
  12. package/dist/api/rest/Blog_Post_Categories.d.ts +37 -0
  13. package/dist/api/rest/Blog_Post_Categories.test.d.ts +13 -0
  14. package/dist/api/rest/Blog_Post_Tags.d.ts +37 -0
  15. package/dist/api/rest/Blog_Post_Tags.test.d.ts +13 -0
  16. package/dist/api/rest/Blog_Posts.d.ts +37 -0
  17. package/dist/api/rest/Blog_Posts.test.d.ts +21 -0
  18. package/dist/api/rest/Blog_Tags.d.ts +37 -0
  19. package/dist/api/rest/Blog_Tags.test.d.ts +11 -0
  20. package/dist/api/rest/C6.d.ts +1000 -0
  21. package/dist/api/rest/Cache.d.ts +37 -0
  22. package/dist/api/rest/Cache.test.d.ts +12 -0
  23. package/dist/api/rest/Cities.d.ts +37 -0
  24. package/dist/api/rest/Cities.test.d.ts +17 -0
  25. package/dist/api/rest/Counties.d.ts +37 -0
  26. package/dist/api/rest/Counties.test.d.ts +18 -0
  27. package/dist/api/rest/Countries.d.ts +37 -0
  28. package/dist/api/rest/Countries.test.d.ts +24 -0
  29. package/dist/api/rest/Geometries.d.ts +37 -0
  30. package/dist/api/rest/Geometries.test.d.ts +16 -0
  31. package/dist/api/rest/Images.d.ts +37 -0
  32. package/dist/api/rest/Images.test.d.ts +16 -0
  33. package/dist/api/rest/Land_Section_Info.d.ts +37 -0
  34. package/dist/api/rest/Land_Section_Info.test.d.ts +15 -0
  35. package/dist/api/rest/Neighborhoods.d.ts +37 -0
  36. package/dist/api/rest/Neighborhoods.test.d.ts +12 -0
  37. package/dist/api/rest/Parcel_Building_Details.d.ts +37 -0
  38. package/dist/api/rest/Parcel_Building_Details.test.d.ts +40 -0
  39. package/dist/api/rest/Parcel_Neighborhoods.d.ts +37 -0
  40. package/dist/api/rest/Parcel_Neighborhoods.test.d.ts +15 -0
  41. package/dist/api/rest/Parcel_Owners.d.ts +37 -0
  42. package/dist/api/rest/Parcel_Owners.test.d.ts +23 -0
  43. package/dist/api/rest/Parcel_Sales.d.ts +37 -0
  44. package/dist/api/rest/Parcel_Sales.test.d.ts +19 -0
  45. package/dist/api/rest/Parcel_Tax_History.d.ts +37 -0
  46. package/dist/api/rest/Parcel_Tax_History.test.d.ts +24 -0
  47. package/dist/api/rest/Parcels.d.ts +37 -0
  48. package/dist/api/rest/Parcels.test.d.ts +42 -0
  49. package/dist/api/rest/Payment_Charge_Logs.d.ts +37 -0
  50. package/dist/api/rest/Payment_Charge_Logs.test.d.ts +17 -0
  51. package/dist/api/rest/Payment_Subscriptions.d.ts +37 -0
  52. package/dist/api/rest/Payment_Subscriptions.test.d.ts +20 -0
  53. package/dist/api/rest/Property_Units.d.ts +37 -0
  54. package/dist/api/rest/Property_Units.test.d.ts +55 -0
  55. package/dist/api/rest/Sources.d.ts +37 -0
  56. package/dist/api/rest/Sources.test.d.ts +17 -0
  57. package/dist/api/rest/States.d.ts +37 -0
  58. package/dist/api/rest/States.test.d.ts +20 -0
  59. package/dist/api/rest/Tax_Districts.d.ts +37 -0
  60. package/dist/api/rest/Tax_Districts.test.d.ts +12 -0
  61. package/dist/api/rest/Users.d.ts +37 -0
  62. package/dist/api/rest/Users.test.d.ts +14 -0
  63. package/dist/api/rest/Valuation_Reports.d.ts +37 -0
  64. package/dist/api/rest/Valuation_Reports.test.d.ts +36 -0
  65. package/dist/api/rest/Zip_Codes.d.ts +37 -0
  66. package/dist/api/rest/Zip_Codes.test.d.ts +15 -0
  67. package/dist/api/restRequest.d.ts +5 -141
  68. package/dist/api/types/dynamicFetching.d.ts +10 -0
  69. package/dist/api/types/modifyTypes.d.ts +9 -0
  70. package/dist/api/types/mysqlTypes.d.ts +4 -0
  71. package/dist/api/types/ormInterfaces.d.ts +223 -0
  72. package/dist/api/utils/apiHelpers.d.ts +9 -0
  73. package/dist/api/utils/cacheManager.d.ts +10 -0
  74. package/dist/api/utils/logger.d.ts +7 -0
  75. package/dist/api/utils/sortAndSerializeQueryObject.d.ts +1 -0
  76. package/dist/api/utils/testHelpers.d.ts +1 -0
  77. package/dist/api/utils/toastNotifier.d.ts +2 -0
  78. package/dist/index.cjs.js +973 -537
  79. package/dist/index.cjs.js.map +1 -1
  80. package/dist/index.d.ts +16 -1
  81. package/dist/index.esm.js +958 -537
  82. package/dist/index.esm.js.map +1 -1
  83. package/dist/variables/isNode.d.ts +2 -0
  84. package/package.json +32 -6
  85. package/scripts/assets/handlebars/C6.ts.handlebars +5 -1
  86. package/scripts/generateRestBindings.cjs +89 -23
  87. package/scripts/generateRestBindings.ts +100 -27
  88. package/src/api/builders/sqlBuilder.ts +173 -0
  89. package/src/api/convertForRequestBody.ts +1 -2
  90. package/src/api/executors/Executor.ts +26 -0
  91. package/src/api/executors/HttpExecutor.ts +790 -0
  92. package/src/api/executors/SqlExecutor.ts +90 -0
  93. package/src/api/restRequest.ts +20 -1128
  94. package/src/api/types/dynamicFetching.ts +10 -0
  95. package/src/api/types/modifyTypes.ts +25 -0
  96. package/src/api/types/mysqlTypes.ts +33 -0
  97. package/src/api/types/ormInterfaces.ts +287 -0
  98. package/src/api/utils/apiHelpers.ts +83 -0
  99. package/src/api/utils/cacheManager.ts +67 -0
  100. package/src/api/utils/logger.ts +24 -0
  101. package/src/api/utils/sortAndSerializeQueryObject.ts +12 -0
  102. package/src/api/utils/testHelpers.ts +24 -0
  103. package/src/api/utils/toastNotifier.ts +11 -0
  104. package/src/index.ts +16 -1
  105. package/src/variables/isNode.ts +3 -0
  106. package/src/api/interfaces/ormInterfaces.ts +0 -79
package/dist/index.esm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import axios from 'axios';
2
2
  import Qs from 'qs';
3
- import { __assign, __spreadArray, __awaiter, __generator } from 'tslib';
3
+ import { __assign, __awaiter, __spreadArray, __generator, __extends } from 'tslib';
4
4
  import { toast } from 'react-toastify';
5
5
 
6
6
  var C6Constants = {
@@ -303,6 +303,224 @@ function convertForRequestBody (restfulObject, tableName, C6, regexErrorHandler)
303
303
  }, {});
304
304
  }
305
305
 
306
+ var _a;
307
+ var isNode = typeof process !== 'undefined' && !!((_a = process.versions) === null || _a === void 0 ? void 0 : _a.node);
308
+
309
+ /**
310
+ * Facade: routes API calls to SQL or HTTP executors based on runtime context.
311
+ */
312
+ function restRequest(config) {
313
+ var _this = this;
314
+ return function () {
315
+ var args_1 = [];
316
+ for (var _i = 0; _i < arguments.length; _i++) {
317
+ args_1[_i] = arguments[_i];
318
+ }
319
+ return __awaiter(_this, __spreadArray([], args_1, true), void 0, function (request) {
320
+ var SqlExecutor, executor, HttpExecutor, http;
321
+ if (request === void 0) { request = {}; }
322
+ return __generator(this, function (_a) {
323
+ switch (_a.label) {
324
+ case 0:
325
+ if (!(isNode && config.mysqlPool)) return [3 /*break*/, 2];
326
+ return [4 /*yield*/, Promise.resolve().then(function () { return SqlExecutor$1; })];
327
+ case 1:
328
+ SqlExecutor = (_a.sent()).SqlExecutor;
329
+ executor = new SqlExecutor(config, request);
330
+ return [2 /*return*/, executor.execute()];
331
+ case 2: return [4 /*yield*/, Promise.resolve().then(function () { return HttpExecutor$1; })];
332
+ case 3:
333
+ HttpExecutor = (_a.sent()).HttpExecutor;
334
+ http = new HttpExecutor(config, request);
335
+ return [2 /*return*/, http.execute()];
336
+ }
337
+ });
338
+ });
339
+ };
340
+ }
341
+
342
+ function timeout(shouldContinueAfterTimeout, cb, timeoutMs) {
343
+ if (timeoutMs === void 0) { timeoutMs = 3000; }
344
+ var timer = function () { return setTimeout(function () {
345
+ if (false === shouldContinueAfterTimeout()) {
346
+ return;
347
+ }
348
+ cb();
349
+ }, timeoutMs); };
350
+ var timerId = timer();
351
+ return function () {
352
+ clearTimeout(timerId);
353
+ };
354
+ }
355
+
356
+ function buildBooleanJoinedConditions(set, andMode) {
357
+ if (andMode === void 0) { andMode = true; }
358
+ var booleanOperator = andMode ? 'AND' : 'OR';
359
+ var sql = '';
360
+ var OPERATORS = ['=', '!=', '<', '<=', '>', '>=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'IS', 'IS NOT'];
361
+ var isAggregateArray = function (value) { return Array.isArray(value) && typeof value[0] === 'string' && OPERATORS.includes(value[0]); };
362
+ var isNumericKeyed = function (obj) { return Array.isArray(obj) && Object.keys(obj).every(function (k) { return /^\d+$/.test(k); }); };
363
+ // todo - we should be doing something with value no????
364
+ var addCondition = function (column, op, _value) {
365
+ var paramName = column.replace(/\W+/g, '_');
366
+ return "(".concat(column, " ").concat(op, " :").concat(paramName, ")");
367
+ };
368
+ if (isNumericKeyed(set)) {
369
+ switch (set.length) {
370
+ case 2:
371
+ sql += addCondition(set[0], '=', set[1]);
372
+ break;
373
+ case 3:
374
+ if (!OPERATORS.includes(set[1])) {
375
+ throw new Error("Invalid operator: ".concat(set[1]));
376
+ }
377
+ sql += addCondition(set[0], set[1], set[2]);
378
+ break;
379
+ default:
380
+ throw new Error("Invalid array condition: ".concat(JSON.stringify(set)));
381
+ }
382
+ }
383
+ else {
384
+ var parts = [];
385
+ for (var _i = 0, _a = Object.entries(set); _i < _a.length; _i++) {
386
+ var _b = _a[_i], key = _b[0], value = _b[1];
387
+ if (/^\d+$/.test(key)) {
388
+ parts.push(buildBooleanJoinedConditions(value, !andMode));
389
+ continue;
390
+ }
391
+ if (!Array.isArray(value) || isAggregateArray(value)) {
392
+ parts.push(addCondition(key, '='));
393
+ continue;
394
+ }
395
+ if (value.length === 2 && OPERATORS.includes(value[0])) {
396
+ parts.push(addCondition(key, value[0], value[1]));
397
+ }
398
+ else if (value.length === 1 && isAggregateArray(value[0])) {
399
+ parts.push(addCondition(key, '=', value[0]));
400
+ }
401
+ else {
402
+ throw new Error("Invalid condition for ".concat(key, ": ").concat(JSON.stringify(value)));
403
+ }
404
+ }
405
+ sql = parts.join(" ".concat(booleanOperator, " "));
406
+ }
407
+ return "(".concat(sql, ")");
408
+ }
409
+ function buildAggregateField(field) {
410
+ if (typeof field === 'string')
411
+ return field;
412
+ if (!Array.isArray(field))
413
+ throw new Error('Invalid SELECT entry: must be string or array');
414
+ var agg = field[0], args = field.slice(1);
415
+ switch (agg) {
416
+ case 'COUNT':
417
+ return "COUNT(".concat(args[0] || '*', ")");
418
+ case 'SUM':
419
+ case 'AVG':
420
+ case 'MIN':
421
+ case 'MAX':
422
+ return "".concat(agg, "(").concat(args[0], ")").concat(args[1] ? " AS ".concat(args[1]) : '');
423
+ case 'DISTINCT':
424
+ return "DISTINCT(".concat(args[0], ")").concat(args[1] ? " AS ".concat(args[1]) : '');
425
+ case 'GROUP_CONCAT': {
426
+ var col = args[0], alias = args[1], sortCol = args[2], sortType = args[3];
427
+ var order = sortCol ? " ORDER BY ".concat(sortCol, " ").concat(sortType || 'ASC') : '';
428
+ return "GROUP_CONCAT(DISTINCT ".concat(col).concat(order, " SEPARATOR ',')").concat(alias ? " AS ".concat(alias) : '');
429
+ }
430
+ case 'AS': {
431
+ var col = args[0], alias = args[1];
432
+ return "".concat(col, " AS ").concat(alias);
433
+ }
434
+ case 'CONVERT_TZ': {
435
+ var ts = args[0], fromTz = args[1], toTz = args[2];
436
+ return "CONVERT_TZ(".concat(ts, ", ").concat(fromTz, ", ").concat(toTz, ")");
437
+ }
438
+ case 'NOW':
439
+ return 'NOW()';
440
+ default:
441
+ throw new Error("Unsupported aggregate: ".concat(agg));
442
+ }
443
+ }
444
+ function buildSelectQuery(table, primary, args, isSubSelect) {
445
+ var _a, _b;
446
+ if (isSubSelect === void 0) { isSubSelect = false; }
447
+ var selectList = (_a = args === null || args === void 0 ? void 0 : args[C6Constants.SELECT]) !== null && _a !== void 0 ? _a : ['*'];
448
+ var selectFields = Array.isArray(selectList)
449
+ ? selectList.map(function (f) { return buildAggregateField(f); }).join(', ')
450
+ : '*';
451
+ var sql = "SELECT ".concat(selectFields, " FROM `").concat(table, "`");
452
+ if (args === null || args === void 0 ? void 0 : args[C6Constants.JOIN]) {
453
+ var joins = args[C6Constants.JOIN];
454
+ for (var joinType in joins) {
455
+ var joinKeyword = joinType.replace('_', ' ').toUpperCase();
456
+ for (var joinTable in joins[joinType]) {
457
+ var onClause = buildBooleanJoinedConditions(joins[joinType][joinTable]);
458
+ sql += " ".concat(joinKeyword, " JOIN `").concat(joinTable, "` ON ").concat(onClause);
459
+ }
460
+ }
461
+ }
462
+ if (args === null || args === void 0 ? void 0 : args[C6Constants.WHERE]) {
463
+ sql += " WHERE ".concat(buildBooleanJoinedConditions(args[C6Constants.WHERE]));
464
+ }
465
+ if (args === null || args === void 0 ? void 0 : args[C6Constants.GROUP_BY]) {
466
+ var groupByFields = Array.isArray(args[C6Constants.GROUP_BY]) ? args[C6Constants.GROUP_BY].join(', ') : args[C6Constants.GROUP_BY];
467
+ sql += " GROUP BY ".concat(groupByFields);
468
+ }
469
+ if (args === null || args === void 0 ? void 0 : args[C6Constants.HAVING]) {
470
+ sql += " HAVING ".concat(buildBooleanJoinedConditions(args[C6Constants.HAVING]));
471
+ }
472
+ if (args === null || args === void 0 ? void 0 : args[C6Constants.PAGINATION]) {
473
+ var p = args[C6Constants.PAGINATION];
474
+ var limitClause = '';
475
+ if (p[C6Constants.ORDER]) {
476
+ var orderArray = Object.entries(p[C6Constants.ORDER]).map(function (_a) {
477
+ var col = _a[0], dir = _a[1];
478
+ if (!['ASC', 'DESC'].includes(String(dir).toUpperCase())) {
479
+ throw new Error("Invalid order direction: ".concat(dir));
480
+ }
481
+ return "".concat(col, " ").concat(String(dir).toUpperCase());
482
+ });
483
+ sql += " ORDER BY ".concat(orderArray.join(', '));
484
+ }
485
+ else if (primary) {
486
+ sql += " ORDER BY ".concat(primary, " DESC");
487
+ } /*else {
488
+ // todo - this is wrong
489
+ const primaryKey = C6Constants.TABLES['users'].PRIMARY_SHORT?.[0] ?? 'user_id';
490
+ sql += ` ORDER BY ${primaryKey} DESC`;
491
+ }*/
492
+ if (p[C6Constants.LIMIT] != null) {
493
+ var limit = parseInt(p[C6Constants.LIMIT], 10);
494
+ if (isNaN(limit) || limit < 0) {
495
+ throw new Error("Invalid LIMIT: ".concat(p[C6Constants.LIMIT]));
496
+ }
497
+ var page = parseInt((_b = p[C6Constants.PAGE]) !== null && _b !== void 0 ? _b : 1, 10);
498
+ if (isNaN(page) || page < 1) {
499
+ throw new Error("PAGE must be >= 1 (got ".concat(p[C6Constants.PAGE], ")"));
500
+ }
501
+ var offset = (page - 1) * limit;
502
+ limitClause += " LIMIT ".concat(offset, ", ").concat(limit);
503
+ }
504
+ sql += limitClause;
505
+ }
506
+ else if (!isSubSelect && primary) {
507
+ sql += " ORDER BY ".concat(primary, " ASC LIMIT 1");
508
+ }
509
+ else if (!isSubSelect && !primary) {
510
+ sql += " ORDER BY id ASC LIMIT 100"; // fallback default limit
511
+ }
512
+ return sql;
513
+ }
514
+
515
+ var Executor = /** @class */ (function () {
516
+ function Executor(config, request) {
517
+ if (request === void 0) { request = {}; }
518
+ this.config = config;
519
+ this.request = request;
520
+ }
521
+ return Executor;
522
+ }());
523
+
306
524
  function getEnvVar(key, fallback) {
307
525
  if (fallback === void 0) { fallback = ''; }
308
526
  // Vite-style injection
@@ -327,6 +545,39 @@ var isTest = getEnvVar('JEST_WORKER_ID') || getEnvVar('NODE_ENV') === 'test'
327
545
  var envVerbose = getEnvVar('VERBOSE') || getEnvVar('REACT_APP_VERBOSE') || getEnvVar('VITE_VERBOSE') || '';
328
546
  var isVerbose = ['true', '1', 'yes', 'on'].includes(envVerbose.toLowerCase());
329
547
 
548
+ var eFetchDependencies;
549
+ (function (eFetchDependencies) {
550
+ eFetchDependencies[eFetchDependencies["NONE"] = 0] = "NONE";
551
+ eFetchDependencies[eFetchDependencies["REFERENCED"] = 1] = "REFERENCED";
552
+ eFetchDependencies[eFetchDependencies["CHILDREN"] = 1] = "CHILDREN";
553
+ eFetchDependencies[eFetchDependencies["REFERENCES"] = 2] = "REFERENCES";
554
+ eFetchDependencies[eFetchDependencies["PARENTS"] = 2] = "PARENTS";
555
+ eFetchDependencies[eFetchDependencies["ALL"] = 3] = "ALL";
556
+ eFetchDependencies[eFetchDependencies["C6ENTITY"] = 4] = "C6ENTITY";
557
+ eFetchDependencies[eFetchDependencies["RECURSIVE"] = 8] = "RECURSIVE";
558
+ })(eFetchDependencies || (eFetchDependencies = {}));
559
+
560
+ /**
561
+ * the first argument ....
562
+ *
563
+ * Our api returns a zero argument function iff the method is get and the previous request reached the predefined limit.
564
+ * This function can be aliased as GetNextPageOfResults(). If the end is reached undefined will be returned.
565
+ *
566
+ *
567
+ * For POST, PUT, and DELETE requests one can expect the primary key of the new or modified index, or a boolean success
568
+ * indication if no primary key exists.
569
+ **/
570
+ var POST = 'POST';
571
+ var PUT = 'PUT';
572
+ var GET = 'GET';
573
+ var DELETE = 'DELETE';
574
+ function isPromise(x) {
575
+ return Object(x).constructor === Promise;
576
+ }
577
+ function extendedTypeHints() {
578
+ return function (argv) { return restRequest(argv); };
579
+ }
580
+
330
581
  var toastOptions = {
331
582
  position: "bottom-left",
332
583
  autoClose: 10000,
@@ -367,6 +618,12 @@ function TestRestfulResponse(response, success, error) {
367
618
  }
368
619
  return false;
369
620
  }
621
+ function removePrefixIfExists(tableName, prefix) {
622
+ if (tableName.startsWith(prefix.toLowerCase())) {
623
+ return tableName.slice(prefix.length);
624
+ }
625
+ return tableName;
626
+ }
370
627
  function removeInvalidKeys(request, c6Tables) {
371
628
  var intersection = {};
372
629
  var restfulObjectKeys = [];
@@ -384,32 +641,17 @@ function removeInvalidKeys(request, c6Tables) {
384
641
  isTest || console.log('intersection', intersection);
385
642
  return intersection;
386
643
  }
387
- var eFetchDependencies;
388
- (function (eFetchDependencies) {
389
- eFetchDependencies[eFetchDependencies["NONE"] = 0] = "NONE";
390
- eFetchDependencies[eFetchDependencies["REFERENCED"] = 1] = "REFERENCED";
391
- eFetchDependencies[eFetchDependencies["CHILDREN"] = 1] = "CHILDREN";
392
- eFetchDependencies[eFetchDependencies["REFERENCES"] = 2] = "REFERENCES";
393
- eFetchDependencies[eFetchDependencies["PARENTS"] = 2] = "PARENTS";
394
- eFetchDependencies[eFetchDependencies["ALL"] = 3] = "ALL";
395
- eFetchDependencies[eFetchDependencies["C6ENTITY"] = 4] = "C6ENTITY";
396
- eFetchDependencies[eFetchDependencies["RECURSIVE"] = 8] = "RECURSIVE";
397
- })(eFetchDependencies || (eFetchDependencies = {}));
644
+
398
645
  // do not remove entries from this array. It is used to track the progress of API requests.
399
646
  // position in array is important. Do not sort. To not add to begging.
400
647
  var apiRequestCache = [];
401
648
  var userCustomClearCache = [];
402
- function checkAllRequestsComplete() {
403
- var stillRunning = apiRequestCache.filter(function (cache) { return undefined === cache.response; });
404
- if (stillRunning.length !== 0) {
405
- if (document === null || document === undefined) {
406
- throw new Error('document is undefined while waiting for API requests to complete (' + JSON.stringify(apiRequestCache) + ')');
407
- }
408
- // when requests return emtpy sets in full renders, it may not be possible to track their progress.
409
- console.warn('stillRunning...', stillRunning);
410
- return stillRunning.map(function (cache) { return cache.requestArgumentsSerialized; });
649
+ function clearCache(props) {
650
+ if (false === (props === null || props === void 0 ? void 0 : props.ignoreWarning)) {
651
+ console.warn('The rest api clearCache should only be used with extreme care! Avoid using this in favor of using `cacheResults : boolean`.');
411
652
  }
412
- return true;
653
+ userCustomClearCache.map(function (f) { return 'function' === typeof f && f(); });
654
+ userCustomClearCache = apiRequestCache = [];
413
655
  }
414
656
  function checkCache(cacheResult, requestMethod, tableName, request) {
415
657
  var _a, _b, _c;
@@ -432,6 +674,7 @@ function checkCache(cacheResult, requestMethod, tableName, request) {
432
674
  }
433
675
  return false;
434
676
  }
677
+
435
678
  function sortAndSerializeQueryObject(tables, query) {
436
679
  var orderedQuery = Object.keys(query).sort().reduce(function (obj, key) {
437
680
  obj[key] = query[key];
@@ -439,550 +682,728 @@ function sortAndSerializeQueryObject(tables, query) {
439
682
  }, {});
440
683
  return tables + ' ' + JSON.stringify(orderedQuery);
441
684
  }
442
- function clearCache(props) {
443
- if (false === (props === null || props === void 0 ? void 0 : props.ignoreWarning)) {
444
- console.warn('The rest api clearCache should only be used with extreme care! Avoid using this in favor of using `cacheResults : boolean`.');
445
- }
446
- userCustomClearCache.map(function (f) { return 'function' === typeof f && f(); });
447
- userCustomClearCache = apiRequestCache = [];
448
- }
449
- function removePrefixIfExists(tableName, prefix) {
450
- if (tableName.startsWith(prefix.toLowerCase())) {
451
- return tableName.slice(prefix.length);
452
- }
453
- return tableName;
454
- }
455
- /**
456
- * the first argument ....
457
- *
458
- * Our api returns a zero argument function iff the method is get and the previous request reached the predefined limit.
459
- * This function can be aliased as GetNextPageOfResults(). If the end is reached undefined will be returned.
460
- *
461
- *
462
- * For POST, PUT, and DELETE requests one can expect the primary key of the new or modified index, or a boolean success
463
- * indication if no primary key exists.
464
- **/
465
- var POST = 'POST';
466
- var PUT = 'PUT';
467
- var GET = 'GET';
468
- var DELETE = 'DELETE';
469
- function isPromise(x) {
470
- return Object(x).constructor === Promise;
471
- }
472
- function extendedTypeHints() {
473
- return function (argv) { return restRequest(argv); };
474
- }
475
- function restRequest(_a) {
476
- var C6 = _a.C6, _b = _a.axios, axios = _b === void 0 ? axiosInstance : _b, _c = _a.restURL, restURL = _c === void 0 ? '/rest/' : _c, _d = _a.withCredentials, withCredentials = _d === void 0 ? true : _d, tableName = _a.tableName, _e = _a.requestMethod, requestMethod = _e === void 0 ? GET : _e, _f = _a.queryCallback, queryCallback = _f === void 0 ? {} : _f, responseCallback = _a.responseCallback, _g = _a.skipPrimaryCheck, skipPrimaryCheck = _g === void 0 ? false : _g, _h = _a.clearCache, clearCache = _h === void 0 ? undefined : _h;
477
- var fullTableList = Array.isArray(tableName) ? tableName : [tableName];
478
- var operatingTableFullName = fullTableList[0];
479
- var operatingTable = removePrefixIfExists(operatingTableFullName, C6.PREFIX);
480
- var tables = fullTableList.join(',');
481
- switch (requestMethod) {
482
- case GET:
483
- case POST:
484
- case PUT:
485
- case DELETE:
486
- break;
487
- default:
488
- throw Error('Bad request method passed to getApi');
489
- }
490
- if (null !== clearCache || undefined !== clearCache) {
491
- userCustomClearCache[tables + requestMethod] = clearCache;
685
+
686
+ var HttpExecutor = /** @class */ (function (_super) {
687
+ __extends(HttpExecutor, _super);
688
+ function HttpExecutor() {
689
+ return _super !== null && _super.apply(this, arguments) || this;
492
690
  }
493
- return function (request) {
494
- if (request === void 0) { request = {}; }
495
- console.groupCollapsed('%c API: (' + requestMethod + ') Request for (' + operatingTable + ')', 'color: #0c0');
496
- console.log('request', request);
497
- console.groupEnd();
498
- // an undefined query would indicate queryCallback returned undefined,
499
- // thus the request shouldn't fire as is in custom cache
500
- var query;
501
- if ('function' === typeof queryCallback) {
502
- query = queryCallback(request); // obj or obj[]
503
- }
504
- else {
505
- query = queryCallback;
506
- }
507
- if (undefined === query || null === query) {
508
- if (request.debug && isDevelopment) {
509
- toast.warning("DEV: queryCallback returned undefined, signaling in Custom Cache. (returning null)", toastOptionsDevs);
510
- }
511
- console.groupCollapsed('%c API: (' + requestMethod + ') Request Query for (' + operatingTable + ') undefined, returning null (will not fire ajax)!', 'color: #c00');
512
- 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');
513
- console.trace();
514
- console.groupEnd();
515
- return null;
516
- }
517
- if (C6.GET === requestMethod) {
518
- if (undefined === query[C6.PAGINATION]) {
519
- query[C6.PAGINATION] = {};
520
- }
521
- query[C6.PAGINATION][C6.PAGE] = query[C6.PAGINATION][C6.PAGE] || 1;
522
- query[C6.PAGINATION][C6.LIMIT] = query[C6.PAGINATION][C6.LIMIT] || 100;
523
- }
524
- // this could return itself with a new page number, or undefined if the end is reached
525
- function apiRequest() {
691
+ HttpExecutor.prototype.execute = function () {
692
+ return __awaiter(this, void 0, void 0, function () {
693
+ var _a, C6, axios, restURL, withCredentials, tableName, requestMethod, queryCallback, responseCallback, skipPrimaryCheck, clearCache, fullTableList, operatingTableFullName, operatingTable, tables, query, apiRequest;
526
694
  var _this = this;
527
- var _a, _b, _c, _d, _e, _f, _g;
528
- (_a = request.cacheResults) !== null && _a !== void 0 ? _a : (request.cacheResults = C6.GET === requestMethod);
529
- if (C6.GET === requestMethod
530
- && undefined !== ((_b = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _b === void 0 ? void 0 : _b[C6.PAGE])
531
- && 1 !== query[C6.PAGINATION][C6.PAGE]) {
532
- console.groupCollapsed('Request on table (' + tableName + ') is firing for page (' + query[C6.PAGINATION][C6.PAGE] + '), please wait!');
533
- console.log('Request Data (note you may see the success and/or error prompt):', request);
534
- console.trace();
535
- console.groupEnd();
536
- }
537
- // 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.
538
- // 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
539
- // literally impossible for query to be undefined or null here but the editor is too busy licking windows to understand that
540
- var querySerialized = sortAndSerializeQueryObject(tables, query !== null && query !== void 0 ? query : {});
541
- var cacheResult = apiRequestCache.find(function (cache) { return cache.requestArgumentsSerialized === querySerialized; });
542
- var cachingConfirmed = false;
543
- // determine if we need to paginate.
544
- if (requestMethod === C6.GET) {
545
- if (undefined === (query === null || query === void 0 ? void 0 : query[C6.PAGINATION])) {
546
- if (undefined === query || null === query) {
547
- query = {};
548
- }
549
- query[C6.PAGINATION] = {};
550
- }
551
- query[C6.PAGINATION][C6.PAGE] = query[C6.PAGINATION][C6.PAGE] || 1;
552
- query[C6.PAGINATION][C6.LIMIT] = query[C6.PAGINATION][C6.LIMIT] || 100;
553
- // this will evaluate true most the time
554
- if (true === request.cacheResults) {
555
- // just find the next, non-fetched, page and return a function to request it
556
- if (undefined !== cacheResult) {
557
- do {
558
- var cacheCheck = checkCache(cacheResult, requestMethod, tableName, request);
559
- if (false !== cacheCheck) {
560
- return cacheCheck;
561
- }
562
- // this line incrementing page is why we return recursively
563
- ++query[C6.PAGINATION][C6.PAGE];
564
- // this json stringify is to capture the new page number
565
- querySerialized = sortAndSerializeQueryObject(tables, query !== null && query !== void 0 ? query : {});
566
- cacheResult = apiRequestCache.find(function (cache) { return cache.requestArgumentsSerialized === querySerialized; });
567
- } while (undefined !== cacheResult);
568
- if (request.debug && isDevelopment) {
569
- toast.warning("DEVS: Request in cache. (" + apiRequestCache.findIndex(function (cache) { return cache.requestArgumentsSerialized === querySerialized; }) + "). Returning function to request page (" + query[C6.PAGINATION][C6.PAGE] + ")", toastOptionsDevs);
695
+ return __generator(this, function (_b) {
696
+ switch (_b.label) {
697
+ case 0:
698
+ _a = this.config, C6 = _a.C6, axios = _a.axios, restURL = _a.restURL, withCredentials = _a.withCredentials, tableName = _a.tableName, requestMethod = _a.requestMethod, queryCallback = _a.queryCallback, responseCallback = _a.responseCallback, skipPrimaryCheck = _a.skipPrimaryCheck, clearCache = _a.clearCache;
699
+ fullTableList = Array.isArray(tableName) ? tableName : [tableName];
700
+ operatingTableFullName = fullTableList[0];
701
+ operatingTable = removePrefixIfExists(operatingTableFullName, C6.PREFIX);
702
+ tables = fullTableList.join(',');
703
+ switch (requestMethod) {
704
+ case GET:
705
+ case POST:
706
+ case PUT:
707
+ case DELETE:
708
+ break;
709
+ default:
710
+ throw Error('Bad request method passed to getApi');
570
711
  }
571
- // @ts-ignore - this is an incorrect warning on TS, it's well typed
572
- return apiRequest;
573
- }
574
- cachingConfirmed = true;
575
- }
576
- else {
577
- if (request.debug && isDevelopment) {
578
- toast.info("DEVS: Ignore cache was set to true.", toastOptionsDevs);
579
- }
580
- }
581
- if (request.debug && isDevelopment) {
582
- toast.success("DEVS: Request not in cache." + (requestMethod === C6.GET ? "Page (" + query[C6.PAGINATION][C6.PAGE] + ")." : '') + " Logging cache 2 console.", toastOptionsDevs);
583
- }
584
- }
585
- else if (request.cacheResults) { // if we are not getting, we are updating, deleting, or inserting
586
- if (cacheResult) {
587
- var cacheCheck = checkCache(cacheResult, requestMethod, tableName, request);
588
- if (false !== cacheCheck) {
589
- return cacheCheck;
590
- }
591
- }
592
- cachingConfirmed = true;
593
- // push to cache so we do not repeat the request
594
- }
595
- var addBackPK;
596
- var apiResponse;
597
- var returnGetNextPageFunction = false;
598
- var restRequestUri = restURL + operatingTable + '/';
599
- var needsConditionOrPrimaryCheck = (PUT === requestMethod || DELETE === requestMethod)
600
- && false === skipPrimaryCheck;
601
- var TABLES = C6.TABLES;
602
- // todo - aggregate primary key check with condition check
603
- // check if PK exists in query, clone so pop does not affect the real data
604
- var primaryKey = (_f = (_e = (_d = structuredClone((_c = TABLES[operatingTable]) === null || _c === void 0 ? void 0 : _c.PRIMARY)) === null || _d === void 0 ? void 0 : _d.pop()) === null || _e === void 0 ? void 0 : _e.split('.')) === null || _f === void 0 ? void 0 : _f.pop();
605
- if (needsConditionOrPrimaryCheck) {
606
- if (undefined === primaryKey) {
607
- if (null === query
608
- || undefined === query
609
- || undefined === (query === null || query === void 0 ? void 0 : query[C6.WHERE])
610
- || (true === Array.isArray(query[C6.WHERE])
611
- || query[C6.WHERE].length === 0)
612
- || (Object.keys(query === null || query === void 0 ? void 0 : query[C6.WHERE]).length === 0)) {
613
- console.error(query);
614
- throw Error('Failed to parse primary key information. Query: (' + JSON.stringify(query) + ') Primary Key: (' + JSON.stringify(primaryKey) + ') TABLES[operatingTable]?.PRIMARY: (' + JSON.stringify((_g = TABLES[operatingTable]) === null || _g === void 0 ? void 0 : _g.PRIMARY) + ') for operatingTable (' + operatingTable + ').');
615
- }
616
- }
617
- else {
618
- if (undefined === query
619
- || null === query
620
- || false === primaryKey in query) {
621
- if (true === request.debug && isDevelopment) {
622
- toast.error('DEVS: The primary key (' + primaryKey + ') was not provided!!');
712
+ if (null !== clearCache || undefined !== clearCache) {
713
+ userCustomClearCache[tables + requestMethod] = clearCache;
623
714
  }
624
- throw Error('You must provide the primary key (' + primaryKey + ') for table (' + operatingTable + '). Request (' + JSON.stringify(request, undefined, 4) + ') Query (' + JSON.stringify(query) + ')');
625
- }
626
- if (undefined === (query === null || query === void 0 ? void 0 : query[primaryKey])
627
- || null === (query === null || query === void 0 ? void 0 : query[primaryKey])) {
628
- toast.error('The primary key (' + primaryKey + ') provided is undefined or null explicitly!!');
629
- throw Error('The primary key (' + primaryKey + ') provided in the request was exactly equal to undefined.');
630
- }
631
- }
632
- }
633
- // A part of me exists that wants to remove this, but it's a good feature
634
- // this allows developers the ability to cache requests based on primary key
635
- // for tables like `photos` this can be a huge performance boost
636
- if (undefined !== query
637
- && null !== query
638
- && undefined !== primaryKey
639
- && primaryKey in query) {
640
- restRequestUri += query[primaryKey] + '/';
641
- var removedPkValue_1 = query[primaryKey];
642
- addBackPK = function () {
643
- query !== null && query !== void 0 ? query : (query = {});
644
- query[primaryKey] = removedPkValue_1;
645
- };
646
- delete query[primaryKey];
647
- console.log('query', query, 'primaryKey', primaryKey, 'removedPkValue', removedPkValue_1);
648
- }
649
- else {
650
- console.log('query', query);
651
- }
652
- try {
653
- console.groupCollapsed('%c API: (' + requestMethod + ') Request Query for (' + operatingTable + ') is about to fire, will return with promise!', 'color: #A020F0');
654
- console.log(request);
655
- 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');
656
- 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');
657
- console.trace();
658
- console.groupEnd();
659
- var axiosActiveRequest = axios[requestMethod.toLowerCase()].apply(axios, __spreadArray([restRequestUri], ((function () {
660
- // @link - https://axios-http.com/docs/instance
661
- // How configuration vs data is passed is variable, use documentation above for reference
662
- if (requestMethod === GET) {
663
- return [{
664
- withCredentials: withCredentials,
665
- params: query
666
- }];
667
- }
668
- else if (requestMethod === POST) {
669
- if (undefined !== (request === null || request === void 0 ? void 0 : request.dataInsertMultipleRows)) {
670
- return [
671
- request.dataInsertMultipleRows.map(function (data) {
672
- return convertForRequestBody(data, fullTableList, C6, function (message) { return toast.error(message, toastOptions); });
673
- }),
674
- {
675
- withCredentials: withCredentials,
676
- }
677
- ];
715
+ console.groupCollapsed('%c API: (' + requestMethod + ') Request for (' + tableName + ')', 'color: #0c0');
716
+ console.log('request', this.request);
717
+ console.groupEnd();
718
+ if ('function' === typeof queryCallback) {
719
+ query = queryCallback(this.request); // obj or obj[]
678
720
  }
679
- return [
680
- convertForRequestBody(query, fullTableList, C6, function (message) { return toast.error(message, toastOptions); }),
681
- {
682
- withCredentials: withCredentials,
721
+ else {
722
+ query = queryCallback;
723
+ }
724
+ if (undefined === query || null === query) {
725
+ if (this.request.debug && isDevelopment) {
726
+ toast.warning("DEV: queryCallback returned undefined, signaling in Custom Cache. (returning null)", toastOptionsDevs);
683
727
  }
684
- ];
685
- }
686
- else if (requestMethod === PUT) {
687
- return [
688
- convertForRequestBody(query, fullTableList, C6, function (message) { return toast.error(message, toastOptions); }),
689
- {
690
- withCredentials: withCredentials,
728
+ console.groupCollapsed('%c API: (' + requestMethod + ') Request Query for (' + tableName + ') undefined, returning null (will not fire ajax)!', 'color: #c00');
729
+ 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');
730
+ console.trace();
731
+ console.groupEnd();
732
+ return [2 /*return*/, null];
733
+ }
734
+ if (C6.GET === requestMethod) {
735
+ if (undefined === query[C6.PAGINATION]) {
736
+ query[C6.PAGINATION] = {};
691
737
  }
692
- ];
693
- }
694
- else if (requestMethod === DELETE) {
695
- return [{
696
- withCredentials: withCredentials,
697
- data: convertForRequestBody(query, fullTableList, C6, function (message) { return toast.error(message, toastOptions); })
698
- }];
699
- }
700
- else {
701
- throw new Error('The request method (' + requestMethod + ') was not recognized.');
702
- }
703
- })()), false));
704
- if (cachingConfirmed) {
705
- // push to cache so we do not repeat the request
706
- apiRequestCache.push({
707
- requestArgumentsSerialized: querySerialized,
708
- request: axiosActiveRequest
709
- });
710
- }
711
- // todo - wip verify this works
712
- // we had removed the value from the request to add to the URI.
713
- addBackPK === null || addBackPK === void 0 ? void 0 : addBackPK(); // adding back so post-processing methods work
714
- // returning the promise with this then is important for tests. todo - we could make that optional.
715
- // https://rapidapi.com/guides/axios-async-await
716
- return axiosActiveRequest.then(function (response) { return __awaiter(_this, void 0, void 0, function () {
717
- var cacheIndex, responseData_1, fetchDependencies, dependencies_1, fetchReferences_1, apiRequestPromises, _loop_1, _a, _b, _c, _i, tableToFetch;
718
- var _this = this;
719
- var _d, _e, _f, _g, _h, _j, _k, _l, _m;
720
- return __generator(this, function (_o) {
721
- switch (_o.label) {
722
- case 0:
723
- if (typeof response.data === 'string') {
724
- if (isTest) {
725
- console.trace();
726
- 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 + ')');
738
+ query[C6.PAGINATION][C6.PAGE] = query[C6.PAGINATION][C6.PAGE] || 1;
739
+ query[C6.PAGINATION][C6.LIMIT] = query[C6.PAGINATION][C6.LIMIT] || 100;
740
+ }
741
+ apiRequest = function () { return __awaiter(_this, void 0, void 0, function () {
742
+ 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;
743
+ var _e;
744
+ var _this = this;
745
+ var _f, _g, _h, _j, _k, _l;
746
+ return __generator(this, function (_m) {
747
+ _a = this.request, debug = _a.debug, _b = _a.cacheResults, cacheResults = _b === void 0 ? (C6.GET === requestMethod) : _b, dataInsertMultipleRows = _a.dataInsertMultipleRows, success = _a.success, _c = _a.fetchDependencies, fetchDependencies = _c === void 0 ? eFetchDependencies.NONE : _c, _d = _a.error, error = _d === void 0 ? "An unexpected API error occurred!" : _d;
748
+ if (C6.GET === requestMethod
749
+ && undefined !== ((_f = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _f === void 0 ? void 0 : _f[C6.PAGE])
750
+ && 1 !== query[C6.PAGINATION][C6.PAGE]) {
751
+ console.groupCollapsed('Request on table (' + tableName + ') is firing for page (' + query[C6.PAGINATION][C6.PAGE] + '), please wait!');
752
+ console.log('Request Data (note you may see the success and/or error prompt):', this.request);
753
+ console.trace();
754
+ console.groupEnd();
755
+ }
756
+ querySerialized = sortAndSerializeQueryObject(tables, query !== null && query !== void 0 ? query : {});
757
+ cacheResult = apiRequestCache.find(function (cache) { return cache.requestArgumentsSerialized === querySerialized; });
758
+ cachingConfirmed = false;
759
+ // determine if we need to paginate.
760
+ if (requestMethod === C6.GET) {
761
+ if (undefined === (query === null || query === void 0 ? void 0 : query[C6.PAGINATION])) {
762
+ if (undefined === query || null === query) {
763
+ query = {};
764
+ }
765
+ query[C6.PAGINATION] = {};
766
+ }
767
+ query[C6.PAGINATION][C6.PAGE] = query[C6.PAGINATION][C6.PAGE] || 1;
768
+ query[C6.PAGINATION][C6.LIMIT] = query[C6.PAGINATION][C6.LIMIT] || 100;
769
+ // this will evaluate true most the time
770
+ if (true === cacheResults) {
771
+ // just find the next, non-fetched, page and return a function to request it
772
+ if (undefined !== cacheResult) {
773
+ do {
774
+ cacheCheck = checkCache(cacheResult, requestMethod, tableName, this.request);
775
+ if (false !== cacheCheck) {
776
+ return [2 /*return*/, cacheCheck];
777
+ }
778
+ // this line incrementing page is why we return recursively
779
+ ++query[C6.PAGINATION][C6.PAGE];
780
+ // this json stringify is to capture the new page number
781
+ querySerialized = sortAndSerializeQueryObject(tables, query !== null && query !== void 0 ? query : {});
782
+ cacheResult = apiRequestCache.find(function (cache) { return cache.requestArgumentsSerialized === querySerialized; });
783
+ } while (undefined !== cacheResult);
784
+ if (debug && isDevelopment) {
785
+ toast.warning("DEVS: Request in cache. (" + apiRequestCache.findIndex(function (cache) { return cache.requestArgumentsSerialized === querySerialized; }) + "). Returning function to request page (" + query[C6.PAGINATION][C6.PAGE] + ")", toastOptionsDevs);
786
+ }
787
+ // @ts-ignore - this is an incorrect warning on TS, it's well typed
788
+ return [2 /*return*/, apiRequest];
789
+ }
790
+ cachingConfirmed = true;
791
+ }
792
+ else {
793
+ if (debug && isDevelopment) {
794
+ toast.info("DEVS: Ignore cache was set to true.", toastOptionsDevs);
795
+ }
796
+ }
797
+ if (debug && isDevelopment) {
798
+ toast.success("DEVS: Request not in cache." + (requestMethod === C6.GET ? "Page (" + query[C6.PAGINATION][C6.PAGE] + ")." : '') + " Logging cache 2 console.", toastOptionsDevs);
727
799
  }
728
- return [2 /*return*/, Promise.reject(response)];
729
800
  }
730
- if (cachingConfirmed) {
731
- cacheIndex = apiRequestCache.findIndex(function (cache) { return cache.requestArgumentsSerialized === querySerialized; });
732
- apiRequestCache[cacheIndex].final = false === returnGetNextPageFunction;
733
- // only cache get method requests
734
- apiRequestCache[cacheIndex].response = response;
801
+ else if (cacheResults) { // if we are not getting, we are updating, deleting, or inserting
802
+ if (cacheResult) {
803
+ cacheCheck = checkCache(cacheResult, requestMethod, tableName, this.request);
804
+ if (false !== cacheCheck) {
805
+ return [2 /*return*/, cacheCheck];
806
+ }
807
+ }
808
+ cachingConfirmed = true;
809
+ // push to cache so we do not repeat the request
735
810
  }
736
- apiResponse = TestRestfulResponse(response, request === null || request === void 0 ? void 0 : request.success, (_d = request === null || request === void 0 ? void 0 : request.error) !== null && _d !== void 0 ? _d : "An unexpected API error occurred!");
737
- if (false === apiResponse) {
738
- if (request.debug && isDevelopment) {
739
- toast.warning("DEVS: TestRestfulResponse returned false for (" + operatingTable + ").", toastOptionsDevs);
811
+ returnGetNextPageFunction = false;
812
+ restRequestUri = restURL + operatingTable + '/';
813
+ needsConditionOrPrimaryCheck = (PUT === requestMethod || DELETE === requestMethod)
814
+ && false === skipPrimaryCheck;
815
+ TABLES = C6.TABLES;
816
+ 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();
817
+ if (needsConditionOrPrimaryCheck) {
818
+ if (undefined === primaryKey) {
819
+ if (null === query
820
+ || undefined === query
821
+ || undefined === (query === null || query === void 0 ? void 0 : query[C6.WHERE])
822
+ || (true === Array.isArray(query[C6.WHERE])
823
+ || query[C6.WHERE].length === 0)
824
+ || (Object.keys(query === null || query === void 0 ? void 0 : query[C6.WHERE]).length === 0)) {
825
+ console.error(query);
826
+ 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 + ').');
827
+ }
828
+ }
829
+ else {
830
+ if (undefined === query
831
+ || null === query
832
+ || false === primaryKey in query) {
833
+ if (true === debug && isDevelopment) {
834
+ toast.error('DEVS: The primary key (' + primaryKey + ') was not provided!!');
835
+ }
836
+ throw Error('You must provide the primary key (' + primaryKey + ') for table (' + operatingTable + '). Request (' + JSON.stringify(this.request, undefined, 4) + ') Query (' + JSON.stringify(query) + ')');
837
+ }
838
+ if (undefined === (query === null || query === void 0 ? void 0 : query[primaryKey])
839
+ || null === (query === null || query === void 0 ? void 0 : query[primaryKey])) {
840
+ toast.error('The primary key (' + primaryKey + ') provided is undefined or null explicitly!!');
841
+ throw Error('The primary key (' + primaryKey + ') provided in the request was exactly equal to undefined.');
842
+ }
740
843
  }
741
- return [2 /*return*/, response];
742
844
  }
743
- // stateful operations are done in the response callback - its leverages rest generated functions
744
- if (responseCallback) {
745
- responseCallback(response, request, apiResponse);
845
+ // A part of me exists that wants to remove this, but it's a good feature
846
+ // this allows developers the ability to cache requests based on primary key
847
+ // for tables like `photos` this can be a huge performance boost
848
+ if (undefined !== query
849
+ && null !== query
850
+ && undefined !== primaryKey
851
+ && primaryKey in query) {
852
+ restRequestUri += query[primaryKey] + '/';
853
+ removedPkValue_1 = query[primaryKey];
854
+ addBackPK = function () {
855
+ query !== null && query !== void 0 ? query : (query = {});
856
+ query[primaryKey] = removedPkValue_1;
857
+ };
858
+ delete query[primaryKey];
859
+ console.log('query', query, 'primaryKey', primaryKey, 'removedPkValue', removedPkValue_1);
746
860
  }
747
- if (!(C6.GET === requestMethod)) return [3 /*break*/, 6];
748
- responseData_1 = response.data;
749
- returnGetNextPageFunction = 1 !== ((_e = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _e === void 0 ? void 0 : _e[C6.LIMIT]) &&
750
- ((_f = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _f === void 0 ? void 0 : _f[C6.LIMIT]) === responseData_1.rest.length;
751
- if (false === isTest || true === isVerbose) {
752
- console.groupCollapsed('%c API: Response (' + requestMethod + ' ' + tableName + ') returned length (' + ((_g = responseData_1.rest) === null || _g === void 0 ? void 0 : _g.length) + ') of possible (' + ((_h = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _h === void 0 ? void 0 : _h[C6.LIMIT]) + ') limit!', 'color: #0c0');
753
- console.log('%c ' + requestMethod + ' ' + tableName, 'color: #0c0');
754
- console.log('%c Request Data (note you may see the success and/or error prompt):', 'color: #0c0', request);
755
- console.log('%c Response Data:', 'color: #0c0', responseData_1.rest);
756
- console.log('%c Will return get next page function:' + (1 !== ((_j = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _j === void 0 ? void 0 : _j[C6.LIMIT]) ? '' : ' (Will not return with explicit limit 1 set)'), 'color: #0c0', true === returnGetNextPageFunction);
861
+ else {
862
+ console.log('query', query);
863
+ }
864
+ try {
865
+ console.groupCollapsed('%c API: (' + requestMethod + ') Request Query for (' + operatingTable + ') is about to fire, will return with promise!', 'color: #A020F0');
866
+ console.log(this.request);
867
+ 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');
868
+ 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');
757
869
  console.trace();
758
870
  console.groupEnd();
759
- }
760
- if (false === returnGetNextPageFunction
761
- && true === request.debug
762
- && isDevelopment) {
763
- toast.success("DEVS: Response returned length (" + ((_k = responseData_1.rest) === null || _k === void 0 ? void 0 : _k.length) + ") less than limit (" + ((_l = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _l === void 0 ? void 0 : _l[C6.LIMIT]) + ").", toastOptionsDevs);
764
- }
765
- (_m = request.fetchDependencies) !== null && _m !== void 0 ? _m : (request.fetchDependencies = eFetchDependencies.NONE);
766
- if (!(request.fetchDependencies
767
- && 'number' === typeof request.fetchDependencies
768
- && responseData_1.rest.length > 0)) return [3 /*break*/, 6];
769
- fetchDependencies = request.fetchDependencies;
770
- console.groupCollapsed('%c API: Fetch Dependencies segment (' + requestMethod + ' ' + tableName + ')'
771
- + (fetchDependencies & eFetchDependencies.CHILDREN ? ' | (CHILDREN|REFERENCED) ' : '')
772
- + (fetchDependencies & eFetchDependencies.PARENTS ? ' | (PARENTS|REFERENCED_BY)' : '')
773
- + (fetchDependencies & eFetchDependencies.C6ENTITY ? ' | (C6ENTITY)' : '')
774
- + (fetchDependencies & eFetchDependencies.RECURSIVE ? ' | (RECURSIVE)' : ''), 'color: #33ccff');
775
- console.groupCollapsed('Collapsed JS Trace');
776
- console.trace(); // hidden in collapsed group
777
- console.groupEnd();
778
- dependencies_1 = {};
779
- if (fetchDependencies & eFetchDependencies.C6ENTITY) {
780
- dependencies_1 = operatingTable.endsWith("carbon_carbons")
781
- ? __assign(__assign({}, fetchDependencies & eFetchDependencies.CHILDREN // REFERENCED === CHILDREN
782
- ? C6.TABLES[operatingTable].TABLE_REFERENCED_BY
783
- : {}), fetchDependencies & eFetchDependencies.PARENTS // REFERENCES === PARENTS
784
- ? C6.TABLES[operatingTable].TABLE_REFERENCES
785
- : {}) : __assign(__assign({}, fetchDependencies & eFetchDependencies.CHILDREN // REFERENCED === CHILDREN
786
- ? __assign(__assign({}, Object.keys(C6.TABLES[operatingTable].TABLE_REFERENCES).reduce(function (accumulator, columnName) {
787
- if (!C6.TABLES[operatingTable].PRIMARY_SHORT.includes(columnName)) {
788
- accumulator[columnName] = C6.TABLES[operatingTable].TABLE_REFERENCES[columnName];
789
- }
790
- return accumulator;
791
- }, {})), C6.TABLES[operatingTable].TABLE_REFERENCED_BY // it is unlikely that a C6 table will have any TABLE_REFERENCED_BY
792
- ) : {}), fetchDependencies & eFetchDependencies.PARENTS // REFERENCES === PARENTS
793
- ? C6.TABLES[operatingTable].PRIMARY_SHORT.reduce(function (accumulator, primaryKey) {
794
- if (primaryKey in C6.TABLES[operatingTable].TABLE_REFERENCES) {
795
- accumulator[primaryKey] = C6.TABLES[operatingTable].TABLE_REFERENCES[primaryKey];
871
+ axiosActiveRequest = (_e = axios)[requestMethod.toLowerCase()].apply(_e, __spreadArray([restRequestUri], ((function () {
872
+ // @link - https://axios-http.com/docs/instance
873
+ // How configuration vs data is passed is variable, use documentation above for reference
874
+ if (requestMethod === GET) {
875
+ return [{
876
+ withCredentials: withCredentials,
877
+ params: query
878
+ }];
879
+ }
880
+ else if (requestMethod === POST) {
881
+ if (undefined !== dataInsertMultipleRows) {
882
+ return [
883
+ dataInsertMultipleRows.map(function (data) {
884
+ return convertForRequestBody(data, fullTableList, C6, function (message) { return toast.error(message, toastOptions); });
885
+ }),
886
+ {
887
+ withCredentials: withCredentials,
888
+ }
889
+ ];
796
890
  }
797
- return accumulator;
798
- }, {})
799
- : {});
800
- }
801
- else {
802
- // this is the natural mysql context
803
- dependencies_1 = __assign(__assign({}, fetchDependencies & eFetchDependencies.REFERENCED // REFERENCED === CHILDREN
804
- ? C6.TABLES[operatingTable].TABLE_REFERENCED_BY
805
- : {}), fetchDependencies & eFetchDependencies.REFERENCES // REFERENCES === PARENTS
806
- ? C6.TABLES[operatingTable].TABLE_REFERENCES
807
- : {});
808
- }
809
- fetchReferences_1 = {};
810
- apiRequestPromises = [];
811
- console.log('%c Dependencies', 'color: #005555', dependencies_1);
812
- Object.keys(dependencies_1)
813
- .forEach(function (column) { return dependencies_1[column]
814
- .forEach(function (constraint) {
815
- var _a, _b, _c, _d;
816
- var _e, _f, _g;
817
- var columnValues = (_b = (_a = responseData_1.rest[column]) !== null && _a !== void 0 ? _a : responseData_1.rest.map(function (row) {
818
- if (operatingTable.endsWith("carbons")
819
- && 'entity_tag' in row
820
- && !constraint.TABLE.endsWith(row['entity_tag'].split('\\').pop().toLowerCase())) {
821
- return false; // map
891
+ return [
892
+ convertForRequestBody(query, fullTableList, C6, function (message) { return toast.error(message, toastOptions); }),
893
+ {
894
+ withCredentials: withCredentials,
895
+ }
896
+ ];
897
+ }
898
+ else if (requestMethod === PUT) {
899
+ return [
900
+ convertForRequestBody(query, fullTableList, C6, function (message) { return toast.error(message, toastOptions); }),
901
+ {
902
+ withCredentials: withCredentials,
903
+ }
904
+ ];
822
905
  }
823
- if (!(column in row)) {
824
- return false;
906
+ else if (requestMethod === DELETE) {
907
+ return [{
908
+ withCredentials: withCredentials,
909
+ data: convertForRequestBody(query, fullTableList, C6, function (message) { return toast.error(message, toastOptions); })
910
+ }];
825
911
  }
826
- // todo - row[column] is a FK value, we should optionally remove values that are already in state
827
- // this could be any column in the table constraint.TABLE, not just the primary key
828
- return row[column];
829
- }).filter(function (n) { return n; })) !== null && _b !== void 0 ? _b : [];
830
- if (columnValues.length === 0) {
831
- return; // forEach
912
+ else {
913
+ throw new Error('The request method (' + requestMethod + ') was not recognized.');
914
+ }
915
+ })()), false));
916
+ if (cachingConfirmed) {
917
+ // push to cache so we do not repeat the request
918
+ apiRequestCache.push({
919
+ requestArgumentsSerialized: querySerialized,
920
+ request: axiosActiveRequest
921
+ });
832
922
  }
833
- (_c = fetchReferences_1[_e = constraint.TABLE]) !== null && _c !== void 0 ? _c : (fetchReferences_1[_e] = {});
834
- (_d = (_f = fetchReferences_1[constraint.TABLE])[_g = constraint.COLUMN]) !== null && _d !== void 0 ? _d : (_f[_g] = []);
835
- fetchReferences_1[constraint.TABLE][constraint.COLUMN].push(columnValues);
836
- }); });
837
- console.log('fetchReferences', fetchReferences_1);
838
- _loop_1 = function (tableToFetch) {
839
- var referencesTables, shouldContinue, fetchTable, RestApi, nextFetchDependencies;
840
- var _p;
841
- return __generator(this, function (_q) {
842
- switch (_q.label) {
843
- case 0:
844
- if (fetchDependencies & eFetchDependencies.C6ENTITY
845
- && 'string' === typeof tableName
846
- && tableName.endsWith("carbon_carbons")) {
847
- referencesTables = responseData_1.rest.reduce(function (accumulator, row) {
848
- if ('entity_tag' in row && !accumulator.includes(row['entity_tag'])) {
849
- accumulator.push(row['entity_tag']);
923
+ // todo - wip verify this works
924
+ // we had removed the value from the request to add to the URI.
925
+ addBackPK === null || addBackPK === void 0 ? void 0 : addBackPK(); // adding back so post-processing methods work
926
+ // returning the promise with this then is important for tests. todo - we could make that optional.
927
+ // https://rapidapi.com/guides/axios-async-await
928
+ return [2 /*return*/, axiosActiveRequest.then(function (response) { return __awaiter(_this, void 0, void 0, function () {
929
+ var cacheIndex, responseData_1, dependencies_1, fetchReferences_1, apiRequestPromises, _loop_1, _a, _b, _c, _i, tableToFetch;
930
+ var _this = this;
931
+ var _d, _e, _f, _g, _h, _j, _k;
932
+ return __generator(this, function (_l) {
933
+ switch (_l.label) {
934
+ case 0:
935
+ if (typeof response.data === 'string') {
936
+ if (isTest) {
937
+ console.trace();
938
+ 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 + ')');
939
+ }
940
+ return [2 /*return*/, Promise.reject(response)];
850
941
  }
851
- return accumulator;
852
- }, []).map(function (entityTag) { return entityTag.split('\\').pop().toLowerCase(); });
853
- shouldContinue = referencesTables.find(function (referencesTable) { return tableToFetch.endsWith(referencesTable); });
854
- if (!shouldContinue) {
855
- console.log('%c C6ENTITY: The constraintTableName (' + tableToFetch + ') did not end with any value in referencesTables', 'color: #c00', referencesTables);
856
- return [2 /*return*/, "continue"];
857
- }
858
- console.log('%c C6ENTITY: The constraintTableName (' + tableToFetch + ') will be fetched.', 'color: #0c0');
859
- }
860
- return [4 /*yield*/, C6.IMPORT(tableToFetch)];
861
- case 1:
862
- fetchTable = _q.sent();
863
- RestApi = fetchTable.default;
864
- console.log('%c Fetch Dependencies will select (' + tableToFetch + ') using GET request', 'color: #33ccff');
865
- nextFetchDependencies = eFetchDependencies.NONE;
866
- if (fetchDependencies & eFetchDependencies.RECURSIVE) {
867
- if (fetchDependencies & eFetchDependencies.ALL) {
868
- 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.');
869
- }
870
- nextFetchDependencies = fetchDependencies;
871
- }
872
- else if (fetchDependencies & eFetchDependencies.C6ENTITY) {
873
- if (tableToFetch === "carbon_carbons") {
874
- nextFetchDependencies = fetchDependencies;
875
- }
876
- else {
877
- nextFetchDependencies = fetchDependencies ^ eFetchDependencies.C6ENTITY;
878
- }
879
- }
880
- console.log('fetchReferences', fetchReferences_1[tableToFetch], "Current fetchDependencies for (" + operatingTable + "):", fetchDependencies, "New fetchDependencies for (" + tableToFetch + "): ", nextFetchDependencies);
881
- // 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
882
- // it not certain that they are using carbons' entities either
883
- // this is a dynamic call to the rest api, any generated table may resolve with (RestApi)
884
- // todo - using value to avoid joins.... but. maybe this should be a parameterizable option -- think race conditions; its safer to join
885
- apiRequestPromises.push(RestApi.Get((_p = {},
886
- _p[C6.WHERE] = {
887
- 0: Object.keys(fetchReferences_1[tableToFetch]).reduce(function (sum, column) {
888
- fetchReferences_1[tableToFetch][column] = fetchReferences_1[tableToFetch][column].flat(Infinity);
889
- if (0 === fetchReferences_1[tableToFetch][column].length) {
890
- console.warn('The column (' + column + ') was not found in the response data. We will not fetch.', responseData_1);
891
- return false;
942
+ if (cachingConfirmed) {
943
+ cacheIndex = apiRequestCache.findIndex(function (cache) { return cache.requestArgumentsSerialized === querySerialized; });
944
+ apiRequestCache[cacheIndex].final = false === returnGetNextPageFunction;
945
+ // only cache get method requests
946
+ apiRequestCache[cacheIndex].response = response;
947
+ }
948
+ apiResponse = TestRestfulResponse(response, success, error);
949
+ if (false === apiResponse) {
950
+ if (debug && isDevelopment) {
951
+ toast.warning("DEVS: TestRestfulResponse returned false for (" + operatingTable + ").", toastOptionsDevs);
892
952
  }
893
- sum[column] = fetchReferences_1[tableToFetch][column].length === 1
894
- ? fetchReferences_1[tableToFetch][column][0]
895
- : [
896
- C6.IN, fetchReferences_1[tableToFetch][column]
897
- ];
898
- return sum;
899
- }, {})
900
- },
901
- _p.fetchDependencies = nextFetchDependencies,
902
- _p)));
903
- return [2 /*return*/];
904
- }
905
- });
906
- };
907
- _a = fetchReferences_1;
908
- _b = [];
909
- for (_c in _a)
910
- _b.push(_c);
911
- _i = 0;
912
- _o.label = 1;
913
- case 1:
914
- if (!(_i < _b.length)) return [3 /*break*/, 4];
915
- _c = _b[_i];
916
- if (!(_c in _a)) return [3 /*break*/, 3];
917
- tableToFetch = _c;
918
- return [5 /*yield**/, _loop_1(tableToFetch)];
919
- case 2:
920
- _o.sent();
921
- _o.label = 3;
922
- case 3:
923
- _i++;
924
- return [3 /*break*/, 1];
925
- case 4:
926
- console.groupEnd();
927
- return [4 /*yield*/, Promise.all(apiRequestPromises)];
928
- case 5:
929
- _o.sent();
930
- apiRequestPromises.map(function (promise) { return __awaiter(_this, void 0, void 0, function () {
931
- var _a, _b;
932
- return __generator(this, function (_c) {
933
- switch (_c.label) {
934
- case 0:
935
- if (!Array.isArray(request.fetchDependencies)) {
936
- request.fetchDependencies = [];
953
+ return [2 /*return*/, response];
954
+ }
955
+ // stateful operations are done in the response callback - its leverages rest generated functions
956
+ if (responseCallback) {
957
+ responseCallback(response, this.request, apiResponse);
958
+ }
959
+ if (!(C6.GET === requestMethod)) return [3 /*break*/, 6];
960
+ responseData_1 = response.data;
961
+ returnGetNextPageFunction = 1 !== ((_d = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _d === void 0 ? void 0 : _d[C6.LIMIT]) &&
962
+ ((_e = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _e === void 0 ? void 0 : _e[C6.LIMIT]) === responseData_1.rest.length;
963
+ if (false === isTest || true === isVerbose) {
964
+ 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');
965
+ console.log('%c ' + requestMethod + ' ' + tableName, 'color: #0c0');
966
+ console.log('%c Request Data (note you may see the success and/or error prompt):', 'color: #0c0', this.request);
967
+ console.log('%c Response Data:', 'color: #0c0', responseData_1.rest);
968
+ console.log('%c Will return get next page function:' + (1 !== ((_h = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _h === void 0 ? void 0 : _h[C6.LIMIT]) ? '' : ' (Will not return with explicit limit 1 set)'), 'color: #0c0', true === returnGetNextPageFunction);
969
+ console.trace();
970
+ console.groupEnd();
971
+ }
972
+ if (false === returnGetNextPageFunction
973
+ && true === debug
974
+ && isDevelopment) {
975
+ toast.success("DEVS: Response returned length (" + ((_j = responseData_1.rest) === null || _j === void 0 ? void 0 : _j.length) + ") less than limit (" + ((_k = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _k === void 0 ? void 0 : _k[C6.LIMIT]) + ").", toastOptionsDevs);
976
+ }
977
+ if (!(fetchDependencies
978
+ && 'number' === typeof fetchDependencies
979
+ && responseData_1.rest.length > 0)) return [3 /*break*/, 6];
980
+ console.groupCollapsed('%c API: Fetch Dependencies segment (' + requestMethod + ' ' + tableName + ')'
981
+ + (fetchDependencies & eFetchDependencies.CHILDREN ? ' | (CHILDREN|REFERENCED) ' : '')
982
+ + (fetchDependencies & eFetchDependencies.PARENTS ? ' | (PARENTS|REFERENCED_BY)' : '')
983
+ + (fetchDependencies & eFetchDependencies.C6ENTITY ? ' | (C6ENTITY)' : '')
984
+ + (fetchDependencies & eFetchDependencies.RECURSIVE ? ' | (RECURSIVE)' : ''), 'color: #33ccff');
985
+ console.groupCollapsed('Collapsed JS Trace');
986
+ console.trace(); // hidden in collapsed group
987
+ console.groupEnd();
988
+ dependencies_1 = {};
989
+ if (fetchDependencies & eFetchDependencies.C6ENTITY) {
990
+ dependencies_1 = operatingTable.endsWith("carbon_carbons")
991
+ ? __assign(__assign({}, fetchDependencies & eFetchDependencies.CHILDREN // REFERENCED === CHILDREN
992
+ ? C6.TABLES[operatingTable].TABLE_REFERENCED_BY
993
+ : {}), fetchDependencies & eFetchDependencies.PARENTS // REFERENCES === PARENTS
994
+ ? C6.TABLES[operatingTable].TABLE_REFERENCES
995
+ : {}) : __assign(__assign({}, fetchDependencies & eFetchDependencies.CHILDREN // REFERENCED === CHILDREN
996
+ ? __assign(__assign({}, Object.keys(C6.TABLES[operatingTable].TABLE_REFERENCES).reduce(function (accumulator, columnName) {
997
+ if (!C6.TABLES[operatingTable].PRIMARY_SHORT.includes(columnName)) {
998
+ accumulator[columnName] = C6.TABLES[operatingTable].TABLE_REFERENCES[columnName];
999
+ }
1000
+ return accumulator;
1001
+ }, {})), C6.TABLES[operatingTable].TABLE_REFERENCED_BY // it is unlikely that a C6 table will have any TABLE_REFERENCED_BY
1002
+ ) : {}), fetchDependencies & eFetchDependencies.PARENTS // REFERENCES === PARENTS
1003
+ ? C6.TABLES[operatingTable].PRIMARY_SHORT.reduce(function (accumulator, primaryKey) {
1004
+ if (primaryKey in C6.TABLES[operatingTable].TABLE_REFERENCES) {
1005
+ accumulator[primaryKey] = C6.TABLES[operatingTable].TABLE_REFERENCES[primaryKey];
1006
+ }
1007
+ return accumulator;
1008
+ }, {})
1009
+ : {});
1010
+ }
1011
+ else {
1012
+ // this is the natural mysql context
1013
+ dependencies_1 = __assign(__assign({}, fetchDependencies & eFetchDependencies.REFERENCED // REFERENCED === CHILDREN
1014
+ ? C6.TABLES[operatingTable].TABLE_REFERENCED_BY
1015
+ : {}), fetchDependencies & eFetchDependencies.REFERENCES // REFERENCES === PARENTS
1016
+ ? C6.TABLES[operatingTable].TABLE_REFERENCES
1017
+ : {});
1018
+ }
1019
+ fetchReferences_1 = {};
1020
+ apiRequestPromises = [];
1021
+ console.log('%c Dependencies', 'color: #005555', dependencies_1);
1022
+ Object.keys(dependencies_1)
1023
+ .forEach(function (column) { return dependencies_1[column]
1024
+ .forEach(function (constraint) {
1025
+ var _a, _b, _c, _d;
1026
+ var _e, _f, _g;
1027
+ var columnValues = (_b = (_a = responseData_1.rest[column]) !== null && _a !== void 0 ? _a : responseData_1.rest.map(function (row) {
1028
+ if (operatingTable.endsWith("carbons")
1029
+ && 'entity_tag' in row
1030
+ && !constraint.TABLE.endsWith(row['entity_tag'].split('\\').pop().toLowerCase())) {
1031
+ return false; // map
1032
+ }
1033
+ if (!(column in row)) {
1034
+ return false;
1035
+ }
1036
+ // todo - row[column] is a FK value, we should optionally remove values that are already in state
1037
+ // this could be any column in the table constraint.TABLE, not just the primary key
1038
+ return row[column];
1039
+ }).filter(function (n) { return n; })) !== null && _b !== void 0 ? _b : [];
1040
+ if (columnValues.length === 0) {
1041
+ return; // forEach
1042
+ }
1043
+ (_c = fetchReferences_1[_e = constraint.TABLE]) !== null && _c !== void 0 ? _c : (fetchReferences_1[_e] = {});
1044
+ (_d = (_f = fetchReferences_1[constraint.TABLE])[_g = constraint.COLUMN]) !== null && _d !== void 0 ? _d : (_f[_g] = []);
1045
+ fetchReferences_1[constraint.TABLE][constraint.COLUMN].push(columnValues);
1046
+ }); });
1047
+ console.log('fetchReferences', fetchReferences_1);
1048
+ _loop_1 = function (tableToFetch) {
1049
+ var referencesTables, shouldContinue, fetchTable, RestApi, nextFetchDependencies;
1050
+ var _m;
1051
+ return __generator(this, function (_o) {
1052
+ switch (_o.label) {
1053
+ case 0:
1054
+ if (fetchDependencies & eFetchDependencies.C6ENTITY
1055
+ && 'string' === typeof tableName
1056
+ && tableName.endsWith("carbon_carbons")) {
1057
+ referencesTables = responseData_1.rest.reduce(function (accumulator, row) {
1058
+ if ('entity_tag' in row && !accumulator.includes(row['entity_tag'])) {
1059
+ accumulator.push(row['entity_tag']);
1060
+ }
1061
+ return accumulator;
1062
+ }, []).map(function (entityTag) { return entityTag.split('\\').pop().toLowerCase(); });
1063
+ shouldContinue = referencesTables.find(function (referencesTable) { return tableToFetch.endsWith(referencesTable); });
1064
+ if (!shouldContinue) {
1065
+ console.log('%c C6ENTITY: The constraintTableName (' + tableToFetch + ') did not end with any value in referencesTables', 'color: #c00', referencesTables);
1066
+ return [2 /*return*/, "continue"];
1067
+ }
1068
+ console.log('%c C6ENTITY: The constraintTableName (' + tableToFetch + ') will be fetched.', 'color: #0c0');
1069
+ }
1070
+ return [4 /*yield*/, C6.IMPORT(tableToFetch)];
1071
+ case 1:
1072
+ fetchTable = _o.sent();
1073
+ RestApi = fetchTable.default;
1074
+ console.log('%c Fetch Dependencies will select (' + tableToFetch + ') using GET request', 'color: #33ccff');
1075
+ nextFetchDependencies = eFetchDependencies.NONE;
1076
+ if (fetchDependencies & eFetchDependencies.RECURSIVE) {
1077
+ if (fetchDependencies & eFetchDependencies.ALL) {
1078
+ 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.');
1079
+ }
1080
+ nextFetchDependencies = fetchDependencies;
1081
+ }
1082
+ else if (fetchDependencies & eFetchDependencies.C6ENTITY) {
1083
+ if (tableToFetch === "carbon_carbons") {
1084
+ nextFetchDependencies = fetchDependencies;
1085
+ }
1086
+ else {
1087
+ nextFetchDependencies = fetchDependencies ^ eFetchDependencies.C6ENTITY;
1088
+ }
1089
+ }
1090
+ console.log('fetchReferences', fetchReferences_1[tableToFetch], "Current fetchDependencies for (" + operatingTable + "):", fetchDependencies, "New fetchDependencies for (" + tableToFetch + "): ", nextFetchDependencies);
1091
+ // 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
1092
+ // it not certain that they are using carbons' entities either
1093
+ // this is a dynamic call to the rest api, any generated table may resolve with (RestApi)
1094
+ // todo - using value to avoid joins.... but. maybe this should be a parameterizable option -- think race conditions; its safer to join
1095
+ apiRequestPromises.push(RestApi.Get((_m = {},
1096
+ _m[C6.WHERE] = {
1097
+ 0: Object.keys(fetchReferences_1[tableToFetch]).reduce(function (sum, column) {
1098
+ fetchReferences_1[tableToFetch][column] = fetchReferences_1[tableToFetch][column].flat(Infinity);
1099
+ if (0 === fetchReferences_1[tableToFetch][column].length) {
1100
+ console.warn('The column (' + column + ') was not found in the response data. We will not fetch.', responseData_1);
1101
+ return false;
1102
+ }
1103
+ sum[column] = fetchReferences_1[tableToFetch][column].length === 1
1104
+ ? fetchReferences_1[tableToFetch][column][0]
1105
+ : [
1106
+ C6.IN, fetchReferences_1[tableToFetch][column]
1107
+ ];
1108
+ return sum;
1109
+ }, {})
1110
+ },
1111
+ _m.fetchDependencies = nextFetchDependencies,
1112
+ _m)));
1113
+ return [2 /*return*/];
1114
+ }
1115
+ });
1116
+ };
1117
+ _a = fetchReferences_1;
1118
+ _b = [];
1119
+ for (_c in _a)
1120
+ _b.push(_c);
1121
+ _i = 0;
1122
+ _l.label = 1;
1123
+ case 1:
1124
+ if (!(_i < _b.length)) return [3 /*break*/, 4];
1125
+ _c = _b[_i];
1126
+ if (!(_c in _a)) return [3 /*break*/, 3];
1127
+ tableToFetch = _c;
1128
+ return [5 /*yield**/, _loop_1(tableToFetch)];
1129
+ case 2:
1130
+ _l.sent();
1131
+ _l.label = 3;
1132
+ case 3:
1133
+ _i++;
1134
+ return [3 /*break*/, 1];
1135
+ case 4:
1136
+ console.groupEnd();
1137
+ return [4 /*yield*/, Promise.all(apiRequestPromises)];
1138
+ case 5:
1139
+ _l.sent();
1140
+ apiRequestPromises.map(function (promise) { return __awaiter(_this, void 0, void 0, function () {
1141
+ var _a, _b;
1142
+ return __generator(this, function (_c) {
1143
+ switch (_c.label) {
1144
+ case 0:
1145
+ if (!Array.isArray(this.request.fetchDependencies)) {
1146
+ // to reassign value we must ref the root
1147
+ this.request.fetchDependencies = [];
1148
+ }
1149
+ _b = (_a = this.request.fetchDependencies).push;
1150
+ return [4 /*yield*/, promise];
1151
+ case 1:
1152
+ _b.apply(_a, [_c.sent()]);
1153
+ return [2 /*return*/];
1154
+ }
1155
+ });
1156
+ }); });
1157
+ _l.label = 6;
1158
+ case 6:
1159
+ if (debug && isDevelopment) {
1160
+ toast.success("DEVS: (" + requestMethod + ") request complete.", toastOptionsDevs);
1161
+ }
1162
+ return [2 /*return*/, response];
937
1163
  }
938
- _b = (_a = request.fetchDependencies).push;
939
- return [4 /*yield*/, promise];
940
- case 1:
941
- _b.apply(_a, [_c.sent()]);
942
- return [2 /*return*/];
943
- }
944
- });
945
- }); });
946
- _o.label = 6;
947
- case 6:
948
- if (request.debug && isDevelopment) {
949
- toast.success("DEVS: (" + requestMethod + ") request complete.", toastOptionsDevs);
1164
+ });
1165
+ }); })];
950
1166
  }
951
- return [2 /*return*/, response];
952
- }
953
- });
954
- }); });
955
- }
956
- catch (error) {
957
- if (isTest) {
958
- throw new Error(JSON.stringify(error));
1167
+ catch (throwableError) {
1168
+ if (isTest) {
1169
+ throw new Error(JSON.stringify(throwableError));
1170
+ }
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*/];
1180
+ });
1181
+ }); };
1182
+ return [4 /*yield*/, apiRequest()];
1183
+ case 1: return [2 /*return*/, _b.sent()];
959
1184
  }
960
- console.groupCollapsed('%c API: An error occurred in the try catch block. returning null!', 'color: #ff0000');
961
- console.log('%c ' + requestMethod + ' ' + tableName, 'color: #A020F0');
962
- console.warn(error);
963
- console.trace();
964
- console.groupEnd();
965
- TestRestfulResponse(error, request === null || request === void 0 ? void 0 : request.success, (request === null || request === void 0 ? void 0 : request.error) || "An restful API error occurred!");
966
- return null;
967
- }
1185
+ });
1186
+ });
1187
+ };
1188
+ return HttpExecutor;
1189
+ }(Executor));
1190
+
1191
+ var HttpExecutor$1 = /*#__PURE__*/Object.freeze({
1192
+ __proto__: null,
1193
+ HttpExecutor: HttpExecutor
1194
+ });
1195
+
1196
+ var SqlExecutor = /** @class */ (function (_super) {
1197
+ __extends(SqlExecutor, _super);
1198
+ function SqlExecutor() {
1199
+ return _super !== null && _super.apply(this, arguments) || this;
1200
+ }
1201
+ SqlExecutor.prototype.execute = function () {
1202
+ switch (this.config.requestMethod) {
1203
+ case 'GET':
1204
+ return this.select(this.config.tableName, undefined, this.request).then(function (rows) { return ({ rest: rows }); });
1205
+ case 'POST':
1206
+ return this.insert(this.config.tableName, this.request);
1207
+ case 'PUT':
1208
+ return this.update(this.config.tableName, undefined, this.request);
1209
+ case 'DELETE':
1210
+ return this.delete(this.config.tableName, undefined, this.request);
968
1211
  }
969
- return apiRequest();
970
1212
  };
1213
+ SqlExecutor.prototype.withConnection = function (cb) {
1214
+ return __awaiter(this, void 0, void 0, function () {
1215
+ var conn;
1216
+ return __generator(this, function (_a) {
1217
+ switch (_a.label) {
1218
+ case 0: return [4 /*yield*/, this.config.mysqlPool.getConnection()];
1219
+ case 1:
1220
+ conn = _a.sent();
1221
+ _a.label = 2;
1222
+ case 2:
1223
+ _a.trys.push([2, , 4, 5]);
1224
+ return [4 /*yield*/, cb(conn)];
1225
+ case 3: return [2 /*return*/, _a.sent()];
1226
+ case 4:
1227
+ conn.release();
1228
+ return [7 /*endfinally*/];
1229
+ case 5: return [2 /*return*/];
1230
+ }
1231
+ });
1232
+ });
1233
+ };
1234
+ SqlExecutor.prototype.select = function (table, primary, args) {
1235
+ return __awaiter(this, void 0, void 0, function () {
1236
+ var sql;
1237
+ var _this = this;
1238
+ return __generator(this, function (_a) {
1239
+ switch (_a.label) {
1240
+ case 0:
1241
+ sql = buildSelectQuery(table, primary, args);
1242
+ return [4 /*yield*/, this.withConnection(function (conn) { return __awaiter(_this, void 0, void 0, function () {
1243
+ var rows;
1244
+ return __generator(this, function (_a) {
1245
+ switch (_a.label) {
1246
+ case 0:
1247
+ console.log(sql);
1248
+ return [4 /*yield*/, conn.query(sql)];
1249
+ case 1:
1250
+ rows = (_a.sent())[0];
1251
+ return [2 /*return*/, rows];
1252
+ }
1253
+ });
1254
+ }); })];
1255
+ case 1: return [2 /*return*/, _a.sent()];
1256
+ }
1257
+ });
1258
+ });
1259
+ };
1260
+ SqlExecutor.prototype.insert = function (table, data) {
1261
+ return __awaiter(this, void 0, void 0, function () {
1262
+ var keys, values, placeholders, sql;
1263
+ var _this = this;
1264
+ return __generator(this, function (_a) {
1265
+ switch (_a.label) {
1266
+ case 0:
1267
+ keys = Object.keys(data);
1268
+ values = keys.map(function (k) { return data[k]; });
1269
+ placeholders = keys.map(function () { return '?'; }).join(', ');
1270
+ sql = "INSERT INTO `".concat(table, "` (").concat(keys.join(', '), ") VALUES (").concat(placeholders, ")");
1271
+ return [4 /*yield*/, this.withConnection(function (conn) { return __awaiter(_this, void 0, void 0, function () {
1272
+ var result;
1273
+ return __generator(this, function (_a) {
1274
+ switch (_a.label) {
1275
+ case 0: return [4 /*yield*/, conn.execute(sql, values)];
1276
+ case 1:
1277
+ result = (_a.sent())[0];
1278
+ return [2 /*return*/, result];
1279
+ }
1280
+ });
1281
+ }); })];
1282
+ case 1: return [2 /*return*/, _a.sent()];
1283
+ }
1284
+ });
1285
+ });
1286
+ };
1287
+ SqlExecutor.prototype.update = function (table, primary, data) {
1288
+ return __awaiter(this, void 0, void 0, function () {
1289
+ var keys, values, updates, sql;
1290
+ var _this = this;
1291
+ return __generator(this, function (_a) {
1292
+ switch (_a.label) {
1293
+ case 0:
1294
+ if (!primary) {
1295
+ throw new Error('Primary key is required for update');
1296
+ }
1297
+ keys = Object.keys(data);
1298
+ values = keys.map(function (k) { return data[k]; });
1299
+ updates = keys.map(function (k) { return "`".concat(k, "` = ?"); }).join(', ');
1300
+ sql = "UPDATE `".concat(table, "` SET ").concat(updates, " WHERE `").concat(primary, "` = ?");
1301
+ values.push(data[primary]);
1302
+ return [4 /*yield*/, this.withConnection(function (conn) { return __awaiter(_this, void 0, void 0, function () {
1303
+ var result;
1304
+ return __generator(this, function (_a) {
1305
+ switch (_a.label) {
1306
+ case 0: return [4 /*yield*/, conn.execute(sql, values)];
1307
+ case 1:
1308
+ result = (_a.sent())[0];
1309
+ return [2 /*return*/, result];
1310
+ }
1311
+ });
1312
+ }); })];
1313
+ case 1: return [2 /*return*/, _a.sent()];
1314
+ }
1315
+ });
1316
+ });
1317
+ };
1318
+ SqlExecutor.prototype.delete = function (table, primary, args) {
1319
+ return __awaiter(this, void 0, void 0, function () {
1320
+ var sql;
1321
+ var _this = this;
1322
+ return __generator(this, function (_a) {
1323
+ switch (_a.label) {
1324
+ case 0:
1325
+ if (!primary || !(args === null || args === void 0 ? void 0 : args[primary])) {
1326
+ throw new Error('Primary key and value required for delete');
1327
+ }
1328
+ sql = "DELETE FROM `".concat(table, "` WHERE `").concat(primary, "` = ?");
1329
+ return [4 /*yield*/, this.withConnection(function (conn) { return __awaiter(_this, void 0, void 0, function () {
1330
+ var result;
1331
+ return __generator(this, function (_a) {
1332
+ switch (_a.label) {
1333
+ case 0: return [4 /*yield*/, conn.execute(sql, [args[primary]])];
1334
+ case 1:
1335
+ result = (_a.sent())[0];
1336
+ return [2 /*return*/, result];
1337
+ }
1338
+ });
1339
+ }); })];
1340
+ case 1: return [2 /*return*/, _a.sent()];
1341
+ }
1342
+ });
1343
+ });
1344
+ };
1345
+ return SqlExecutor;
1346
+ }(Executor));
1347
+
1348
+ var SqlExecutor$1 = /*#__PURE__*/Object.freeze({
1349
+ __proto__: null,
1350
+ SqlExecutor: SqlExecutor
1351
+ });
1352
+
1353
+ /**
1354
+ * Conditionally group a log if verbose.
1355
+ */
1356
+ function group(title, data) {
1357
+ if (!isVerbose)
1358
+ return;
1359
+ console.groupCollapsed("%c".concat(title), "color: #007acc");
1360
+ if (data !== undefined)
1361
+ console.log(data);
1362
+ console.groupEnd();
1363
+ }
1364
+ function info(message) {
1365
+ var optional = [];
1366
+ for (var _i = 1; _i < arguments.length; _i++) {
1367
+ optional[_i - 1] = arguments[_i];
1368
+ }
1369
+ if (!isVerbose)
1370
+ return;
1371
+ console.info.apply(console, __spreadArray(["%cINFO: ".concat(message), "color: #0a0"], optional, false));
1372
+ }
1373
+ function warn(message) {
1374
+ var optional = [];
1375
+ for (var _i = 1; _i < arguments.length; _i++) {
1376
+ optional[_i - 1] = arguments[_i];
1377
+ }
1378
+ console.warn.apply(console, __spreadArray(["%cWARN: ".concat(message), "color: #e90"], optional, false));
1379
+ }
1380
+ function error(message) {
1381
+ var optional = [];
1382
+ for (var _i = 1; _i < arguments.length; _i++) {
1383
+ optional[_i - 1] = arguments[_i];
1384
+ }
1385
+ console.error.apply(console, __spreadArray(["%cERROR: ".concat(message), "color: #c00"], optional, false));
971
1386
  }
972
1387
 
973
- function timeout(shouldContinueAfterTimeout, cb, timeoutMs) {
974
- if (timeoutMs === void 0) { timeoutMs = 3000; }
975
- var timer = function () { return setTimeout(function () {
976
- if (false === shouldContinueAfterTimeout()) {
977
- return;
1388
+ function checkAllRequestsComplete() {
1389
+ var stillRunning = apiRequestCache.filter(function (cache) { return undefined === cache.response; });
1390
+ if (stillRunning.length !== 0) {
1391
+ if (document === null || document === undefined) {
1392
+ throw new Error('document is undefined while waiting for API requests to complete (' + JSON.stringify(apiRequestCache) + ')');
978
1393
  }
979
- cb();
980
- }, timeoutMs); };
981
- var timerId = timer();
982
- return function () {
983
- clearTimeout(timerId);
984
- };
1394
+ // when requests return emtpy sets in full renders, it may not be possible to track their progress.
1395
+ console.warn('stillRunning...', stillRunning);
1396
+ return stillRunning.map(function (cache) { return cache.requestArgumentsSerialized; });
1397
+ }
1398
+ return true;
1399
+ }
1400
+
1401
+ function onSuccess(message) {
1402
+ toast.success(message, isDevelopment ? toastOptionsDevs : toastOptions);
1403
+ }
1404
+ function onError(message) {
1405
+ toast.error(message, isDevelopment ? toastOptionsDevs : toastOptions);
985
1406
  }
986
1407
 
987
- export { C6Constants, DELETE, GET, POST, PUT, TestRestfulResponse, axiosInstance, checkAllRequestsComplete, clearCache, convertForRequestBody, eFetchDependencies, extendedTypeHints, getEnvVar, isDevelopment as isLocal, isPromise, isTest, isVerbose, removeInvalidKeys, removePrefixIfExists, restRequest, timeout, toastOptions, toastOptionsDevs };
1408
+ export { C6Constants, DELETE, Executor, GET, HttpExecutor, POST, PUT, SqlExecutor, TestRestfulResponse, apiRequestCache, axiosInstance, buildAggregateField, buildBooleanJoinedConditions, buildSelectQuery, checkAllRequestsComplete, checkCache, clearCache, convertForRequestBody, eFetchDependencies, error, extendedTypeHints, getEnvVar, group, info, isDevelopment as isLocal, isNode, isPromise, isTest, isVerbose, onError, onSuccess, removeInvalidKeys, removePrefixIfExists, restRequest, sortAndSerializeQueryObject, timeout, toastOptions, toastOptionsDevs, userCustomClearCache, warn };
988
1409
  //# sourceMappingURL=index.esm.js.map