@carbonorm/carbonnode 6.1.0 → 6.1.1
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/README.md +509 -292
- package/dist/index.cjs.js +209 -37
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +208 -38
- package/dist/index.esm.js.map +1 -1
- package/dist/orm/utils/sqlUtils.d.ts +1 -0
- package/dist/types/ormInterfaces.d.ts +1 -0
- package/dist/utils/sqlAllowList.d.ts +5 -3
- package/package.json +1 -1
- package/src/__tests__/fixtures/c6.fixture.ts +33 -0
- 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.ts +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.actor.post.json +6 -6
- 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 +10 -10
- 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 +4 -4
- 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 +4 -4
- 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 +4 -4
- 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 +10 -10
- 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 +4 -4
- 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 +2 -2
- 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 +4 -4
- 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 +4 -4
- 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 +6 -6
- 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 +56 -1
- package/src/__tests__/sqlBuilders.test.ts +38 -1
- package/src/executors/SqlExecutor.ts +4 -3
- package/src/orm/builders/ConditionBuilder.ts +3 -10
- package/src/orm/utils/sqlUtils.ts +172 -4
- package/src/types/ormInterfaces.ts +1 -0
- package/src/utils/sqlAllowList.ts +44 -11
package/dist/index.cjs.js
CHANGED
|
@@ -956,7 +956,7 @@ function colorSql(sql) {
|
|
|
956
956
|
return s;
|
|
957
957
|
}
|
|
958
958
|
|
|
959
|
-
var version = "6.1.
|
|
959
|
+
var version = "6.1.1";
|
|
960
960
|
|
|
961
961
|
var DEFAULT_STEP = 8;
|
|
962
962
|
function parseSemver(version) {
|
|
@@ -1801,14 +1801,176 @@ var HttpExecutor$1 = /*#__PURE__*/Object.freeze({
|
|
|
1801
1801
|
});
|
|
1802
1802
|
|
|
1803
1803
|
function convertHexIfBinary(_col, val, columnDef) {
|
|
1804
|
+
var _a;
|
|
1804
1805
|
if (typeof val === 'string' &&
|
|
1805
1806
|
/^[0-9a-fA-F]{32}$/.test(val) &&
|
|
1806
1807
|
typeof columnDef === 'object' &&
|
|
1807
|
-
columnDef.MYSQL_TYPE.toUpperCase().includes('BINARY')) {
|
|
1808
|
+
String((_a = columnDef.MYSQL_TYPE) !== null && _a !== void 0 ? _a : '').toUpperCase().includes('BINARY')) {
|
|
1808
1809
|
return Buffer.from(val, 'hex');
|
|
1809
1810
|
}
|
|
1810
1811
|
return val;
|
|
1811
1812
|
}
|
|
1813
|
+
var TEMPORAL_TYPES = new Set([
|
|
1814
|
+
'date',
|
|
1815
|
+
'datetime',
|
|
1816
|
+
'timestamp',
|
|
1817
|
+
'time',
|
|
1818
|
+
'year',
|
|
1819
|
+
]);
|
|
1820
|
+
var MYSQL_DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
|
|
1821
|
+
var MYSQL_DATETIME_REGEX = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.\d{1,6})?$/;
|
|
1822
|
+
var MYSQL_TIME_REGEX = /^-?\d{2,3}:\d{2}:\d{2}(?:\.\d{1,6})?$/;
|
|
1823
|
+
var ISO_DATETIME_REGEX = /^(\d{4}-\d{2}-\d{2})[Tt](\d{2}:\d{2}:\d{2})(\.\d{1,6})?([zZ]|[+-]\d{2}:\d{2})?$/;
|
|
1824
|
+
var pad2 = function (value) { return value.toString().padStart(2, '0'); };
|
|
1825
|
+
function trimFraction(value, precision) {
|
|
1826
|
+
var _a = value.split('.', 2), base = _a[0], fractionRaw = _a[1];
|
|
1827
|
+
if (precision <= 0 || !fractionRaw)
|
|
1828
|
+
return base;
|
|
1829
|
+
return "".concat(base, ".").concat(fractionRaw.slice(0, precision).padEnd(precision, '0'));
|
|
1830
|
+
}
|
|
1831
|
+
function normalizeFraction(raw, precision) {
|
|
1832
|
+
if (precision <= 0)
|
|
1833
|
+
return '';
|
|
1834
|
+
if (!raw)
|
|
1835
|
+
return '';
|
|
1836
|
+
var digits = raw.startsWith('.') ? raw.slice(1) : raw;
|
|
1837
|
+
return ".".concat(digits.slice(0, precision).padEnd(precision, '0'));
|
|
1838
|
+
}
|
|
1839
|
+
function formatDateUtc(value) {
|
|
1840
|
+
return "".concat(value.getUTCFullYear(), "-").concat(pad2(value.getUTCMonth() + 1), "-").concat(pad2(value.getUTCDate()));
|
|
1841
|
+
}
|
|
1842
|
+
function formatTimeUtc(value, precision) {
|
|
1843
|
+
var base = "".concat(pad2(value.getUTCHours()), ":").concat(pad2(value.getUTCMinutes()), ":").concat(pad2(value.getUTCSeconds()));
|
|
1844
|
+
if (precision <= 0)
|
|
1845
|
+
return base;
|
|
1846
|
+
var millis = value.getUTCMilliseconds().toString().padStart(3, '0');
|
|
1847
|
+
var fraction = millis.slice(0, Math.min(precision, 3)).padEnd(precision, '0');
|
|
1848
|
+
return "".concat(base, ".").concat(fraction);
|
|
1849
|
+
}
|
|
1850
|
+
function formatDateTimeUtc(value, precision) {
|
|
1851
|
+
return "".concat(formatDateUtc(value), " ").concat(formatTimeUtc(value, precision));
|
|
1852
|
+
}
|
|
1853
|
+
function parseEpochNumber(value) {
|
|
1854
|
+
if (!Number.isFinite(value))
|
|
1855
|
+
return undefined;
|
|
1856
|
+
var abs = Math.abs(value);
|
|
1857
|
+
if (abs >= 1e12) {
|
|
1858
|
+
var date = new Date(value);
|
|
1859
|
+
return Number.isNaN(date.getTime()) ? undefined : date;
|
|
1860
|
+
}
|
|
1861
|
+
if (abs >= 1e9) {
|
|
1862
|
+
var date = new Date(value * 1000);
|
|
1863
|
+
return Number.isNaN(date.getTime()) ? undefined : date;
|
|
1864
|
+
}
|
|
1865
|
+
return undefined;
|
|
1866
|
+
}
|
|
1867
|
+
function parseTemporalType(columnDef) {
|
|
1868
|
+
var _a;
|
|
1869
|
+
var raw = String((_a = columnDef === null || columnDef === void 0 ? void 0 : columnDef.MYSQL_TYPE) !== null && _a !== void 0 ? _a : '').trim().toLowerCase();
|
|
1870
|
+
if (!raw)
|
|
1871
|
+
return { baseType: undefined, precision: 0 };
|
|
1872
|
+
var base = raw.split(/[\s(]/, 1)[0];
|
|
1873
|
+
if (!TEMPORAL_TYPES.has(base))
|
|
1874
|
+
return { baseType: undefined, precision: 0 };
|
|
1875
|
+
var precisionMatch = raw.match(/^(?:datetime|timestamp|time)\((\d+)\)/);
|
|
1876
|
+
if (!precisionMatch)
|
|
1877
|
+
return { baseType: base, precision: 0 };
|
|
1878
|
+
var parsed = Number.parseInt(precisionMatch[1], 10);
|
|
1879
|
+
if (!Number.isFinite(parsed))
|
|
1880
|
+
return { baseType: base, precision: 0 };
|
|
1881
|
+
return { baseType: base, precision: Math.max(0, Math.min(6, parsed)) };
|
|
1882
|
+
}
|
|
1883
|
+
function normalizeTemporalString(value, baseType, precision) {
|
|
1884
|
+
var trimmed = value.trim();
|
|
1885
|
+
if (!trimmed)
|
|
1886
|
+
return value;
|
|
1887
|
+
if (baseType === 'date') {
|
|
1888
|
+
if (MYSQL_DATE_REGEX.test(trimmed))
|
|
1889
|
+
return trimmed;
|
|
1890
|
+
var iso_1 = trimmed.match(ISO_DATETIME_REGEX);
|
|
1891
|
+
if (iso_1) {
|
|
1892
|
+
var datePart = iso_1[1], timezonePart = iso_1[4];
|
|
1893
|
+
if (!timezonePart)
|
|
1894
|
+
return datePart;
|
|
1895
|
+
var parsed_1 = new Date(trimmed);
|
|
1896
|
+
return Number.isNaN(parsed_1.getTime()) ? value : formatDateUtc(parsed_1);
|
|
1897
|
+
}
|
|
1898
|
+
var parsed_2 = new Date(trimmed);
|
|
1899
|
+
return Number.isNaN(parsed_2.getTime()) ? value : formatDateUtc(parsed_2);
|
|
1900
|
+
}
|
|
1901
|
+
if (baseType === 'time') {
|
|
1902
|
+
if (MYSQL_TIME_REGEX.test(trimmed))
|
|
1903
|
+
return trimFraction(trimmed, precision);
|
|
1904
|
+
var iso_2 = trimmed.match(ISO_DATETIME_REGEX);
|
|
1905
|
+
if (iso_2) {
|
|
1906
|
+
var timePart = iso_2[2], fractionPart = iso_2[3], timezonePart = iso_2[4];
|
|
1907
|
+
if (!timezonePart) {
|
|
1908
|
+
return "".concat(timePart).concat(normalizeFraction(fractionPart, precision));
|
|
1909
|
+
}
|
|
1910
|
+
var parsed_3 = new Date(trimmed);
|
|
1911
|
+
return Number.isNaN(parsed_3.getTime()) ? value : formatTimeUtc(parsed_3, precision);
|
|
1912
|
+
}
|
|
1913
|
+
var parsed_4 = new Date(trimmed);
|
|
1914
|
+
return Number.isNaN(parsed_4.getTime()) ? value : formatTimeUtc(parsed_4, precision);
|
|
1915
|
+
}
|
|
1916
|
+
if (baseType === 'year') {
|
|
1917
|
+
if (/^\d{2,4}$/.test(trimmed))
|
|
1918
|
+
return trimmed;
|
|
1919
|
+
var parsed_5 = new Date(trimmed);
|
|
1920
|
+
return Number.isNaN(parsed_5.getTime()) ? value : String(parsed_5.getUTCFullYear());
|
|
1921
|
+
}
|
|
1922
|
+
if (MYSQL_DATETIME_REGEX.test(trimmed))
|
|
1923
|
+
return trimFraction(trimmed, precision);
|
|
1924
|
+
var iso = trimmed.match(ISO_DATETIME_REGEX);
|
|
1925
|
+
if (iso) {
|
|
1926
|
+
var datePart = iso[1], timePart = iso[2], fractionPart = iso[3], timezonePart = iso[4];
|
|
1927
|
+
if (!timezonePart) {
|
|
1928
|
+
return "".concat(datePart, " ").concat(timePart).concat(normalizeFraction(fractionPart, precision));
|
|
1929
|
+
}
|
|
1930
|
+
var parsed_6 = new Date(trimmed);
|
|
1931
|
+
return Number.isNaN(parsed_6.getTime()) ? value : formatDateTimeUtc(parsed_6, precision);
|
|
1932
|
+
}
|
|
1933
|
+
var parsed = new Date(trimmed);
|
|
1934
|
+
return Number.isNaN(parsed.getTime()) ? value : formatDateTimeUtc(parsed, precision);
|
|
1935
|
+
}
|
|
1936
|
+
function convertTemporalIfNeeded(value, columnDef) {
|
|
1937
|
+
var _a = parseTemporalType(columnDef), baseType = _a.baseType, precision = _a.precision;
|
|
1938
|
+
if (!baseType)
|
|
1939
|
+
return value;
|
|
1940
|
+
if (value === null || value === undefined)
|
|
1941
|
+
return value;
|
|
1942
|
+
if (typeof Buffer !== 'undefined' && Buffer.isBuffer && Buffer.isBuffer(value))
|
|
1943
|
+
return value;
|
|
1944
|
+
if (value instanceof Date) {
|
|
1945
|
+
if (baseType === 'date')
|
|
1946
|
+
return formatDateUtc(value);
|
|
1947
|
+
if (baseType === 'time')
|
|
1948
|
+
return formatTimeUtc(value, precision);
|
|
1949
|
+
if (baseType === 'year')
|
|
1950
|
+
return String(value.getUTCFullYear());
|
|
1951
|
+
return formatDateTimeUtc(value, precision);
|
|
1952
|
+
}
|
|
1953
|
+
if (typeof value === 'number') {
|
|
1954
|
+
var parsed = parseEpochNumber(value);
|
|
1955
|
+
if (!parsed)
|
|
1956
|
+
return value;
|
|
1957
|
+
if (baseType === 'date')
|
|
1958
|
+
return formatDateUtc(parsed);
|
|
1959
|
+
if (baseType === 'time')
|
|
1960
|
+
return formatTimeUtc(parsed, precision);
|
|
1961
|
+
if (baseType === 'year')
|
|
1962
|
+
return String(parsed.getUTCFullYear());
|
|
1963
|
+
return formatDateTimeUtc(parsed, precision);
|
|
1964
|
+
}
|
|
1965
|
+
if (typeof value === 'string') {
|
|
1966
|
+
return normalizeTemporalString(value, baseType, precision);
|
|
1967
|
+
}
|
|
1968
|
+
return value;
|
|
1969
|
+
}
|
|
1970
|
+
function convertSqlValueForColumn(col, val, columnDef) {
|
|
1971
|
+
var binaryConverted = convertHexIfBinary(col, val, columnDef);
|
|
1972
|
+
return convertTemporalIfNeeded(binaryConverted, columnDef);
|
|
1973
|
+
}
|
|
1812
1974
|
|
|
1813
1975
|
// ========================
|
|
1814
1976
|
// SQL Operators & Expressions
|
|
@@ -2454,16 +2616,8 @@ var ConditionBuilder = /** @class */ (function (_super) {
|
|
|
2454
2616
|
Object.values(table.COLUMNS).includes(column));
|
|
2455
2617
|
};
|
|
2456
2618
|
ConditionBuilder.prototype.addParam = function (params, column, value) {
|
|
2457
|
-
var
|
|
2458
|
-
|
|
2459
|
-
var columnDef;
|
|
2460
|
-
if (typeof column === 'string' && column.includes('.')) {
|
|
2461
|
-
var _f = column.split('.', 2), tableName = _f[0], colName = _f[1];
|
|
2462
|
-
var table = (_b = (_a = this.config.C6) === null || _a === void 0 ? void 0 : _a.TABLES) === null || _b === void 0 ? void 0 : _b[tableName];
|
|
2463
|
-
// Support both short-keyed and fully-qualified TYPE_VALIDATION entries
|
|
2464
|
-
columnDef = (_d = (_c = table === null || table === void 0 ? void 0 : table.TYPE_VALIDATION) === null || _c === void 0 ? void 0 : _c[colName]) !== null && _d !== void 0 ? _d : (_e = table === null || table === void 0 ? void 0 : table.TYPE_VALIDATION) === null || _e === void 0 ? void 0 : _e["".concat(tableName, ".").concat(colName)];
|
|
2465
|
-
}
|
|
2466
|
-
var val = convertHexIfBinary(column, value, columnDef);
|
|
2619
|
+
var columnDef = this.resolveColumnDefinition(column);
|
|
2620
|
+
var val = convertSqlValueForColumn(column, value, columnDef);
|
|
2467
2621
|
if (this.useNamedParams) {
|
|
2468
2622
|
var key = "param".concat(Object.keys(params).length);
|
|
2469
2623
|
params[key] = val;
|
|
@@ -3777,6 +3931,7 @@ function normalizeSingularRequest(requestMethod, request, restModel, removedPrim
|
|
|
3777
3931
|
return tslib.__assign(tslib.__assign({}, normalized), { dataInsertMultipleRows: dataInsertMultipleRows, cacheResults: cacheResults, skipReactBootstrap: skipReactBootstrap, fetchDependencies: fetchDependencies, debug: debug, success: success, error: error });
|
|
3778
3932
|
}
|
|
3779
3933
|
|
|
3934
|
+
var DEFAULT_NORMALIZER_CACHE_KEY = "__default__";
|
|
3780
3935
|
var allowListCache = new Map();
|
|
3781
3936
|
var ANSI_ESCAPE_REGEX = /\x1b\[[0-9;]*m/g;
|
|
3782
3937
|
var COLLAPSED_BIND_ROW_REGEX = /\(\?\s*×\d+\)/g;
|
|
@@ -3828,7 +3983,17 @@ var normalizeSql = function (sql) {
|
|
|
3828
3983
|
normalized = normalized.replace(/;\s*$/, "");
|
|
3829
3984
|
return normalized.replace(/\s+/g, " ").trim();
|
|
3830
3985
|
};
|
|
3831
|
-
var
|
|
3986
|
+
var normalizeSqlWith = function (sql, sqlQueryNormalizer) {
|
|
3987
|
+
var normalized = normalizeSql(sql);
|
|
3988
|
+
if (!sqlQueryNormalizer)
|
|
3989
|
+
return normalized;
|
|
3990
|
+
var customized = sqlQueryNormalizer(normalized);
|
|
3991
|
+
if (typeof customized !== "string") {
|
|
3992
|
+
throw new Error("sqlQueryNormalizer must return a string.");
|
|
3993
|
+
}
|
|
3994
|
+
return customized.replace(/\s+/g, " ").trim();
|
|
3995
|
+
};
|
|
3996
|
+
var parseAllowList = function (raw, sourcePath, sqlQueryNormalizer) {
|
|
3832
3997
|
var parsed;
|
|
3833
3998
|
try {
|
|
3834
3999
|
parsed = JSON.parse(raw);
|
|
@@ -3841,59 +4006,63 @@ var parseAllowList = function (raw, sourcePath) {
|
|
|
3841
4006
|
}
|
|
3842
4007
|
var sqlEntries = parsed
|
|
3843
4008
|
.filter(function (entry) { return typeof entry === "string"; })
|
|
3844
|
-
.map(
|
|
4009
|
+
.map(function (entry) { return normalizeSqlWith(entry, sqlQueryNormalizer); })
|
|
3845
4010
|
.filter(function (entry) { return entry.length > 0; });
|
|
3846
4011
|
if (sqlEntries.length !== parsed.length) {
|
|
3847
4012
|
throw new Error("SQL allowlist at ".concat(sourcePath, " must contain only string entries."));
|
|
3848
4013
|
}
|
|
3849
4014
|
return sqlEntries;
|
|
3850
4015
|
};
|
|
3851
|
-
var loadSqlAllowList = function (allowListPath) { return tslib.__awaiter(void 0, void 0, void 0, function () {
|
|
3852
|
-
var _a, readFile, stat, fileStat, cached, raw, sqlEntries, allowList;
|
|
3853
|
-
|
|
3854
|
-
|
|
4016
|
+
var loadSqlAllowList = function (allowListPath, sqlQueryNormalizer) { return tslib.__awaiter(void 0, void 0, void 0, function () {
|
|
4017
|
+
var _a, readFile, stat, fileStat, pathCache, cacheKey, cached, raw, sqlEntries, allowList;
|
|
4018
|
+
var _b;
|
|
4019
|
+
return tslib.__generator(this, function (_c) {
|
|
4020
|
+
switch (_c.label) {
|
|
3855
4021
|
case 0:
|
|
3856
4022
|
if (!isNode()) {
|
|
3857
4023
|
throw new Error("SQL allowlist validation requires a Node runtime.");
|
|
3858
4024
|
}
|
|
3859
4025
|
return [4 /*yield*/, import('node:fs/promises')];
|
|
3860
4026
|
case 1:
|
|
3861
|
-
_a =
|
|
3862
|
-
|
|
4027
|
+
_a = _c.sent(), readFile = _a.readFile, stat = _a.stat;
|
|
4028
|
+
_c.label = 2;
|
|
3863
4029
|
case 2:
|
|
3864
|
-
|
|
4030
|
+
_c.trys.push([2, 4, , 5]);
|
|
3865
4031
|
return [4 /*yield*/, stat(allowListPath)];
|
|
3866
4032
|
case 3:
|
|
3867
|
-
fileStat =
|
|
4033
|
+
fileStat = _c.sent();
|
|
3868
4034
|
return [3 /*break*/, 5];
|
|
3869
4035
|
case 4:
|
|
3870
|
-
|
|
4036
|
+
_c.sent();
|
|
3871
4037
|
throw new Error("SQL allowlist file not found at ".concat(allowListPath, "."));
|
|
3872
4038
|
case 5:
|
|
3873
|
-
|
|
4039
|
+
pathCache = (_b = allowListCache.get(allowListPath)) !== null && _b !== void 0 ? _b : new Map();
|
|
4040
|
+
cacheKey = sqlQueryNormalizer !== null && sqlQueryNormalizer !== void 0 ? sqlQueryNormalizer : DEFAULT_NORMALIZER_CACHE_KEY;
|
|
4041
|
+
cached = pathCache.get(cacheKey);
|
|
3874
4042
|
if (cached &&
|
|
3875
4043
|
cached.mtimeMs === fileStat.mtimeMs &&
|
|
3876
4044
|
cached.size === fileStat.size) {
|
|
3877
4045
|
return [2 /*return*/, cached.allowList];
|
|
3878
4046
|
}
|
|
3879
|
-
|
|
4047
|
+
_c.label = 6;
|
|
3880
4048
|
case 6:
|
|
3881
|
-
|
|
4049
|
+
_c.trys.push([6, 8, , 9]);
|
|
3882
4050
|
return [4 /*yield*/, readFile(allowListPath, "utf-8")];
|
|
3883
4051
|
case 7:
|
|
3884
|
-
raw =
|
|
4052
|
+
raw = _c.sent();
|
|
3885
4053
|
return [3 /*break*/, 9];
|
|
3886
4054
|
case 8:
|
|
3887
|
-
|
|
4055
|
+
_c.sent();
|
|
3888
4056
|
throw new Error("SQL allowlist file not found at ".concat(allowListPath, "."));
|
|
3889
4057
|
case 9:
|
|
3890
|
-
sqlEntries = parseAllowList(raw, allowListPath);
|
|
4058
|
+
sqlEntries = parseAllowList(raw, allowListPath, sqlQueryNormalizer);
|
|
3891
4059
|
allowList = new Set(sqlEntries);
|
|
3892
|
-
|
|
4060
|
+
pathCache.set(cacheKey, {
|
|
3893
4061
|
allowList: allowList,
|
|
3894
4062
|
mtimeMs: fileStat.mtimeMs,
|
|
3895
4063
|
size: fileStat.size,
|
|
3896
4064
|
});
|
|
4065
|
+
allowListCache.set(allowListPath, pathCache);
|
|
3897
4066
|
return [2 /*return*/, allowList];
|
|
3898
4067
|
}
|
|
3899
4068
|
});
|
|
@@ -3920,15 +4089,15 @@ var extractSqlEntries = function (payload) {
|
|
|
3920
4089
|
}
|
|
3921
4090
|
return [];
|
|
3922
4091
|
};
|
|
3923
|
-
var collectSqlAllowListEntries = function (payload, entries) {
|
|
4092
|
+
var collectSqlAllowListEntries = function (payload, entries, sqlQueryNormalizer) {
|
|
3924
4093
|
if (entries === void 0) { entries = new Set(); }
|
|
3925
4094
|
var sqlEntries = extractSqlEntries(payload)
|
|
3926
|
-
.map(
|
|
4095
|
+
.map(function (entry) { return normalizeSqlWith(entry, sqlQueryNormalizer); })
|
|
3927
4096
|
.filter(function (entry) { return entry.length > 0; });
|
|
3928
4097
|
sqlEntries.forEach(function (entry) { return entries.add(entry); });
|
|
3929
4098
|
return entries;
|
|
3930
4099
|
};
|
|
3931
|
-
var compileSqlAllowList = function (allowListPath, entries) { return tslib.__awaiter(void 0, void 0, void 0, function () {
|
|
4100
|
+
var compileSqlAllowList = function (allowListPath, entries, sqlQueryNormalizer) { return tslib.__awaiter(void 0, void 0, void 0, function () {
|
|
3932
4101
|
var _a, writeFile, mkdir, path, compiled;
|
|
3933
4102
|
return tslib.__generator(this, function (_b) {
|
|
3934
4103
|
switch (_b.label) {
|
|
@@ -3946,7 +4115,7 @@ var compileSqlAllowList = function (allowListPath, entries) { return tslib.__awa
|
|
|
3946
4115
|
case 3:
|
|
3947
4116
|
_b.sent();
|
|
3948
4117
|
compiled = Array.from(new Set(Array.from(entries)
|
|
3949
|
-
.map(
|
|
4118
|
+
.map(function (entry) { return normalizeSqlWith(entry, sqlQueryNormalizer); })
|
|
3950
4119
|
.filter(function (entry) { return entry.length > 0; }))).sort();
|
|
3951
4120
|
return [4 /*yield*/, writeFile(allowListPath, JSON.stringify(compiled, null, 2))];
|
|
3952
4121
|
case 4:
|
|
@@ -4799,7 +4968,7 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
4799
4968
|
};
|
|
4800
4969
|
SqlExecutor.prototype.validateSqlAllowList = function (sql) {
|
|
4801
4970
|
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
4802
|
-
var allowListPath, allowList, normalized;
|
|
4971
|
+
var allowListPath, sqlQueryNormalizer, allowList, normalized;
|
|
4803
4972
|
var _a;
|
|
4804
4973
|
return tslib.__generator(this, function (_b) {
|
|
4805
4974
|
switch (_b.label) {
|
|
@@ -4808,10 +4977,11 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
4808
4977
|
if (!allowListPath) {
|
|
4809
4978
|
return [2 /*return*/, "not verified"];
|
|
4810
4979
|
}
|
|
4811
|
-
|
|
4980
|
+
sqlQueryNormalizer = this.config.sqlQueryNormalizer;
|
|
4981
|
+
return [4 /*yield*/, loadSqlAllowList(allowListPath, sqlQueryNormalizer)];
|
|
4812
4982
|
case 1:
|
|
4813
4983
|
allowList = _b.sent();
|
|
4814
|
-
normalized =
|
|
4984
|
+
normalized = normalizeSqlWith(sql, sqlQueryNormalizer);
|
|
4815
4985
|
if (!allowList.has(normalized)) {
|
|
4816
4986
|
throw createSqlAllowListBlockedError({
|
|
4817
4987
|
tableName: typeof ((_a = this.config.restModel) === null || _a === void 0 ? void 0 : _a.TABLE_NAME) === "string"
|
|
@@ -5096,6 +5266,7 @@ exports.colorSql = colorSql;
|
|
|
5096
5266
|
exports.compileSqlAllowList = compileSqlAllowList;
|
|
5097
5267
|
exports.convertForRequestBody = convertForRequestBody;
|
|
5098
5268
|
exports.convertHexIfBinary = convertHexIfBinary;
|
|
5269
|
+
exports.convertSqlValueForColumn = convertSqlValueForColumn;
|
|
5099
5270
|
exports.derivedTable = derivedTable;
|
|
5100
5271
|
exports.determineRuntimeJsType = determineRuntimeJsType;
|
|
5101
5272
|
exports.distSphere = distSphere;
|
|
@@ -5124,6 +5295,7 @@ exports.logSql = logSql;
|
|
|
5124
5295
|
exports.logWithLevel = logWithLevel;
|
|
5125
5296
|
exports.normalizeSingularRequest = normalizeSingularRequest;
|
|
5126
5297
|
exports.normalizeSql = normalizeSql;
|
|
5298
|
+
exports.normalizeSqlWith = normalizeSqlWith;
|
|
5127
5299
|
exports.notifyToast = notifyToast;
|
|
5128
5300
|
exports.onError = onError;
|
|
5129
5301
|
exports.onSuccess = onSuccess;
|