@carbonorm/carbonnode 6.0.13 → 6.0.17

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 (74) hide show
  1. package/dist/executors/SqlExecutor.d.ts +17 -0
  2. package/dist/index.cjs.js +413 -245
  3. package/dist/index.cjs.js.map +1 -1
  4. package/dist/index.esm.js +413 -245
  5. package/dist/index.esm.js.map +1 -1
  6. package/dist/utils/cacheManager.d.ts +2 -1
  7. package/dist/utils/logLevel.d.ts +3 -3
  8. package/dist/utils/logSql.d.ts +10 -1
  9. package/package.json +1 -1
  10. package/scripts/assets/handlebars/C6.ts.handlebars +1 -1
  11. package/src/__tests__/fixtures/sqlResponses/sqlAllowList.json +1 -1
  12. package/src/__tests__/httpExecutor.multiRowUpsert.test.ts +50 -0
  13. package/src/__tests__/logSql.test.ts +54 -2
  14. package/src/__tests__/sakila-db/C6.js +1 -1
  15. package/src/__tests__/sakila-db/C6.mysqldump.json +1 -1
  16. package/src/__tests__/sakila-db/C6.mysqldump.sql +1 -1
  17. package/src/__tests__/sakila-db/C6.sqlAllowList.json +59 -70
  18. package/src/__tests__/sakila-db/C6.ts +2 -2
  19. package/src/__tests__/sakila-db/sqlResponses/C6.actor.post.json +3 -3
  20. package/src/__tests__/sakila-db/sqlResponses/C6.actor.post.latest.json +3 -3
  21. package/src/__tests__/sakila-db/sqlResponses/C6.actor.put.json +1 -1
  22. package/src/__tests__/sakila-db/sqlResponses/C6.actor.put.lookup.json +3 -3
  23. package/src/__tests__/sakila-db/sqlResponses/C6.address.post.json +5 -5
  24. package/src/__tests__/sakila-db/sqlResponses/C6.address.post.latest.json +5 -5
  25. package/src/__tests__/sakila-db/sqlResponses/C6.address.put.json +1 -1
  26. package/src/__tests__/sakila-db/sqlResponses/C6.address.put.lookup.json +5 -5
  27. package/src/__tests__/sakila-db/sqlResponses/C6.category.post.json +2 -2
  28. package/src/__tests__/sakila-db/sqlResponses/C6.category.post.latest.json +2 -2
  29. package/src/__tests__/sakila-db/sqlResponses/C6.category.put.json +1 -1
  30. package/src/__tests__/sakila-db/sqlResponses/C6.category.put.lookup.json +2 -2
  31. package/src/__tests__/sakila-db/sqlResponses/C6.city.post.json +2 -2
  32. package/src/__tests__/sakila-db/sqlResponses/C6.city.post.latest.json +2 -2
  33. package/src/__tests__/sakila-db/sqlResponses/C6.city.put.json +1 -1
  34. package/src/__tests__/sakila-db/sqlResponses/C6.city.put.lookup.json +2 -2
  35. package/src/__tests__/sakila-db/sqlResponses/C6.country.post.json +2 -2
  36. package/src/__tests__/sakila-db/sqlResponses/C6.country.post.latest.json +2 -2
  37. package/src/__tests__/sakila-db/sqlResponses/C6.country.put.json +1 -1
  38. package/src/__tests__/sakila-db/sqlResponses/C6.country.put.lookup.json +2 -2
  39. package/src/__tests__/sakila-db/sqlResponses/C6.customer.post.json +5 -5
  40. package/src/__tests__/sakila-db/sqlResponses/C6.customer.post.latest.json +5 -5
  41. package/src/__tests__/sakila-db/sqlResponses/C6.customer.put.json +1 -1
  42. package/src/__tests__/sakila-db/sqlResponses/C6.customer.put.lookup.json +5 -5
  43. package/src/__tests__/sakila-db/sqlResponses/C6.film.post.json +2 -2
  44. package/src/__tests__/sakila-db/sqlResponses/C6.film.post.latest.json +2 -2
  45. package/src/__tests__/sakila-db/sqlResponses/C6.film.put.json +1 -1
  46. package/src/__tests__/sakila-db/sqlResponses/C6.film.put.lookup.json +2 -2
  47. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.post.json +1 -1
  48. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.post.latest.json +1 -1
  49. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.put.json +1 -1
  50. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.put.lookup.json +1 -1
  51. package/src/__tests__/sakila-db/sqlResponses/C6.language.post.json +2 -2
  52. package/src/__tests__/sakila-db/sqlResponses/C6.language.post.latest.json +2 -2
  53. package/src/__tests__/sakila-db/sqlResponses/C6.language.put.json +1 -1
  54. package/src/__tests__/sakila-db/sqlResponses/C6.language.put.lookup.json +2 -2
  55. package/src/__tests__/sakila-db/sqlResponses/C6.payment.post.json +2 -2
  56. package/src/__tests__/sakila-db/sqlResponses/C6.payment.post.latest.json +2 -2
  57. package/src/__tests__/sakila-db/sqlResponses/C6.payment.put.lookup.json +2 -2
  58. package/src/__tests__/sakila-db/sqlResponses/C6.rental.join.json +10 -10
  59. package/src/__tests__/sakila-db/sqlResponses/C6.rental.post.json +3 -3
  60. package/src/__tests__/sakila-db/sqlResponses/C6.rental.post.latest.json +3 -3
  61. package/src/__tests__/sakila-db/sqlResponses/C6.rental.put.json +1 -1
  62. package/src/__tests__/sakila-db/sqlResponses/C6.rental.put.lookup.json +3 -3
  63. package/src/__tests__/sqlAllowList.test.ts +100 -0
  64. package/src/__tests__/sqlBuilders.test.ts +3 -4
  65. package/src/executors/HttpExecutor.ts +7 -2
  66. package/src/executors/SqlExecutor.ts +108 -7
  67. package/src/orm/queries/DeleteQueryBuilder.ts +0 -4
  68. package/src/orm/queries/PostQueryBuilder.ts +0 -4
  69. package/src/orm/queries/SelectQueryBuilder.ts +0 -4
  70. package/src/orm/queries/UpdateQueryBuilder.ts +0 -4
  71. package/src/utils/cacheManager.ts +17 -9
  72. package/src/utils/logLevel.ts +3 -4
  73. package/src/utils/logSql.ts +51 -6
  74. 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.17";
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
  }
