@carbonorm/carbonnode 6.0.13 → 6.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/executors/SqlExecutor.d.ts +17 -0
- package/dist/index.cjs.js +413 -245
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +413 -245
- 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__/httpExecutor.multiRowUpsert.test.ts +50 -0
- package/src/__tests__/logSql.test.ts +54 -2
- package/src/__tests__/sakila-db/C6.js +1 -1
- package/src/__tests__/sakila-db/C6.mysqldump.json +1 -1
- package/src/__tests__/sakila-db/C6.mysqldump.sql +1 -1
- package/src/__tests__/sakila-db/C6.sqlAllowList.json +59 -70
- package/src/__tests__/sakila-db/C6.ts +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.actor.post.json +3 -3
- package/src/__tests__/sakila-db/sqlResponses/C6.actor.post.latest.json +3 -3
- package/src/__tests__/sakila-db/sqlResponses/C6.actor.put.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.actor.put.lookup.json +3 -3
- package/src/__tests__/sakila-db/sqlResponses/C6.address.post.json +5 -5
- package/src/__tests__/sakila-db/sqlResponses/C6.address.post.latest.json +5 -5
- package/src/__tests__/sakila-db/sqlResponses/C6.address.put.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.address.put.lookup.json +5 -5
- package/src/__tests__/sakila-db/sqlResponses/C6.category.post.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.category.post.latest.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.category.put.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.category.put.lookup.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.city.post.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.city.post.latest.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.city.put.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.city.put.lookup.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.country.post.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.country.post.latest.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.country.put.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.country.put.lookup.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.customer.post.json +5 -5
- package/src/__tests__/sakila-db/sqlResponses/C6.customer.post.latest.json +5 -5
- package/src/__tests__/sakila-db/sqlResponses/C6.customer.put.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.customer.put.lookup.json +5 -5
- package/src/__tests__/sakila-db/sqlResponses/C6.film.post.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.film.post.latest.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.film.put.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.film.put.lookup.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.inventory.post.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.inventory.post.latest.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.inventory.put.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.inventory.put.lookup.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.language.post.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.language.post.latest.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.language.put.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.language.put.lookup.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.payment.post.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.payment.post.latest.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.payment.put.lookup.json +2 -2
- package/src/__tests__/sakila-db/sqlResponses/C6.rental.join.json +10 -10
- package/src/__tests__/sakila-db/sqlResponses/C6.rental.post.json +3 -3
- package/src/__tests__/sakila-db/sqlResponses/C6.rental.post.latest.json +3 -3
- package/src/__tests__/sakila-db/sqlResponses/C6.rental.put.json +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.rental.put.lookup.json +3 -3
- package/src/__tests__/sqlAllowList.test.ts +100 -0
- package/src/__tests__/sqlBuilders.test.ts +3 -4
- package/src/executors/HttpExecutor.ts +7 -2
- 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];
|
|
@@ -1177,8 +1391,10 @@ var HttpExecutor = /** @class */ (function (_super) {
|
|
|
1177
1391
|
return [__assign(__assign({}, baseConfig), { params: query })];
|
|
1178
1392
|
case POST:
|
|
1179
1393
|
if (dataInsertMultipleRows !== undefined) {
|
|
1394
|
+
var convertedRows = dataInsertMultipleRows.map(convert);
|
|
1395
|
+
var convertedQuery = convert(query);
|
|
1180
1396
|
return [
|
|
1181
|
-
|
|
1397
|
+
__assign(__assign({}, convertedQuery), { dataInsertMultipleRows: convertedRows }),
|
|
1182
1398
|
baseConfig
|
|
1183
1399
|
];
|
|
1184
1400
|
}
|
|
@@ -2940,186 +3156,6 @@ var PaginationBuilder = /** @class */ (function (_super) {
|
|
|
2940
3156
|
return PaginationBuilder;
|
|
2941
3157
|
}(JoinBuilder));
|
|
2942
3158
|
|
|
2943
|
-
/* eslint-disable no-control-regex */
|
|
2944
|
-
var RESET = "\x1b[0m";
|
|
2945
|
-
var C$1 = {
|
|
2946
|
-
KEYWORD: "\x1b[94m", // blue
|
|
2947
|
-
LIMIT: "\x1b[93m", // yellow
|
|
2948
|
-
NUMBER: "\x1b[92m", // green
|
|
2949
|
-
DIM: "\x1b[90m", // gray
|
|
2950
|
-
};
|
|
2951
|
-
/* ---------- ANSI helpers ---------- */
|
|
2952
|
-
var ansi256 = function (n) { return "\u001B[38;5;".concat(n, "m"); };
|
|
2953
|
-
/* ---------- hashing ---------- */
|
|
2954
|
-
function hashString$1(str) {
|
|
2955
|
-
var hash = 0;
|
|
2956
|
-
for (var i = 0; i < str.length; i++) {
|
|
2957
|
-
hash = (hash * 31 + str.charCodeAt(i)) | 0;
|
|
2958
|
-
}
|
|
2959
|
-
return Math.abs(hash);
|
|
2960
|
-
}
|
|
2961
|
-
/* ---------- table color ---------- */
|
|
2962
|
-
function tableRGB(tableName) {
|
|
2963
|
-
var name = tableName.replace(/[`"]/g, "").toLowerCase();
|
|
2964
|
-
var hash = hashString$1(name);
|
|
2965
|
-
// Stable hue bucket by first letter
|
|
2966
|
-
var first = name.charCodeAt(0) || 97;
|
|
2967
|
-
var hueBase = (first - 97) % 6;
|
|
2968
|
-
var r = (hueBase + (hash % 3)) % 6;
|
|
2969
|
-
var g = (hash >> 3) % 6;
|
|
2970
|
-
var b = (hash >> 6) % 6;
|
|
2971
|
-
return [r, g, Math.max(2, b)]; // avoid muddy dark blues
|
|
2972
|
-
}
|
|
2973
|
-
function tableColor(table) {
|
|
2974
|
-
var _a = tableRGB(table), r = _a[0], g = _a[1], b = _a[2];
|
|
2975
|
-
return ansi256(16 + 36 * r + 6 * g + b);
|
|
2976
|
-
}
|
|
2977
|
-
/* ---------- column color (same hue, lighter) ---------- */
|
|
2978
|
-
function columnColorFromTable(table) {
|
|
2979
|
-
var _a = tableRGB(table), r = _a[0], g = _a[1], b = _a[2];
|
|
2980
|
-
// Lift toward white, preserve hue
|
|
2981
|
-
var lr = Math.min(5, r + 1);
|
|
2982
|
-
var lg = Math.min(5, g + 1);
|
|
2983
|
-
var lb = Math.min(5, b + 2);
|
|
2984
|
-
return ansi256(16 + 36 * lr + 6 * lg + lb);
|
|
2985
|
-
}
|
|
2986
|
-
/* ---------- bind collapsing ---------- */
|
|
2987
|
-
/**
|
|
2988
|
-
* ?, ?, ?, ?, ?, ? → ? ×6
|
|
2989
|
-
* triggers at 4+
|
|
2990
|
-
*/
|
|
2991
|
-
function collapseBinds(sql) {
|
|
2992
|
-
return sql.replace(/(\?\s*,\s*){3,}\?/g, function (match) {
|
|
2993
|
-
var count = match.split("?").length - 1;
|
|
2994
|
-
return "".concat(C$1.DIM, "? \u00D7").concat(count).concat(RESET);
|
|
2995
|
-
});
|
|
2996
|
-
}
|
|
2997
|
-
/**
|
|
2998
|
-
* ( ? ×9 ), ( ? ×9 ), ( ? ×9 ) -> ( ? ×9 ) ×3
|
|
2999
|
-
*/
|
|
3000
|
-
function collapseRepeatedValueRows(sql) {
|
|
3001
|
-
var repeatedRowPattern = /(\((?:\x1b\[[0-9;]*m)?\?\s*×\d+(?:\x1b\[[0-9;]*m)?\)|\(\s*(?:\?\s*,\s*)+\?\s*\))(?:\s*,\s*\1){2,}/g;
|
|
3002
|
-
return sql.replace(repeatedRowPattern, function (match, row) {
|
|
3003
|
-
var _a, _b;
|
|
3004
|
-
var rowMatches = match.match(new RegExp(row.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"));
|
|
3005
|
-
var count = (_a = rowMatches === null || rowMatches === void 0 ? void 0 : rowMatches.length) !== null && _a !== void 0 ? _a : 1;
|
|
3006
|
-
var normalizedRow = row.includes("×")
|
|
3007
|
-
? row
|
|
3008
|
-
: "(".concat(C$1.DIM, "? \u00D7").concat(((_b = row.match(/\?/g)) !== null && _b !== void 0 ? _b : []).length).concat(RESET, ")");
|
|
3009
|
-
return "".concat(normalizedRow, " ").concat(C$1.DIM, "\u00D7").concat(count).concat(RESET);
|
|
3010
|
-
});
|
|
3011
|
-
}
|
|
3012
|
-
/* ---------- main formatter ---------- */
|
|
3013
|
-
function colorSql(sql) {
|
|
3014
|
-
var s = sql.trim();
|
|
3015
|
-
/* 1️⃣ collapse bind noise */
|
|
3016
|
-
s = collapseBinds(s);
|
|
3017
|
-
s = collapseRepeatedValueRows(s);
|
|
3018
|
-
/* 2️⃣ table.column coloring (core visual grouping) */
|
|
3019
|
-
s = s.replace(/\b(`?\w+`?)\.(\w+)\b/g, function (_, table, column) {
|
|
3020
|
-
return "".concat(tableColor(table)).concat(table).concat(RESET, ".") +
|
|
3021
|
-
"".concat(columnColorFromTable(table)).concat(column).concat(RESET);
|
|
3022
|
-
});
|
|
3023
|
-
/* 3️⃣ FROM / JOIN tables */
|
|
3024
|
-
s = s.replace(/\b(FROM|JOIN|UPDATE|INTO)\s+(`[^`]+`|\w+)/gi, function (_, kw, table) {
|
|
3025
|
-
return "".concat(C$1.KEYWORD).concat(kw).concat(RESET, " ").concat(tableColor(table)).concat(table).concat(RESET);
|
|
3026
|
-
});
|
|
3027
|
-
/* 4️⃣ SQL keywords */
|
|
3028
|
-
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));
|
|
3029
|
-
/* 5️⃣ LIMIT */
|
|
3030
|
-
s = s.replace(/\bLIMIT\s+(\d+)/gi, "".concat(C$1.LIMIT, "LIMIT").concat(RESET, " ").concat(C$1.NUMBER, "$1").concat(RESET));
|
|
3031
|
-
return s;
|
|
3032
|
-
}
|
|
3033
|
-
|
|
3034
|
-
var version = "6.0.13";
|
|
3035
|
-
|
|
3036
|
-
var DEFAULT_STEP = 8;
|
|
3037
|
-
function parseSemver(version) {
|
|
3038
|
-
var _a = version.trim().split("-"), core = _a[0], prerelease = _a[1];
|
|
3039
|
-
var _b = core.split("."), majorRaw = _b[0], minorRaw = _b[1], patchRaw = _b[2];
|
|
3040
|
-
var major = Number.parseInt(majorRaw !== null && majorRaw !== void 0 ? majorRaw : "0", 10);
|
|
3041
|
-
var minor = Number.parseInt(minorRaw !== null && minorRaw !== void 0 ? minorRaw : "0", 10);
|
|
3042
|
-
var patch = Number.parseInt(patchRaw !== null && patchRaw !== void 0 ? patchRaw : "0", 10);
|
|
3043
|
-
var prereleaseParts = prerelease ? prerelease.split(".").filter(Boolean).length : 0;
|
|
3044
|
-
return {
|
|
3045
|
-
major: Number.isFinite(major) ? major : 0,
|
|
3046
|
-
minor: Number.isFinite(minor) ? minor : 0,
|
|
3047
|
-
patch: Number.isFinite(patch) ? patch : 0,
|
|
3048
|
-
prereleaseParts: prereleaseParts,
|
|
3049
|
-
};
|
|
3050
|
-
}
|
|
3051
|
-
function channelValue(n, step) {
|
|
3052
|
-
var value = 255 - ((n * step) % 256);
|
|
3053
|
-
return (value + 256) % 256;
|
|
3054
|
-
}
|
|
3055
|
-
function versionToRgb(version, step) {
|
|
3056
|
-
if (step === void 0) { step = DEFAULT_STEP; }
|
|
3057
|
-
var safeStep = Number.isFinite(step) && step > 0 ? Math.floor(step) : DEFAULT_STEP;
|
|
3058
|
-
var _a = parseSemver(version), major = _a.major, minor = _a.minor, patch = _a.patch, prereleaseParts = _a.prereleaseParts;
|
|
3059
|
-
var rotation = (major + minor + patch + prereleaseParts) % 3;
|
|
3060
|
-
var base = [major, minor, patch];
|
|
3061
|
-
var rotated = rotation === 1
|
|
3062
|
-
? [base[2], base[0], base[1]]
|
|
3063
|
-
: rotation === 2
|
|
3064
|
-
? [base[1], base[2], base[0]]
|
|
3065
|
-
: base;
|
|
3066
|
-
return {
|
|
3067
|
-
r: channelValue(rotated[0], safeStep),
|
|
3068
|
-
g: channelValue(rotated[1], safeStep),
|
|
3069
|
-
b: channelValue(rotated[2], safeStep),
|
|
3070
|
-
};
|
|
3071
|
-
}
|
|
3072
|
-
|
|
3073
|
-
var C = {
|
|
3074
|
-
SSR: "\x1b[95m", // bright magenta
|
|
3075
|
-
HTTP: "\x1b[94m", // bright blue
|
|
3076
|
-
METHOD_COLORS: {
|
|
3077
|
-
SELECT: "\x1b[92m", // green
|
|
3078
|
-
INSERT: "\x1b[96m", // cyan
|
|
3079
|
-
REPLACE: "\x1b[96m", // cyan
|
|
3080
|
-
UPDATE: "\x1b[95m", // magenta
|
|
3081
|
-
DELETE: "\x1b[91m", // red
|
|
3082
|
-
},
|
|
3083
|
-
METHOD_FALLBACK: [
|
|
3084
|
-
"\x1b[92m", // green
|
|
3085
|
-
"\x1b[93m", // yellow
|
|
3086
|
-
"\x1b[95m", // magenta
|
|
3087
|
-
"\x1b[96m", // cyan
|
|
3088
|
-
"\x1b[94m", // blue
|
|
3089
|
-
"\x1b[97m", // white
|
|
3090
|
-
],
|
|
3091
|
-
RESET: "\x1b[0m",
|
|
3092
|
-
};
|
|
3093
|
-
var rgbAnsi = function (_a) {
|
|
3094
|
-
var r = _a.r, g = _a.g, b = _a.b;
|
|
3095
|
-
return "\u001B[38;2;".concat(r, ";").concat(g, ";").concat(b, "m");
|
|
3096
|
-
};
|
|
3097
|
-
function hashString(value) {
|
|
3098
|
-
var hash = 0;
|
|
3099
|
-
for (var i = 0; i < value.length; i++) {
|
|
3100
|
-
hash = (hash * 31 + value.charCodeAt(i)) | 0;
|
|
3101
|
-
}
|
|
3102
|
-
return Math.abs(hash);
|
|
3103
|
-
}
|
|
3104
|
-
function methodColor(method) {
|
|
3105
|
-
var key = method.toUpperCase();
|
|
3106
|
-
if (key in C.METHOD_COLORS) {
|
|
3107
|
-
return C.METHOD_COLORS[key];
|
|
3108
|
-
}
|
|
3109
|
-
var idx = hashString(key) % C.METHOD_FALLBACK.length;
|
|
3110
|
-
return C.METHOD_FALLBACK[idx];
|
|
3111
|
-
}
|
|
3112
|
-
function logSql(method, sql, context) {
|
|
3113
|
-
if (!shouldLog(LogLevel.INFO, context))
|
|
3114
|
-
return;
|
|
3115
|
-
var preText = getEnvBool("SSR", false)
|
|
3116
|
-
? "".concat(C.SSR, "[SSR]").concat(C.RESET, " ")
|
|
3117
|
-
: "".concat(C.HTTP, "[API]").concat(C.RESET, " ");
|
|
3118
|
-
var labelColor = methodColor(method);
|
|
3119
|
-
var versionColor = rgbAnsi(versionToRgb(version));
|
|
3120
|
-
console.log("".concat(versionColor, "[").concat(version, "]").concat(C.RESET, " ").concat(preText).concat(labelColor, "[").concat(method, "]").concat(C.RESET, " ").concat(colorSql(sql)));
|
|
3121
|
-
}
|
|
3122
|
-
|
|
3123
3159
|
var SelectQueryBuilder = /** @class */ (function (_super) {
|
|
3124
3160
|
__extends(SelectQueryBuilder, _super);
|
|
3125
3161
|
function SelectQueryBuilder() {
|
|
@@ -3171,7 +3207,6 @@ var SelectQueryBuilder = /** @class */ (function (_super) {
|
|
|
3171
3207
|
else if (!isSubSelect) {
|
|
3172
3208
|
sql += " LIMIT 100";
|
|
3173
3209
|
}
|
|
3174
|
-
logSql("SELECT", sql, getLogContext(this.config, this.request));
|
|
3175
3210
|
return { sql: sql, params: params };
|
|
3176
3211
|
};
|
|
3177
3212
|
return SelectQueryBuilder;
|
|
@@ -3196,7 +3231,6 @@ var DeleteQueryBuilder = /** @class */ (function (_super) {
|
|
|
3196
3231
|
if (this.request.WHERE) {
|
|
3197
3232
|
sql += this.buildWhereClause(this.request.WHERE, params);
|
|
3198
3233
|
}
|
|
3199
|
-
logSql("DELETE", sql, getLogContext(this.config, this.request));
|
|
3200
3234
|
return { sql: sql, params: params };
|
|
3201
3235
|
};
|
|
3202
3236
|
return DeleteQueryBuilder;
|
|
@@ -3255,7 +3289,6 @@ var PostQueryBuilder = /** @class */ (function (_super) {
|
|
|
3255
3289
|
var updateClause = updateData.map(function (k) { return "`".concat(k, "` = VALUES(`").concat(k, "`)"); }).join(', ');
|
|
3256
3290
|
sql += " ON DUPLICATE KEY UPDATE ".concat(updateClause);
|
|
3257
3291
|
}
|
|
3258
|
-
logSql(verb, sql, getLogContext(this.config, this.request));
|
|
3259
3292
|
return { sql: sql, params: params };
|
|
3260
3293
|
};
|
|
3261
3294
|
return PostQueryBuilder;
|
|
@@ -3307,7 +3340,6 @@ var UpdateQueryBuilder = /** @class */ (function (_super) {
|
|
|
3307
3340
|
if (args.PAGINATION) {
|
|
3308
3341
|
sql += this.buildPaginationClause(args.PAGINATION, params);
|
|
3309
3342
|
}
|
|
3310
|
-
logSql("UPDATE", sql, getLogContext(this.config, this.request));
|
|
3311
3343
|
return { sql: sql, params: params };
|
|
3312
3344
|
};
|
|
3313
3345
|
return UpdateQueryBuilder;
|
|
@@ -3441,8 +3473,55 @@ function normalizeSingularRequest(requestMethod, request, restModel, removedPrim
|
|
|
3441
3473
|
}
|
|
3442
3474
|
|
|
3443
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
|
+
}
|
|
3444
3515
|
var normalizeSql = function (sql) {
|
|
3445
|
-
|
|
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();
|
|
3446
3525
|
};
|
|
3447
3526
|
var parseAllowList = function (raw, sourcePath) {
|
|
3448
3527
|
var parsed;
|
|
@@ -3465,33 +3544,51 @@ var parseAllowList = function (raw, sourcePath) {
|
|
|
3465
3544
|
return sqlEntries;
|
|
3466
3545
|
};
|
|
3467
3546
|
var loadSqlAllowList = function (allowListPath) { return __awaiter(void 0, void 0, void 0, function () {
|
|
3468
|
-
var readFile, raw, sqlEntries, allowList;
|
|
3469
|
-
return __generator(this, function (
|
|
3470
|
-
switch (
|
|
3547
|
+
var _a, readFile, stat, fileStat, cached, raw, sqlEntries, allowList;
|
|
3548
|
+
return __generator(this, function (_b) {
|
|
3549
|
+
switch (_b.label) {
|
|
3471
3550
|
case 0:
|
|
3472
|
-
if (allowListCache.has(allowListPath)) {
|
|
3473
|
-
return [2 /*return*/, allowListCache.get(allowListPath)];
|
|
3474
|
-
}
|
|
3475
3551
|
if (!isNode()) {
|
|
3476
3552
|
throw new Error("SQL allowlist validation requires a Node runtime.");
|
|
3477
3553
|
}
|
|
3478
3554
|
return [4 /*yield*/, import('node:fs/promises')];
|
|
3479
3555
|
case 1:
|
|
3480
|
-
|
|
3481
|
-
|
|
3556
|
+
_a = _b.sent(), readFile = _a.readFile, stat = _a.stat;
|
|
3557
|
+
_b.label = 2;
|
|
3482
3558
|
case 2:
|
|
3483
|
-
|
|
3484
|
-
return [4 /*yield*/,
|
|
3559
|
+
_b.trys.push([2, 4, , 5]);
|
|
3560
|
+
return [4 /*yield*/, stat(allowListPath)];
|
|
3485
3561
|
case 3:
|
|
3486
|
-
|
|
3562
|
+
fileStat = _b.sent();
|
|
3487
3563
|
return [3 /*break*/, 5];
|
|
3488
3564
|
case 4:
|
|
3489
|
-
|
|
3565
|
+
_b.sent();
|
|
3490
3566
|
throw new Error("SQL allowlist file not found at ".concat(allowListPath, "."));
|
|
3491
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:
|
|
3492
3585
|
sqlEntries = parseAllowList(raw, allowListPath);
|
|
3493
3586
|
allowList = new Set(sqlEntries);
|
|
3494
|
-
allowListCache.set(allowListPath,
|
|
3587
|
+
allowListCache.set(allowListPath, {
|
|
3588
|
+
allowList: allowList,
|
|
3589
|
+
mtimeMs: fileStat.mtimeMs,
|
|
3590
|
+
size: fileStat.size,
|
|
3591
|
+
});
|
|
3495
3592
|
return [2 /*return*/, allowList];
|
|
3496
3593
|
}
|
|
3497
3594
|
});
|
|
@@ -3554,6 +3651,25 @@ var compileSqlAllowList = function (allowListPath, entries) { return __awaiter(v
|
|
|
3554
3651
|
});
|
|
3555
3652
|
}); };
|
|
3556
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
|
+
};
|
|
3557
3673
|
var SqlExecutor = /** @class */ (function (_super) {
|
|
3558
3674
|
__extends(SqlExecutor, _super);
|
|
3559
3675
|
function SqlExecutor() {
|
|
@@ -3564,6 +3680,22 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
3564
3680
|
})); };
|
|
3565
3681
|
return _this;
|
|
3566
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
|
+
};
|
|
3567
3699
|
SqlExecutor.prototype.execute = function () {
|
|
3568
3700
|
return __awaiter(this, void 0, void 0, function () {
|
|
3569
3701
|
var TABLE_NAME, method, logContext, response, _a, rest, getResponse, restRows, result, result, result;
|
|
@@ -3935,7 +4067,7 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
3935
4067
|
};
|
|
3936
4068
|
SqlExecutor.prototype.runQuery = function () {
|
|
3937
4069
|
return __awaiter(this, void 0, void 0, function () {
|
|
3938
|
-
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;
|
|
3939
4071
|
var _this = this;
|
|
3940
4072
|
var _a, _b;
|
|
3941
4073
|
return __generator(this, function (_c) {
|
|
@@ -3945,8 +4077,7 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
3945
4077
|
tableName = this.config.restModel.TABLE_NAME;
|
|
3946
4078
|
logContext = getLogContext(this.config, this.request);
|
|
3947
4079
|
cacheResults = method === C6Constants.GET
|
|
3948
|
-
&&
|
|
3949
|
-
&& ((_a = this.request) === null || _a === void 0 ? void 0 : _a.cacheResults) !== false;
|
|
4080
|
+
&& ((_a = this.request.cacheResults) !== null && _a !== void 0 ? _a : true);
|
|
3950
4081
|
cacheRequestData = cacheResults
|
|
3951
4082
|
? JSON.parse(JSON.stringify((_b = this.request) !== null && _b !== void 0 ? _b : {}))
|
|
3952
4083
|
: undefined;
|
|
@@ -3954,15 +4085,18 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
3954
4085
|
? sortAndSerializeQueryObject(tableName, cacheRequestData !== null && cacheRequestData !== void 0 ? cacheRequestData : {})
|
|
3955
4086
|
: undefined;
|
|
3956
4087
|
if (!cacheResults) return [3 /*break*/, 2];
|
|
3957
|
-
cachedRequest = checkCache(method, tableName, cacheRequestData);
|
|
4088
|
+
cachedRequest = checkCache(method, tableName, cacheRequestData, logContext);
|
|
3958
4089
|
if (!cachedRequest) return [3 /*break*/, 2];
|
|
3959
4090
|
return [4 /*yield*/, cachedRequest];
|
|
3960
4091
|
case 1: return [2 /*return*/, (_c.sent()).data];
|
|
3961
4092
|
case 2:
|
|
3962
4093
|
sqlExecution = this.buildSqlExecutionContext(method, tableName, logContext);
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
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
|
+
}); });
|
|
3966
4100
|
if (!(!cacheResults || !cacheRequestData || !requestArgumentsSerialized)) return [3 /*break*/, 4];
|
|
3967
4101
|
return [4 /*yield*/, queryPromise];
|
|
3968
4102
|
case 3: return [2 /*return*/, _c.sent()];
|
|
@@ -4040,9 +4174,9 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
4040
4174
|
},
|
|
4041
4175
|
};
|
|
4042
4176
|
};
|
|
4043
|
-
SqlExecutor.prototype.executeQueryWithLifecycle = function (conn, method, sqlExecution, logContext) {
|
|
4177
|
+
SqlExecutor.prototype.executeQueryWithLifecycle = function (conn, method, sqlExecution, logContext, sqlMethod) {
|
|
4044
4178
|
return __awaiter(this, void 0, void 0, function () {
|
|
4045
|
-
var useTransaction, committed, result, response, hookResponse, err_1, rollbackErr_1;
|
|
4179
|
+
var useTransaction, committed, allowListStatus, error_2, result, response, hookResponse, err_1, rollbackErr_1;
|
|
4046
4180
|
return __generator(this, function (_a) {
|
|
4047
4181
|
switch (_a.label) {
|
|
4048
4182
|
case 0:
|
|
@@ -4050,25 +4184,49 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
4050
4184
|
committed = false;
|
|
4051
4185
|
_a.label = 1;
|
|
4052
4186
|
case 1:
|
|
4053
|
-
_a.trys.push([1,
|
|
4187
|
+
_a.trys.push([1, 14, , 19]);
|
|
4054
4188
|
if (!useTransaction) return [3 /*break*/, 3];
|
|
4055
4189
|
logWithLevel(LogLevel.DEBUG, logContext, console.log, "[SQL EXECUTOR] \uD83E\uDDFE Beginning transaction");
|
|
4056
4190
|
return [4 /*yield*/, conn.beginTransaction()];
|
|
4057
4191
|
case 2:
|
|
4058
4192
|
_a.sent();
|
|
4059
4193
|
_a.label = 3;
|
|
4060
|
-
case 3:
|
|
4194
|
+
case 3:
|
|
4195
|
+
allowListStatus = "not verified";
|
|
4196
|
+
_a.label = 4;
|
|
4061
4197
|
case 4:
|
|
4062
|
-
_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
|
+
});
|
|
4063
4221
|
return [4 /*yield*/, this.runLifecycleHooks("beforeExecution", {
|
|
4064
4222
|
config: this.config,
|
|
4065
4223
|
request: this.request,
|
|
4066
4224
|
sqlExecution: sqlExecution,
|
|
4067
4225
|
})];
|
|
4068
|
-
case
|
|
4226
|
+
case 8:
|
|
4069
4227
|
_a.sent();
|
|
4070
4228
|
return [4 /*yield*/, conn.query(sqlExecution.sql, sqlExecution.values)];
|
|
4071
|
-
case
|
|
4229
|
+
case 9:
|
|
4072
4230
|
result = (_a.sent())[0];
|
|
4073
4231
|
response = this.createResponseFromQueryResult(method, result, sqlExecution, logContext);
|
|
4074
4232
|
hookResponse = this.createLifecycleHookResponse(response);
|
|
@@ -4077,40 +4235,40 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
4077
4235
|
request: this.request,
|
|
4078
4236
|
response: hookResponse,
|
|
4079
4237
|
})];
|
|
4080
|
-
case
|
|
4238
|
+
case 10:
|
|
4081
4239
|
_a.sent();
|
|
4082
|
-
if (!useTransaction) return [3 /*break*/,
|
|
4240
|
+
if (!useTransaction) return [3 /*break*/, 12];
|
|
4083
4241
|
return [4 /*yield*/, conn.commit()];
|
|
4084
|
-
case
|
|
4242
|
+
case 11:
|
|
4085
4243
|
_a.sent();
|
|
4086
4244
|
committed = true;
|
|
4087
4245
|
logWithLevel(LogLevel.DEBUG, logContext, console.log, "[SQL EXECUTOR] \uD83E\uDDFE Transaction committed");
|
|
4088
|
-
_a.label =
|
|
4089
|
-
case
|
|
4246
|
+
_a.label = 12;
|
|
4247
|
+
case 12: return [4 /*yield*/, this.runLifecycleHooks("afterCommit", {
|
|
4090
4248
|
config: this.config,
|
|
4091
4249
|
request: this.request,
|
|
4092
4250
|
response: hookResponse,
|
|
4093
4251
|
})];
|
|
4094
|
-
case
|
|
4252
|
+
case 13:
|
|
4095
4253
|
_a.sent();
|
|
4096
4254
|
return [2 /*return*/, response];
|
|
4097
|
-
case
|
|
4255
|
+
case 14:
|
|
4098
4256
|
err_1 = _a.sent();
|
|
4099
|
-
if (!(useTransaction && !committed)) return [3 /*break*/,
|
|
4100
|
-
_a.label =
|
|
4101
|
-
case
|
|
4102
|
-
_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]);
|
|
4103
4261
|
return [4 /*yield*/, conn.rollback()];
|
|
4104
|
-
case
|
|
4262
|
+
case 16:
|
|
4105
4263
|
_a.sent();
|
|
4106
4264
|
logWithLevel(LogLevel.WARN, logContext, console.warn, "[SQL EXECUTOR] \uD83E\uDDFE Transaction rolled back");
|
|
4107
|
-
return [3 /*break*/,
|
|
4108
|
-
case
|
|
4265
|
+
return [3 /*break*/, 18];
|
|
4266
|
+
case 17:
|
|
4109
4267
|
rollbackErr_1 = _a.sent();
|
|
4110
4268
|
logWithLevel(LogLevel.ERROR, logContext, console.error, "[SQL EXECUTOR] Rollback failed", rollbackErr_1);
|
|
4111
|
-
return [3 /*break*/,
|
|
4112
|
-
case
|
|
4113
|
-
case
|
|
4269
|
+
return [3 /*break*/, 18];
|
|
4270
|
+
case 18: throw err_1;
|
|
4271
|
+
case 19: return [2 /*return*/];
|
|
4114
4272
|
}
|
|
4115
4273
|
});
|
|
4116
4274
|
});
|
|
@@ -4118,21 +4276,31 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
4118
4276
|
SqlExecutor.prototype.validateSqlAllowList = function (sql) {
|
|
4119
4277
|
return __awaiter(this, void 0, void 0, function () {
|
|
4120
4278
|
var allowListPath, allowList, normalized;
|
|
4121
|
-
|
|
4122
|
-
|
|
4279
|
+
var _a;
|
|
4280
|
+
return __generator(this, function (_b) {
|
|
4281
|
+
switch (_b.label) {
|
|
4123
4282
|
case 0:
|
|
4124
4283
|
allowListPath = this.config.sqlAllowListPath;
|
|
4125
4284
|
if (!allowListPath) {
|
|
4126
|
-
return [2 /*return
|
|
4285
|
+
return [2 /*return*/, "not verified"];
|
|
4127
4286
|
}
|
|
4128
4287
|
return [4 /*yield*/, loadSqlAllowList(allowListPath)];
|
|
4129
4288
|
case 1:
|
|
4130
|
-
allowList =
|
|
4289
|
+
allowList = _b.sent();
|
|
4131
4290
|
normalized = normalizeSql(sql);
|
|
4132
4291
|
if (!allowList.has(normalized)) {
|
|
4133
|
-
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
|
+
});
|
|
4134
4302
|
}
|
|
4135
|
-
return [2 /*return
|
|
4303
|
+
return [2 /*return*/, "allowed"];
|
|
4136
4304
|
}
|
|
4137
4305
|
});
|
|
4138
4306
|
});
|