@carbonorm/carbonnode 6.0.14 → 6.0.18

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 (77) hide show
  1. package/dist/executors/SqlExecutor.d.ts +17 -0
  2. package/dist/index.cjs.js +450 -248
  3. package/dist/index.cjs.js.map +1 -1
  4. package/dist/index.esm.js +450 -249
  5. package/dist/index.esm.js.map +1 -1
  6. package/dist/types/ormInterfaces.d.ts +1 -0
  7. package/dist/utils/cacheManager.d.ts +3 -1
  8. package/dist/utils/logLevel.d.ts +3 -3
  9. package/dist/utils/logSql.d.ts +10 -1
  10. package/package.json +2 -2
  11. package/scripts/assets/handlebars/C6.ts.handlebars +1 -1
  12. package/src/__tests__/fixtures/sqlResponses/sqlAllowList.json +1 -1
  13. package/src/__tests__/httpExecutor.cacheEviction.test.ts +70 -0
  14. package/src/__tests__/logSql.test.ts +54 -2
  15. package/src/__tests__/sakila-db/C6.js +1 -1
  16. package/src/__tests__/sakila-db/C6.mysqldump.json +1 -1
  17. package/src/__tests__/sakila-db/C6.mysqldump.sql +1 -1
  18. package/src/__tests__/sakila-db/C6.sqlAllowList.json +59 -70
  19. package/src/__tests__/sakila-db/C6.ts +2 -2
  20. package/src/__tests__/sakila-db/sqlResponses/C6.actor.post.json +3 -3
  21. package/src/__tests__/sakila-db/sqlResponses/C6.actor.post.latest.json +3 -3
  22. package/src/__tests__/sakila-db/sqlResponses/C6.actor.put.json +1 -1
  23. package/src/__tests__/sakila-db/sqlResponses/C6.actor.put.lookup.json +3 -3
  24. package/src/__tests__/sakila-db/sqlResponses/C6.address.post.json +5 -5
  25. package/src/__tests__/sakila-db/sqlResponses/C6.address.post.latest.json +5 -5
  26. package/src/__tests__/sakila-db/sqlResponses/C6.address.put.json +1 -1
  27. package/src/__tests__/sakila-db/sqlResponses/C6.address.put.lookup.json +5 -5
  28. package/src/__tests__/sakila-db/sqlResponses/C6.category.post.json +2 -2
  29. package/src/__tests__/sakila-db/sqlResponses/C6.category.post.latest.json +2 -2
  30. package/src/__tests__/sakila-db/sqlResponses/C6.category.put.json +1 -1
  31. package/src/__tests__/sakila-db/sqlResponses/C6.category.put.lookup.json +2 -2
  32. package/src/__tests__/sakila-db/sqlResponses/C6.city.post.json +2 -2
  33. package/src/__tests__/sakila-db/sqlResponses/C6.city.post.latest.json +2 -2
  34. package/src/__tests__/sakila-db/sqlResponses/C6.city.put.json +1 -1
  35. package/src/__tests__/sakila-db/sqlResponses/C6.city.put.lookup.json +2 -2
  36. package/src/__tests__/sakila-db/sqlResponses/C6.country.post.json +2 -2
  37. package/src/__tests__/sakila-db/sqlResponses/C6.country.post.latest.json +2 -2
  38. package/src/__tests__/sakila-db/sqlResponses/C6.country.put.json +1 -1
  39. package/src/__tests__/sakila-db/sqlResponses/C6.country.put.lookup.json +2 -2
  40. package/src/__tests__/sakila-db/sqlResponses/C6.customer.post.json +5 -5
  41. package/src/__tests__/sakila-db/sqlResponses/C6.customer.post.latest.json +5 -5
  42. package/src/__tests__/sakila-db/sqlResponses/C6.customer.put.json +1 -1
  43. package/src/__tests__/sakila-db/sqlResponses/C6.customer.put.lookup.json +5 -5
  44. package/src/__tests__/sakila-db/sqlResponses/C6.film.post.json +2 -2
  45. package/src/__tests__/sakila-db/sqlResponses/C6.film.post.latest.json +2 -2
  46. package/src/__tests__/sakila-db/sqlResponses/C6.film.put.json +1 -1
  47. package/src/__tests__/sakila-db/sqlResponses/C6.film.put.lookup.json +2 -2
  48. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.post.json +1 -1
  49. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.post.latest.json +1 -1
  50. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.put.json +1 -1
  51. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.put.lookup.json +1 -1
  52. package/src/__tests__/sakila-db/sqlResponses/C6.language.post.json +2 -2
  53. package/src/__tests__/sakila-db/sqlResponses/C6.language.post.latest.json +2 -2
  54. package/src/__tests__/sakila-db/sqlResponses/C6.language.put.json +1 -1
  55. package/src/__tests__/sakila-db/sqlResponses/C6.language.put.lookup.json +2 -2
  56. package/src/__tests__/sakila-db/sqlResponses/C6.payment.post.json +2 -2
  57. package/src/__tests__/sakila-db/sqlResponses/C6.payment.post.latest.json +2 -2
  58. package/src/__tests__/sakila-db/sqlResponses/C6.payment.put.lookup.json +2 -2
  59. package/src/__tests__/sakila-db/sqlResponses/C6.rental.join.json +10 -10
  60. package/src/__tests__/sakila-db/sqlResponses/C6.rental.post.json +3 -3
  61. package/src/__tests__/sakila-db/sqlResponses/C6.rental.post.latest.json +3 -3
  62. package/src/__tests__/sakila-db/sqlResponses/C6.rental.put.json +1 -1
  63. package/src/__tests__/sakila-db/sqlResponses/C6.rental.put.lookup.json +3 -3
  64. package/src/__tests__/sqlAllowList.test.ts +100 -0
  65. package/src/__tests__/sqlBuilders.test.ts +3 -4
  66. package/src/__tests__/sqlExecutor.cacheEviction.test.ts +79 -0
  67. package/src/executors/HttpExecutor.ts +20 -4
  68. package/src/executors/SqlExecutor.ts +131 -12
  69. package/src/orm/queries/DeleteQueryBuilder.ts +0 -4
  70. package/src/orm/queries/PostQueryBuilder.ts +0 -4
  71. package/src/orm/queries/SelectQueryBuilder.ts +0 -4
  72. package/src/orm/queries/UpdateQueryBuilder.ts +0 -4
  73. package/src/types/ormInterfaces.ts +4 -1
  74. package/src/utils/cacheManager.ts +26 -9
  75. package/src/utils/logLevel.ts +3 -4
  76. package/src/utils/logSql.ts +51 -6
  77. package/src/utils/sqlAllowList.ts +111 -9
package/dist/index.cjs.js CHANGED
@@ -517,8 +517,6 @@ var applyLogLevelDefaults = function (config, request) {
517
517
  };