@@ -1084,7 +1298,7 @@ var HttpExecutor = /** @class */ (function (_super) {
1084
1298
  querySerialized = sortAndSerializeQueryObject(tables, cacheRequestData !== null && cacheRequestData !== void 0 ? cacheRequestData : {});
1085
1299
  cachedRequest = false;
1086
1300
  if (cacheResults) {
1087
- cachedRequest = checkCache(requestMethod, tableName, cacheRequestData);
1301
+ cachedRequest = checkCache(requestMethod, tableName, cacheRequestData, logContext);
1088
1302
  }
1089
1303
  if (!cachedRequest) return [3 /*break*/, 2];
1090
1304
  return [4 /*yield*/, cachedRequest];
@@ -1180,8 +1394,10 @@ var HttpExecutor = /** @class */ (function (_super) {
1180
1394
  return [tslib.__assign(tslib.__assign({}, baseConfig), { params: query })];
1181
1395
  case POST:
1182
1396
  if (dataInsertMultipleRows !== undefined) {
1397
+ var convertedRows = dataInsertMultipleRows.map(convert);
1398
+ var convertedQuery = convert(query);
1183
1399
  return [
1184
- dataInsertMultipleRows.map(convert),
1400
+ tslib.__assign(tslib.__assign({}, convertedQuery), { dataInsertMultipleRows: convertedRows }),
1185
1401
  baseConfig
1186
1402
  ];
1187
1403
  }
@@ -2943,186 +3159,6 @@ var PaginationBuilder = /** @class */ (function (_super) {
2943
3159
  return PaginationBuilder;
2944
3160
  }(JoinBuilder));
2945
3161
 
2946
- /* eslint-disable no-control-regex */
2947
- var RESET = "\x1b[0m";
2948
- var C$1 = {
2949
- KEYWORD: "\x1b[94m", // blue
2950
- LIMIT: "\x1b[93m", // yellow
2951
- NUMBER: "\x1b[92m", // green
2952
- DIM: "\x1b[90m", // gray
2953
- };
2954
- /* ---------- ANSI helpers ---------- */
2955
- var ansi256 = function (n) { return "\u001B[38;5;".concat(n, "m"); };
2956
- /* ---------- hashing ---------- */
2957
- function hashString$1(str) {
2958
- var hash = 0;
2959
- for (var i = 0; i < str.length; i++) {
2960
- hash = (hash * 31 + str.charCodeAt(i)) | 0;
2961
- }
2962
- return Math.abs(hash);
2963
- }
2964
- /* ---------- table color ---------- */
2965
- function tableRGB(tableName) {
2966
- var name = tableName.replace(/[`"]/g, "").toLowerCase();
2967
- var hash = hashString$1(name);
2968
- // Stable hue bucket by first letter
2969
- var first = name.charCodeAt(0) || 97;
2970
- var hueBase = (first - 97) % 6;
2971
- var r = (hueBase + (hash % 3)) % 6;
2972
- var g = (hash >> 3) % 6;
2973
- var b = (hash >> 6) % 6;
2974
- return [r, g, Math.max(2, b)]; // avoid muddy dark blues
2975
- }
2976
- function tableColor(table) {
2977
- var _a = tableRGB(table), r = _a[0], g = _a[1], b = _a[2];
2978
- return ansi256(16 + 36 * r + 6 * g + b);
2979
- }
2980
- /* ---------- column color (same hue, lighter) ---------- */
2981
- function columnColorFromTable(table) {
2982
- var _a = tableRGB(table), r = _a[0], g = _a[1], b = _a[2];
2983
- // Lift toward white, preserve hue
2984
- var lr = Math.min(5, r + 1);
2985
- var lg = Math.min(5, g + 1);
2986
- var lb = Math.min(5, b + 2);
2987
- return ansi256(16 + 36 * lr + 6 * lg + lb);
2988
- }
2989
- /* ---------- bind collapsing ---------- */
2990
- /**
2991
- * ?, ?, ?, ?, ?, ? → ? ×6
2992
- * triggers at 4+
2993
- */
2994
- function collapseBinds(sql) {
2995
- return sql.replace(/(\?\s*,\s*){3,}\?/g, function (match) {
2996
- var count = match.split("?").length - 1;
2997
- return "".concat(C$1.DIM, "? \u00D7").concat(count).concat(RESET);
2998
- });
2999
- }
3000
- /**
3001
- * ( ? ×9 ), ( ? ×9 ), ( ? ×9 ) -> ( ? ×9 ) ×3
3002
- */
3003
- function collapseRepeatedValueRows(sql) {
3004
- var repeatedRowPattern = /(\((?:\x1b\[[0-9;]*m)?\?\s*×\d+(?:\x1b\[[0-9;]*m)?\)|\(\s*(?:\?\s*,\s*)+\?\s*\))(?:\s*,\s*\1){2,}/g;
3005
- return sql.replace(repeatedRowPattern, function (match, row) {
3006
- var _a, _b;
3007
- var rowMatches = match.match(new RegExp(row.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"));
3008
- var count = (_a = rowMatches === null || rowMatches === void 0 ? void 0 : rowMatches.length) !== null && _a !== void 0 ? _a : 1;
3009
- var normalizedRow = row.includes("×")
3010
- ? row
3011
- : "(".concat(C$1.DIM, "? \u00D7").concat(((_b = row.match(/\?/g)) !== null && _b !== void 0 ? _b : []).length).concat(RESET, ")");
3012
- return "".concat(normalizedRow, " ").concat(C$1.DIM, "\u00D7").concat(count).concat(RESET);
3013
- });
3014
- }
3015
- /* ---------- main formatter ---------- */
3016
- function colorSql(sql) {
3017
- var s = sql.trim();
3018
- /* 1️⃣ collapse bind noise */
3019
- s = collapseBinds(s);
3020
- s = collapseRepeatedValueRows(s);
3021
- /* 2️⃣ table.column coloring (core visual grouping) */
3022
- s = s.replace(/\b(`?\w+`?)\.(\w+)\b/g, function (_, table, column) {
3023
- return "".concat(tableColor(table)).concat(table).concat(RESET, ".") +
3024
- "".concat(columnColorFromTable(table)).concat(column).concat(RESET);
3025
- });
3026
- /* 3️⃣ FROM / JOIN tables */
3027
- s = s.replace(/\b(FROM|JOIN|UPDATE|INTO)\s+(`[^`]+`|\w+)/gi, function (_, kw, table) {
3028
- return "".concat(C$1.KEYWORD).concat(kw).concat(RESET, " ").concat(tableColor(table)).concat(table).concat(RESET);
3029
- });
3030
- /* 4️⃣ SQL keywords */
3031
- 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));
3032
- /* 5️⃣ LIMIT */
3033
- s = s.replace(/\bLIMIT\s+(\d+)/gi, "".concat(C$1.LIMIT, "LIMIT").concat(RESET, " ").concat(C$1.NUMBER, "$1").concat(RESET));
3034
- return s;
3035
- }
3036
-
3037
- var version = "6.0.13";
3038
-
3039
- var DEFAULT_STEP = 8;
3040
- function parseSemver(version) {
3041
- var _a = version.trim().split("-"), core = _a[0], prerelease = _a[1];
3042
- var _b = core.split("."), majorRaw = _b[0], minorRaw = _b[1], patchRaw = _b[2];
3043
- var major = Number.parseInt(majorRaw !== null && majorRaw !== void 0 ? majorRaw : "0", 10);
3044
- var minor = Number.parseInt(minorRaw !== null && minorRaw !== void 0 ? minorRaw : "0", 10);
3045
- var patch = Number.parseInt(patchRaw !== null && patchRaw !== void 0 ? patchRaw : "0", 10);
3046
- var prereleaseParts = prerelease ? prerelease.split(".").filter(Boolean).length : 0;
3047
- return {
3048
- major: Number.isFinite(major) ? major : 0,
3049
- minor: Number.isFinite(minor) ? minor : 0,
3050
- patch: Number.isFinite(patch) ? patch : 0,
3051
- prereleaseParts: prereleaseParts,
3052
- };
3053
- }
3054
- function channelValue(n, step) {
3055
- var value = 255 - ((n * step) % 256);
3056
- return (value + 256) % 256;
3057
- }
3058
- function versionToRgb(version, step) {
3059
- if (step === void 0) { step = DEFAULT_STEP; }
3060
- var safeStep = Number.isFinite(step) && step > 0 ? Math.floor(step) : DEFAULT_STEP;
3061
- var _a = parseSemver(version), major = _a.major, minor = _a.minor, patch = _a.patch, prereleaseParts = _a.prereleaseParts;
3062
- var rotation = (major + minor + patch + prereleaseParts) % 3;
3063
- var base = [major, minor, patch];
3064
- var rotated = rotation === 1
3065
- ? [base[2], base[0], base[1]]
3066
- : rotation === 2
3067
- ? [base[1], base[2], base[0]]
3068
- : base;
3069
- return {
3070
- r: channelValue(rotated[0], safeStep),
3071
- g: channelValue(rotated[1], safeStep),
3072
- b: channelValue(rotated[2], safeStep),
3073
- };
3074
- }
3075
-
3076
- var C = {
3077
- SSR: "\x1b[95m", // bright magenta
3078
- HTTP: "\x1b[94m", // bright blue
3079
- METHOD_COLORS: {
3080
- SELECT: "\x1b[92m", // green
3081
- INSERT: "\x1b[96m", // cyan
3082
- REPLACE: "\x1b[96m", // cyan
3083
- UPDATE: "\x1b[95m", // magenta
3084
- DELETE: "\x1b[91m", // red
3085
- },
3086
- METHOD_FALLBACK: [
3087
- "\x1b[92m", // green
3088
- "\x1b[93m", // yellow
3089
- "\x1b[95m", // magenta
3090
- "\x1b[96m", // cyan
3091
- "\x1b[94m", // blue
3092
- "\x1b[97m", // white
3093
- ],
3094
- RESET: "\x1b[0m",
3095
- };
3096
- var rgbAnsi = function (_a) {
3097
- var r = _a.r, g = _a.g, b = _a.b;
3098
- return "\u001B[38;2;".concat(r, ";").concat(g, ";").concat(b, "m");
3099
- };
3100
- function hashString(value) {
3101
- var hash = 0;
3102
- for (var i = 0; i < value.length; i++) {
3103
- hash = (hash * 31 + value.charCodeAt(i)) | 0;
3104
- }
3105
- return Math.abs(hash);
3106
- }
3107
- function methodColor(method) {
3108
- var key = method.toUpperCase();
3109
- if (key in C.METHOD_COLORS) {
3110
- return C.METHOD_COLORS[key];
3111
- }
3112
- var idx = hashString(key) % C.METHOD_FALLBACK.length;
3113
- return C.METHOD_FALLBACK[idx];
3114
- }
3115
- function logSql(method, sql, context) {
3116
- if (!shouldLog(exports.LogLevel.INFO, context))
3117
- return;
3118
- var preText = getEnvBool("SSR", false)
3119
- ? "".concat(C.SSR, "[SSR]").concat(C.RESET, " ")
3120
- : "".concat(C.HTTP, "[API]").concat(C.RESET, " ");
3121
- var labelColor = methodColor(method);
3122
- var versionColor = rgbAnsi(versionToRgb(version));
3123
- console.log("".concat(versionColor, "[").concat(version, "]").concat(C.RESET, " ").concat(preText).concat(labelColor, "[").concat(method, "]").concat(C.RESET, " ").concat(colorSql(sql)));
3124
- }
3125
-
3126
3162
  var SelectQueryBuilder = /** @class */ (function (_super) {
3127
3163
  tslib.__extends(SelectQueryBuilder, _super);
3128
3164
  function SelectQueryBuilder() {
@@ -3174,7 +3210,6 @@ var SelectQueryBuilder = /** @class */ (function (_super) {
3174
3210
  else if (!isSubSelect) {
3175
3211
  sql += " LIMIT 100";
3176
3212
  }
3177
- logSql("SELECT", sql, getLogContext(this.config, this.request));
3178
3213
  return { sql: sql, params: params };
3179
3214
  };
3180
3215
  return SelectQueryBuilder;
@@ -3199,7 +3234,6 @@ var DeleteQueryBuilder = /** @class */ (function (_super) {
3199
3234
  if (this.request.WHERE) {
3200
3235
  sql += this.buildWhereClause(this.request.WHERE, params);
3201
3236
  }
3202
- logSql("DELETE", sql, getLogContext(this.config, this.request));
3203
3237
  return { sql: sql, params: params };
3204
3238
  };
3205
3239
  return DeleteQueryBuilder;
@@ -3258,7 +3292,6 @@ var PostQueryBuilder = /** @class */ (function (_super) {
3258
3292
  var updateClause = updateData.map(function (k) { return "`".concat(k, "` = VALUES(`").concat(k, "`)"); }).join(', ');
3259
3293
  sql += " ON DUPLICATE KEY UPDATE ".concat(updateClause);
3260
3294
  }
3261
- logSql(verb, sql, getLogContext(this.config, this.request));
3262
3295
  return { sql: sql, params: params };
3263
3296
  };
3264
3297
  return PostQueryBuilder;
@@ -3310,7 +3343,6 @@ var UpdateQueryBuilder = /** @class */ (function (_super) {
3310
3343
  if (args.PAGINATION) {
3311
3344
  sql += this.buildPaginationClause(args.PAGINATION, params);
3312
3345
  }
3313
- logSql("UPDATE", sql, getLogContext(this.config, this.request));
3314
3346
  return { sql: sql, params: params };
3315
3347
  };
3316
3348
  return UpdateQueryBuilder;
@@ -3444,8 +3476,55 @@ function normalizeSingularRequest(requestMethod, request, restModel, removedPrim
3444
3476
  }
3445
3477
 
3446
3478
  var allowListCache = new Map();
3479
+ var ANSI_ESCAPE_REGEX = /\x1b\[[0-9;]*m/g;
3480
+ var COLLAPSED_BIND_ROW_REGEX = /\(\?\s*×\d+\)/g;
3481
+ function collapseBindGroups(sql) {
3482
+ var normalized = sql.replace(/\(\s*(\?(?:\s*,\s*\?)*)\s*\)/g, function (_match, binds) {
3483
+ var _a;
3484
+ var bindCount = ((_a = binds.match(/\?/g)) !== null && _a !== void 0 ? _a : []).length;
3485
+ return "(? \u00D7".concat(bindCount, ")");
3486
+ });
3487
+ normalized = normalized.replace(/(\(\?\s*×\d+\))(?:\s*,\s*\1)+/g, function (_match, row) { return "".concat(row, " \u00D7*"); });
3488
+ normalized = normalized.replace(/\b(VALUES|VALUE)\s+(\(\?\s*×\d+\))(?:\s*×\d+|\s*×\*)?/gi, function (_match, keyword, row) { return "".concat(keyword, " ").concat(row, " \u00D7*"); });
3489
+ normalized = normalized.replace(/\bIN\s*\(\?\s*×\d+\)/gi, "IN (? ×*)");
3490
+ normalized = normalized.replace(/\(\?\s*×\d+\)\s*×\d+/g, function (match) {
3491
+ var _a;
3492
+ var row = (_a = match.match(COLLAPSED_BIND_ROW_REGEX)) === null || _a === void 0 ? void 0 : _a[0];
3493
+ return row ? "".concat(row, " \u00D7*") : match;
3494
+ });
3495
+ return normalized;
3496
+ }
3497
+ function normalizeLimitOffset(sql) {
3498
+ return sql
3499
+ .replace(/\bLIMIT\s+\d+\s*,\s*\d+\b/gi, "LIMIT ?, ?")
3500
+ .replace(/\bLIMIT\s+\d+\s+OFFSET\s+\d+\b/gi, "LIMIT ? OFFSET ?")
3501
+ .replace(/\bLIMIT\s+\d+\b/gi, "LIMIT ?")
3502
+ .replace(/\bOFFSET\s+\d+\b/gi, "OFFSET ?");
3503
+ }
3504
+ function normalizeGeomFromTextLiterals(sql) {
3505
+ var normalized = sql.replace(/ST_GEOMFROMTEXT\(\s*'POINT\([^']*\)'\s*,\s*(?:\d+|\?)\s*\)/gi, "ST_GEOMFROMTEXT('POINT(? ?)', ?)");
3506
+ normalized = normalized.replace(/ST_GEOMFROMTEXT\(\s*'POLYGON\(\([^']*\)\)'\s*,\s*(?:\d+|\?)\s*\)/gi, "ST_GEOMFROMTEXT('POLYGON((?))', ?)");
3507
+ return normalized;
3508
+ }
3509
+ function normalizeGeoFunctionNames(sql) {
3510
+ return sql
3511
+ .replace(/\bST_DISTANCE_SPHERE\b/gi, "ST_DISTANCE_SPHERE")
3512
+ .replace(/\bST_GEOMFROMTEXT\b/gi, "ST_GEOMFROMTEXT")
3513
+ .replace(/\bMBRCONTAINS\b/gi, "MBRCONTAINS");
3514
+ }
3515
+ function normalizeTokenPunctuationSpacing(sql) {
3516
+ return sql.replace(/`,\s*`/g, "`, `");
3517
+ }
3447
3518
  var normalizeSql = function (sql) {
3448
- return sql.replace(/\s+/g, " ").trim();
3519
+ var normalized = sql.replace(ANSI_ESCAPE_REGEX, " ");
3520
+ normalized = normalized.replace(/\s+/g, " ").trim();
3521
+ normalized = normalizeGeoFunctionNames(normalized);
3522
+ normalized = normalizeTokenPunctuationSpacing(normalized);
3523
+ normalized = collapseBindGroups(normalized);
3524
+ normalized = normalizeLimitOffset(normalized);
3525
+ normalized = normalizeGeomFromTextLiterals(normalized);
3526
+ normalized = normalized.replace(/;\s*$/, "");
3527
+ return normalized.replace(/\s+/g, " ").trim();
3449
3528
  };
3450
3529
  var parseAllowList = function (raw, sourcePath) {
3451
3530
  var parsed;
@@ -3468,33 +3547,51 @@ var parseAllowList = function (raw, sourcePath) {
3468
3547
  return sqlEntries;
3469
3548
  };
3470
3549
  var loadSqlAllowList = function (allowListPath) { return tslib.__awaiter(void 0, void 0, void 0, function () {
3471
- var readFile, raw, sqlEntries, allowList;
3472
- return tslib.__generator(this, function (_a) {
3473
- switch (_a.label) {
3550
+ var _a, readFile, stat, fileStat, cached, raw, sqlEntries, allowList;
3551
+ return tslib.__generator(this, function (_b) {
3552
+ switch (_b.label) {
3474
3553
  case 0:
3475
- if (allowListCache.has(allowListPath)) {
3476
- return [2 /*return*/, allowListCache.get(allowListPath)];
3477
- }
3478
3554
  if (!isNode()) {
3479
3555
  throw new Error("SQL allowlist validation requires a Node runtime.");
3480
3556
  }
3481
3557
  return [4 /*yield*/, import('node:fs/promises')];
3482
3558
  case 1:
3483
- readFile = (_a.sent()).readFile;
3484
- _a.label = 2;
3559
+ _a = _b.sent(), readFile = _a.readFile, stat = _a.stat;
3560
+ _b.label = 2;
3485
3561
  case 2:
3486
- _a.trys.push([2, 4, , 5]);
3487
- return [4 /*yield*/, readFile(allowListPath, "utf-8")];
3562
+ _b.trys.push([2, 4, , 5]);
3563
+ return [4 /*yield*/, stat(allowListPath)];
3488
3564
  case 3:
3489
- raw = _a.sent();
3565
+ fileStat = _b.sent();
3490
3566
  return [3 /*break*/, 5];
3491
3567
  case 4:
3492
- _a.sent();
3568
+ _b.sent();
3493
3569
  throw new Error("SQL allowlist file not found at ".concat(allowListPath, "."));
3494
3570
  case 5:
3571
+ cached = allowListCache.get(allowListPath);
3572
+ if (cached &&
3573
+ cached.mtimeMs === fileStat.mtimeMs &&
3574
+ cached.size === fileStat.size) {
3575
+ return [2 /*return*/, cached.allowList];
3576
+ }
3577
+ _b.label = 6;
3578
+ case 6:
3579
+ _b.trys.push([6, 8, , 9]);
3580
+ return [4 /*yield*/, readFile(allowListPath, "utf-8")];
3581
+ case 7:
3582
+ raw = _b.sent();
3583
+ return [3 /*break*/, 9];
3584
+ case 8:
3585
+ _b.sent();
3586
+ throw new Error("SQL allowlist file not found at ".concat(allowListPath, "."));
3587
+ case 9:
3495
3588
  sqlEntries = parseAllowList(raw, allowListPath);
3496
3589
  allowList = new Set(sqlEntries);
3497
- allowListCache.set(allowListPath, allowList);
3590
+ allowListCache.set(allowListPath, {
3591
+ allowList: allowList,
3592
+ mtimeMs: fileStat.mtimeMs,
3593
+ size: fileStat.size,
3594
+ });
3498
3595
  return [2 /*return*/, allowList];
3499
3596
  }
3500
3597
  });
@@ -3557,6 +3654,25 @@ var compileSqlAllowList = function (allowListPath, entries) { return tslib.__awa
3557
3654
  });
3558
3655
  }); };
3559
3656
 
3657
+ var SQL_ALLOWLIST_BLOCKED_CODE = "SQL_ALLOWLIST_BLOCKED";
3658
+ var createSqlAllowListBlockedError = function (args) {
3659
+ var _a, _b;
3660
+ var error = new Error("SQL statement is not permitted by allowlist (".concat(args.allowListPath, ")."));
3661
+ error.name = "SqlAllowListBlockedError";
3662
+ error.code = SQL_ALLOWLIST_BLOCKED_CODE;
3663
+ error.tableName = args.tableName;
3664
+ error.method = args.method;
3665
+ error.normalizedSql = args.normalizedSql;
3666
+ error.allowListPath = args.allowListPath;
3667
+ error.sqlAllowList = {
3668
+ sql: args.normalizedSql,
3669
+ table: (_a = args.tableName) !== null && _a !== void 0 ? _a : null,
3670
+ method: (_b = args.method) !== null && _b !== void 0 ? _b : null,
3671
+ allowListPath: args.allowListPath,
3672
+ canAdd: true,
3673
+ };
3674
+ return error;
3675
+ };
3560
3676
  var SqlExecutor = /** @class */ (function (_super) {
3561
3677
  tslib.__extends(SqlExecutor, _super);
3562
3678
  function SqlExecutor() {
@@ -3567,6 +3683,22 @@ var SqlExecutor = /** @class */ (function (_super) {
3567
3683
  })); };
3568
3684
  return _this;
3569
3685
  }
3686
+ SqlExecutor.prototype.resolveSqlLogMethod = function (method, sql) {
3687
+ var _a;
3688
+ var token = (_a = sql.trim().split(/\s+/, 1)[0]) === null || _a === void 0 ? void 0 : _a.toUpperCase();
3689
+ if (token)
3690
+ return token;
3691
+ switch (method) {
3692
+ case C6Constants.GET:
3693
+ return "SELECT";
3694
+ case C6Constants.POST:
3695
+ return "INSERT";
3696
+ case C6Constants.PUT:
3697
+ return "UPDATE";
3698
+ default:
3699
+ return "DELETE";
3700
+ }
3701
+ };
3570
3702
  SqlExecutor.prototype.execute = function () {
3571
3703
  return tslib.__awaiter(this, void 0, void 0, function () {
3572
3704
  var TABLE_NAME, method, logContext, response, _a, rest, getResponse, restRows, result, result, result;
@@ -3938,7 +4070,7 @@ var SqlExecutor = /** @class */ (function (_super) {
3938
4070
  };
3939
4071
  SqlExecutor.prototype.runQuery = function () {
3940
4072
  return tslib.__awaiter(this, void 0, void 0, function () {
3941
- var method, tableName, logContext, cacheResults, cacheRequestData, requestArgumentsSerialized, cachedRequest, sqlExecution, queryPromise, cacheRequest, cacheResponse;
4073
+ var method, tableName, logContext, cacheResults, cacheRequestData, requestArgumentsSerialized, cachedRequest, sqlExecution, sqlMethod, queryPromise, cacheRequest, cacheResponse;
3942
4074
  var _this = this;
3943
4075
  var _a, _b;
3944
4076
  return tslib.__generator(this, function (_c) {
@@ -3948,8 +4080,7 @@ var SqlExecutor = /** @class */ (function (_super) {
3948
4080
  tableName = this.config.restModel.TABLE_NAME;
3949
4081
  logContext = getLogContext(this.config, this.request);
3950
4082
  cacheResults = method === C6Constants.GET
3951
- && !this.config.sqlAllowListPath
3952
- && ((_a = this.request) === null || _a === void 0 ? void 0 : _a.cacheResults) !== false;
4083
+ && ((_a = this.request.cacheResults) !== null && _a !== void 0 ? _a : true);
3953
4084
  cacheRequestData = cacheResults
3954
4085
  ? JSON.parse(JSON.stringify((_b = this.request) !== null && _b !== void 0 ? _b : {}))
3955
4086
  : undefined;
@@ -3957,15 +4088,18 @@ var SqlExecutor = /** @class */ (function (_super) {
3957
4088
  ? sortAndSerializeQueryObject(tableName, cacheRequestData !== null && cacheRequestData !== void 0 ? cacheRequestData : {})
3958
4089
  : undefined;
3959
4090
  if (!cacheResults) return [3 /*break*/, 2];
3960
- cachedRequest = checkCache(method, tableName, cacheRequestData);
4091
+ cachedRequest = checkCache(method, tableName, cacheRequestData, logContext);
3961
4092
  if (!cachedRequest) return [3 /*break*/, 2];
3962
4093
  return [4 /*yield*/, cachedRequest];
3963
4094
  case 1: return [2 /*return*/, (_c.sent()).data];
3964
4095
  case 2:
3965
4096
  sqlExecution = this.buildSqlExecutionContext(method, tableName, logContext);
3966
- queryPromise = this.withConnection(function (conn) { return tslib.__awaiter(_this, void 0, void 0, function () { return tslib.__generator(this, function (_a) {
3967
- return [2 /*return*/, this.executeQueryWithLifecycle(conn, method, sqlExecution, logContext)];
3968
- }); }); });
4097
+ sqlMethod = this.resolveSqlLogMethod(method, sqlExecution.sql);
4098
+ queryPromise = this.withConnection(function (conn) { return tslib.__awaiter(_this, void 0, void 0, function () {
4099
+ return tslib.__generator(this, function (_a) {
4100
+ return [2 /*return*/, this.executeQueryWithLifecycle(conn, method, sqlExecution, logContext, sqlMethod)];
4101
+ });
4102
+ }); });
3969
4103
  if (!(!cacheResults || !cacheRequestData || !requestArgumentsSerialized)) return [3 /*break*/, 4];
3970
4104
  return [4 /*yield*/, queryPromise];
3971
4105
  case 3: return [2 /*return*/, _c.sent()];
@@ -4043,9 +4177,9 @@ var SqlExecutor = /** @class */ (function (_super) {
4043
4177
  },
4044
4178
  };
4045
4179
  };
4046
- SqlExecutor.prototype.executeQueryWithLifecycle = function (conn, method, sqlExecution, logContext) {
4180
+ SqlExecutor.prototype.executeQueryWithLifecycle = function (conn, method, sqlExecution, logContext, sqlMethod) {
4047
4181
  return tslib.__awaiter(this, void 0, void 0, function () {
4048
- var useTransaction, committed, result, response, hookResponse, err_1, rollbackErr_1;
4182
+ var useTransaction, committed, allowListStatus, error_2, result, response, hookResponse, err_1, rollbackErr_1;
4049
4183
  return tslib.__generator(this, function (_a) {
4050
4184
  switch (_a.label) {
4051
4185
  case 0:
@@ -4053,25 +4187,49 @@ var SqlExecutor = /** @class */ (function (_super) {
4053
4187
  committed = false;
4054
4188
  _a.label = 1;
4055
4189
  case 1:
4056
- _a.trys.push([1, 11, , 16]);
4190
+ _a.trys.push([1, 14, , 19]);
4057
4191
  if (!useTransaction) return [3 /*break*/, 3];
4058
4192
  logWithLevel(exports.LogLevel.DEBUG, logContext, console.log, "[SQL EXECUTOR] \uD83E\uDDFE Beginning transaction");
4059
4193
  return [4 /*yield*/, conn.beginTransaction()];
4060
4194
  case 2:
4061
4195
  _a.sent();
4062
4196
  _a.label = 3;
4063
- case 3: return [4 /*yield*/, this.validateSqlAllowList(sqlExecution.sql)];
4197
+ case 3:
4198
+ allowListStatus = "not verified";
4199
+ _a.label = 4;
4064
4200
  case 4:
4065
- _a.sent();
4201
+ _a.trys.push([4, 6, , 7]);
4202
+ return [4 /*yield*/, this.validateSqlAllowList(sqlExecution.sql)];
4203
+ case 5:
4204
+ allowListStatus = _a.sent();
4205
+ return [3 /*break*/, 7];
4206
+ case 6:
4207
+ error_2 = _a.sent();
4208
+ logSql({
4209
+ method: sqlMethod,
4210
+ sql: sqlExecution.sql,
4211
+ context: logContext,
4212
+ cacheStatus: this.request.cacheResults === false ? "ignored" : "miss",
4213
+ allowListStatus: "denied",
4214
+ });
4215
+ throw error_2;
4216
+ case 7:
4217
+ logSql({
4218
+ method: sqlMethod,
4219
+ sql: sqlExecution.sql,
4220
+ context: logContext,
4221
+ cacheStatus: this.request.cacheResults === false ? "ignored" : "miss",
4222
+ allowListStatus: allowListStatus,
4223
+ });
4066
4224
  return [4 /*yield*/, this.runLifecycleHooks("beforeExecution", {
4067
4225
  config: this.config,
4068
4226
  request: this.request,
4069
4227
  sqlExecution: sqlExecution,
4070
4228
  })];
4071
- case 5:
4229
+ case 8:
4072
4230
  _a.sent();
4073
4231
  return [4 /*yield*/, conn.query(sqlExecution.sql, sqlExecution.values)];
4074
- case 6:
4232
+ case 9:
4075
4233
  result = (_a.sent())[0];
4076
4234
  response = this.createResponseFromQueryResult(method, result, sqlExecution, logContext);
4077
4235
  hookResponse = this.createLifecycleHookResponse(response);
@@ -4080,40 +4238,40 @@ var SqlExecutor = /** @class */ (function (_super) {
4080
4238
  request: this.request,
4081
4239
  response: hookResponse,
4082
4240
  })];
4083
- case 7:
4241
+ case 10:
4084
4242
  _a.sent();
4085
- if (!useTransaction) return [3 /*break*/, 9];
4243
+ if (!useTransaction) return [3 /*break*/, 12];
4086
4244
  return [4 /*yield*/, conn.commit()];
4087
- case 8:
4245
+ case 11:
4088
4246
  _a.sent();
4089
4247
  committed = true;
4090
4248
  logWithLevel(exports.LogLevel.DEBUG, logContext, console.log, "[SQL EXECUTOR] \uD83E\uDDFE Transaction committed");
4091
- _a.label = 9;
4092
- case 9: return [4 /*yield*/, this.runLifecycleHooks("afterCommit", {
4249
+ _a.label = 12;
4250
+ case 12: return [4 /*yield*/, this.runLifecycleHooks("afterCommit", {
4093
4251
  config: this.config,
4094
4252
  request: this.request,
4095
4253
  response: hookResponse,
4096
4254
  })];
4097
- case 10:
4255
+ case 13:
4098
4256
  _a.sent();
4099
4257
  return [2 /*return*/, response];
4100
- case 11:
4258
+ case 14:
4101
4259
  err_1 = _a.sent();
4102
- if (!(useTransaction && !committed)) return [3 /*break*/, 15];
4103
- _a.label = 12;
4104
- case 12:
4105
- _a.trys.push([12, 14, , 15]);
4260
+ if (!(useTransaction && !committed)) return [3 /*break*/, 18];
4261
+ _a.label = 15;
4262
+ case 15:
4263
+ _a.trys.push([15, 17, , 18]);
4106
4264
  return [4 /*yield*/, conn.rollback()];
4107
- case 13:
4265
+ case 16:
4108
4266
  _a.sent();
4109
4267
  logWithLevel(exports.LogLevel.WARN, logContext, console.warn, "[SQL EXECUTOR] \uD83E\uDDFE Transaction rolled back");
4110
- return [3 /*break*/, 15];
4111
- case 14:
4268
+ return [3 /*break*/, 18];
4269
+ case 17:
4112
4270
  rollbackErr_1 = _a.sent();
4113
4271
  logWithLevel(exports.LogLevel.ERROR, logContext, console.error, "[SQL EXECUTOR] Rollback failed", rollbackErr_1);
4114
- return [3 /*break*/, 15];
4115
- case 15: throw err_1;
4116
- case 16: return [2 /*return*/];
4272
+ return [3 /*break*/, 18];
4273
+ case 18: throw err_1;
4274
+ case 19: return [2 /*return*/];
4117
4275
  }
4118
4276
  });
4119
4277
  });
@@ -4121,21 +4279,31 @@ var SqlExecutor = /** @class */ (function (_super) {
4121
4279
  SqlExecutor.prototype.validateSqlAllowList = function (sql) {
4122
4280
  return tslib.__awaiter(this, void 0, void 0, function () {
4123
4281
  var allowListPath, allowList, normalized;
4124
- return tslib.__generator(this, function (_a) {
4125
- switch (_a.label) {
4282
+ var _a;
4283
+ return tslib.__generator(this, function (_b) {
4284
+ switch (_b.label) {
4126
4285
  case 0:
4127
4286
  allowListPath = this.config.sqlAllowListPath;
4128
4287
  if (!allowListPath) {
4129
- return [2 /*return*/];
4288
+ return [2 /*return*/, "not verified"];
4130
4289
  }
4131
4290
  return [4 /*yield*/, loadSqlAllowList(allowListPath)];
4132
4291
  case 1:
4133
- allowList = _a.sent();
4292
+ allowList = _b.sent();
4134
4293
  normalized = normalizeSql(sql);
4135
4294
  if (!allowList.has(normalized)) {
4136
- throw new Error("SQL statement is not permitted by allowlist (".concat(allowListPath, ")."));
4295
+ throw createSqlAllowListBlockedError({
4296
+ tableName: typeof ((_a = this.config.restModel) === null || _a === void 0 ? void 0 : _a.TABLE_NAME) === "string"
4297
+ ? this.config.restModel.TABLE_NAME
4298
+ : undefined,
4299
+ method: typeof this.config.requestMethod === "string"
4300
+ ? this.config.requestMethod
4301
+ : undefined,
4302
+ normalizedSql: normalized,
4303
+ allowListPath: allowListPath,
4304
+ });
4137
4305
  }
4138
- return [2 /*return*/];
4306
+ return [2 /*return*/, "allowed"];
4139
4307
  }
4140
4308
  });
4141
4309
  });