@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.
- package/dist/executors/SqlExecutor.d.ts +17 -0
- package/dist/index.cjs.js +450 -248
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +450 -249
- package/dist/index.esm.js.map +1 -1
- package/dist/types/ormInterfaces.d.ts +1 -0
- package/dist/utils/cacheManager.d.ts +3 -1
- package/dist/utils/logLevel.d.ts +3 -3
- package/dist/utils/logSql.d.ts +10 -1
- package/package.json +2 -2
- package/scripts/assets/handlebars/C6.ts.handlebars +1 -1
- package/src/__tests__/fixtures/sqlResponses/sqlAllowList.json +1 -1
- package/src/__tests__/httpExecutor.cacheEviction.test.ts +70 -0
- package/src/__tests__/logSql.test.ts +54 -2
- package/src/__tests__/sakila-db/C6.js +1 -1
- package/src/__tests__/sakila-db/C6.mysqldump.json +1 -1
- package/src/__tests__/sakila-db/C6.mysqldump.sql +1 -1
- package/src/__tests__/sakila-db/C6.sqlAllowList.json +59 -70
- package/src/__tests__/sakila-db/C6.ts +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.actor.post.json +3 -3
- package/src/__tests__/sakila-db/sqlResponses/C6.actor.post.latest.json +3 -3
- package/src/__tests__/sakila-db/sqlResponses/C6.actor.put.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.actor.put.lookup.json +3 -3
- package/src/__tests__/sakila-db/sqlResponses/C6.address.post.json +5 -5
- package/src/__tests__/sakila-db/sqlResponses/C6.address.post.latest.json +5 -5
- package/src/__tests__/sakila-db/sqlResponses/C6.address.put.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.address.put.lookup.json +5 -5
- package/src/__tests__/sakila-db/sqlResponses/C6.category.post.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.category.post.latest.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.category.put.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.category.put.lookup.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.city.post.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.city.post.latest.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.city.put.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.city.put.lookup.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.country.post.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.country.post.latest.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.country.put.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.country.put.lookup.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.customer.post.json +5 -5
- package/src/__tests__/sakila-db/sqlResponses/C6.customer.post.latest.json +5 -5
- package/src/__tests__/sakila-db/sqlResponses/C6.customer.put.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.customer.put.lookup.json +5 -5
- package/src/__tests__/sakila-db/sqlResponses/C6.film.post.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.film.post.latest.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.film.put.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.film.put.lookup.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.inventory.post.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.inventory.post.latest.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.inventory.put.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.inventory.put.lookup.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.language.post.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.language.post.latest.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.language.put.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.language.put.lookup.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.payment.post.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.payment.post.latest.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.payment.put.lookup.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.rental.join.json +10 -10
- package/src/__tests__/sakila-db/sqlResponses/C6.rental.post.json +3 -3
- package/src/__tests__/sakila-db/sqlResponses/C6.rental.post.latest.json +3 -3
- package/src/__tests__/sakila-db/sqlResponses/C6.rental.put.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.rental.put.lookup.json +3 -3
- package/src/__tests__/sqlAllowList.test.ts +100 -0
- package/src/__tests__/sqlBuilders.test.ts +3 -4
- package/src/__tests__/sqlExecutor.cacheEviction.test.ts +79 -0
- package/src/executors/HttpExecutor.ts +20 -4
- package/src/executors/SqlExecutor.ts +131 -12
- package/src/orm/queries/DeleteQueryBuilder.ts +0 -4
- package/src/orm/queries/PostQueryBuilder.ts +0 -4
- package/src/orm/queries/SelectQueryBuilder.ts +0 -4
- package/src/orm/queries/UpdateQueryBuilder.ts +0 -4
- package/src/types/ormInterfaces.ts +4 -1
- package/src/utils/cacheManager.ts +26 -9
- package/src/utils/logLevel.ts +3 -4
- package/src/utils/logSql.ts +51 -6
- 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
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
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:
|
|
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 (!(
|
|
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
|
-
|
|
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 (
|
|
3475
|
-
switch (
|
|
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
|
-
|
|
3486
|
-
|
|
3577
|
+
_a = _b.sent(), readFile = _a.readFile, stat = _a.stat;
|
|
3578
|
+
_b.label = 2;
|
|
3487
3579
|
case 2:
|
|
3488
|
-
|
|
3489
|
-
return [4 /*yield*/,
|
|
3580
|
+
_b.trys.push([2, 4, , 5]);
|
|
3581
|
+
return [4 /*yield*/, stat(allowListPath)];
|
|
3490
3582
|
case 3:
|
|
3491
|
-
|
|
3583
|
+
fileStat = _b.sent();
|
|
3492
3584
|
return [3 /*break*/, 5];
|
|
3493
3585
|
case 4:
|
|
3494
|
-
|
|
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,
|
|
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
|
-
&&
|
|
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:
|
|
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
|
-
|
|
3969
|
-
|
|
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,
|
|
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:
|
|
4232
|
+
case 3:
|
|
4233
|
+
allowListStatus = "not verified";
|
|
4234
|
+
_a.label = 4;
|
|
4066
4235
|
case 4:
|
|
4067
|
-
_a.
|
|
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
|
|
4264
|
+
case 8:
|
|
4074
4265
|
_a.sent();
|
|
4075
4266
|
return [4 /*yield*/, conn.query(sqlExecution.sql, sqlExecution.values)];
|
|
4076
|
-
case
|
|
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
|
|
4276
|
+
case 10:
|
|
4086
4277
|
_a.sent();
|
|
4087
|
-
if (!useTransaction) return [3 /*break*/,
|
|
4278
|
+
if (!useTransaction) return [3 /*break*/, 12];
|
|
4088
4279
|
return [4 /*yield*/, conn.commit()];
|
|
4089
|
-
case
|
|
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 =
|
|
4094
|
-
case
|
|
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
|
|
4290
|
+
case 13:
|
|
4100
4291
|
_a.sent();
|
|
4101
4292
|
return [2 /*return*/, response];
|
|
4102
|
-
case
|
|
4293
|
+
case 14:
|
|
4103
4294
|
err_1 = _a.sent();
|
|
4104
|
-
if (!(useTransaction && !committed)) return [3 /*break*/,
|
|
4105
|
-
_a.label =
|
|
4106
|
-
case
|
|
4107
|
-
_a.trys.push([
|
|
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
|
|
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*/,
|
|
4113
|
-
case
|
|
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*/,
|
|
4117
|
-
case
|
|
4118
|
-
case
|
|
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
|
-
|
|
4127
|
-
|
|
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 =
|
|
4327
|
+
allowList = _b.sent();
|
|
4136
4328
|
normalized = normalizeSql(sql);
|
|
4137
4329
|
if (!allowList.has(normalized)) {
|
|
4138
|
-
throw
|
|
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;
|