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