@carbonorm/carbonnode 6.0.14 → 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.
- package/dist/executors/SqlExecutor.d.ts +17 -0
- package/dist/index.cjs.js +410 -244
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +410 -244
- package/dist/index.esm.js.map +1 -1
- package/dist/utils/cacheManager.d.ts +2 -1
- package/dist/utils/logLevel.d.ts +3 -3
- package/dist/utils/logSql.d.ts +10 -1
- package/package.json +1 -1
- package/scripts/assets/handlebars/C6.ts.handlebars +1 -1
- package/src/__tests__/fixtures/sqlResponses/sqlAllowList.json +1 -1
- 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.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/executors/HttpExecutor.ts +1 -1
- package/src/executors/SqlExecutor.ts +108 -7
- 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/utils/cacheManager.ts +17 -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.esm.js
CHANGED
|
@@ -514,8 +514,6 @@ var applyLogLevelDefaults = function (config, request) {
|
|
|
514
514
|
};
|
|
515
515
|
var getLogContext = function (config, request) {
|
|
516
516
|
var _a, _b;
|
|
517
|
-
if (!config && !request)
|
|
518
|
-
return undefined;
|
|
519
517
|
return {
|
|
520
518
|
logLevel: (_a = config === null || config === void 0 ? void 0 : config.logLevel) !== null && _a !== void 0 ? _a : undefined,
|
|
521
519
|
verbose: (_b = config === null || config === void 0 ? void 0 : config.verbose) !== null && _b !== void 0 ? _b : undefined,
|
|
@@ -862,6 +860,213 @@ function removeInvalidKeys(request, c6Tables) {
|
|
|
862
860
|
return intersection;
|
|
863
861
|
}
|
|
864
862
|
|
|
863
|
+
/* eslint-disable no-control-regex */
|
|
864
|
+
var RESET = "\x1b[0m";
|
|
865
|
+
var C$1 = {
|
|
866
|
+
KEYWORD: "\x1b[94m", // blue
|
|
867
|
+
LIMIT: "\x1b[93m", // yellow
|
|
868
|
+
NUMBER: "\x1b[92m", // green
|
|
869
|
+
DIM: "\x1b[90m", // gray
|
|
870
|
+
};
|
|
871
|
+
/* ---------- ANSI helpers ---------- */
|
|
872
|
+
var ansi256 = function (n) { return "\u001B[38;5;".concat(n, "m"); };
|
|
873
|
+
/* ---------- hashing ---------- */
|
|
874
|
+
function hashString$1(str) {
|
|
875
|
+
var hash = 0;
|
|
876
|
+
for (var i = 0; i < str.length; i++) {
|
|
877
|
+
hash = (hash * 31 + str.charCodeAt(i)) | 0;
|
|
878
|
+
}
|
|
879
|
+
return Math.abs(hash);
|
|
880
|
+
}
|
|
881
|
+
/* ---------- table color ---------- */
|
|
882
|
+
function tableRGB(tableName) {
|
|
883
|
+
var name = tableName.replace(/[`"]/g, "").toLowerCase();
|
|
884
|
+
var hash = hashString$1(name);
|
|
885
|
+
// Stable hue bucket by first letter
|
|
886
|
+
var first = name.charCodeAt(0) || 97;
|
|
887
|
+
var hueBase = (first - 97) % 6;
|
|
888
|
+
var r = (hueBase + (hash % 3)) % 6;
|
|
889
|
+
var g = (hash >> 3) % 6;
|
|
890
|
+
var b = (hash >> 6) % 6;
|
|
891
|
+
return [r, g, Math.max(2, b)]; // avoid muddy dark blues
|
|
892
|
+
}
|
|
893
|
+
function tableColor(table) {
|
|
894
|
+
var _a = tableRGB(table), r = _a[0], g = _a[1], b = _a[2];
|
|
895
|
+
return ansi256(16 + 36 * r + 6 * g + b);
|
|
896
|
+
}
|
|
897
|
+
/* ---------- column color (same hue, lighter) ---------- */
|
|
898
|
+
function columnColorFromTable(table) {
|
|
899
|
+
var _a = tableRGB(table), r = _a[0], g = _a[1], b = _a[2];
|
|
900
|
+
// Lift toward white, preserve hue
|
|
901
|
+
var lr = Math.min(5, r + 1);
|
|
902
|
+
var lg = Math.min(5, g + 1);
|
|
903
|
+
var lb = Math.min(5, b + 2);
|
|
904
|
+
return ansi256(16 + 36 * lr + 6 * lg + lb);
|
|
905
|
+
}
|
|
906
|
+
/* ---------- bind collapsing ---------- */
|
|
907
|
+
/**
|
|
908
|
+
* ?, ?, ?, ?, ?, ? → ? ×6
|
|
909
|
+
* triggers at 4+
|
|
910
|
+
*/
|
|
911
|
+
function collapseBinds(sql) {
|
|
912
|
+
return sql.replace(/(\?\s*,\s*){3,}\?/g, function (match) {
|
|
913
|
+
var count = match.split("?").length - 1;
|
|
914
|
+
return "".concat(C$1.DIM, "? \u00D7").concat(count).concat(RESET);
|
|
915
|
+
});
|
|
916
|
+
}
|
|
917
|
+
/**
|
|
918
|
+
* ( ? ×9 ), ( ? ×9 ), ( ? ×9 ) -> ( ? ×9 ) ×3
|
|
919
|
+
*/
|
|
920
|
+
function collapseRepeatedValueRows(sql) {
|
|
921
|
+
var repeatedRowPattern = /(\((?:\x1b\[[0-9;]*m)?\?\s*×\d+(?:\x1b\[[0-9;]*m)?\)|\(\s*(?:\?\s*,\s*)+\?\s*\))(?:\s*,\s*\1){2,}/g;
|
|
922
|
+
return sql.replace(repeatedRowPattern, function (match, row) {
|
|
923
|
+
var _a, _b;
|
|
924
|
+
var rowMatches = match.match(new RegExp(row.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"));
|
|
925
|
+
var count = (_a = rowMatches === null || rowMatches === void 0 ? void 0 : rowMatches.length) !== null && _a !== void 0 ? _a : 1;
|
|
926
|
+
var normalizedRow = row.includes("×")
|
|
927
|
+
? row
|
|
928
|
+
: "(".concat(C$1.DIM, "? \u00D7").concat(((_b = row.match(/\?/g)) !== null && _b !== void 0 ? _b : []).length).concat(RESET, ")");
|
|
929
|
+
return "".concat(normalizedRow, " ").concat(C$1.DIM, "\u00D7").concat(count).concat(RESET);
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
/* ---------- main formatter ---------- */
|
|
933
|
+
function colorSql(sql) {
|
|
934
|
+
var s = sql.trim();
|
|
935
|
+
/* 1️⃣ collapse bind noise */
|
|
936
|
+
s = collapseBinds(s);
|
|
937
|
+
s = collapseRepeatedValueRows(s);
|
|
938
|
+
/* 2️⃣ table.column coloring (core visual grouping) */
|
|
939
|
+
s = s.replace(/\b(`?\w+`?)\.(\w+)\b/g, function (_, table, column) {
|
|
940
|
+
return "".concat(tableColor(table)).concat(table).concat(RESET, ".") +
|
|
941
|
+
"".concat(columnColorFromTable(table)).concat(column).concat(RESET);
|
|
942
|
+
});
|
|
943
|
+
/* 3️⃣ FROM / JOIN tables */
|
|
944
|
+
s = s.replace(/\b(FROM|JOIN|UPDATE|INTO)\s+(`[^`]+`|\w+)/gi, function (_, kw, table) {
|
|
945
|
+
return "".concat(C$1.KEYWORD).concat(kw).concat(RESET, " ").concat(tableColor(table)).concat(table).concat(RESET);
|
|
946
|
+
});
|
|
947
|
+
/* 4️⃣ SQL keywords */
|
|
948
|
+
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));
|
|
949
|
+
/* 5️⃣ LIMIT */
|
|
950
|
+
s = s.replace(/\bLIMIT\s+(\d+)/gi, "".concat(C$1.LIMIT, "LIMIT").concat(RESET, " ").concat(C$1.NUMBER, "$1").concat(RESET));
|
|
951
|
+
return s;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
var version = "6.0.17";
|
|
955
|
+
|
|
956
|
+
var DEFAULT_STEP = 8;
|
|
957
|
+
function parseSemver(version) {
|
|
958
|
+
var _a = version.trim().split("-"), core = _a[0], prerelease = _a[1];
|
|
959
|
+
var _b = core.split("."), majorRaw = _b[0], minorRaw = _b[1], patchRaw = _b[2];
|
|
960
|
+
var major = Number.parseInt(majorRaw !== null && majorRaw !== void 0 ? majorRaw : "0", 10);
|
|
961
|
+
var minor = Number.parseInt(minorRaw !== null && minorRaw !== void 0 ? minorRaw : "0", 10);
|
|
962
|
+
var patch = Number.parseInt(patchRaw !== null && patchRaw !== void 0 ? patchRaw : "0", 10);
|
|
963
|
+
var prereleaseParts = prerelease ? prerelease.split(".").filter(Boolean).length : 0;
|
|
964
|
+
return {
|
|
965
|
+
major: Number.isFinite(major) ? major : 0,
|
|
966
|
+
minor: Number.isFinite(minor) ? minor : 0,
|
|
967
|
+
patch: Number.isFinite(patch) ? patch : 0,
|
|
968
|
+
prereleaseParts: prereleaseParts,
|
|
969
|
+
};
|
|
970
|
+
}
|
|
971
|
+
function channelValue(n, step) {
|
|
972
|
+
var value = 255 - ((n * step) % 256);
|
|
973
|
+
return (value + 256) % 256;
|
|
974
|
+
}
|
|
975
|
+
function versionToRgb(version, step) {
|
|
976
|
+
if (step === void 0) { step = DEFAULT_STEP; }
|
|
977
|
+
var safeStep = Number.isFinite(step) && step > 0 ? Math.floor(step) : DEFAULT_STEP;
|
|
978
|
+
var _a = parseSemver(version), major = _a.major, minor = _a.minor, patch = _a.patch, prereleaseParts = _a.prereleaseParts;
|
|
979
|
+
var rotation = (major + minor + patch + prereleaseParts) % 3;
|
|
980
|
+
var base = [major, minor, patch];
|
|
981
|
+
var rotated = rotation === 1
|
|
982
|
+
? [base[2], base[0], base[1]]
|
|
983
|
+
: rotation === 2
|
|
984
|
+
? [base[1], base[2], base[0]]
|
|
985
|
+
: base;
|
|
986
|
+
return {
|
|
987
|
+
r: channelValue(rotated[0], safeStep),
|
|
988
|
+
g: channelValue(rotated[1], safeStep),
|
|
989
|
+
b: channelValue(rotated[2], safeStep),
|
|
990
|
+
};
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
var C = {
|
|
994
|
+
SSR: "\x1b[95m", // bright magenta
|
|
995
|
+
HTTP: "\x1b[94m", // bright blue
|
|
996
|
+
WARN: "\x1b[93m", // yellow
|
|
997
|
+
ORANGE: "\x1b[38;2;255;165;0m", // orange (truecolor)
|
|
998
|
+
ERROR: "\x1b[91m", // red
|
|
999
|
+
METHOD_COLORS: {
|
|
1000
|
+
SELECT: "\x1b[92m", // green
|
|
1001
|
+
INSERT: "\x1b[96m", // cyan
|
|
1002
|
+
REPLACE: "\x1b[96m", // cyan
|
|
1003
|
+
UPDATE: "\x1b[95m", // magenta
|
|
1004
|
+
DELETE: "\x1b[38;2;255;179;179m", // very light red (truecolor)
|
|
1005
|
+
},
|
|
1006
|
+
METHOD_FALLBACK: [
|
|
1007
|
+
"\x1b[92m", // green
|
|
1008
|
+
"\x1b[93m", // yellow
|
|
1009
|
+
"\x1b[95m", // magenta
|
|
1010
|
+
"\x1b[96m", // cyan
|
|
1011
|
+
"\x1b[94m", // blue
|
|
1012
|
+
"\x1b[97m", // white
|
|
1013
|
+
],
|
|
1014
|
+
GREY: "\x1b[90m", // light grey
|
|
1015
|
+
RESET: "\x1b[0m",
|
|
1016
|
+
};
|
|
1017
|
+
var rgbAnsi = function (_a) {
|
|
1018
|
+
var r = _a.r, g = _a.g, b = _a.b;
|
|
1019
|
+
return "\u001B[38;2;".concat(r, ";").concat(g, ";").concat(b, "m");
|
|
1020
|
+
};
|
|
1021
|
+
function hashString(value) {
|
|
1022
|
+
var hash = 0;
|
|
1023
|
+
for (var i = 0; i < value.length; i++) {
|
|
1024
|
+
hash = (hash * 31 + value.charCodeAt(i)) | 0;
|
|
1025
|
+
}
|
|
1026
|
+
return Math.abs(hash);
|
|
1027
|
+
}
|
|
1028
|
+
function methodColor(method) {
|
|
1029
|
+
var key = method.toUpperCase();
|
|
1030
|
+
if (key in C.METHOD_COLORS) {
|
|
1031
|
+
return C.METHOD_COLORS[key];
|
|
1032
|
+
}
|
|
1033
|
+
var idx = hashString(key) % C.METHOD_FALLBACK.length;
|
|
1034
|
+
return C.METHOD_FALLBACK[idx];
|
|
1035
|
+
}
|
|
1036
|
+
var cacheLabel = function (cacheStatus) {
|
|
1037
|
+
switch (cacheStatus) {
|
|
1038
|
+
case "hit":
|
|
1039
|
+
return "".concat(C.METHOD_COLORS.SELECT, "[CACHE HIT]").concat(C.RESET);
|
|
1040
|
+
case "ignored":
|
|
1041
|
+
return "".concat(C.WARN, "[CACHE IGNORED]").concat(C.RESET);
|
|
1042
|
+
default:
|
|
1043
|
+
return "".concat(C.ORANGE, "[CACHE MISS]").concat(C.RESET);
|
|
1044
|
+
}
|
|
1045
|
+
};
|
|
1046
|
+
var allowListLabel = function (status) {
|
|
1047
|
+
switch (status) {
|
|
1048
|
+
case "allowed":
|
|
1049
|
+
return "".concat(C.METHOD_COLORS.SELECT, "[VERIFIED]").concat(C.RESET);
|
|
1050
|
+
case "denied":
|
|
1051
|
+
return "".concat(C.ERROR, "[DENIED]").concat(C.RESET);
|
|
1052
|
+
default:
|
|
1053
|
+
return "".concat(C.GREY, "[NOT VERIFIED]").concat(C.RESET);
|
|
1054
|
+
}
|
|
1055
|
+
};
|
|
1056
|
+
function logSql(options) {
|
|
1057
|
+
var method = options.method.toUpperCase();
|
|
1058
|
+
if (!shouldLog(LogLevel.INFO, options.context))
|
|
1059
|
+
return;
|
|
1060
|
+
var preText = getEnvBool("SSR", false)
|
|
1061
|
+
? "".concat(C.SSR, "[SSR]").concat(C.RESET, " ")
|
|
1062
|
+
: "".concat(C.HTTP, "[API]").concat(C.RESET, " ");
|
|
1063
|
+
var labelColor = methodColor(method);
|
|
1064
|
+
var versionColor = rgbAnsi(versionToRgb(version));
|
|
1065
|
+
var cacheText = cacheLabel(options.cacheStatus);
|
|
1066
|
+
var allowListText = allowListLabel(options.allowListStatus);
|
|
1067
|
+
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)));
|
|
1068
|
+
}
|
|
1069
|
+
|
|
865
1070
|
// -----------------------------------------------------------------------------
|
|
866
1071
|
// Cache Storage
|
|
867
1072
|
// -----------------------------------------------------------------------------
|
|
@@ -904,15 +1109,24 @@ function clearCache(props) {
|
|
|
904
1109
|
// -----------------------------------------------------------------------------
|
|
905
1110
|
// Check Cache (dedupe via hashed key)
|
|
906
1111
|
// -----------------------------------------------------------------------------
|
|
907
|
-
function checkCache(method, tableName, requestData) {
|
|
1112
|
+
function checkCache(method, tableName, requestData, logContext) {
|
|
1113
|
+
var _a, _b, _c, _d, _e;
|
|
908
1114
|
var key = makeCacheKey(method, tableName, requestData);
|
|
909
1115
|
var cached = apiRequestCache.get(key);
|
|
910
|
-
if (!cached)
|
|
1116
|
+
if (!cached) {
|
|
1117
|
+
console.log('apiRequestCache.size', apiRequestCache.size);
|
|
911
1118
|
return false;
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
1119
|
+
}
|
|
1120
|
+
if (shouldLog(LogLevel.INFO, logContext)) {
|
|
1121
|
+
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 : "";
|
|
1122
|
+
var sqlMethod = ((_e = sql.trim().split(/\s+/, 1)[0]) === null || _e === void 0 ? void 0 : _e.toUpperCase()) || method;
|
|
1123
|
+
logSql({
|
|
1124
|
+
allowListStatus: "not verified",
|
|
1125
|
+
cacheStatus: "hit",
|
|
1126
|
+
context: logContext,
|
|
1127
|
+
method: sqlMethod,
|
|
1128
|
+
sql: sql
|
|
1129
|
+
});
|
|
916
1130
|
}
|
|
917
1131
|
return cached.request;
|
|
918
1132
|
}
|
|
@@ -1081,7 +1295,7 @@ var HttpExecutor = /** @class */ (function (_super) {
|
|
|
1081
1295
|
querySerialized = sortAndSerializeQueryObject(tables, cacheRequestData !== null && cacheRequestData !== void 0 ? cacheRequestData : {});
|
|
1082
1296
|
cachedRequest = false;
|
|
1083
1297
|
if (cacheResults) {
|
|
1084
|
-
cachedRequest = checkCache(requestMethod, tableName, cacheRequestData);
|
|
1298
|
+
cachedRequest = checkCache(requestMethod, tableName, cacheRequestData, logContext);
|
|
1085
1299
|
}
|
|
1086
1300
|
if (!cachedRequest) return [3 /*break*/, 2];
|
|
1087
1301
|
return [4 /*yield*/, cachedRequest];
|
|
@@ -2942,186 +3156,6 @@ var PaginationBuilder = /** @class */ (function (_super) {
|
|
|
2942
3156
|
return PaginationBuilder;
|
|
2943
3157
|
}(JoinBuilder));
|
|
2944
3158
|
|
|
2945
|
-
/* eslint-disable no-control-regex */
|
|
2946
|
-
var RESET = "\x1b[0m";
|
|
2947
|
-
var C$1 = {
|
|
2948
|
-
KEYWORD: "\x1b[94m", // blue
|
|
2949
|
-
LIMIT: "\x1b[93m", // yellow
|
|
2950
|
-
NUMBER: "\x1b[92m", // green
|
|
2951
|
-
DIM: "\x1b[90m", // gray
|
|
2952
|
-
};
|
|
2953
|
-
/* ---------- ANSI helpers ---------- */
|
|
2954
|
-
var ansi256 = function (n) { return "\u001B[38;5;".concat(n, "m"); };
|
|
2955
|
-
/* ---------- hashing ---------- */
|
|
2956
|
-
function hashString$1(str) {
|
|
2957
|
-
var hash = 0;
|
|
2958
|
-
for (var i = 0; i < str.length; i++) {
|
|
2959
|
-
hash = (hash * 31 + str.charCodeAt(i)) | 0;
|
|
2960
|
-
}
|
|
2961
|
-
return Math.abs(hash);
|
|
2962
|
-
}
|
|
2963
|
-
/* ---------- table color ---------- */
|
|
2964
|
-
function tableRGB(tableName) {
|
|
2965
|
-
var name = tableName.replace(/[`"]/g, "").toLowerCase();
|
|
2966
|
-
var hash = hashString$1(name);
|
|
2967
|
-
// Stable hue bucket by first letter
|
|
2968
|
-
var first = name.charCodeAt(0) || 97;
|
|
2969
|
-
var hueBase = (first - 97) % 6;
|
|
2970
|
-
var r = (hueBase + (hash % 3)) % 6;
|
|
2971
|
-
var g = (hash >> 3) % 6;
|
|
2972
|
-
var b = (hash >> 6) % 6;
|
|
2973
|
-
return [r, g, Math.max(2, b)]; // avoid muddy dark blues
|
|
2974
|
-
}
|
|
2975
|
-
function tableColor(table) {
|
|
2976
|
-
var _a = tableRGB(table), r = _a[0], g = _a[1], b = _a[2];
|
|
2977
|
-
return ansi256(16 + 36 * r + 6 * g + b);
|
|
2978
|
-
}
|
|
2979
|
-
/* ---------- column color (same hue, lighter) ---------- */
|
|
2980
|
-
function columnColorFromTable(table) {
|
|
2981
|
-
var _a = tableRGB(table), r = _a[0], g = _a[1], b = _a[2];
|
|
2982
|
-
// Lift toward white, preserve hue
|
|
2983
|
-
var lr = Math.min(5, r + 1);
|
|
2984
|
-
var lg = Math.min(5, g + 1);
|
|
2985
|
-
var lb = Math.min(5, b + 2);
|
|
2986
|
-
return ansi256(16 + 36 * lr + 6 * lg + lb);
|
|
2987
|
-
}
|
|
2988
|
-
/* ---------- bind collapsing ---------- */
|
|
2989
|
-
/**
|
|
2990
|
-
* ?, ?, ?, ?, ?, ? → ? ×6
|
|
2991
|
-
* triggers at 4+
|
|
2992
|
-
*/
|
|
2993
|
-
function collapseBinds(sql) {
|
|
2994
|
-
return sql.replace(/(\?\s*,\s*){3,}\?/g, function (match) {
|
|
2995
|
-
var count = match.split("?").length - 1;
|
|
2996
|
-
return "".concat(C$1.DIM, "? \u00D7").concat(count).concat(RESET);
|
|
2997
|
-
});
|
|
2998
|
-
}
|
|
2999
|
-
/**
|
|
3000
|
-
* ( ? ×9 ), ( ? ×9 ), ( ? ×9 ) -> ( ? ×9 ) ×3
|
|
3001
|
-
*/
|
|
3002
|
-
function collapseRepeatedValueRows(sql) {
|
|
3003
|
-
var repeatedRowPattern = /(\((?:\x1b\[[0-9;]*m)?\?\s*×\d+(?:\x1b\[[0-9;]*m)?\)|\(\s*(?:\?\s*,\s*)+\?\s*\))(?:\s*,\s*\1){2,}/g;
|
|
3004
|
-
return sql.replace(repeatedRowPattern, function (match, row) {
|
|
3005
|
-
var _a, _b;
|
|
3006
|
-
var rowMatches = match.match(new RegExp(row.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"));
|
|
3007
|
-
var count = (_a = rowMatches === null || rowMatches === void 0 ? void 0 : rowMatches.length) !== null && _a !== void 0 ? _a : 1;
|
|
3008
|
-
var normalizedRow = row.includes("×")
|
|
3009
|
-
? row
|
|
3010
|
-
: "(".concat(C$1.DIM, "? \u00D7").concat(((_b = row.match(/\?/g)) !== null && _b !== void 0 ? _b : []).length).concat(RESET, ")");
|
|
3011
|
-
return "".concat(normalizedRow, " ").concat(C$1.DIM, "\u00D7").concat(count).concat(RESET);
|
|
3012
|
-
});
|
|
3013
|
-
}
|
|
3014
|
-
/* ---------- main formatter ---------- */
|
|
3015
|
-
function colorSql(sql) {
|
|
3016
|
-
var s = sql.trim();
|
|
3017
|
-
/* 1️⃣ collapse bind noise */
|
|
3018
|
-
s = collapseBinds(s);
|
|
3019
|
-
s = collapseRepeatedValueRows(s);
|
|
3020
|
-
/* 2️⃣ table.column coloring (core visual grouping) */
|
|
3021
|
-
s = s.replace(/\b(`?\w+`?)\.(\w+)\b/g, function (_, table, column) {
|
|
3022
|
-
return "".concat(tableColor(table)).concat(table).concat(RESET, ".") +
|
|
3023
|
-
"".concat(columnColorFromTable(table)).concat(column).concat(RESET);
|
|
3024
|
-
});
|
|
3025
|
-
/* 3️⃣ FROM / JOIN tables */
|
|
3026
|
-
s = s.replace(/\b(FROM|JOIN|UPDATE|INTO)\s+(`[^`]+`|\w+)/gi, function (_, kw, table) {
|
|
3027
|
-
return "".concat(C$1.KEYWORD).concat(kw).concat(RESET, " ").concat(tableColor(table)).concat(table).concat(RESET);
|
|
3028
|
-
});
|
|
3029
|
-
/* 4️⃣ SQL keywords */
|
|
3030
|
-
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));
|
|
3031
|
-
/* 5️⃣ LIMIT */
|
|
3032
|
-
s = s.replace(/\bLIMIT\s+(\d+)/gi, "".concat(C$1.LIMIT, "LIMIT").concat(RESET, " ").concat(C$1.NUMBER, "$1").concat(RESET));
|
|
3033
|
-
return s;
|
|
3034
|
-
}
|
|
3035
|
-
|
|
3036
|
-
var version = "6.0.14";
|
|
3037
|
-
|
|
3038
|
-
var DEFAULT_STEP = 8;
|
|
3039
|
-
function parseSemver(version) {
|
|
3040
|
-
var _a = version.trim().split("-"), core = _a[0], prerelease = _a[1];
|
|
3041
|
-
var _b = core.split("."), majorRaw = _b[0], minorRaw = _b[1], patchRaw = _b[2];
|
|
3042
|
-
var major = Number.parseInt(majorRaw !== null && majorRaw !== void 0 ? majorRaw : "0", 10);
|
|
3043
|
-
var minor = Number.parseInt(minorRaw !== null && minorRaw !== void 0 ? minorRaw : "0", 10);
|
|
3044
|
-
var patch = Number.parseInt(patchRaw !== null && patchRaw !== void 0 ? patchRaw : "0", 10);
|
|
3045
|
-
var prereleaseParts = prerelease ? prerelease.split(".").filter(Boolean).length : 0;
|
|
3046
|
-
return {
|
|
3047
|
-
major: Number.isFinite(major) ? major : 0,
|
|
3048
|
-
minor: Number.isFinite(minor) ? minor : 0,
|
|
3049
|
-
patch: Number.isFinite(patch) ? patch : 0,
|
|
3050
|
-
prereleaseParts: prereleaseParts,
|
|
3051
|
-
};
|
|
3052
|
-
}
|
|
3053
|
-
function channelValue(n, step) {
|
|
3054
|
-
var value = 255 - ((n * step) % 256);
|
|
3055
|
-
return (value + 256) % 256;
|
|
3056
|
-
}
|
|
3057
|
-
function versionToRgb(version, step) {
|
|
3058
|
-
if (step === void 0) { step = DEFAULT_STEP; }
|
|
3059
|
-
var safeStep = Number.isFinite(step) && step > 0 ? Math.floor(step) : DEFAULT_STEP;
|
|
3060
|
-
var _a = parseSemver(version), major = _a.major, minor = _a.minor, patch = _a.patch, prereleaseParts = _a.prereleaseParts;
|
|
3061
|
-
var rotation = (major + minor + patch + prereleaseParts) % 3;
|
|
3062
|
-
var base = [major, minor, patch];
|
|
3063
|
-
var rotated = rotation === 1
|
|
3064
|
-
? [base[2], base[0], base[1]]
|
|
3065
|
-
: rotation === 2
|
|
3066
|
-
? [base[1], base[2], base[0]]
|
|
3067
|
-
: base;
|
|
3068
|
-
return {
|
|
3069
|
-
r: channelValue(rotated[0], safeStep),
|
|
3070
|
-
g: channelValue(rotated[1], safeStep),
|
|
3071
|
-
b: channelValue(rotated[2], safeStep),
|
|
3072
|
-
};
|
|
3073
|
-
}
|
|
3074
|
-
|
|
3075
|
-
var C = {
|
|
3076
|
-
SSR: "\x1b[95m", // bright magenta
|
|
3077
|
-
HTTP: "\x1b[94m", // bright blue
|
|
3078
|
-
METHOD_COLORS: {
|
|
3079
|
-
SELECT: "\x1b[92m", // green
|
|
3080
|
-
INSERT: "\x1b[96m", // cyan
|
|
3081
|
-
REPLACE: "\x1b[96m", // cyan
|
|
3082
|
-
UPDATE: "\x1b[95m", // magenta
|
|
3083
|
-
DELETE: "\x1b[91m", // red
|
|
3084
|
-
},
|
|
3085
|
-
METHOD_FALLBACK: [
|
|
3086
|
-
"\x1b[92m", // green
|
|
3087
|
-
"\x1b[93m", // yellow
|
|
3088
|
-
"\x1b[95m", // magenta
|
|
3089
|
-
"\x1b[96m", // cyan
|
|
3090
|
-
"\x1b[94m", // blue
|
|
3091
|
-
"\x1b[97m", // white
|
|
3092
|
-
],
|
|
3093
|
-
RESET: "\x1b[0m",
|
|
3094
|
-
};
|
|
3095
|
-
var rgbAnsi = function (_a) {
|
|
3096
|
-
var r = _a.r, g = _a.g, b = _a.b;
|
|
3097
|
-
return "\u001B[38;2;".concat(r, ";").concat(g, ";").concat(b, "m");
|
|
3098
|
-
};
|
|
3099
|
-
function hashString(value) {
|
|
3100
|
-
var hash = 0;
|
|
3101
|
-
for (var i = 0; i < value.length; i++) {
|
|
3102
|
-
hash = (hash * 31 + value.charCodeAt(i)) | 0;
|
|
3103
|
-
}
|
|
3104
|
-
return Math.abs(hash);
|
|
3105
|
-
}
|
|
3106
|
-
function methodColor(method) {
|
|
3107
|
-
var key = method.toUpperCase();
|
|
3108
|
-
if (key in C.METHOD_COLORS) {
|
|
3109
|
-
return C.METHOD_COLORS[key];
|
|
3110
|
-
}
|
|
3111
|
-
var idx = hashString(key) % C.METHOD_FALLBACK.length;
|
|
3112
|
-
return C.METHOD_FALLBACK[idx];
|
|
3113
|
-
}
|
|
3114
|
-
function logSql(method, sql, context) {
|
|
3115
|
-
if (!shouldLog(LogLevel.INFO, context))
|
|
3116
|
-
return;
|
|
3117
|
-
var preText = getEnvBool("SSR", false)
|
|
3118
|
-
? "".concat(C.SSR, "[SSR]").concat(C.RESET, " ")
|
|
3119
|
-
: "".concat(C.HTTP, "[API]").concat(C.RESET, " ");
|
|
3120
|
-
var labelColor = methodColor(method);
|
|
3121
|
-
var versionColor = rgbAnsi(versionToRgb(version));
|
|
3122
|
-
console.log("".concat(versionColor, "[").concat(version, "]").concat(C.RESET, " ").concat(preText).concat(labelColor, "[").concat(method, "]").concat(C.RESET, " ").concat(colorSql(sql)));
|
|
3123
|
-
}
|
|
3124
|
-
|
|
3125
3159
|
var SelectQueryBuilder = /** @class */ (function (_super) {
|
|
3126
3160
|
__extends(SelectQueryBuilder, _super);
|
|
3127
3161
|
function SelectQueryBuilder() {
|
|
@@ -3173,7 +3207,6 @@ var SelectQueryBuilder = /** @class */ (function (_super) {
|
|
|
3173
3207
|
else if (!isSubSelect) {
|
|
3174
3208
|
sql += " LIMIT 100";
|
|
3175
3209
|
}
|
|
3176
|
-
logSql("SELECT", sql, getLogContext(this.config, this.request));
|
|
3177
3210
|
return { sql: sql, params: params };
|
|
3178
3211
|
};
|
|
3179
3212
|
return SelectQueryBuilder;
|
|
@@ -3198,7 +3231,6 @@ var DeleteQueryBuilder = /** @class */ (function (_super) {
|
|
|
3198
3231
|
if (this.request.WHERE) {
|
|
3199
3232
|
sql += this.buildWhereClause(this.request.WHERE, params);
|
|
3200
3233
|
}
|
|
3201
|
-
logSql("DELETE", sql, getLogContext(this.config, this.request));
|
|
3202
3234
|
return { sql: sql, params: params };
|
|
3203
3235
|
};
|
|
3204
3236
|
return DeleteQueryBuilder;
|
|
@@ -3257,7 +3289,6 @@ var PostQueryBuilder = /** @class */ (function (_super) {
|
|
|
3257
3289
|
var updateClause = updateData.map(function (k) { return "`".concat(k, "` = VALUES(`").concat(k, "`)"); }).join(', ');
|
|
3258
3290
|
sql += " ON DUPLICATE KEY UPDATE ".concat(updateClause);
|
|
3259
3291
|
}
|
|
3260
|
-
logSql(verb, sql, getLogContext(this.config, this.request));
|
|
3261
3292
|
return { sql: sql, params: params };
|
|
3262
3293
|
};
|
|
3263
3294
|
return PostQueryBuilder;
|
|
@@ -3309,7 +3340,6 @@ var UpdateQueryBuilder = /** @class */ (function (_super) {
|
|
|
3309
3340
|
if (args.PAGINATION) {
|
|
3310
3341
|
sql += this.buildPaginationClause(args.PAGINATION, params);
|
|
3311
3342
|
}
|
|
3312
|
-
logSql("UPDATE", sql, getLogContext(this.config, this.request));
|
|
3313
3343
|
return { sql: sql, params: params };
|
|
3314
3344
|
};
|
|
3315
3345
|
return UpdateQueryBuilder;
|
|
@@ -3443,8 +3473,55 @@ function normalizeSingularRequest(requestMethod, request, restModel, removedPrim
|
|
|
3443
3473
|
}
|
|
3444
3474
|
|
|
3445
3475
|
var allowListCache = new Map();
|
|
3476
|
+
var ANSI_ESCAPE_REGEX = /\x1b\[[0-9;]*m/g;
|
|
3477
|
+
var COLLAPSED_BIND_ROW_REGEX = /\(\?\s*×\d+\)/g;
|
|
3478
|
+
function collapseBindGroups(sql) {
|
|
3479
|
+
var normalized = sql.replace(/\(\s*(\?(?:\s*,\s*\?)*)\s*\)/g, function (_match, binds) {
|
|
3480
|
+
var _a;
|
|
3481
|
+
var bindCount = ((_a = binds.match(/\?/g)) !== null && _a !== void 0 ? _a : []).length;
|
|
3482
|
+
return "(? \u00D7".concat(bindCount, ")");
|
|
3483
|
+
});
|
|
3484
|
+
normalized = normalized.replace(/(\(\?\s*×\d+\))(?:\s*,\s*\1)+/g, function (_match, row) { return "".concat(row, " \u00D7*"); });
|
|
3485
|
+
normalized = normalized.replace(/\b(VALUES|VALUE)\s+(\(\?\s*×\d+\))(?:\s*×\d+|\s*×\*)?/gi, function (_match, keyword, row) { return "".concat(keyword, " ").concat(row, " \u00D7*"); });
|
|
3486
|
+
normalized = normalized.replace(/\bIN\s*\(\?\s*×\d+\)/gi, "IN (? ×*)");
|
|
3487
|
+
normalized = normalized.replace(/\(\?\s*×\d+\)\s*×\d+/g, function (match) {
|
|
3488
|
+
var _a;
|
|
3489
|
+
var row = (_a = match.match(COLLAPSED_BIND_ROW_REGEX)) === null || _a === void 0 ? void 0 : _a[0];
|
|
3490
|
+
return row ? "".concat(row, " \u00D7*") : match;
|
|
3491
|
+
});
|
|
3492
|
+
return normalized;
|
|
3493
|
+
}
|
|
3494
|
+
function normalizeLimitOffset(sql) {
|
|
3495
|
+
return sql
|
|
3496
|
+
.replace(/\bLIMIT\s+\d+\s*,\s*\d+\b/gi, "LIMIT ?, ?")
|
|
3497
|
+
.replace(/\bLIMIT\s+\d+\s+OFFSET\s+\d+\b/gi, "LIMIT ? OFFSET ?")
|
|
3498
|
+
.replace(/\bLIMIT\s+\d+\b/gi, "LIMIT ?")
|
|
3499
|
+
.replace(/\bOFFSET\s+\d+\b/gi, "OFFSET ?");
|
|
3500
|
+
}
|
|
3501
|
+
function normalizeGeomFromTextLiterals(sql) {
|
|
3502
|
+
var normalized = sql.replace(/ST_GEOMFROMTEXT\(\s*'POINT\([^']*\)'\s*,\s*(?:\d+|\?)\s*\)/gi, "ST_GEOMFROMTEXT('POINT(? ?)', ?)");
|
|
3503
|
+
normalized = normalized.replace(/ST_GEOMFROMTEXT\(\s*'POLYGON\(\([^']*\)\)'\s*,\s*(?:\d+|\?)\s*\)/gi, "ST_GEOMFROMTEXT('POLYGON((?))', ?)");
|
|
3504
|
+
return normalized;
|
|
3505
|
+
}
|
|
3506
|
+
function normalizeGeoFunctionNames(sql) {
|
|
3507
|
+
return sql
|
|
3508
|
+
.replace(/\bST_DISTANCE_SPHERE\b/gi, "ST_DISTANCE_SPHERE")
|
|
3509
|
+
.replace(/\bST_GEOMFROMTEXT\b/gi, "ST_GEOMFROMTEXT")
|
|
3510
|
+
.replace(/\bMBRCONTAINS\b/gi, "MBRCONTAINS");
|
|
3511
|
+
}
|
|
3512
|
+
function normalizeTokenPunctuationSpacing(sql) {
|
|
3513
|
+
return sql.replace(/`,\s*`/g, "`, `");
|
|
3514
|
+
}
|
|
3446
3515
|
var normalizeSql = function (sql) {
|
|
3447
|
-
|
|
3516
|
+
var normalized = sql.replace(ANSI_ESCAPE_REGEX, " ");
|
|
3517
|
+
normalized = normalized.replace(/\s+/g, " ").trim();
|
|
3518
|
+
normalized = normalizeGeoFunctionNames(normalized);
|
|
3519
|
+
normalized = normalizeTokenPunctuationSpacing(normalized);
|
|
3520
|
+
normalized = collapseBindGroups(normalized);
|
|
3521
|
+
normalized = normalizeLimitOffset(normalized);
|
|
3522
|
+
normalized = normalizeGeomFromTextLiterals(normalized);
|
|
3523
|
+
normalized = normalized.replace(/;\s*$/, "");
|
|
3524
|
+
return normalized.replace(/\s+/g, " ").trim();
|
|
3448
3525
|
};
|
|
3449
3526
|
var parseAllowList = function (raw, sourcePath) {
|
|
3450
3527
|
var parsed;
|
|
@@ -3467,33 +3544,51 @@ var parseAllowList = function (raw, sourcePath) {
|
|
|
3467
3544
|
return sqlEntries;
|
|
3468
3545
|
};
|
|
3469
3546
|
var loadSqlAllowList = function (allowListPath) { return __awaiter(void 0, void 0, void 0, function () {
|
|
3470
|
-
var readFile, raw, sqlEntries, allowList;
|
|
3471
|
-
return __generator(this, function (
|
|
3472
|
-
switch (
|
|
3547
|
+
var _a, readFile, stat, fileStat, cached, raw, sqlEntries, allowList;
|
|
3548
|
+
return __generator(this, function (_b) {
|
|
3549
|
+
switch (_b.label) {
|
|
3473
3550
|
case 0:
|
|
3474
|
-
if (allowListCache.has(allowListPath)) {
|
|
3475
|
-
return [2 /*return*/, allowListCache.get(allowListPath)];
|
|
3476
|
-
}
|
|
3477
3551
|
if (!isNode()) {
|
|
3478
3552
|
throw new Error("SQL allowlist validation requires a Node runtime.");
|
|
3479
3553
|
}
|
|
3480
3554
|
return [4 /*yield*/, import('node:fs/promises')];
|
|
3481
3555
|
case 1:
|
|
3482
|
-
|
|
3483
|
-
|
|
3556
|
+
_a = _b.sent(), readFile = _a.readFile, stat = _a.stat;
|
|
3557
|
+
_b.label = 2;
|
|
3484
3558
|
case 2:
|
|
3485
|
-
|
|
3486
|
-
return [4 /*yield*/,
|
|
3559
|
+
_b.trys.push([2, 4, , 5]);
|
|
3560
|
+
return [4 /*yield*/, stat(allowListPath)];
|
|
3487
3561
|
case 3:
|
|
3488
|
-
|
|
3562
|
+
fileStat = _b.sent();
|
|
3489
3563
|
return [3 /*break*/, 5];
|
|
3490
3564
|
case 4:
|
|
3491
|
-
|
|
3565
|
+
_b.sent();
|
|
3492
3566
|
throw new Error("SQL allowlist file not found at ".concat(allowListPath, "."));
|
|
3493
3567
|
case 5:
|
|
3568
|
+
cached = allowListCache.get(allowListPath);
|
|
3569
|
+
if (cached &&
|
|
3570
|
+
cached.mtimeMs === fileStat.mtimeMs &&
|
|
3571
|
+
cached.size === fileStat.size) {
|
|
3572
|
+
return [2 /*return*/, cached.allowList];
|
|
3573
|
+
}
|
|
3574
|
+
_b.label = 6;
|
|
3575
|
+
case 6:
|
|
3576
|
+
_b.trys.push([6, 8, , 9]);
|
|
3577
|
+
return [4 /*yield*/, readFile(allowListPath, "utf-8")];
|
|
3578
|
+
case 7:
|
|
3579
|
+
raw = _b.sent();
|
|
3580
|
+
return [3 /*break*/, 9];
|
|
3581
|
+
case 8:
|
|
3582
|
+
_b.sent();
|
|
3583
|
+
throw new Error("SQL allowlist file not found at ".concat(allowListPath, "."));
|
|
3584
|
+
case 9:
|
|
3494
3585
|
sqlEntries = parseAllowList(raw, allowListPath);
|
|
3495
3586
|
allowList = new Set(sqlEntries);
|
|
3496
|
-
allowListCache.set(allowListPath,
|
|
3587
|
+
allowListCache.set(allowListPath, {
|
|
3588
|
+
allowList: allowList,
|
|
3589
|
+
mtimeMs: fileStat.mtimeMs,
|
|
3590
|
+
size: fileStat.size,
|
|
3591
|
+
});
|
|
3497
3592
|
return [2 /*return*/, allowList];
|
|
3498
3593
|
}
|
|
3499
3594
|
});
|
|
@@ -3556,6 +3651,25 @@ var compileSqlAllowList = function (allowListPath, entries) { return __awaiter(v
|
|
|
3556
3651
|
});
|
|
3557
3652
|
}); };
|
|
3558
3653
|
|
|
3654
|
+
var SQL_ALLOWLIST_BLOCKED_CODE = "SQL_ALLOWLIST_BLOCKED";
|
|
3655
|
+
var createSqlAllowListBlockedError = function (args) {
|
|
3656
|
+
var _a, _b;
|
|
3657
|
+
var error = new Error("SQL statement is not permitted by allowlist (".concat(args.allowListPath, ")."));
|
|
3658
|
+
error.name = "SqlAllowListBlockedError";
|
|
3659
|
+
error.code = SQL_ALLOWLIST_BLOCKED_CODE;
|
|
3660
|
+
error.tableName = args.tableName;
|
|
3661
|
+
error.method = args.method;
|
|
3662
|
+
error.normalizedSql = args.normalizedSql;
|
|
3663
|
+
error.allowListPath = args.allowListPath;
|
|
3664
|
+
error.sqlAllowList = {
|
|
3665
|
+
sql: args.normalizedSql,
|
|
3666
|
+
table: (_a = args.tableName) !== null && _a !== void 0 ? _a : null,
|
|
3667
|
+
method: (_b = args.method) !== null && _b !== void 0 ? _b : null,
|
|
3668
|
+
allowListPath: args.allowListPath,
|
|
3669
|
+
canAdd: true,
|
|
3670
|
+
};
|
|
3671
|
+
return error;
|
|
3672
|
+
};
|
|
3559
3673
|
var SqlExecutor = /** @class */ (function (_super) {
|
|
3560
3674
|
__extends(SqlExecutor, _super);
|
|
3561
3675
|
function SqlExecutor() {
|
|
@@ -3566,6 +3680,22 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
3566
3680
|
})); };
|
|
3567
3681
|
return _this;
|
|
3568
3682
|
}
|
|
3683
|
+
SqlExecutor.prototype.resolveSqlLogMethod = function (method, sql) {
|
|
3684
|
+
var _a;
|
|
3685
|
+
var token = (_a = sql.trim().split(/\s+/, 1)[0]) === null || _a === void 0 ? void 0 : _a.toUpperCase();
|
|
3686
|
+
if (token)
|
|
3687
|
+
return token;
|
|
3688
|
+
switch (method) {
|
|
3689
|
+
case C6Constants.GET:
|
|
3690
|
+
return "SELECT";
|
|
3691
|
+
case C6Constants.POST:
|
|
3692
|
+
return "INSERT";
|
|
3693
|
+
case C6Constants.PUT:
|
|
3694
|
+
return "UPDATE";
|
|
3695
|
+
default:
|
|
3696
|
+
return "DELETE";
|
|
3697
|
+
}
|
|
3698
|
+
};
|
|
3569
3699
|
SqlExecutor.prototype.execute = function () {
|
|
3570
3700
|
return __awaiter(this, void 0, void 0, function () {
|
|
3571
3701
|
var TABLE_NAME, method, logContext, response, _a, rest, getResponse, restRows, result, result, result;
|
|
@@ -3937,7 +4067,7 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
3937
4067
|
};
|
|
3938
4068
|
SqlExecutor.prototype.runQuery = function () {
|
|
3939
4069
|
return __awaiter(this, void 0, void 0, function () {
|
|
3940
|
-
var method, tableName, logContext, cacheResults, cacheRequestData, requestArgumentsSerialized, cachedRequest, sqlExecution, queryPromise, cacheRequest, cacheResponse;
|
|
4070
|
+
var method, tableName, logContext, cacheResults, cacheRequestData, requestArgumentsSerialized, cachedRequest, sqlExecution, sqlMethod, queryPromise, cacheRequest, cacheResponse;
|
|
3941
4071
|
var _this = this;
|
|
3942
4072
|
var _a, _b;
|
|
3943
4073
|
return __generator(this, function (_c) {
|
|
@@ -3947,8 +4077,7 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
3947
4077
|
tableName = this.config.restModel.TABLE_NAME;
|
|
3948
4078
|
logContext = getLogContext(this.config, this.request);
|
|
3949
4079
|
cacheResults = method === C6Constants.GET
|
|
3950
|
-
&&
|
|
3951
|
-
&& ((_a = this.request) === null || _a === void 0 ? void 0 : _a.cacheResults) !== false;
|
|
4080
|
+
&& ((_a = this.request.cacheResults) !== null && _a !== void 0 ? _a : true);
|
|
3952
4081
|
cacheRequestData = cacheResults
|
|
3953
4082
|
? JSON.parse(JSON.stringify((_b = this.request) !== null && _b !== void 0 ? _b : {}))
|
|
3954
4083
|
: undefined;
|
|
@@ -3956,15 +4085,18 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
3956
4085
|
? sortAndSerializeQueryObject(tableName, cacheRequestData !== null && cacheRequestData !== void 0 ? cacheRequestData : {})
|
|
3957
4086
|
: undefined;
|
|
3958
4087
|
if (!cacheResults) return [3 /*break*/, 2];
|
|
3959
|
-
cachedRequest = checkCache(method, tableName, cacheRequestData);
|
|
4088
|
+
cachedRequest = checkCache(method, tableName, cacheRequestData, logContext);
|
|
3960
4089
|
if (!cachedRequest) return [3 /*break*/, 2];
|
|
3961
4090
|
return [4 /*yield*/, cachedRequest];
|
|
3962
4091
|
case 1: return [2 /*return*/, (_c.sent()).data];
|
|
3963
4092
|
case 2:
|
|
3964
4093
|
sqlExecution = this.buildSqlExecutionContext(method, tableName, logContext);
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
4094
|
+
sqlMethod = this.resolveSqlLogMethod(method, sqlExecution.sql);
|
|
4095
|
+
queryPromise = this.withConnection(function (conn) { return __awaiter(_this, void 0, void 0, function () {
|
|
4096
|
+
return __generator(this, function (_a) {
|
|
4097
|
+
return [2 /*return*/, this.executeQueryWithLifecycle(conn, method, sqlExecution, logContext, sqlMethod)];
|
|
4098
|
+
});
|
|
4099
|
+
}); });
|
|
3968
4100
|
if (!(!cacheResults || !cacheRequestData || !requestArgumentsSerialized)) return [3 /*break*/, 4];
|
|
3969
4101
|
return [4 /*yield*/, queryPromise];
|
|
3970
4102
|
case 3: return [2 /*return*/, _c.sent()];
|
|
@@ -4042,9 +4174,9 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
4042
4174
|
},
|
|
4043
4175
|
};
|
|
4044
4176
|
};
|
|
4045
|
-
SqlExecutor.prototype.executeQueryWithLifecycle = function (conn, method, sqlExecution, logContext) {
|
|
4177
|
+
SqlExecutor.prototype.executeQueryWithLifecycle = function (conn, method, sqlExecution, logContext, sqlMethod) {
|
|
4046
4178
|
return __awaiter(this, void 0, void 0, function () {
|
|
4047
|
-
var useTransaction, committed, result, response, hookResponse, err_1, rollbackErr_1;
|
|
4179
|
+
var useTransaction, committed, allowListStatus, error_2, result, response, hookResponse, err_1, rollbackErr_1;
|
|
4048
4180
|
return __generator(this, function (_a) {
|
|
4049
4181
|
switch (_a.label) {
|
|
4050
4182
|
case 0:
|
|
@@ -4052,25 +4184,49 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
4052
4184
|
committed = false;
|
|
4053
4185
|
_a.label = 1;
|
|
4054
4186
|
case 1:
|
|
4055
|
-
_a.trys.push([1,
|
|
4187
|
+
_a.trys.push([1, 14, , 19]);
|
|
4056
4188
|
if (!useTransaction) return [3 /*break*/, 3];
|
|
4057
4189
|
logWithLevel(LogLevel.DEBUG, logContext, console.log, "[SQL EXECUTOR] \uD83E\uDDFE Beginning transaction");
|
|
4058
4190
|
return [4 /*yield*/, conn.beginTransaction()];
|
|
4059
4191
|
case 2:
|
|
4060
4192
|
_a.sent();
|
|
4061
4193
|
_a.label = 3;
|
|
4062
|
-
case 3:
|
|
4194
|
+
case 3:
|
|
4195
|
+
allowListStatus = "not verified";
|
|
4196
|
+
_a.label = 4;
|
|
4063
4197
|
case 4:
|
|
4064
|
-
_a.
|
|
4198
|
+
_a.trys.push([4, 6, , 7]);
|
|
4199
|
+
return [4 /*yield*/, this.validateSqlAllowList(sqlExecution.sql)];
|
|
4200
|
+
case 5:
|
|
4201
|
+
allowListStatus = _a.sent();
|
|
4202
|
+
return [3 /*break*/, 7];
|
|
4203
|
+
case 6:
|
|
4204
|
+
error_2 = _a.sent();
|
|
4205
|
+
logSql({
|
|
4206
|
+
method: sqlMethod,
|
|
4207
|
+
sql: sqlExecution.sql,
|
|
4208
|
+
context: logContext,
|
|
4209
|
+
cacheStatus: this.request.cacheResults === false ? "ignored" : "miss",
|
|
4210
|
+
allowListStatus: "denied",
|
|
4211
|
+
});
|
|
4212
|
+
throw error_2;
|
|
4213
|
+
case 7:
|
|
4214
|
+
logSql({
|
|
4215
|
+
method: sqlMethod,
|
|
4216
|
+
sql: sqlExecution.sql,
|
|
4217
|
+
context: logContext,
|
|
4218
|
+
cacheStatus: this.request.cacheResults === false ? "ignored" : "miss",
|
|
4219
|
+
allowListStatus: allowListStatus,
|
|
4220
|
+
});
|
|
4065
4221
|
return [4 /*yield*/, this.runLifecycleHooks("beforeExecution", {
|
|
4066
4222
|
config: this.config,
|
|
4067
4223
|
request: this.request,
|
|
4068
4224
|
sqlExecution: sqlExecution,
|
|
4069
4225
|
})];
|
|
4070
|
-
case
|
|
4226
|
+
case 8:
|
|
4071
4227
|
_a.sent();
|
|
4072
4228
|
return [4 /*yield*/, conn.query(sqlExecution.sql, sqlExecution.values)];
|
|
4073
|
-
case
|
|
4229
|
+
case 9:
|
|
4074
4230
|
result = (_a.sent())[0];
|
|
4075
4231
|
response = this.createResponseFromQueryResult(method, result, sqlExecution, logContext);
|
|
4076
4232
|
hookResponse = this.createLifecycleHookResponse(response);
|
|
@@ -4079,40 +4235,40 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
4079
4235
|
request: this.request,
|
|
4080
4236
|
response: hookResponse,
|
|
4081
4237
|
})];
|
|
4082
|
-
case
|
|
4238
|
+
case 10:
|
|
4083
4239
|
_a.sent();
|
|
4084
|
-
if (!useTransaction) return [3 /*break*/,
|
|
4240
|
+
if (!useTransaction) return [3 /*break*/, 12];
|
|
4085
4241
|
return [4 /*yield*/, conn.commit()];
|
|
4086
|
-
case
|
|
4242
|
+
case 11:
|
|
4087
4243
|
_a.sent();
|
|
4088
4244
|
committed = true;
|
|
4089
4245
|
logWithLevel(LogLevel.DEBUG, logContext, console.log, "[SQL EXECUTOR] \uD83E\uDDFE Transaction committed");
|
|
4090
|
-
_a.label =
|
|
4091
|
-
case
|
|
4246
|
+
_a.label = 12;
|
|
4247
|
+
case 12: return [4 /*yield*/, this.runLifecycleHooks("afterCommit", {
|
|
4092
4248
|
config: this.config,
|
|
4093
4249
|
request: this.request,
|
|
4094
4250
|
response: hookResponse,
|
|
4095
4251
|
})];
|
|
4096
|
-
case
|
|
4252
|
+
case 13:
|
|
4097
4253
|
_a.sent();
|
|
4098
4254
|
return [2 /*return*/, response];
|
|
4099
|
-
case
|
|
4255
|
+
case 14:
|
|
4100
4256
|
err_1 = _a.sent();
|
|
4101
|
-
if (!(useTransaction && !committed)) return [3 /*break*/,
|
|
4102
|
-
_a.label =
|
|
4103
|
-
case
|
|
4104
|
-
_a.trys.push([
|
|
4257
|
+
if (!(useTransaction && !committed)) return [3 /*break*/, 18];
|
|
4258
|
+
_a.label = 15;
|
|
4259
|
+
case 15:
|
|
4260
|
+
_a.trys.push([15, 17, , 18]);
|
|
4105
4261
|
return [4 /*yield*/, conn.rollback()];
|
|
4106
|
-
case
|
|
4262
|
+
case 16:
|
|
4107
4263
|
_a.sent();
|
|
4108
4264
|
logWithLevel(LogLevel.WARN, logContext, console.warn, "[SQL EXECUTOR] \uD83E\uDDFE Transaction rolled back");
|
|
4109
|
-
return [3 /*break*/,
|
|
4110
|
-
case
|
|
4265
|
+
return [3 /*break*/, 18];
|
|
4266
|
+
case 17:
|
|
4111
4267
|
rollbackErr_1 = _a.sent();
|
|
4112
4268
|
logWithLevel(LogLevel.ERROR, logContext, console.error, "[SQL EXECUTOR] Rollback failed", rollbackErr_1);
|
|
4113
|
-
return [3 /*break*/,
|
|
4114
|
-
case
|
|
4115
|
-
case
|
|
4269
|
+
return [3 /*break*/, 18];
|
|
4270
|
+
case 18: throw err_1;
|
|
4271
|
+
case 19: return [2 /*return*/];
|
|
4116
4272
|
}
|
|
4117
4273
|
});
|
|
4118
4274
|
});
|
|
@@ -4120,21 +4276,31 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
4120
4276
|
SqlExecutor.prototype.validateSqlAllowList = function (sql) {
|
|
4121
4277
|
return __awaiter(this, void 0, void 0, function () {
|
|
4122
4278
|
var allowListPath, allowList, normalized;
|
|
4123
|
-
|
|
4124
|
-
|
|
4279
|
+
var _a;
|
|
4280
|
+
return __generator(this, function (_b) {
|
|
4281
|
+
switch (_b.label) {
|
|
4125
4282
|
case 0:
|
|
4126
4283
|
allowListPath = this.config.sqlAllowListPath;
|
|
4127
4284
|
if (!allowListPath) {
|
|
4128
|
-
return [2 /*return
|
|
4285
|
+
return [2 /*return*/, "not verified"];
|
|
4129
4286
|
}
|
|
4130
4287
|
return [4 /*yield*/, loadSqlAllowList(allowListPath)];
|
|
4131
4288
|
case 1:
|
|
4132
|
-
allowList =
|
|
4289
|
+
allowList = _b.sent();
|
|
4133
4290
|
normalized = normalizeSql(sql);
|
|
4134
4291
|
if (!allowList.has(normalized)) {
|
|
4135
|
-
throw
|
|
4292
|
+
throw createSqlAllowListBlockedError({
|
|
4293
|
+
tableName: typeof ((_a = this.config.restModel) === null || _a === void 0 ? void 0 : _a.TABLE_NAME) === "string"
|
|
4294
|
+
? this.config.restModel.TABLE_NAME
|
|
4295
|
+
: undefined,
|
|
4296
|
+
method: typeof this.config.requestMethod === "string"
|
|
4297
|
+
? this.config.requestMethod
|
|
4298
|
+
: undefined,
|
|
4299
|
+
normalizedSql: normalized,
|
|
4300
|
+
allowListPath: allowListPath,
|
|
4301
|
+
});
|
|
4136
4302
|
}
|
|
4137
|
-
return [2 /*return
|
|
4303
|
+
return [2 /*return*/, "allowed"];
|
|
4138
4304
|
}
|
|
4139
4305
|
});
|
|
4140
4306
|
});
|