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