@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.cjs.js
CHANGED
|
@@ -517,8 +517,6 @@ var applyLogLevelDefaults = function (config, request) {
|
|
|
517
517
|
};
|
|
518
518
|
var getLogContext = function (config, request) {
|
|
519
519
|
var _a, _b;
|
|
520
|
-
if (!config && !request)
|
|
521
|
-
return undefined;
|
|
522
520
|
return {
|
|
523
521
|
logLevel: (_a = config === null || config === void 0 ? void 0 : config.logLevel) !== null && _a !== void 0 ? _a : undefined,
|
|
524
522
|
verbose: (_b = config === null || config === void 0 ? void 0 : config.verbose) !== null && _b !== void 0 ? _b : undefined,
|
|
@@ -865,6 +863,213 @@ function removeInvalidKeys(request, c6Tables) {
|
|
|
865
863
|
return intersection;
|
|
866
864
|
}
|
|
867
865
|
|
|
866
|
+
/* eslint-disable no-control-regex */
|
|
867
|
+
var RESET = "\x1b[0m";
|
|
868
|
+
var C$1 = {
|
|
869
|
+
KEYWORD: "\x1b[94m", // blue
|
|
870
|
+
LIMIT: "\x1b[93m", // yellow
|
|
871
|
+
NUMBER: "\x1b[92m", // green
|
|
872
|
+
DIM: "\x1b[90m", // gray
|
|
873
|
+
};
|
|
874
|
+
/* ---------- ANSI helpers ---------- */
|
|
875
|
+
var ansi256 = function (n) { return "\u001B[38;5;".concat(n, "m"); };
|
|
876
|
+
/* ---------- hashing ---------- */
|
|
877
|
+
function hashString$1(str) {
|
|
878
|
+
var hash = 0;
|
|
879
|
+
for (var i = 0; i < str.length; i++) {
|
|
880
|
+
hash = (hash * 31 + str.charCodeAt(i)) | 0;
|
|
881
|
+
}
|
|
882
|
+
return Math.abs(hash);
|
|
883
|
+
}
|
|
884
|
+
/* ---------- table color ---------- */
|
|
885
|
+
function tableRGB(tableName) {
|
|
886
|
+
var name = tableName.replace(/[`"]/g, "").toLowerCase();
|
|
887
|
+
var hash = hashString$1(name);
|
|
888
|
+
// Stable hue bucket by first letter
|
|
889
|
+
var first = name.charCodeAt(0) || 97;
|
|
890
|
+
var hueBase = (first - 97) % 6;
|
|
891
|
+
var r = (hueBase + (hash % 3)) % 6;
|
|
892
|
+
var g = (hash >> 3) % 6;
|
|
893
|
+
var b = (hash >> 6) % 6;
|
|
894
|
+
return [r, g, Math.max(2, b)]; // avoid muddy dark blues
|
|
895
|
+
}
|
|
896
|
+
function tableColor(table) {
|
|
897
|
+
var _a = tableRGB(table), r = _a[0], g = _a[1], b = _a[2];
|
|
898
|
+
return ansi256(16 + 36 * r + 6 * g + b);
|
|
899
|
+
}
|
|
900
|
+
/* ---------- column color (same hue, lighter) ---------- */
|
|
901
|
+
function columnColorFromTable(table) {
|
|
902
|
+
var _a = tableRGB(table), r = _a[0], g = _a[1], b = _a[2];
|
|
903
|
+
// Lift toward white, preserve hue
|
|
904
|
+
var lr = Math.min(5, r + 1);
|
|
905
|
+
var lg = Math.min(5, g + 1);
|
|
906
|
+
var lb = Math.min(5, b + 2);
|
|
907
|
+
return ansi256(16 + 36 * lr + 6 * lg + lb);
|
|
908
|
+
}
|
|
909
|
+
/* ---------- bind collapsing ---------- */
|
|
910
|
+
/**
|
|
911
|
+
* ?, ?, ?, ?, ?, ? → ? ×6
|
|
912
|
+
* triggers at 4+
|
|
913
|
+
*/
|
|
914
|
+
function collapseBinds(sql) {
|
|
915
|
+
return sql.replace(/(\?\s*,\s*){3,}\?/g, function (match) {
|
|
916
|
+
var count = match.split("?").length - 1;
|
|
917
|
+
return "".concat(C$1.DIM, "? \u00D7").concat(count).concat(RESET);
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* ( ? ×9 ), ( ? ×9 ), ( ? ×9 ) -> ( ? ×9 ) ×3
|
|
922
|
+
*/
|
|
923
|
+
function collapseRepeatedValueRows(sql) {
|
|
924
|
+
var repeatedRowPattern = /(\((?:\x1b\[[0-9;]*m)?\?\s*×\d+(?:\x1b\[[0-9;]*m)?\)|\(\s*(?:\?\s*,\s*)+\?\s*\))(?:\s*,\s*\1){2,}/g;
|
|
925
|
+
return sql.replace(repeatedRowPattern, function (match, row) {
|
|
926
|
+
var _a, _b;
|
|
927
|
+
var rowMatches = match.match(new RegExp(row.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"));
|
|
928
|
+
var count = (_a = rowMatches === null || rowMatches === void 0 ? void 0 : rowMatches.length) !== null && _a !== void 0 ? _a : 1;
|
|
929
|
+
var normalizedRow = row.includes("×")
|
|
930
|
+
? row
|
|
931
|
+
: "(".concat(C$1.DIM, "? \u00D7").concat(((_b = row.match(/\?/g)) !== null && _b !== void 0 ? _b : []).length).concat(RESET, ")");
|
|
932
|
+
return "".concat(normalizedRow, " ").concat(C$1.DIM, "\u00D7").concat(count).concat(RESET);
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
/* ---------- main formatter ---------- */
|
|
936
|
+
function colorSql(sql) {
|
|
937
|
+
var s = sql.trim();
|
|
938
|
+
/* 1️⃣ collapse bind noise */
|
|
939
|
+
s = collapseBinds(s);
|
|
940
|
+
s = collapseRepeatedValueRows(s);
|
|
941
|
+
/* 2️⃣ table.column coloring (core visual grouping) */
|
|
942
|
+
s = s.replace(/\b(`?\w+`?)\.(\w+)\b/g, function (_, table, column) {
|
|
943
|
+
return "".concat(tableColor(table)).concat(table).concat(RESET, ".") +
|
|
944
|
+
"".concat(columnColorFromTable(table)).concat(column).concat(RESET);
|
|
945
|
+
});
|
|
946
|
+
/* 3️⃣ FROM / JOIN tables */
|
|
947
|
+
s = s.replace(/\b(FROM|JOIN|UPDATE|INTO)\s+(`[^`]+`|\w+)/gi, function (_, kw, table) {
|
|
948
|
+
return "".concat(C$1.KEYWORD).concat(kw).concat(RESET, " ").concat(tableColor(table)).concat(table).concat(RESET);
|
|
949
|
+
});
|
|
950
|
+
/* 4️⃣ SQL keywords */
|
|
951
|
+
s = s.replace(/\b(SELECT|WHERE|AND|OR|ON|IN|BETWEEN|EXISTS|ORDER BY|GROUP BY|HAVING|SET|VALUES|INSERT|REPLACE|DELETE|UPDATE|DUPLICATE|KEY)\b/gi, "".concat(C$1.KEYWORD, "$1").concat(RESET));
|
|
952
|
+
/* 5️⃣ LIMIT */
|
|
953
|
+
s = s.replace(/\bLIMIT\s+(\d+)/gi, "".concat(C$1.LIMIT, "LIMIT").concat(RESET, " ").concat(C$1.NUMBER, "$1").concat(RESET));
|
|
954
|
+
return s;
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
var version = "6.0.17";
|
|
958
|
+
|
|
959
|
+
var DEFAULT_STEP = 8;
|
|
960
|
+
function parseSemver(version) {
|
|
961
|
+
var _a = version.trim().split("-"), core = _a[0], prerelease = _a[1];
|
|
962
|
+
var _b = core.split("."), majorRaw = _b[0], minorRaw = _b[1], patchRaw = _b[2];
|
|
963
|
+
var major = Number.parseInt(majorRaw !== null && majorRaw !== void 0 ? majorRaw : "0", 10);
|
|
964
|
+
var minor = Number.parseInt(minorRaw !== null && minorRaw !== void 0 ? minorRaw : "0", 10);
|
|
965
|
+
var patch = Number.parseInt(patchRaw !== null && patchRaw !== void 0 ? patchRaw : "0", 10);
|
|
966
|
+
var prereleaseParts = prerelease ? prerelease.split(".").filter(Boolean).length : 0;
|
|
967
|
+
return {
|
|
968
|
+
major: Number.isFinite(major) ? major : 0,
|
|
969
|
+
minor: Number.isFinite(minor) ? minor : 0,
|
|
970
|
+
patch: Number.isFinite(patch) ? patch : 0,
|
|
971
|
+
prereleaseParts: prereleaseParts,
|
|
972
|
+
};
|
|
973
|
+
}
|
|
974
|
+
function channelValue(n, step) {
|
|
975
|
+
var value = 255 - ((n * step) % 256);
|
|
976
|
+
return (value + 256) % 256;
|
|
977
|
+
}
|
|
978
|
+
function versionToRgb(version, step) {
|
|
979
|
+
if (step === void 0) { step = DEFAULT_STEP; }
|
|
980
|
+
var safeStep = Number.isFinite(step) && step > 0 ? Math.floor(step) : DEFAULT_STEP;
|
|
981
|
+
var _a = parseSemver(version), major = _a.major, minor = _a.minor, patch = _a.patch, prereleaseParts = _a.prereleaseParts;
|
|
982
|
+
var rotation = (major + minor + patch + prereleaseParts) % 3;
|
|
983
|
+
var base = [major, minor, patch];
|
|
984
|
+
var rotated = rotation === 1
|
|
985
|
+
? [base[2], base[0], base[1]]
|
|
986
|
+
: rotation === 2
|
|
987
|
+
? [base[1], base[2], base[0]]
|
|
988
|
+
: base;
|
|
989
|
+
return {
|
|
990
|
+
r: channelValue(rotated[0], safeStep),
|
|
991
|
+
g: channelValue(rotated[1], safeStep),
|
|
992
|
+
b: channelValue(rotated[2], safeStep),
|
|
993
|
+
};
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
var C = {
|
|
997
|
+
SSR: "\x1b[95m", // bright magenta
|
|
998
|
+
HTTP: "\x1b[94m", // bright blue
|
|
999
|
+
WARN: "\x1b[93m", // yellow
|
|
1000
|
+
ORANGE: "\x1b[38;2;255;165;0m", // orange (truecolor)
|
|
1001
|
+
ERROR: "\x1b[91m", // red
|
|
1002
|
+
METHOD_COLORS: {
|
|
1003
|
+
SELECT: "\x1b[92m", // green
|
|
1004
|
+
INSERT: "\x1b[96m", // cyan
|
|
1005
|
+
REPLACE: "\x1b[96m", // cyan
|
|
1006
|
+
UPDATE: "\x1b[95m", // magenta
|
|
1007
|
+
DELETE: "\x1b[38;2;255;179;179m", // very light red (truecolor)
|
|
1008
|
+
},
|
|
1009
|
+
METHOD_FALLBACK: [
|
|
1010
|
+
"\x1b[92m", // green
|
|
1011
|
+
"\x1b[93m", // yellow
|
|
1012
|
+
"\x1b[95m", // magenta
|
|
1013
|
+
"\x1b[96m", // cyan
|
|
1014
|
+
"\x1b[94m", // blue
|
|
1015
|
+
"\x1b[97m", // white
|
|
1016
|
+
],
|
|
1017
|
+
GREY: "\x1b[90m", // light grey
|
|
1018
|
+
RESET: "\x1b[0m",
|
|
1019
|
+
};
|
|
1020
|
+
var rgbAnsi = function (_a) {
|
|
1021
|
+
var r = _a.r, g = _a.g, b = _a.b;
|
|
1022
|
+
return "\u001B[38;2;".concat(r, ";").concat(g, ";").concat(b, "m");
|
|
1023
|
+
};
|
|
1024
|
+
function hashString(value) {
|
|
1025
|
+
var hash = 0;
|
|
1026
|
+
for (var i = 0; i < value.length; i++) {
|
|
1027
|
+
hash = (hash * 31 + value.charCodeAt(i)) | 0;
|
|
1028
|
+
}
|
|
1029
|
+
return Math.abs(hash);
|
|
1030
|
+
}
|
|
1031
|
+
function methodColor(method) {
|
|
1032
|
+
var key = method.toUpperCase();
|
|
1033
|
+
if (key in C.METHOD_COLORS) {
|
|
1034
|
+
return C.METHOD_COLORS[key];
|
|
1035
|
+
}
|
|
1036
|
+
var idx = hashString(key) % C.METHOD_FALLBACK.length;
|
|
1037
|
+
return C.METHOD_FALLBACK[idx];
|
|
1038
|
+
}
|
|
1039
|
+
var cacheLabel = function (cacheStatus) {
|
|
1040
|
+
switch (cacheStatus) {
|
|
1041
|
+
case "hit":
|
|
1042
|
+
return "".concat(C.METHOD_COLORS.SELECT, "[CACHE HIT]").concat(C.RESET);
|
|
1043
|
+
case "ignored":
|
|
1044
|
+
return "".concat(C.WARN, "[CACHE IGNORED]").concat(C.RESET);
|
|
1045
|
+
default:
|
|
1046
|
+
return "".concat(C.ORANGE, "[CACHE MISS]").concat(C.RESET);
|
|
1047
|
+
}
|
|
1048
|
+
};
|
|
1049
|
+
var allowListLabel = function (status) {
|
|
1050
|
+
switch (status) {
|
|
1051
|
+
case "allowed":
|
|
1052
|
+
return "".concat(C.METHOD_COLORS.SELECT, "[VERIFIED]").concat(C.RESET);
|
|
1053
|
+
case "denied":
|
|
1054
|
+
return "".concat(C.ERROR, "[DENIED]").concat(C.RESET);
|
|
1055
|
+
default:
|
|
1056
|
+
return "".concat(C.GREY, "[NOT VERIFIED]").concat(C.RESET);
|
|
1057
|
+
}
|
|
1058
|
+
};
|
|
1059
|
+
function logSql(options) {
|
|
1060
|
+
var method = options.method.toUpperCase();
|
|
1061
|
+
if (!shouldLog(exports.LogLevel.INFO, options.context))
|
|
1062
|
+
return;
|
|
1063
|
+
var preText = getEnvBool("SSR", false)
|
|
1064
|
+
? "".concat(C.SSR, "[SSR]").concat(C.RESET, " ")
|
|
1065
|
+
: "".concat(C.HTTP, "[API]").concat(C.RESET, " ");
|
|
1066
|
+
var labelColor = methodColor(method);
|
|
1067
|
+
var versionColor = rgbAnsi(versionToRgb(version));
|
|
1068
|
+
var cacheText = cacheLabel(options.cacheStatus);
|
|
1069
|
+
var allowListText = allowListLabel(options.allowListStatus);
|
|
1070
|
+
console.log("".concat(versionColor, "[").concat(version, "]").concat(C.RESET, " ").concat(cacheText, " ").concat(allowListText, " ").concat(preText).concat(labelColor, "[").concat(method, "]").concat(C.RESET, " ").concat(colorSql(options.sql)));
|
|
1071
|
+
}
|
|
1072
|
+
|
|
868
1073
|
// -----------------------------------------------------------------------------
|
|
869
1074
|
// Cache Storage
|
|
870
1075
|
// -----------------------------------------------------------------------------
|
|
@@ -907,15 +1112,24 @@ function clearCache(props) {
|
|
|
907
1112
|
// -----------------------------------------------------------------------------
|
|
908
1113
|
// Check Cache (dedupe via hashed key)
|
|
909
1114
|
// -----------------------------------------------------------------------------
|
|
910
|
-
function checkCache(method, tableName, requestData) {
|
|
1115
|
+
function checkCache(method, tableName, requestData, logContext) {
|
|
1116
|
+
var _a, _b, _c, _d, _e;
|
|
911
1117
|
var key = makeCacheKey(method, tableName, requestData);
|
|
912
1118
|
var cached = apiRequestCache.get(key);
|
|
913
|
-
if (!cached)
|
|
1119
|
+
if (!cached) {
|
|
1120
|
+
console.log('apiRequestCache.size', apiRequestCache.size);
|
|
914
1121
|
return false;
|
|
915
|
-
|
|
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
|
}
|
|
@@ -1084,7 +1298,7 @@ var HttpExecutor = /** @class */ (function (_super) {
|
|
|
1084
1298
|
querySerialized = sortAndSerializeQueryObject(tables, cacheRequestData !== null && cacheRequestData !== void 0 ? cacheRequestData : {});
|
|
1085
1299
|
cachedRequest = false;
|
|
1086
1300
|
if (cacheResults) {
|
|
1087
|
-
cachedRequest = checkCache(requestMethod, tableName, cacheRequestData);
|
|
1301
|
+
cachedRequest = checkCache(requestMethod, tableName, cacheRequestData, logContext);
|
|
1088
1302
|
}
|
|
1089
1303
|
if (!cachedRequest) return [3 /*break*/, 2];
|
|
1090
1304
|
return [4 /*yield*/, cachedRequest];
|
|
@@ -2945,186 +3159,6 @@ var PaginationBuilder = /** @class */ (function (_super) {
|
|
|
2945
3159
|
return PaginationBuilder;
|
|
2946
3160
|
}(JoinBuilder));
|
|
2947
3161
|
|
|
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
3162
|
var SelectQueryBuilder = /** @class */ (function (_super) {
|
|
3129
3163
|
tslib.__extends(SelectQueryBuilder, _super);
|
|
3130
3164
|
function SelectQueryBuilder() {
|
|
@@ -3176,7 +3210,6 @@ var SelectQueryBuilder = /** @class */ (function (_super) {
|
|
|
3176
3210
|
else if (!isSubSelect) {
|
|
3177
3211
|
sql += " LIMIT 100";
|
|
3178
3212
|
}
|
|
3179
|
-
logSql("SELECT", sql, getLogContext(this.config, this.request));
|
|
3180
3213
|
return { sql: sql, params: params };
|
|
3181
3214
|
};
|
|
3182
3215
|
return SelectQueryBuilder;
|
|
@@ -3201,7 +3234,6 @@ var DeleteQueryBuilder = /** @class */ (function (_super) {
|
|
|
3201
3234
|
if (this.request.WHERE) {
|
|
3202
3235
|
sql += this.buildWhereClause(this.request.WHERE, params);
|
|
3203
3236
|
}
|
|
3204
|
-
logSql("DELETE", sql, getLogContext(this.config, this.request));
|
|
3205
3237
|
return { sql: sql, params: params };
|
|
3206
3238
|
};
|
|
3207
3239
|
return DeleteQueryBuilder;
|
|
@@ -3260,7 +3292,6 @@ var PostQueryBuilder = /** @class */ (function (_super) {
|
|
|
3260
3292
|
var updateClause = updateData.map(function (k) { return "`".concat(k, "` = VALUES(`").concat(k, "`)"); }).join(', ');
|
|
3261
3293
|
sql += " ON DUPLICATE KEY UPDATE ".concat(updateClause);
|
|
3262
3294
|
}
|
|
3263
|
-
logSql(verb, sql, getLogContext(this.config, this.request));
|
|
3264
3295
|
return { sql: sql, params: params };
|
|
3265
3296
|
};
|
|
3266
3297
|
return PostQueryBuilder;
|
|
@@ -3312,7 +3343,6 @@ var UpdateQueryBuilder = /** @class */ (function (_super) {
|
|
|
3312
3343
|
if (args.PAGINATION) {
|
|
3313
3344
|
sql += this.buildPaginationClause(args.PAGINATION, params);
|
|
3314
3345
|
}
|
|
3315
|
-
logSql("UPDATE", sql, getLogContext(this.config, this.request));
|
|
3316
3346
|
return { sql: sql, params: params };
|
|
3317
3347
|
};
|
|
3318
3348
|
return UpdateQueryBuilder;
|
|
@@ -3446,8 +3476,55 @@ function normalizeSingularRequest(requestMethod, request, restModel, removedPrim
|
|
|
3446
3476
|
}
|
|
3447
3477
|
|
|
3448
3478
|
var allowListCache = new Map();
|
|
3479
|
+
var ANSI_ESCAPE_REGEX = /\x1b\[[0-9;]*m/g;
|
|
3480
|
+
var COLLAPSED_BIND_ROW_REGEX = /\(\?\s*×\d+\)/g;
|
|
3481
|
+
function collapseBindGroups(sql) {
|
|
3482
|
+
var normalized = sql.replace(/\(\s*(\?(?:\s*,\s*\?)*)\s*\)/g, function (_match, binds) {
|
|
3483
|
+
var _a;
|
|
3484
|
+
var bindCount = ((_a = binds.match(/\?/g)) !== null && _a !== void 0 ? _a : []).length;
|
|
3485
|
+
return "(? \u00D7".concat(bindCount, ")");
|
|
3486
|
+
});
|
|
3487
|
+
normalized = normalized.replace(/(\(\?\s*×\d+\))(?:\s*,\s*\1)+/g, function (_match, row) { return "".concat(row, " \u00D7*"); });
|
|
3488
|
+
normalized = normalized.replace(/\b(VALUES|VALUE)\s+(\(\?\s*×\d+\))(?:\s*×\d+|\s*×\*)?/gi, function (_match, keyword, row) { return "".concat(keyword, " ").concat(row, " \u00D7*"); });
|
|
3489
|
+
normalized = normalized.replace(/\bIN\s*\(\?\s*×\d+\)/gi, "IN (? ×*)");
|
|
3490
|
+
normalized = normalized.replace(/\(\?\s*×\d+\)\s*×\d+/g, function (match) {
|
|
3491
|
+
var _a;
|
|
3492
|
+
var row = (_a = match.match(COLLAPSED_BIND_ROW_REGEX)) === null || _a === void 0 ? void 0 : _a[0];
|
|
3493
|
+
return row ? "".concat(row, " \u00D7*") : match;
|
|
3494
|
+
});
|
|
3495
|
+
return normalized;
|
|
3496
|
+
}
|
|
3497
|
+
function normalizeLimitOffset(sql) {
|
|
3498
|
+
return sql
|
|
3499
|
+
.replace(/\bLIMIT\s+\d+\s*,\s*\d+\b/gi, "LIMIT ?, ?")
|
|
3500
|
+
.replace(/\bLIMIT\s+\d+\s+OFFSET\s+\d+\b/gi, "LIMIT ? OFFSET ?")
|
|
3501
|
+
.replace(/\bLIMIT\s+\d+\b/gi, "LIMIT ?")
|
|
3502
|
+
.replace(/\bOFFSET\s+\d+\b/gi, "OFFSET ?");
|
|
3503
|
+
}
|
|
3504
|
+
function normalizeGeomFromTextLiterals(sql) {
|
|
3505
|
+
var normalized = sql.replace(/ST_GEOMFROMTEXT\(\s*'POINT\([^']*\)'\s*,\s*(?:\d+|\?)\s*\)/gi, "ST_GEOMFROMTEXT('POINT(? ?)', ?)");
|
|
3506
|
+
normalized = normalized.replace(/ST_GEOMFROMTEXT\(\s*'POLYGON\(\([^']*\)\)'\s*,\s*(?:\d+|\?)\s*\)/gi, "ST_GEOMFROMTEXT('POLYGON((?))', ?)");
|
|
3507
|
+
return normalized;
|
|
3508
|
+
}
|
|
3509
|
+
function normalizeGeoFunctionNames(sql) {
|
|
3510
|
+
return sql
|
|
3511
|
+
.replace(/\bST_DISTANCE_SPHERE\b/gi, "ST_DISTANCE_SPHERE")
|
|
3512
|
+
.replace(/\bST_GEOMFROMTEXT\b/gi, "ST_GEOMFROMTEXT")
|
|
3513
|
+
.replace(/\bMBRCONTAINS\b/gi, "MBRCONTAINS");
|
|
3514
|
+
}
|
|
3515
|
+
function normalizeTokenPunctuationSpacing(sql) {
|
|
3516
|
+
return sql.replace(/`,\s*`/g, "`, `");
|
|
3517
|
+
}
|
|
3449
3518
|
var normalizeSql = function (sql) {
|
|
3450
|
-
|
|
3519
|
+
var normalized = sql.replace(ANSI_ESCAPE_REGEX, " ");
|
|
3520
|
+
normalized = normalized.replace(/\s+/g, " ").trim();
|
|
3521
|
+
normalized = normalizeGeoFunctionNames(normalized);
|
|
3522
|
+
normalized = normalizeTokenPunctuationSpacing(normalized);
|
|
3523
|
+
normalized = collapseBindGroups(normalized);
|
|
3524
|
+
normalized = normalizeLimitOffset(normalized);
|
|
3525
|
+
normalized = normalizeGeomFromTextLiterals(normalized);
|
|
3526
|
+
normalized = normalized.replace(/;\s*$/, "");
|
|
3527
|
+
return normalized.replace(/\s+/g, " ").trim();
|
|
3451
3528
|
};
|
|
3452
3529
|
var parseAllowList = function (raw, sourcePath) {
|
|
3453
3530
|
var parsed;
|
|
@@ -3470,33 +3547,51 @@ var parseAllowList = function (raw, sourcePath) {
|
|
|
3470
3547
|
return sqlEntries;
|
|
3471
3548
|
};
|
|
3472
3549
|
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 (
|
|
3550
|
+
var _a, readFile, stat, fileStat, cached, raw, sqlEntries, allowList;
|
|
3551
|
+
return tslib.__generator(this, function (_b) {
|
|
3552
|
+
switch (_b.label) {
|
|
3476
3553
|
case 0:
|
|
3477
|
-
if (allowListCache.has(allowListPath)) {
|
|
3478
|
-
return [2 /*return*/, allowListCache.get(allowListPath)];
|
|
3479
|
-
}
|
|
3480
3554
|
if (!isNode()) {
|
|
3481
3555
|
throw new Error("SQL allowlist validation requires a Node runtime.");
|
|
3482
3556
|
}
|
|
3483
3557
|
return [4 /*yield*/, import('node:fs/promises')];
|
|
3484
3558
|
case 1:
|
|
3485
|
-
|
|
3486
|
-
|
|
3559
|
+
_a = _b.sent(), readFile = _a.readFile, stat = _a.stat;
|
|
3560
|
+
_b.label = 2;
|
|
3487
3561
|
case 2:
|
|
3488
|
-
|
|
3489
|
-
return [4 /*yield*/,
|
|
3562
|
+
_b.trys.push([2, 4, , 5]);
|
|
3563
|
+
return [4 /*yield*/, stat(allowListPath)];
|
|
3490
3564
|
case 3:
|
|
3491
|
-
|
|
3565
|
+
fileStat = _b.sent();
|
|
3492
3566
|
return [3 /*break*/, 5];
|
|
3493
3567
|
case 4:
|
|
3494
|
-
|
|
3568
|
+
_b.sent();
|
|
3495
3569
|
throw new Error("SQL allowlist file not found at ".concat(allowListPath, "."));
|
|
3496
3570
|
case 5:
|
|
3571
|
+
cached = allowListCache.get(allowListPath);
|
|
3572
|
+
if (cached &&
|
|
3573
|
+
cached.mtimeMs === fileStat.mtimeMs &&
|
|
3574
|
+
cached.size === fileStat.size) {
|
|
3575
|
+
return [2 /*return*/, cached.allowList];
|
|
3576
|
+
}
|
|
3577
|
+
_b.label = 6;
|
|
3578
|
+
case 6:
|
|
3579
|
+
_b.trys.push([6, 8, , 9]);
|
|
3580
|
+
return [4 /*yield*/, readFile(allowListPath, "utf-8")];
|
|
3581
|
+
case 7:
|
|
3582
|
+
raw = _b.sent();
|
|
3583
|
+
return [3 /*break*/, 9];
|
|
3584
|
+
case 8:
|
|
3585
|
+
_b.sent();
|
|
3586
|
+
throw new Error("SQL allowlist file not found at ".concat(allowListPath, "."));
|
|
3587
|
+
case 9:
|
|
3497
3588
|
sqlEntries = parseAllowList(raw, allowListPath);
|
|
3498
3589
|
allowList = new Set(sqlEntries);
|
|
3499
|
-
allowListCache.set(allowListPath,
|
|
3590
|
+
allowListCache.set(allowListPath, {
|
|
3591
|
+
allowList: allowList,
|
|
3592
|
+
mtimeMs: fileStat.mtimeMs,
|
|
3593
|
+
size: fileStat.size,
|
|
3594
|
+
});
|
|
3500
3595
|
return [2 /*return*/, allowList];
|
|
3501
3596
|
}
|
|
3502
3597
|
});
|
|
@@ -3559,6 +3654,25 @@ var compileSqlAllowList = function (allowListPath, entries) { return tslib.__awa
|
|
|
3559
3654
|
});
|
|
3560
3655
|
}); };
|
|
3561
3656
|
|
|
3657
|
+
var SQL_ALLOWLIST_BLOCKED_CODE = "SQL_ALLOWLIST_BLOCKED";
|
|
3658
|
+
var createSqlAllowListBlockedError = function (args) {
|
|
3659
|
+
var _a, _b;
|
|
3660
|
+
var error = new Error("SQL statement is not permitted by allowlist (".concat(args.allowListPath, ")."));
|
|
3661
|
+
error.name = "SqlAllowListBlockedError";
|
|
3662
|
+
error.code = SQL_ALLOWLIST_BLOCKED_CODE;
|
|
3663
|
+
error.tableName = args.tableName;
|
|
3664
|
+
error.method = args.method;
|
|
3665
|
+
error.normalizedSql = args.normalizedSql;
|
|
3666
|
+
error.allowListPath = args.allowListPath;
|
|
3667
|
+
error.sqlAllowList = {
|
|
3668
|
+
sql: args.normalizedSql,
|
|
3669
|
+
table: (_a = args.tableName) !== null && _a !== void 0 ? _a : null,
|
|
3670
|
+
method: (_b = args.method) !== null && _b !== void 0 ? _b : null,
|
|
3671
|
+
allowListPath: args.allowListPath,
|
|
3672
|
+
canAdd: true,
|
|
3673
|
+
};
|
|
3674
|
+
return error;
|
|
3675
|
+
};
|
|
3562
3676
|
var SqlExecutor = /** @class */ (function (_super) {
|
|
3563
3677
|
tslib.__extends(SqlExecutor, _super);
|
|
3564
3678
|
function SqlExecutor() {
|
|
@@ -3569,6 +3683,22 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
3569
3683
|
})); };
|
|
3570
3684
|
return _this;
|
|
3571
3685
|
}
|
|
3686
|
+
SqlExecutor.prototype.resolveSqlLogMethod = function (method, sql) {
|
|
3687
|
+
var _a;
|
|
3688
|
+
var token = (_a = sql.trim().split(/\s+/, 1)[0]) === null || _a === void 0 ? void 0 : _a.toUpperCase();
|
|
3689
|
+
if (token)
|
|
3690
|
+
return token;
|
|
3691
|
+
switch (method) {
|
|
3692
|
+
case C6Constants.GET:
|
|
3693
|
+
return "SELECT";
|
|
3694
|
+
case C6Constants.POST:
|
|
3695
|
+
return "INSERT";
|
|
3696
|
+
case C6Constants.PUT:
|
|
3697
|
+
return "UPDATE";
|
|
3698
|
+
default:
|
|
3699
|
+
return "DELETE";
|
|
3700
|
+
}
|
|
3701
|
+
};
|
|
3572
3702
|
SqlExecutor.prototype.execute = function () {
|
|
3573
3703
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
3574
3704
|
var TABLE_NAME, method, logContext, response, _a, rest, getResponse, restRows, result, result, result;
|
|
@@ -3940,7 +4070,7 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
3940
4070
|
};
|
|
3941
4071
|
SqlExecutor.prototype.runQuery = function () {
|
|
3942
4072
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
3943
|
-
var method, tableName, logContext, cacheResults, cacheRequestData, requestArgumentsSerialized, cachedRequest, sqlExecution, queryPromise, cacheRequest, cacheResponse;
|
|
4073
|
+
var method, tableName, logContext, cacheResults, cacheRequestData, requestArgumentsSerialized, cachedRequest, sqlExecution, sqlMethod, queryPromise, cacheRequest, cacheResponse;
|
|
3944
4074
|
var _this = this;
|
|
3945
4075
|
var _a, _b;
|
|
3946
4076
|
return tslib.__generator(this, function (_c) {
|
|
@@ -3950,8 +4080,7 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
3950
4080
|
tableName = this.config.restModel.TABLE_NAME;
|
|
3951
4081
|
logContext = getLogContext(this.config, this.request);
|
|
3952
4082
|
cacheResults = method === C6Constants.GET
|
|
3953
|
-
&&
|
|
3954
|
-
&& ((_a = this.request) === null || _a === void 0 ? void 0 : _a.cacheResults) !== false;
|
|
4083
|
+
&& ((_a = this.request.cacheResults) !== null && _a !== void 0 ? _a : true);
|
|
3955
4084
|
cacheRequestData = cacheResults
|
|
3956
4085
|
? JSON.parse(JSON.stringify((_b = this.request) !== null && _b !== void 0 ? _b : {}))
|
|
3957
4086
|
: undefined;
|
|
@@ -3959,15 +4088,18 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
3959
4088
|
? sortAndSerializeQueryObject(tableName, cacheRequestData !== null && cacheRequestData !== void 0 ? cacheRequestData : {})
|
|
3960
4089
|
: undefined;
|
|
3961
4090
|
if (!cacheResults) return [3 /*break*/, 2];
|
|
3962
|
-
cachedRequest = checkCache(method, tableName, cacheRequestData);
|
|
4091
|
+
cachedRequest = checkCache(method, tableName, cacheRequestData, logContext);
|
|
3963
4092
|
if (!cachedRequest) return [3 /*break*/, 2];
|
|
3964
4093
|
return [4 /*yield*/, cachedRequest];
|
|
3965
4094
|
case 1: return [2 /*return*/, (_c.sent()).data];
|
|
3966
4095
|
case 2:
|
|
3967
4096
|
sqlExecution = this.buildSqlExecutionContext(method, tableName, logContext);
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
4097
|
+
sqlMethod = this.resolveSqlLogMethod(method, sqlExecution.sql);
|
|
4098
|
+
queryPromise = this.withConnection(function (conn) { return tslib.__awaiter(_this, void 0, void 0, function () {
|
|
4099
|
+
return tslib.__generator(this, function (_a) {
|
|
4100
|
+
return [2 /*return*/, this.executeQueryWithLifecycle(conn, method, sqlExecution, logContext, sqlMethod)];
|
|
4101
|
+
});
|
|
4102
|
+
}); });
|
|
3971
4103
|
if (!(!cacheResults || !cacheRequestData || !requestArgumentsSerialized)) return [3 /*break*/, 4];
|
|
3972
4104
|
return [4 /*yield*/, queryPromise];
|
|
3973
4105
|
case 3: return [2 /*return*/, _c.sent()];
|
|
@@ -4045,9 +4177,9 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
4045
4177
|
},
|
|
4046
4178
|
};
|
|
4047
4179
|
};
|
|
4048
|
-
SqlExecutor.prototype.executeQueryWithLifecycle = function (conn, method, sqlExecution, logContext) {
|
|
4180
|
+
SqlExecutor.prototype.executeQueryWithLifecycle = function (conn, method, sqlExecution, logContext, sqlMethod) {
|
|
4049
4181
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
4050
|
-
var useTransaction, committed, result, response, hookResponse, err_1, rollbackErr_1;
|
|
4182
|
+
var useTransaction, committed, allowListStatus, error_2, result, response, hookResponse, err_1, rollbackErr_1;
|
|
4051
4183
|
return tslib.__generator(this, function (_a) {
|
|
4052
4184
|
switch (_a.label) {
|
|
4053
4185
|
case 0:
|
|
@@ -4055,25 +4187,49 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
4055
4187
|
committed = false;
|
|
4056
4188
|
_a.label = 1;
|
|
4057
4189
|
case 1:
|
|
4058
|
-
_a.trys.push([1,
|
|
4190
|
+
_a.trys.push([1, 14, , 19]);
|
|
4059
4191
|
if (!useTransaction) return [3 /*break*/, 3];
|
|
4060
4192
|
logWithLevel(exports.LogLevel.DEBUG, logContext, console.log, "[SQL EXECUTOR] \uD83E\uDDFE Beginning transaction");
|
|
4061
4193
|
return [4 /*yield*/, conn.beginTransaction()];
|
|
4062
4194
|
case 2:
|
|
4063
4195
|
_a.sent();
|
|
4064
4196
|
_a.label = 3;
|
|
4065
|
-
case 3:
|
|
4197
|
+
case 3:
|
|
4198
|
+
allowListStatus = "not verified";
|
|
4199
|
+
_a.label = 4;
|
|
4066
4200
|
case 4:
|
|
4067
|
-
_a.
|
|
4201
|
+
_a.trys.push([4, 6, , 7]);
|
|
4202
|
+
return [4 /*yield*/, this.validateSqlAllowList(sqlExecution.sql)];
|
|
4203
|
+
case 5:
|
|
4204
|
+
allowListStatus = _a.sent();
|
|
4205
|
+
return [3 /*break*/, 7];
|
|
4206
|
+
case 6:
|
|
4207
|
+
error_2 = _a.sent();
|
|
4208
|
+
logSql({
|
|
4209
|
+
method: sqlMethod,
|
|
4210
|
+
sql: sqlExecution.sql,
|
|
4211
|
+
context: logContext,
|
|
4212
|
+
cacheStatus: this.request.cacheResults === false ? "ignored" : "miss",
|
|
4213
|
+
allowListStatus: "denied",
|
|
4214
|
+
});
|
|
4215
|
+
throw error_2;
|
|
4216
|
+
case 7:
|
|
4217
|
+
logSql({
|
|
4218
|
+
method: sqlMethod,
|
|
4219
|
+
sql: sqlExecution.sql,
|
|
4220
|
+
context: logContext,
|
|
4221
|
+
cacheStatus: this.request.cacheResults === false ? "ignored" : "miss",
|
|
4222
|
+
allowListStatus: allowListStatus,
|
|
4223
|
+
});
|
|
4068
4224
|
return [4 /*yield*/, this.runLifecycleHooks("beforeExecution", {
|
|
4069
4225
|
config: this.config,
|
|
4070
4226
|
request: this.request,
|
|
4071
4227
|
sqlExecution: sqlExecution,
|
|
4072
4228
|
})];
|
|
4073
|
-
case
|
|
4229
|
+
case 8:
|
|
4074
4230
|
_a.sent();
|
|
4075
4231
|
return [4 /*yield*/, conn.query(sqlExecution.sql, sqlExecution.values)];
|
|
4076
|
-
case
|
|
4232
|
+
case 9:
|
|
4077
4233
|
result = (_a.sent())[0];
|
|
4078
4234
|
response = this.createResponseFromQueryResult(method, result, sqlExecution, logContext);
|
|
4079
4235
|
hookResponse = this.createLifecycleHookResponse(response);
|
|
@@ -4082,40 +4238,40 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
4082
4238
|
request: this.request,
|
|
4083
4239
|
response: hookResponse,
|
|
4084
4240
|
})];
|
|
4085
|
-
case
|
|
4241
|
+
case 10:
|
|
4086
4242
|
_a.sent();
|
|
4087
|
-
if (!useTransaction) return [3 /*break*/,
|
|
4243
|
+
if (!useTransaction) return [3 /*break*/, 12];
|
|
4088
4244
|
return [4 /*yield*/, conn.commit()];
|
|
4089
|
-
case
|
|
4245
|
+
case 11:
|
|
4090
4246
|
_a.sent();
|
|
4091
4247
|
committed = true;
|
|
4092
4248
|
logWithLevel(exports.LogLevel.DEBUG, logContext, console.log, "[SQL EXECUTOR] \uD83E\uDDFE Transaction committed");
|
|
4093
|
-
_a.label =
|
|
4094
|
-
case
|
|
4249
|
+
_a.label = 12;
|
|
4250
|
+
case 12: return [4 /*yield*/, this.runLifecycleHooks("afterCommit", {
|
|
4095
4251
|
config: this.config,
|
|
4096
4252
|
request: this.request,
|
|
4097
4253
|
response: hookResponse,
|
|
4098
4254
|
})];
|
|
4099
|
-
case
|
|
4255
|
+
case 13:
|
|
4100
4256
|
_a.sent();
|
|
4101
4257
|
return [2 /*return*/, response];
|
|
4102
|
-
case
|
|
4258
|
+
case 14:
|
|
4103
4259
|
err_1 = _a.sent();
|
|
4104
|
-
if (!(useTransaction && !committed)) return [3 /*break*/,
|
|
4105
|
-
_a.label =
|
|
4106
|
-
case
|
|
4107
|
-
_a.trys.push([
|
|
4260
|
+
if (!(useTransaction && !committed)) return [3 /*break*/, 18];
|
|
4261
|
+
_a.label = 15;
|
|
4262
|
+
case 15:
|
|
4263
|
+
_a.trys.push([15, 17, , 18]);
|
|
4108
4264
|
return [4 /*yield*/, conn.rollback()];
|
|
4109
|
-
case
|
|
4265
|
+
case 16:
|
|
4110
4266
|
_a.sent();
|
|
4111
4267
|
logWithLevel(exports.LogLevel.WARN, logContext, console.warn, "[SQL EXECUTOR] \uD83E\uDDFE Transaction rolled back");
|
|
4112
|
-
return [3 /*break*/,
|
|
4113
|
-
case
|
|
4268
|
+
return [3 /*break*/, 18];
|
|
4269
|
+
case 17:
|
|
4114
4270
|
rollbackErr_1 = _a.sent();
|
|
4115
4271
|
logWithLevel(exports.LogLevel.ERROR, logContext, console.error, "[SQL EXECUTOR] Rollback failed", rollbackErr_1);
|
|
4116
|
-
return [3 /*break*/,
|
|
4117
|
-
case
|
|
4118
|
-
case
|
|
4272
|
+
return [3 /*break*/, 18];
|
|
4273
|
+
case 18: throw err_1;
|
|
4274
|
+
case 19: return [2 /*return*/];
|
|
4119
4275
|
}
|
|
4120
4276
|
});
|
|
4121
4277
|
});
|
|
@@ -4123,21 +4279,31 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
4123
4279
|
SqlExecutor.prototype.validateSqlAllowList = function (sql) {
|
|
4124
4280
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
4125
4281
|
var allowListPath, allowList, normalized;
|
|
4126
|
-
|
|
4127
|
-
|
|
4282
|
+
var _a;
|
|
4283
|
+
return tslib.__generator(this, function (_b) {
|
|
4284
|
+
switch (_b.label) {
|
|
4128
4285
|
case 0:
|
|
4129
4286
|
allowListPath = this.config.sqlAllowListPath;
|
|
4130
4287
|
if (!allowListPath) {
|
|
4131
|
-
return [2 /*return
|
|
4288
|
+
return [2 /*return*/, "not verified"];
|
|
4132
4289
|
}
|
|
4133
4290
|
return [4 /*yield*/, loadSqlAllowList(allowListPath)];
|
|
4134
4291
|
case 1:
|
|
4135
|
-
allowList =
|
|
4292
|
+
allowList = _b.sent();
|
|
4136
4293
|
normalized = normalizeSql(sql);
|
|
4137
4294
|
if (!allowList.has(normalized)) {
|
|
4138
|
-
throw
|
|
4295
|
+
throw createSqlAllowListBlockedError({
|
|
4296
|
+
tableName: typeof ((_a = this.config.restModel) === null || _a === void 0 ? void 0 : _a.TABLE_NAME) === "string"
|
|
4297
|
+
? this.config.restModel.TABLE_NAME
|
|
4298
|
+
: undefined,
|
|
4299
|
+
method: typeof this.config.requestMethod === "string"
|
|
4300
|
+
? this.config.requestMethod
|
|
4301
|
+
: undefined,
|
|
4302
|
+
normalizedSql: normalized,
|
|
4303
|
+
allowListPath: allowListPath,
|
|
4304
|
+
});
|
|
4139
4305
|
}
|
|
4140
|
-
return [2 /*return
|
|
4306
|
+
return [2 /*return*/, "allowed"];
|
|
4141
4307
|
}
|
|
4142
4308
|
});
|
|
4143
4309
|
});
|