518
518
  var getLogContext = function (config, request) {
519
519
  var _a, _b;
520
- if (!config && !request)
521
- return undefined;
522
520
  return {
523
521
  logLevel: (_a = config === null || config === void 0 ? void 0 : config.logLevel) !== null && _a !== void 0 ? _a : undefined,
524
522
  verbose: (_b = config === null || config === void 0 ? void 0 : config.verbose) !== null && _b !== void 0 ? _b : undefined,
@@ -865,6 +863,213 @@ function removeInvalidKeys(request, c6Tables) {
865
863
  return intersection;
866
864
  }
867
865
 
866
+ /* eslint-disable no-control-regex */
867
+ var RESET = "\x1b[0m";
868
+ var C$1 = {
869
+ KEYWORD: "\x1b[94m", // blue
870
+ LIMIT: "\x1b[93m", // yellow
871
+ NUMBER: "\x1b[92m", // green
872
+ DIM: "\x1b[90m", // gray
873
+ };
874
+ /* ---------- ANSI helpers ---------- */
875
+ var ansi256 = function (n) { return "\u001B[38;5;".concat(n, "m"); };
876
+ /* ---------- hashing ---------- */
877
+ function hashString$1(str) {
878
+ var hash = 0;
879
+ for (var i = 0; i < str.length; i++) {
880
+ hash = (hash * 31 + str.charCodeAt(i)) | 0;
881
+ }
882
+ return Math.abs(hash);
883
+ }
884
+ /* ---------- table color ---------- */
885
+ function tableRGB(tableName) {
886
+ var name = tableName.replace(/[`"]/g, "").toLowerCase();
887
+ var hash = hashString$1(name);
888
+ // Stable hue bucket by first letter
889
+ var first = name.charCodeAt(0) || 97;
890
+ var hueBase = (first - 97) % 6;
891
+ var r = (hueBase + (hash % 3)) % 6;
892
+ var g = (hash >> 3) % 6;
893
+ var b = (hash >> 6) % 6;
894
+ return [r, g, Math.max(2, b)]; // avoid muddy dark blues
895
+ }
896
+ function tableColor(table) {
897
+ var _a = tableRGB(table), r = _a[0], g = _a[1], b = _a[2];
898
+ return ansi256(16 + 36 * r + 6 * g + b);
899
+ }
900
+ /* ---------- column color (same hue, lighter) ---------- */
901
+ function columnColorFromTable(table) {
902
+ var _a = tableRGB(table), r = _a[0], g = _a[1], b = _a[2];
903
+ // Lift toward white, preserve hue
904
+ var lr = Math.min(5, r + 1);
905
+ var lg = Math.min(5, g + 1);
906
+ var lb = Math.min(5, b + 2);
907
+ return ansi256(16 + 36 * lr + 6 * lg + lb);
908
+ }
909
+ /* ---------- bind collapsing ---------- */
910
+ /**
911
+ * ?, ?, ?, ?, ?, ? → ? ×6
912
+ * triggers at 4+
913
+ */
914
+ function collapseBinds(sql) {
915
+ return sql.replace(/(\?\s*,\s*){3,}\?/g, function (match) {
916
+ var count = match.split("?").length - 1;
917
+ return "".concat(C$1.DIM, "? \u00D7").concat(count).concat(RESET);
918
+ });
919
+ }
920
+ /**
921
+ * ( ? ×9 ), ( ? ×9 ), ( ? ×9 ) -> ( ? ×9 ) ×3
922
+ */
923
+ function collapseRepeatedValueRows(sql) {
924
+ var repeatedRowPattern = /(\((?:\x1b\[[0-9;]*m)?\?\s*×\d+(?:\x1b\[[0-9;]*m)?\)|\(\s*(?:\?\s*,\s*)+\?\s*\))(?:\s*,\s*\1){2,}/g;
925
+ return sql.replace(repeatedRowPattern, function (match, row) {
926
+ var _a, _b;
927
+ var rowMatches = match.match(new RegExp(row.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"));
928
+ var count = (_a = rowMatches === null || rowMatches === void 0 ? void 0 : rowMatches.length) !== null && _a !== void 0 ? _a : 1;
929
+ var normalizedRow = row.includes("×")
930
+ ? row
931
+ : "(".concat(C$1.DIM, "? \u00D7").concat(((_b = row.match(/\?/g)) !== null && _b !== void 0 ? _b : []).length).concat(RESET, ")");
932
+ return "".concat(normalizedRow, " ").concat(C$1.DIM, "\u00D7").concat(count).concat(RESET);
933
+ });
934
+ }
935
+ /* ---------- main formatter ---------- */
936
+ function colorSql(sql) {
937
+ var s = sql.trim();
938
+ /* 1️⃣ collapse bind noise */
939
+ s = collapseBinds(s);
940
+ s = collapseRepeatedValueRows(s);
941
+ /* 2️⃣ table.column coloring (core visual grouping) */
942
+ s = s.replace(/\b(`?\w+`?)\.(\w+)\b/g, function (_, table, column) {
943
+ return "".concat(tableColor(table)).concat(table).concat(RESET, ".") +
944
+ "".concat(columnColorFromTable(table)).concat(column).concat(RESET);
945
+ });
946
+ /* 3️⃣ FROM / JOIN tables */
947
+ s = s.replace(/\b(FROM|JOIN|UPDATE|INTO)\s+(`[^`]+`|\w+)/gi, function (_, kw, table) {
948
+ return "".concat(C$1.KEYWORD).concat(kw).concat(RESET, " ").concat(tableColor(table)).concat(table).concat(RESET);
949
+ });
950
+ /* 4️⃣ SQL keywords */
951
+ s = s.replace(/\b(SELECT|WHERE|AND|OR|ON|IN|BETWEEN|EXISTS|ORDER BY|GROUP BY|HAVING|SET|VALUES|INSERT|REPLACE|DELETE|UPDATE|DUPLICATE|KEY)\b/gi, "".concat(C$1.KEYWORD, "$1").concat(RESET));
952
+ /* 5️⃣ LIMIT */
953
+ s = s.replace(/\bLIMIT\s+(\d+)/gi, "".concat(C$1.LIMIT, "LIMIT").concat(RESET, " ").concat(C$1.NUMBER, "$1").concat(RESET));
954
+ return s;
955
+ }
956
+
957
+ var version = "6.0.18";
958
+
959
+ var DEFAULT_STEP = 8;
960
+ function parseSemver(version) {
961
+ var _a = version.trim().split("-"), core = _a[0], prerelease = _a[1];
962
+ var _b = core.split("."), majorRaw = _b[0], minorRaw = _b[1], patchRaw = _b[2];
963
+ var major = Number.parseInt(majorRaw !== null && majorRaw !== void 0 ? majorRaw : "0", 10);
964
+ var minor = Number.parseInt(minorRaw !== null && minorRaw !== void 0 ? minorRaw : "0", 10);
965
+ var patch = Number.parseInt(patchRaw !== null && patchRaw !== void 0 ? patchRaw : "0", 10);
966
+ var prereleaseParts = prerelease ? prerelease.split(".").filter(Boolean).length : 0;
967
+ return {
968
+ major: Number.isFinite(major) ? major : 0,
969
+ minor: Number.isFinite(minor) ? minor : 0,
970
+ patch: Number.isFinite(patch) ? patch : 0,
971
+ prereleaseParts: prereleaseParts,
972
+ };
973
+ }
974
+ function channelValue(n, step) {
975
+ var value = 255 - ((n * step) % 256);
976
+ return (value + 256) % 256;
977
+ }
978
+ function versionToRgb(version, step) {
979
+ if (step === void 0) { step = DEFAULT_STEP; }
980
+ var safeStep = Number.isFinite(step) && step > 0 ? Math.floor(step) : DEFAULT_STEP;
981
+ var _a = parseSemver(version), major = _a.major, minor = _a.minor, patch = _a.patch, prereleaseParts = _a.prereleaseParts;
982
+ var rotation = (major + minor + patch + prereleaseParts) % 3;
983
+ var base = [major, minor, patch];
984
+ var rotated = rotation === 1
985
+ ? [base[2], base[0], base[1]]
986
+ : rotation === 2
987
+ ? [base[1], base[2], base[0]]
988
+ : base;
989
+ return {
990
+ r: channelValue(rotated[0], safeStep),
991
+ g: channelValue(rotated[1], safeStep),
992
+ b: channelValue(rotated[2], safeStep),
993
+ };
994
+ }
995
+
996
+ var C = {
997
+ SSR: "\x1b[95m", // bright magenta
998
+ HTTP: "\x1b[94m", // bright blue
999
+ WARN: "\x1b[93m", // yellow
1000
+ ORANGE: "\x1b[38;2;255;165;0m", // orange (truecolor)
1001
+ ERROR: "\x1b[91m", // red
1002
+ METHOD_COLORS: {
1003
+ SELECT: "\x1b[92m", // green
1004
+ INSERT: "\x1b[96m", // cyan
1005
+ REPLACE: "\x1b[96m", // cyan
1006
+ UPDATE: "\x1b[95m", // magenta
1007
+ DELETE: "\x1b[38;2;255;179;179m", // very light red (truecolor)
1008
+ },
1009
+ METHOD_FALLBACK: [
1010
+ "\x1b[92m", // green
1011
+ "\x1b[93m", // yellow
1012
+ "\x1b[95m", // magenta
1013
+ "\x1b[96m", // cyan
1014
+ "\x1b[94m", // blue
1015
+ "\x1b[97m", // white
1016
+ ],
1017
+ GREY: "\x1b[90m", // light grey
1018
+ RESET: "\x1b[0m",
1019
+ };
1020
+ var rgbAnsi = function (_a) {
1021
+ var r = _a.r, g = _a.g, b = _a.b;
1022
+ return "\u001B[38;2;".concat(r, ";").concat(g, ";").concat(b, "m");
1023
+ };
1024
+ function hashString(value) {
1025
+ var hash = 0;
1026
+ for (var i = 0; i < value.length; i++) {
1027
+ hash = (hash * 31 + value.charCodeAt(i)) | 0;
1028
+ }
1029
+ return Math.abs(hash);
1030
+ }
1031
+ function methodColor(method) {
1032
+ var key = method.toUpperCase();
1033
+ if (key in C.METHOD_COLORS) {
1034
+ return C.METHOD_COLORS[key];
1035
+ }
1036
+ var idx = hashString(key) % C.METHOD_FALLBACK.length;
1037
+ return C.METHOD_FALLBACK[idx];
1038
+ }
1039
+ var cacheLabel = function (cacheStatus) {
1040
+ switch (cacheStatus) {
1041
+ case "hit":
1042
+ return "".concat(C.METHOD_COLORS.SELECT, "[CACHE HIT]").concat(C.RESET);
1043
+ case "ignored":
1044
+ return "".concat(C.WARN, "[CACHE IGNORED]").concat(C.RESET);
1045
+ default:
1046
+ return "".concat(C.ORANGE, "[CACHE MISS]").concat(C.RESET);
1047
+ }
1048
+ };
1049
+ var allowListLabel = function (status) {
1050
+ switch (status) {
1051
+ case "allowed":
1052
+ return "".concat(C.METHOD_COLORS.SELECT, "[VERIFIED]").concat(C.RESET);
1053
+ case "denied":
1054
+ return "".concat(C.ERROR, "[DENIED]").concat(C.RESET);
1055
+ default:
1056
+ return "".concat(C.GREY, "[NOT VERIFIED]").concat(C.RESET);
1057
+ }
1058
+ };
1059
+ function logSql(options) {
1060
+ var method = options.method.toUpperCase();
1061
+ if (!shouldLog(exports.LogLevel.INFO, options.context))
1062
+ return;
1063
+ var preText = getEnvBool("SSR", false)
1064
+ ? "".concat(C.SSR, "[SSR]").concat(C.RESET, " ")
1065
+ : "".concat(C.HTTP, "[API]").concat(C.RESET, " ");
1066
+ var labelColor = methodColor(method);
1067
+ var versionColor = rgbAnsi(versionToRgb(version));
1068
+ var cacheText = cacheLabel(options.cacheStatus);
1069
+ var allowListText = allowListLabel(options.allowListStatus);
1070
+ console.log("".concat(versionColor, "[").concat(version, "]").concat(C.RESET, " ").concat(cacheText, " ").concat(allowListText, " ").concat(preText).concat(labelColor, "[").concat(method, "]").concat(C.RESET, " ").concat(colorSql(options.sql)));
1071
+ }
1072
+
868
1073
  // -----------------------------------------------------------------------------
869
1074
  // Cache Storage
870
1075
  // -----------------------------------------------------------------------------
@@ -907,15 +1112,24 @@ function clearCache(props) {
907
1112
  // -----------------------------------------------------------------------------
908
1113
  // Check Cache (dedupe via hashed key)
909
1114
  // -----------------------------------------------------------------------------
910
- function checkCache(method, tableName, requestData) {
1115
+ function checkCache(method, tableName, requestData, logContext) {
1116
+ var _a, _b, _c, _d, _e;
911
1117
  var key = makeCacheKey(method, tableName, requestData);
912
1118
  var cached = apiRequestCache.get(key);
913
- if (!cached)
1119
+ if (!cached) {
1120
+ console.log('apiRequestCache.size', apiRequestCache.size);
914
1121
  return false;
915
- if (shouldLog(exports.LogLevel.INFO, undefined)) {
916
- console.groupCollapsed("%c API cache hit for ".concat(method, " ").concat(tableName), "color:#0c0");
917
- console.log("Request Data:", requestData);
918
- console.groupEnd();
1122
+ }
1123
+ if (shouldLog(exports.LogLevel.INFO, logContext)) {
1124
+ var sql = (_d = (_c = (_b = (_a = cached.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.sql) === null || _c === void 0 ? void 0 : _c.sql) !== null && _d !== void 0 ? _d : "";
1125
+ var sqlMethod = ((_e = sql.trim().split(/\s+/, 1)[0]) === null || _e === void 0 ? void 0 : _e.toUpperCase()) || method;
1126
+ logSql({
1127
+ allowListStatus: "not verified",
1128
+ cacheStatus: "hit",
1129
+ context: logContext,
1130
+ method: sqlMethod,
1131
+ sql: sql
1132
+ });
919
1133
  }
920
1134
  return cached.request;
921
1135
  }
@@ -926,6 +1140,10 @@ function setCache(method, tableName, requestData, cacheEntry) {
926
1140
  var key = makeCacheKey(method, tableName, requestData);
927
1141
  apiRequestCache.set(key, cacheEntry);
928
1142
  }
1143
+ function evictCacheEntry(method, tableName, requestData) {
1144
+ var key = makeCacheKey(method, tableName, requestData);
1145
+ return apiRequestCache.delete(key);
1146
+ }
929
1147
 
930
1148
  function sortAndSerializeQueryObject(tables, query) {
931
1149
  var orderedQuery = Object.keys(query).sort().reduce(function (obj, key) {
@@ -1051,7 +1269,7 @@ var HttpExecutor = /** @class */ (function (_super) {
1051
1269
  }
1052
1270
  query = this.request;
1053
1271
  apiRequest = function () { return tslib.__awaiter(_this, void 0, void 0, function () {
1054
- var _a, debug, _b, cacheResults, dataInsertMultipleRows, success, _c, fetchDependencies, _d, error, cachingConfirmed, cacheRequestData, querySerialized, cachedRequest, apiResponse, restRequestUri, needsConditionOrPrimaryCheck, TABLES, primaryKeyList, primaryKeyFullyQualified, primaryKey, whereVal, whereIsEmpty, providedPrimary, primaryVal, axiosActiveRequest_1;
1272
+ var _a, debug, _b, cacheResults, dataInsertMultipleRows, success, _c, fetchDependencies, _d, error, cachingConfirmed, cacheRequestData, evictFromCache, querySerialized, cachedRequest, cachedData, apiResponse, restRequestUri, needsConditionOrPrimaryCheck, TABLES, primaryKeyList, primaryKeyFullyQualified, primaryKey, whereVal, whereIsEmpty, providedPrimary, primaryVal, axiosActiveRequest_1;
1055
1273
  var _e;
1056
1274
  var _this = this;
1057
1275
  var _f, _g, _h, _j, _k, _l;
@@ -1081,14 +1299,25 @@ var HttpExecutor = /** @class */ (function (_super) {
1081
1299
  query[C6.PAGINATION][C6.LIMIT] = query[C6.PAGINATION][C6.LIMIT] || 100;
1082
1300
  }
1083
1301
  cacheRequestData = JSON.parse(JSON.stringify(query !== null && query !== void 0 ? query : {}));
1302
+ evictFromCache = requestMethod === GET && cacheResults
1303
+ ? function () { return evictCacheEntry(requestMethod, tableName, cacheRequestData); }
1304
+ : undefined;
1084
1305
  querySerialized = sortAndSerializeQueryObject(tables, cacheRequestData !== null && cacheRequestData !== void 0 ? cacheRequestData : {});
1085
1306
  cachedRequest = false;
1086
1307
  if (cacheResults) {
1087
- cachedRequest = checkCache(requestMethod, tableName, cacheRequestData);
1308
+ cachedRequest = checkCache(requestMethod, tableName, cacheRequestData, logContext);
1088
1309
  }
1089
1310
  if (!cachedRequest) return [3 /*break*/, 2];
1090
1311
  return [4 /*yield*/, cachedRequest];
1091
- case 1: return [2 /*return*/, (_m.sent()).data];
1312
+ case 1:
1313
+ cachedData = (_m.sent()).data;
1314
+ if (evictFromCache
1315
+ && cachedData
1316
+ && typeof cachedData === "object"
1317
+ && Array.isArray(cachedData.rest)) {
1318
+ cachedData.evictFromCache = evictFromCache;
1319
+ }
1320
+ return [2 /*return*/, cachedData];
1092
1321
  case 2:
1093
1322
  if (cacheResults) {
1094
1323
  cachingConfirmed = true;
@@ -1279,7 +1508,7 @@ var HttpExecutor = /** @class */ (function (_super) {
1279
1508
  else {
1280
1509
  callback();
1281
1510
  }
1282
- if (!(C6.GET === requestMethod && this.isRestResponse(response))) return [3 /*break*/, 2];
1511
+ if (!(requestMethod === GET && this.isRestResponse(response))) return [3 /*break*/, 2];
1283
1512
  responseData_1 = response.data;
1284
1513
  pageLimit = (_a = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _a === void 0 ? void 0 : _a[C6.LIMIT];
1285
1514
  got = responseData_1.rest.length;
@@ -1290,6 +1519,9 @@ var HttpExecutor = /** @class */ (function (_super) {
1290
1519
  else {
1291
1520
  responseData_1.next = undefined; // short page => done
1292
1521
  }
1522
+ if (cachingConfirmed && evictFromCache) {
1523
+ responseData_1.evictFromCache = evictFromCache;
1524
+ }
1293
1525
  if (cachingConfirmed) {
1294
1526
  setCache(requestMethod, tableName, cacheRequestData, {
1295
1527
  requestArgumentsSerialized: querySerialized,
@@ -2945,186 +3177,6 @@ var PaginationBuilder = /** @class */ (function (_super) {
2945
3177
  return PaginationBuilder;
2946
3178
  }(JoinBuilder));
2947
3179
 
2948
- /* eslint-disable no-control-regex */
2949
- var RESET = "\x1b[0m";
2950
- var C$1 = {
2951
- KEYWORD: "\x1b[94m", // blue
2952
- LIMIT: "\x1b[93m", // yellow
2953
- NUMBER: "\x1b[92m", // green
2954
- DIM: "\x1b[90m", // gray
2955
- };
2956
- /* ---------- ANSI helpers ---------- */
2957
- var ansi256 = function (n) { return "\u001B[38;5;".concat(n, "m"); };
2958
- /* ---------- hashing ---------- */
2959
- function hashString$1(str) {
2960
- var hash = 0;
2961
- for (var i = 0; i < str.length; i++) {
2962
- hash = (hash * 31 + str.charCodeAt(i)) | 0;
2963
- }
2964
- return Math.abs(hash);
2965
- }
2966
- /* ---------- table color ---------- */
2967
- function tableRGB(tableName) {
2968
- var name = tableName.replace(/[`"]/g, "").toLowerCase();
2969
- var hash = hashString$1(name);
2970
- // Stable hue bucket by first letter
2971
- var first = name.charCodeAt(0) || 97;
2972
- var hueBase = (first - 97) % 6;
2973
- var r = (hueBase + (hash % 3)) % 6;
2974
- var g = (hash >> 3) % 6;
2975
- var b = (hash >> 6) % 6;
2976
- return [r, g, Math.max(2, b)]; // avoid muddy dark blues
2977
- }
2978
- function tableColor(table) {
2979
- var _a = tableRGB(table), r = _a[0], g = _a[1], b = _a[2];
2980
- return ansi256(16 + 36 * r + 6 * g + b);
2981
- }
2982
- /* ---------- column color (same hue, lighter) ---------- */
2983
- function columnColorFromTable(table) {
2984
- var _a = tableRGB(table), r = _a[0], g = _a[1], b = _a[2];
2985
- // Lift toward white, preserve hue
2986
- var lr = Math.min(5, r + 1);
2987
- var lg = Math.min(5, g + 1);
2988
- var lb = Math.min(5, b + 2);
2989
- return ansi256(16 + 36 * lr + 6 * lg + lb);
2990
- }
2991
- /* ---------- bind collapsing ---------- */
2992
- /**
2993
- * ?, ?, ?, ?, ?, ? → ? ×6
2994
- * triggers at 4+
2995
- */
2996
- function collapseBinds(sql) {
2997
- return sql.replace(/(\?\s*,\s*){3,}\?/g, function (match) {
2998
- var count = match.split("?").length - 1;
2999
- return "".concat(C$1.DIM, "? \u00D7").concat(count).concat(RESET);
3000
- });
3001
- }
3002
- /**
3003
- * ( ? ×9 ), ( ? ×9 ), ( ? ×9 ) -> ( ? ×9 ) ×3
3004
- */
3005
- function collapseRepeatedValueRows(sql) {
3006
- var repeatedRowPattern = /(\((?:\x1b\[[0-9;]*m)?\?\s*×\d+(?:\x1b\[[0-9;]*m)?\)|\(\s*(?:\?\s*,\s*)+\?\s*\))(?:\s*,\s*\1){2,}/g;
3007
- return sql.replace(repeatedRowPattern, function (match, row) {
3008
- var _a, _b;
3009
- var rowMatches = match.match(new RegExp(row.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"));
3010
- var count = (_a = rowMatches === null || rowMatches === void 0 ? void 0 : rowMatches.length) !== null && _a !== void 0 ? _a : 1;
3011
- var normalizedRow = row.includes("×")
3012
- ? row
3013
- : "(".concat(C$1.DIM, "? \u00D7").concat(((_b = row.match(/\?/g)) !== null && _b !== void 0 ? _b : []).length).concat(RESET, ")");
3014
- return "".concat(normalizedRow, " ").concat(C$1.DIM, "\u00D7").concat(count).concat(RESET);
3015
- });
3016
- }
3017
- /* ---------- main formatter ---------- */
3018
- function colorSql(sql) {
3019
- var s = sql.trim();
3020
- /* 1️⃣ collapse bind noise */
3021
- s = collapseBinds(s);
3022
- s = collapseRepeatedValueRows(s);
3023
- /* 2️⃣ table.column coloring (core visual grouping) */
3024
- s = s.replace(/\b(`?\w+`?)\.(\w+)\b/g, function (_, table, column) {
3025
- return "".concat(tableColor(table)).concat(table).concat(RESET, ".") +
3026
- "".concat(columnColorFromTable(table)).concat(column).concat(RESET);
3027
- });
3028
- /* 3️⃣ FROM / JOIN tables */
3029
- s = s.replace(/\b(FROM|JOIN|UPDATE|INTO)\s+(`[^`]+`|\w+)/gi, function (_, kw, table) {
3030
- return "".concat(C$1.KEYWORD).concat(kw).concat(RESET, " ").concat(tableColor(table)).concat(table).concat(RESET);
3031
- });
3032
- /* 4️⃣ SQL keywords */
3033
- s = s.replace(/\b(SELECT|WHERE|AND|OR|ON|IN|BETWEEN|EXISTS|ORDER BY|GROUP BY|HAVING|SET|VALUES|INSERT|REPLACE|DELETE|UPDATE|DUPLICATE|KEY)\b/gi, "".concat(C$1.KEYWORD, "$1").concat(RESET));
3034
- /* 5️⃣ LIMIT */
3035
- s = s.replace(/\bLIMIT\s+(\d+)/gi, "".concat(C$1.LIMIT, "LIMIT").concat(RESET, " ").concat(C$1.NUMBER, "$1").concat(RESET));
3036
- return s;
3037
- }
3038
-
3039
- var version = "6.0.14";
3040
-
3041
- var DEFAULT_STEP = 8;
3042
- function parseSemver(version) {
3043
- var _a = version.trim().split("-"), core = _a[0], prerelease = _a[1];
3044
- var _b = core.split("."), majorRaw = _b[0], minorRaw = _b[1], patchRaw = _b[2];
3045
- var major = Number.parseInt(majorRaw !== null && majorRaw !== void 0 ? majorRaw : "0", 10);
3046
- var minor = Number.parseInt(minorRaw !== null && minorRaw !== void 0 ? minorRaw : "0", 10);
3047
- var patch = Number.parseInt(patchRaw !== null && patchRaw !== void 0 ? patchRaw : "0", 10);
3048
- var prereleaseParts = prerelease ? prerelease.split(".").filter(Boolean).length : 0;
3049
- return {
3050
- major: Number.isFinite(major) ? major : 0,
3051
- minor: Number.isFinite(minor) ? minor : 0,
3052
- patch: Number.isFinite(patch) ? patch : 0,
3053
- prereleaseParts: prereleaseParts,
3054
- };
3055
- }
3056
- function channelValue(n, step) {
3057
- var value = 255 - ((n * step) % 256);
3058
- return (value + 256) % 256;
3059
- }
3060
- function versionToRgb(version, step) {
3061
- if (step === void 0) { step = DEFAULT_STEP; }
3062
- var safeStep = Number.isFinite(step) && step > 0 ? Math.floor(step) : DEFAULT_STEP;
3063
- var _a = parseSemver(version), major = _a.major, minor = _a.minor, patch = _a.patch, prereleaseParts = _a.prereleaseParts;
3064
- var rotation = (major + minor + patch + prereleaseParts) % 3;
3065
- var base = [major, minor, patch];
3066
- var rotated = rotation === 1
3067
- ? [base[2], base[0], base[1]]
3068
- : rotation === 2
3069
- ? [base[1], base[2], base[0]]
3070
- : base;
3071
- return {
3072
- r: channelValue(rotated[0], safeStep),
3073
- g: channelValue(rotated[1], safeStep),
3074
- b: channelValue(rotated[2], safeStep),
3075
- };
3076
- }
3077
-
3078
- var C = {
3079
- SSR: "\x1b[95m", // bright magenta
3080
- HTTP: "\x1b[94m", // bright blue
3081
- METHOD_COLORS: {
3082
- SELECT: "\x1b[92m", // green
3083
- INSERT: "\x1b[96m", // cyan
3084
- REPLACE: "\x1b[96m", // cyan
3085
- UPDATE: "\x1b[95m", // magenta
3086
- DELETE: "\x1b[91m", // red
3087
- },
3088
- METHOD_FALLBACK: [
3089
- "\x1b[92m", // green
3090
- "\x1b[93m", // yellow
3091
- "\x1b[95m", // magenta
3092
- "\x1b[96m", // cyan
3093
- "\x1b[94m", // blue
3094
- "\x1b[97m", // white
3095
- ],
3096
- RESET: "\x1b[0m",
3097
- };
3098
- var rgbAnsi = function (_a) {
3099
- var r = _a.r, g = _a.g, b = _a.b;
3100
- return "\u001B[38;2;".concat(r, ";").concat(g, ";").concat(b, "m");
3101
- };
3102
- function hashString(value) {
3103
- var hash = 0;
3104
- for (var i = 0; i < value.length; i++) {
3105
- hash = (hash * 31 + value.charCodeAt(i)) | 0;
3106
- }
3107
- return Math.abs(hash);
3108
- }
3109
- function methodColor(method) {
3110
- var key = method.toUpperCase();
3111
- if (key in C.METHOD_COLORS) {
3112
- return C.METHOD_COLORS[key];
3113
- }
3114
- var idx = hashString(key) % C.METHOD_FALLBACK.length;
3115
- return C.METHOD_FALLBACK[idx];
3116
- }
3117
- function logSql(method, sql, context) {
3118
- if (!shouldLog(exports.LogLevel.INFO, context))
3119
- return;
3120
- var preText = getEnvBool("SSR", false)
3121
- ? "".concat(C.SSR, "[SSR]").concat(C.RESET, " ")
3122
- : "".concat(C.HTTP, "[API]").concat(C.RESET, " ");
3123
- var labelColor = methodColor(method);
3124
- var versionColor = rgbAnsi(versionToRgb(version));
3125
- console.log("".concat(versionColor, "[").concat(version, "]").concat(C.RESET, " ").concat(preText).concat(labelColor, "[").concat(method, "]").concat(C.RESET, " ").concat(colorSql(sql)));
3126
- }
3127
-
3128
3180
  var SelectQueryBuilder = /** @class */ (function (_super) {
3129
3181
  tslib.__extends(SelectQueryBuilder, _super);
3130
3182
  function SelectQueryBuilder() {
@@ -3176,7 +3228,6 @@ var SelectQueryBuilder = /** @class */ (function (_super) {
3176
3228
  else if (!isSubSelect) {
3177
3229
  sql += " LIMIT 100";
3178
3230
  }
3179
- logSql("SELECT", sql, getLogContext(this.config, this.request));
3180
3231
  return { sql: sql, params: params };
3181
3232
  };
3182
3233
  return SelectQueryBuilder;
@@ -3201,7 +3252,6 @@ var DeleteQueryBuilder = /** @class */ (function (_super) {
3201
3252
  if (this.request.WHERE) {
3202
3253
  sql += this.buildWhereClause(this.request.WHERE, params);
3203
3254
  }
3204
- logSql("DELETE", sql, getLogContext(this.config, this.request));
3205
3255
  return { sql: sql, params: params };
3206
3256
  };
3207
3257
  return DeleteQueryBuilder;
@@ -3260,7 +3310,6 @@ var PostQueryBuilder = /** @class */ (function (_super) {
3260
3310
  var updateClause = updateData.map(function (k) { return "`".concat(k, "` = VALUES(`").concat(k, "`)"); }).join(', ');
3261
3311
  sql += " ON DUPLICATE KEY UPDATE ".concat(updateClause);
3262
3312
  }
3263
- logSql(verb, sql, getLogContext(this.config, this.request));
3264
3313
  return { sql: sql, params: params };
3265
3314
  };
3266
3315
  return PostQueryBuilder;
@@ -3312,7 +3361,6 @@ var UpdateQueryBuilder = /** @class */ (function (_super) {
3312
3361
  if (args.PAGINATION) {
3313
3362
  sql += this.buildPaginationClause(args.PAGINATION, params);
3314
3363
  }
3315
- logSql("UPDATE", sql, getLogContext(this.config, this.request));
3316
3364
  return { sql: sql, params: params };
3317
3365
  };
3318
3366
  return UpdateQueryBuilder;
@@ -3446,8 +3494,55 @@ function normalizeSingularRequest(requestMethod, request, restModel, removedPrim
3446
3494
  }
3447
3495
 
3448
3496
  var allowListCache = new Map();
3497
+ var ANSI_ESCAPE_REGEX = /\x1b\[[0-9;]*m/g;
3498
+ var COLLAPSED_BIND_ROW_REGEX = /\(\?\s*×\d+\)/g;
3499
+ function collapseBindGroups(sql) {
3500
+ var normalized = sql.replace(/\(\s*(\?(?:\s*,\s*\?)*)\s*\)/g, function (_match, binds) {
3501
+ var _a;
3502
+ var bindCount = ((_a = binds.match(/\?/g)) !== null && _a !== void 0 ? _a : []).length;
3503
+ return "(? \u00D7".concat(bindCount, ")");
3504
+ });
3505
+ normalized = normalized.replace(/(\(\?\s*×\d+\))(?:\s*,\s*\1)+/g, function (_match, row) { return "".concat(row, " \u00D7*"); });
3506
+ normalized = normalized.replace(/\b(VALUES|VALUE)\s+(\(\?\s*×\d+\))(?:\s*×\d+|\s*×\*)?/gi, function (_match, keyword, row) { return "".concat(keyword, " ").concat(row, " \u00D7*"); });
3507
+ normalized = normalized.replace(/\bIN\s*\(\?\s*×\d+\)/gi, "IN (? ×*)");
3508
+ normalized = normalized.replace(/\(\?\s*×\d+\)\s*×\d+/g, function (match) {
3509
+ var _a;
3510
+ var row = (_a = match.match(COLLAPSED_BIND_ROW_REGEX)) === null || _a === void 0 ? void 0 : _a[0];
3511
+ return row ? "".concat(row, " \u00D7*") : match;
3512
+ });
3513
+ return normalized;
3514
+ }
3515
+ function normalizeLimitOffset(sql) {
3516
+ return sql
3517
+ .replace(/\bLIMIT\s+\d+\s*,\s*\d+\b/gi, "LIMIT ?, ?")
3518
+ .replace(/\bLIMIT\s+\d+\s+OFFSET\s+\d+\b/gi, "LIMIT ? OFFSET ?")
3519
+ .replace(/\bLIMIT\s+\d+\b/gi, "LIMIT ?")
3520
+ .replace(/\bOFFSET\s+\d+\b/gi, "OFFSET ?");
3521
+ }
3522
+ function normalizeGeomFromTextLiterals(sql) {
3523
+ var normalized = sql.replace(/ST_GEOMFROMTEXT\(\s*'POINT\([^']*\)'\s*,\s*(?:\d+|\?)\s*\)/gi, "ST_GEOMFROMTEXT('POINT(? ?)', ?)");
3524
+ normalized = normalized.replace(/ST_GEOMFROMTEXT\(\s*'POLYGON\(\([^']*\)\)'\s*,\s*(?:\d+|\?)\s*\)/gi, "ST_GEOMFROMTEXT('POLYGON((?))', ?)");
3525
+ return normalized;
3526
+ }
3527
+ function normalizeGeoFunctionNames(sql) {
3528
+ return sql
3529
+ .replace(/\bST_DISTANCE_SPHERE\b/gi, "ST_DISTANCE_SPHERE")
3530
+ .replace(/\bST_GEOMFROMTEXT\b/gi, "ST_GEOMFROMTEXT")
3531
+ .replace(/\bMBRCONTAINS\b/gi, "MBRCONTAINS");
3532
+ }
3533
+ function normalizeTokenPunctuationSpacing(sql) {
3534
+ return sql.replace(/`,\s*`/g, "`, `");
3535
+ }
3449
3536
  var normalizeSql = function (sql) {
3450
- return sql.replace(/\s+/g, " ").trim();
3537
+ var normalized = sql.replace(ANSI_ESCAPE_REGEX, " ");
3538
+ normalized = normalized.replace(/\s+/g, " ").trim();
3539
+ normalized = normalizeGeoFunctionNames(normalized);
3540
+ normalized = normalizeTokenPunctuationSpacing(normalized);
3541
+ normalized = collapseBindGroups(normalized);
3542
+ normalized = normalizeLimitOffset(normalized);
3543
+ normalized = normalizeGeomFromTextLiterals(normalized);
3544
+ normalized = normalized.replace(/;\s*$/, "");
3545
+ return normalized.replace(/\s+/g, " ").trim();
3451
3546
  };
3452
3547
  var parseAllowList = function (raw, sourcePath) {
3453
3548
  var parsed;
@@ -3470,33 +3565,51 @@ var parseAllowList = function (raw, sourcePath) {
3470
3565
  return sqlEntries;
3471
3566
  };
3472
3567
  var loadSqlAllowList = function (allowListPath) { return tslib.__awaiter(void 0, void 0, void 0, function () {
3473
- var readFile, raw, sqlEntries, allowList;
3474
- return tslib.__generator(this, function (_a) {
3475
- switch (_a.label) {
3568
+ var _a, readFile, stat, fileStat, cached, raw, sqlEntries, allowList;
3569
+ return tslib.__generator(this, function (_b) {
3570
+ switch (_b.label) {
3476
3571
  case 0:
3477
- if (allowListCache.has(allowListPath)) {
3478
- return [2 /*return*/, allowListCache.get(allowListPath)];
3479
- }
3480
3572
  if (!isNode()) {
3481
3573
  throw new Error("SQL allowlist validation requires a Node runtime.");
3482
3574
  }
3483
3575
  return [4 /*yield*/, import('node:fs/promises')];
3484
3576
  case 1:
3485
- readFile = (_a.sent()).readFile;
3486
- _a.label = 2;
3577
+ _a = _b.sent(), readFile = _a.readFile, stat = _a.stat;
3578
+ _b.label = 2;
3487
3579
  case 2:
3488
- _a.trys.push([2, 4, , 5]);
3489
- return [4 /*yield*/, readFile(allowListPath, "utf-8")];
3580
+ _b.trys.push([2, 4, , 5]);
3581
+ return [4 /*yield*/, stat(allowListPath)];
3490
3582
  case 3:
3491
- raw = _a.sent();
3583
+ fileStat = _b.sent();
3492
3584
  return [3 /*break*/, 5];
3493
3585
  case 4:
3494
- _a.sent();
3586
+ _b.sent();
3495
3587
  throw new Error("SQL allowlist file not found at ".concat(allowListPath, "."));
3496
3588
  case 5:
3589
+ cached = allowListCache.get(allowListPath);
3590
+ if (cached &&
3591
+ cached.mtimeMs === fileStat.mtimeMs &&
3592
+ cached.size === fileStat.size) {
3593
+ return [2 /*return*/, cached.allowList];
3594
+ }
3595
+ _b.label = 6;
3596
+ case 6:
3597
+ _b.trys.push([6, 8, , 9]);
3598
+ return [4 /*yield*/, readFile(allowListPath, "utf-8")];
3599
+ case 7:
3600
+ raw = _b.sent();
3601
+ return [3 /*break*/, 9];
3602
+ case 8:
3603
+ _b.sent();
3604
+ throw new Error("SQL allowlist file not found at ".concat(allowListPath, "."));
3605
+ case 9:
3497
3606
  sqlEntries = parseAllowList(raw, allowListPath);
3498
3607
  allowList = new Set(sqlEntries);
3499
- allowListCache.set(allowListPath, allowList);
3608
+ allowListCache.set(allowListPath, {
3609
+ allowList: allowList,
3610
+ mtimeMs: fileStat.mtimeMs,
3611
+ size: fileStat.size,
3612
+ });
3500
3613
  return [2 /*return*/, allowList];
3501
3614
  }
3502
3615
  });
@@ -3559,6 +3672,25 @@ var compileSqlAllowList = function (allowListPath, entries) { return tslib.__awa
3559
3672
  });
3560
3673
  }); };
3561
3674
 
3675
+ var SQL_ALLOWLIST_BLOCKED_CODE = "SQL_ALLOWLIST_BLOCKED";
3676
+ var createSqlAllowListBlockedError = function (args) {
3677
+ var _a, _b;
3678
+ var error = new Error("SQL statement is not permitted by allowlist (".concat(args.allowListPath, ")."));
3679
+ error.name = "SqlAllowListBlockedError";
3680
+ error.code = SQL_ALLOWLIST_BLOCKED_CODE;
3681
+ error.tableName = args.tableName;
3682
+ error.method = args.method;
3683
+ error.normalizedSql = args.normalizedSql;
3684
+ error.allowListPath = args.allowListPath;
3685
+ error.sqlAllowList = {
3686
+ sql: args.normalizedSql,
3687
+ table: (_a = args.tableName) !== null && _a !== void 0 ? _a : null,
3688
+ method: (_b = args.method) !== null && _b !== void 0 ? _b : null,
3689
+ allowListPath: args.allowListPath,
3690
+ canAdd: true,
3691
+ };
3692
+ return error;
3693
+ };
3562
3694
  var SqlExecutor = /** @class */ (function (_super) {
3563
3695
  tslib.__extends(SqlExecutor, _super);
3564
3696
  function SqlExecutor() {
@@ -3569,6 +3701,22 @@ var SqlExecutor = /** @class */ (function (_super) {
3569
3701
  })); };
3570
3702
  return _this;
3571
3703
  }
3704
+ SqlExecutor.prototype.resolveSqlLogMethod = function (method, sql) {
3705
+ var _a;
3706
+ var token = (_a = sql.trim().split(/\s+/, 1)[0]) === null || _a === void 0 ? void 0 : _a.toUpperCase();
3707
+ if (token)
3708
+ return token;
3709
+ switch (method) {
3710
+ case C6Constants.GET:
3711
+ return "SELECT";
3712
+ case C6Constants.POST:
3713
+ return "INSERT";
3714
+ case C6Constants.PUT:
3715
+ return "UPDATE";
3716
+ default:
3717
+ return "DELETE";
3718
+ }
3719
+ };
3572
3720
  SqlExecutor.prototype.execute = function () {
3573
3721
  return tslib.__awaiter(this, void 0, void 0, function () {
3574
3722
  var TABLE_NAME, method, logContext, response, _a, rest, getResponse, restRows, result, result, result;
@@ -3940,7 +4088,7 @@ var SqlExecutor = /** @class */ (function (_super) {
3940
4088
  };
3941
4089
  SqlExecutor.prototype.runQuery = function () {
3942
4090
  return tslib.__awaiter(this, void 0, void 0, function () {
3943
- var method, tableName, logContext, cacheResults, cacheRequestData, requestArgumentsSerialized, cachedRequest, sqlExecution, queryPromise, cacheRequest, cacheResponse;
4091
+ var method, tableName, logContext, cacheResults, cacheRequestData, requestArgumentsSerialized, evictFromCache, cachedRequest, cachedData, sqlExecution, sqlMethod, queryPromise, cacheRequest, cacheResponse;
3944
4092
  var _this = this;
3945
4093
  var _a, _b;
3946
4094
  return tslib.__generator(this, function (_c) {
@@ -3950,29 +4098,48 @@ var SqlExecutor = /** @class */ (function (_super) {
3950
4098
  tableName = this.config.restModel.TABLE_NAME;
3951
4099
  logContext = getLogContext(this.config, this.request);
3952
4100
  cacheResults = method === C6Constants.GET
3953
- && !this.config.sqlAllowListPath
3954
- && ((_a = this.request) === null || _a === void 0 ? void 0 : _a.cacheResults) !== false;
4101
+ && ((_a = this.request.cacheResults) !== null && _a !== void 0 ? _a : true);
3955
4102
  cacheRequestData = cacheResults
3956
4103
  ? JSON.parse(JSON.stringify((_b = this.request) !== null && _b !== void 0 ? _b : {}))
3957
4104
  : undefined;
3958
4105
  requestArgumentsSerialized = cacheResults
3959
4106
  ? sortAndSerializeQueryObject(tableName, cacheRequestData !== null && cacheRequestData !== void 0 ? cacheRequestData : {})
3960
4107
  : undefined;
4108
+ evictFromCache = method === C6Constants.GET && cacheResults && cacheRequestData
4109
+ ? function () { return evictCacheEntry(method, tableName, cacheRequestData); }
4110
+ : undefined;
3961
4111
  if (!cacheResults) return [3 /*break*/, 2];
3962
- cachedRequest = checkCache(method, tableName, cacheRequestData);
4112
+ cachedRequest = checkCache(method, tableName, cacheRequestData, logContext);
3963
4113
  if (!cachedRequest) return [3 /*break*/, 2];
3964
4114
  return [4 /*yield*/, cachedRequest];
3965
- case 1: return [2 /*return*/, (_c.sent()).data];
4115
+ case 1:
4116
+ cachedData = (_c.sent()).data;
4117
+ if (evictFromCache
4118
+ && cachedData
4119
+ && typeof cachedData === "object"
4120
+ && Array.isArray(cachedData.rest)) {
4121
+ cachedData.evictFromCache = evictFromCache;
4122
+ }
4123
+ return [2 /*return*/, cachedData];
3966
4124
  case 2:
3967
4125
  sqlExecution = this.buildSqlExecutionContext(method, tableName, logContext);
3968
- queryPromise = this.withConnection(function (conn) { return tslib.__awaiter(_this, void 0, void 0, function () { return tslib.__generator(this, function (_a) {
3969
- return [2 /*return*/, this.executeQueryWithLifecycle(conn, method, sqlExecution, logContext)];
3970
- }); }); });
4126
+ sqlMethod = this.resolveSqlLogMethod(method, sqlExecution.sql);
4127
+ queryPromise = this.withConnection(function (conn) { return tslib.__awaiter(_this, void 0, void 0, function () {
4128
+ return tslib.__generator(this, function (_a) {
4129
+ return [2 /*return*/, this.executeQueryWithLifecycle(conn, method, sqlExecution, logContext, sqlMethod)];
4130
+ });
4131
+ }); });
3971
4132
  if (!(!cacheResults || !cacheRequestData || !requestArgumentsSerialized)) return [3 /*break*/, 4];
3972
4133
  return [4 /*yield*/, queryPromise];
3973
4134
  case 3: return [2 /*return*/, _c.sent()];
3974
4135
  case 4:
3975
4136
  cacheRequest = queryPromise.then(function (data) {
4137
+ if (evictFromCache
4138
+ && data
4139
+ && typeof data === "object"
4140
+ && Array.isArray(data.rest)) {
4141
+ data.evictFromCache = evictFromCache;
4142
+ }
3976
4143
  return _this.createCacheResponseEnvelope(method, tableName, data);
3977
4144
  });
3978
4145
  setCache(method, tableName, cacheRequestData, {
@@ -4045,9 +4212,9 @@ var SqlExecutor = /** @class */ (function (_super) {
4045
4212
  },
4046
4213
  };
4047
4214
  };
4048
- SqlExecutor.prototype.executeQueryWithLifecycle = function (conn, method, sqlExecution, logContext) {
4215
+ SqlExecutor.prototype.executeQueryWithLifecycle = function (conn, method, sqlExecution, logContext, sqlMethod) {
4049
4216
  return tslib.__awaiter(this, void 0, void 0, function () {
4050
- var useTransaction, committed, result, response, hookResponse, err_1, rollbackErr_1;
4217
+ var useTransaction, committed, allowListStatus, error_2, result, response, hookResponse, err_1, rollbackErr_1;
4051
4218
  return tslib.__generator(this, function (_a) {
4052
4219
  switch (_a.label) {
4053
4220
  case 0:
@@ -4055,25 +4222,49 @@ var SqlExecutor = /** @class */ (function (_super) {
4055
4222
  committed = false;
4056
4223
  _a.label = 1;
4057
4224
  case 1:
4058
- _a.trys.push([1, 11, , 16]);
4225
+ _a.trys.push([1, 14, , 19]);
4059
4226
  if (!useTransaction) return [3 /*break*/, 3];
4060
4227
  logWithLevel(exports.LogLevel.DEBUG, logContext, console.log, "[SQL EXECUTOR] \uD83E\uDDFE Beginning transaction");
4061
4228
  return [4 /*yield*/, conn.beginTransaction()];
4062
4229
  case 2:
4063
4230
  _a.sent();
4064
4231
  _a.label = 3;
4065
- case 3: return [4 /*yield*/, this.validateSqlAllowList(sqlExecution.sql)];
4232
+ case 3:
4233
+ allowListStatus = "not verified";
4234
+ _a.label = 4;
4066
4235
  case 4:
4067
- _a.sent();
4236
+ _a.trys.push([4, 6, , 7]);
4237
+ return [4 /*yield*/, this.validateSqlAllowList(sqlExecution.sql)];
4238
+ case 5:
4239
+ allowListStatus = _a.sent();
4240
+ return [3 /*break*/, 7];
4241
+ case 6:
4242
+ error_2 = _a.sent();
4243
+ logSql({
4244
+ method: sqlMethod,
4245
+ sql: sqlExecution.sql,
4246
+ context: logContext,
4247
+ cacheStatus: this.request.cacheResults === false ? "ignored" : "miss",
4248
+ allowListStatus: "denied",
4249
+ });
4250
+ throw error_2;
4251
+ case 7:
4252
+ logSql({
4253
+ method: sqlMethod,
4254
+ sql: sqlExecution.sql,
4255
+ context: logContext,
4256
+ cacheStatus: this.request.cacheResults === false ? "ignored" : "miss",
4257
+ allowListStatus: allowListStatus,
4258
+ });
4068
4259
  return [4 /*yield*/, this.runLifecycleHooks("beforeExecution", {
4069
4260
  config: this.config,
4070
4261
  request: this.request,
4071
4262
  sqlExecution: sqlExecution,
4072
4263
  })];
4073
- case 5:
4264
+ case 8:
4074
4265
  _a.sent();
4075
4266
  return [4 /*yield*/, conn.query(sqlExecution.sql, sqlExecution.values)];
4076
- case 6:
4267
+ case 9:
4077
4268
  result = (_a.sent())[0];
4078
4269
  response = this.createResponseFromQueryResult(method, result, sqlExecution, logContext);
4079
4270
  hookResponse = this.createLifecycleHookResponse(response);
@@ -4082,40 +4273,40 @@ var SqlExecutor = /** @class */ (function (_super) {
4082
4273
  request: this.request,
4083
4274
  response: hookResponse,
4084
4275
  })];
4085
- case 7:
4276
+ case 10:
4086
4277
  _a.sent();
4087
- if (!useTransaction) return [3 /*break*/, 9];
4278
+ if (!useTransaction) return [3 /*break*/, 12];
4088
4279
  return [4 /*yield*/, conn.commit()];
4089
- case 8:
4280
+ case 11:
4090
4281
  _a.sent();
4091
4282
  committed = true;
4092
4283
  logWithLevel(exports.LogLevel.DEBUG, logContext, console.log, "[SQL EXECUTOR] \uD83E\uDDFE Transaction committed");
4093
- _a.label = 9;
4094
- case 9: return [4 /*yield*/, this.runLifecycleHooks("afterCommit", {
4284
+ _a.label = 12;
4285
+ case 12: return [4 /*yield*/, this.runLifecycleHooks("afterCommit", {
4095
4286
  config: this.config,
4096
4287
  request: this.request,
4097
4288
  response: hookResponse,
4098
4289
  })];
4099
- case 10:
4290
+ case 13:
4100
4291
  _a.sent();
4101
4292
  return [2 /*return*/, response];
4102
- case 11:
4293
+ case 14:
4103
4294
  err_1 = _a.sent();
4104
- if (!(useTransaction && !committed)) return [3 /*break*/, 15];
4105
- _a.label = 12;
4106
- case 12:
4107
- _a.trys.push([12, 14, , 15]);
4295
+ if (!(useTransaction && !committed)) return [3 /*break*/, 18];
4296
+ _a.label = 15;
4297
+ case 15:
4298
+ _a.trys.push([15, 17, , 18]);
4108
4299
  return [4 /*yield*/, conn.rollback()];
4109
- case 13:
4300
+ case 16:
4110
4301
  _a.sent();
4111
4302
  logWithLevel(exports.LogLevel.WARN, logContext, console.warn, "[SQL EXECUTOR] \uD83E\uDDFE Transaction rolled back");
4112
- return [3 /*break*/, 15];
4113
- case 14:
4303
+ return [3 /*break*/, 18];
4304
+ case 17:
4114
4305
  rollbackErr_1 = _a.sent();
4115
4306
  logWithLevel(exports.LogLevel.ERROR, logContext, console.error, "[SQL EXECUTOR] Rollback failed", rollbackErr_1);
4116
- return [3 /*break*/, 15];
4117
- case 15: throw err_1;
4118
- case 16: return [2 /*return*/];
4307
+ return [3 /*break*/, 18];
4308
+ case 18: throw err_1;
4309
+ case 19: return [2 /*return*/];
4119
4310
  }
4120
4311
  });
4121
4312
  });
@@ -4123,21 +4314,31 @@ var SqlExecutor = /** @class */ (function (_super) {
4123
4314
  SqlExecutor.prototype.validateSqlAllowList = function (sql) {
4124
4315
  return tslib.__awaiter(this, void 0, void 0, function () {
4125
4316
  var allowListPath, allowList, normalized;
4126
- return tslib.__generator(this, function (_a) {
4127
- switch (_a.label) {
4317
+ var _a;
4318
+ return tslib.__generator(this, function (_b) {
4319
+ switch (_b.label) {
4128
4320
  case 0:
4129
4321
  allowListPath = this.config.sqlAllowListPath;
4130
4322
  if (!allowListPath) {
4131
- return [2 /*return*/];
4323
+ return [2 /*return*/, "not verified"];
4132
4324
  }
4133
4325
  return [4 /*yield*/, loadSqlAllowList(allowListPath)];
4134
4326
  case 1:
4135
- allowList = _a.sent();
4327
+ allowList = _b.sent();
4136
4328
  normalized = normalizeSql(sql);
4137
4329
  if (!allowList.has(normalized)) {
4138
- throw new Error("SQL statement is not permitted by allowlist (".concat(allowListPath, ")."));
4330
+ throw createSqlAllowListBlockedError({
4331
+ tableName: typeof ((_a = this.config.restModel) === null || _a === void 0 ? void 0 : _a.TABLE_NAME) === "string"
4332
+ ? this.config.restModel.TABLE_NAME
4333
+ : undefined,
4334
+ method: typeof this.config.requestMethod === "string"
4335
+ ? this.config.requestMethod
4336
+ : undefined,
4337
+ normalizedSql: normalized,
4338
+ allowListPath: allowListPath,
4339
+ });
4139
4340
  }
4140
- return [2 /*return*/];
4341
+ return [2 /*return*/, "allowed"];
4141
4342
  }
4142
4343
  });
4143
4344
  });
@@ -4410,6 +4611,7 @@ exports.derivedTable = derivedTable;
4410
4611
  exports.determineRuntimeJsType = determineRuntimeJsType;
4411
4612
  exports.distSphere = distSphere;
4412
4613
  exports.error = error;
4614
+ exports.evictCacheEntry = evictCacheEntry;
4413
4615
  exports.extractSqlEntries = extractSqlEntries;
4414
4616
  exports.fieldEq = fieldEq;
4415
4617
  exports.getEnv = getEnv;