@carbonorm/carbonnode 4.0.0 → 5.0.0
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 +246 -507
- package/dist/api/executors/SqlExecutor.d.ts +6 -0
- package/dist/api/handlers/ExpressHandler.d.ts +2 -1
- package/dist/api/orm/builders/ConditionBuilder.d.ts +2 -0
- package/dist/api/types/ormInterfaces.d.ts +12 -0
- package/dist/api/utils/sqlAllowList.d.ts +2 -0
- package/dist/index.cjs.js +279 -20
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.esm.js +278 -21
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
- package/scripts/assets/handlebars/C6.test.ts.handlebars +578 -32
- package/scripts/generateRestBindings.cjs +5 -5
- package/scripts/generateRestBindings.ts +5 -5
- package/src/__tests__/fixtures/createTestServer.ts +11 -3
- package/src/__tests__/fixtures/sqlResponses/actor.get.json +13 -0
- package/src/__tests__/fixtures/sqlResponses/sqlAllowList.blocked.json +3 -0
- package/src/__tests__/fixtures/sqlResponses/sqlAllowList.json +3 -0
- package/src/__tests__/sakila-db/C6.js +1 -1
- package/src/__tests__/sakila-db/C6.mysql.cnf +6 -0
- package/src/__tests__/sakila-db/C6.mysqldump.json +1 -0
- package/src/__tests__/sakila-db/C6.mysqldump.sql +720 -0
- package/src/__tests__/sakila-db/C6.sqlAllowList.json +94 -0
- package/src/__tests__/sakila-db/C6.test.ts +578 -32
- package/src/__tests__/sakila-db/C6.ts +1 -1
- package/src/__tests__/sakila-db/sqlResponses/C6.actor.delete.json +10 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.actor.delete.lookup.json +9 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.actor.get.json +14 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.actor.join.json +15 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.actor.post.json +12 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.actor.post.latest.json +14 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.actor.put.json +11 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.actor.put.lookup.json +16 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.actor.seed.json +14 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.address.delete.json +10 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.address.delete.lookup.json +9 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.address.fk.current.json +358 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.address.fk.referenced.json +158 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.address.get.json +22 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.address.join.json +24 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.address.post.json +16 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.address.post.latest.json +22 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.address.put.json +11 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.address.put.lookup.json +24 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.address.seed.json +22 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.category.delete.json +10 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.category.delete.lookup.json +9 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.category.get.json +13 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.category.join.json +14 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.category.post.json +11 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.category.post.latest.json +13 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.category.put.json +11 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.category.put.lookup.json +15 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.category.seed.json +13 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.city.delete.json +10 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.city.delete.lookup.json +9 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.city.fk.current.json +158 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.city.fk.referenced.json +133 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.city.get.json +14 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.city.join.json +15 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.city.post.json +12 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.city.post.latest.json +14 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.city.put.json +11 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.city.put.lookup.json +16 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.city.seed.json +14 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.country.delete.json +10 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.country.delete.lookup.json +9 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.country.get.json +13 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.country.join.json +15 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.country.post.json +11 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.country.post.latest.json +13 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.country.put.json +11 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.country.put.lookup.json +15 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.country.seed.json +13 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.customer.delete.json +10 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.customer.delete.lookup.json +9 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.customer.fk.current.json +283 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.customer.fk.referenced.json +358 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.customer.get.json +19 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.customer.join.json +29 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.customer.post.json +17 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.customer.post.latest.json +19 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.customer.put.json +11 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.customer.put.lookup.json +21 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.customer.seed.json +19 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.film.delete.json +10 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.film.delete.lookup.json +9 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.film.fk.current.json +383 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.film.fk.referenced.json +38 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.film.get.json +23 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.film.join.json +24 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.film.post.json +20 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.film.post.latest.json +23 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.film.put.json +11 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.film.put.lookup.json +25 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.film.seed.json +23 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.inventory.delete.json +10 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.inventory.delete.lookup.json +9 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.inventory.fk.current.json +158 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.inventory.fk.referenced.json +20 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.inventory.get.json +14 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.inventory.join.json +25 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.inventory.post.json +12 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.inventory.post.latest.json +14 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.inventory.put.json +11 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.inventory.put.lookup.json +16 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.inventory.seed.json +14 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.language.delete.json +10 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.language.delete.lookup.json +9 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.language.get.json +13 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.language.join.json +24 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.language.post.json +11 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.language.post.latest.json +13 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.language.put.json +11 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.language.put.lookup.json +15 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.language.seed.json +13 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.payment.delete.json +10 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.payment.delete.lookup.json +9 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.payment.fk.current.json +233 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.payment.fk.referenced.json +233 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.payment.get.json +17 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.payment.join.json +24 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.payment.post.json +15 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.payment.post.latest.json +17 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.payment.put.json +11 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.payment.put.lookup.json +19 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.payment.seed.json +17 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.rental.delete.json +10 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.rental.delete.lookup.json +9 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.rental.fk.current.json +233 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.rental.fk.referenced.json +34 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.rental.get.json +17 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.rental.join.json +24 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.rental.post.json +15 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.rental.post.latest.json +17 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.rental.put.json +11 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.rental.put.lookup.json +19 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.rental.seed.json +17 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.staff.fk.current.json +34 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.staff.fk.referenced.json +20 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.staff.get.json +21 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.staff.join.json +31 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.staff.seed.json +21 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.store.fk.current.json +20 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.store.fk.referenced.json +34 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.store.get.json +14 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.store.join.json +24 -0
- package/src/__tests__/sakila-db/sqlResponses/C6.store.seed.json +14 -0
- package/src/__tests__/sakila.generated.test.ts +31 -0
- package/src/__tests__/sqlAllowList.test.ts +135 -0
- package/src/__tests__/sqlBuilders.test.ts +17 -0
- package/src/api/executors/SqlExecutor.ts +156 -0
- package/src/api/handlers/ExpressHandler.ts +10 -1
- package/src/api/orm/builders/ConditionBuilder.ts +27 -7
- package/src/api/types/ormInterfaces.ts +15 -0
- package/src/api/utils/sqlAllowList.ts +54 -0
- package/src/index.ts +1 -0
package/dist/index.d.ts
CHANGED
|
@@ -36,6 +36,7 @@ export * from "./api/utils/determineRuntimeJsType";
|
|
|
36
36
|
export * from "./api/utils/logger";
|
|
37
37
|
export * from "./api/utils/normalizeSingularRequest";
|
|
38
38
|
export * from "./api/utils/sortAndSerializeQueryObject";
|
|
39
|
+
export * from "./api/utils/sqlAllowList";
|
|
39
40
|
export * from "./api/utils/testHelpers";
|
|
40
41
|
export * from "./api/utils/toastNotifier";
|
|
41
42
|
export * from "./variables/getEnvVar";
|
package/dist/index.esm.js
CHANGED
|
@@ -1824,8 +1824,9 @@ var ConditionBuilder = /** @class */ (function (_super) {
|
|
|
1824
1824
|
}
|
|
1825
1825
|
throw new Error('Unsupported operand type in SQL expression.');
|
|
1826
1826
|
};
|
|
1827
|
-
ConditionBuilder.prototype.isPlainArrayLiteral = function (value) {
|
|
1827
|
+
ConditionBuilder.prototype.isPlainArrayLiteral = function (value, allowColumnRefs) {
|
|
1828
1828
|
var _this = this;
|
|
1829
|
+
if (allowColumnRefs === void 0) { allowColumnRefs = false; }
|
|
1829
1830
|
if (!Array.isArray(value))
|
|
1830
1831
|
return false;
|
|
1831
1832
|
return value.every(function (item) {
|
|
@@ -1835,14 +1836,15 @@ var ConditionBuilder = /** @class */ (function (_super) {
|
|
|
1835
1836
|
if (type === 'string' || type === 'number' || type === 'boolean')
|
|
1836
1837
|
return true;
|
|
1837
1838
|
if (Array.isArray(item))
|
|
1838
|
-
return _this.isPlainArrayLiteral(item);
|
|
1839
|
+
return _this.isPlainArrayLiteral(item, allowColumnRefs);
|
|
1839
1840
|
if (item && typeof item === 'object')
|
|
1840
|
-
return _this.isPlainObjectLiteral(item);
|
|
1841
|
+
return _this.isPlainObjectLiteral(item, allowColumnRefs);
|
|
1841
1842
|
return false;
|
|
1842
1843
|
});
|
|
1843
1844
|
};
|
|
1844
|
-
ConditionBuilder.prototype.isPlainObjectLiteral = function (value) {
|
|
1845
|
+
ConditionBuilder.prototype.isPlainObjectLiteral = function (value, allowColumnRefs) {
|
|
1845
1846
|
var _this = this;
|
|
1847
|
+
if (allowColumnRefs === void 0) { allowColumnRefs = false; }
|
|
1846
1848
|
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
1847
1849
|
return false;
|
|
1848
1850
|
if (value instanceof Date)
|
|
@@ -1861,17 +1863,37 @@ var ConditionBuilder = /** @class */ (function (_super) {
|
|
|
1861
1863
|
})) {
|
|
1862
1864
|
return false;
|
|
1863
1865
|
}
|
|
1864
|
-
if (
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1866
|
+
if (!allowColumnRefs) {
|
|
1867
|
+
if (entries.some(function (_a) {
|
|
1868
|
+
var key = _a[0];
|
|
1869
|
+
return typeof key === 'string' && (_this.isColumnRef(key) || key.includes('.'));
|
|
1870
|
+
})) {
|
|
1871
|
+
return false;
|
|
1872
|
+
}
|
|
1869
1873
|
}
|
|
1870
1874
|
return true;
|
|
1871
1875
|
};
|
|
1876
|
+
ConditionBuilder.prototype.resolveColumnDefinition = function (column) {
|
|
1877
|
+
var _a, _b, _c, _d;
|
|
1878
|
+
if (!column || typeof column !== 'string' || !column.includes('.'))
|
|
1879
|
+
return undefined;
|
|
1880
|
+
var _e = column.split('.', 2), prefix = _e[0], colName = _e[1];
|
|
1881
|
+
var tableName = (_a = this.aliasMap[prefix]) !== null && _a !== void 0 ? _a : prefix;
|
|
1882
|
+
var table = (_c = (_b = this.config.C6) === null || _b === void 0 ? void 0 : _b.TABLES) === null || _c === void 0 ? void 0 : _c[tableName];
|
|
1883
|
+
if (!(table === null || table === void 0 ? void 0 : table.TYPE_VALIDATION))
|
|
1884
|
+
return undefined;
|
|
1885
|
+
return (_d = table.TYPE_VALIDATION[colName]) !== null && _d !== void 0 ? _d : table.TYPE_VALIDATION["".concat(tableName, ".").concat(colName)];
|
|
1886
|
+
};
|
|
1887
|
+
ConditionBuilder.prototype.isJsonColumn = function (column) {
|
|
1888
|
+
var columnDef = this.resolveColumnDefinition(column);
|
|
1889
|
+
var mysqlType = columnDef === null || columnDef === void 0 ? void 0 : columnDef.MYSQL_TYPE;
|
|
1890
|
+
return typeof mysqlType === 'string' && mysqlType.toLowerCase().includes('json');
|
|
1891
|
+
};
|
|
1872
1892
|
ConditionBuilder.prototype.serializeUpdateValue = function (value, params, contextColumn) {
|
|
1873
1893
|
var normalized = value instanceof Map ? Object.fromEntries(value) : value;
|
|
1874
|
-
|
|
1894
|
+
var allowColumnRefs = this.isJsonColumn(contextColumn);
|
|
1895
|
+
if (this.isPlainArrayLiteral(normalized, allowColumnRefs)
|
|
1896
|
+
|| this.isPlainObjectLiteral(normalized, allowColumnRefs)) {
|
|
1875
1897
|
return this.addParam(params, contextColumn !== null && contextColumn !== void 0 ? contextColumn : '', JSON.stringify(normalized));
|
|
1876
1898
|
}
|
|
1877
1899
|
var _a = this.serializeOperand(normalized, params, contextColumn), sql = _a.sql, isReference = _a.isReference, isExpression = _a.isExpression, isSubSelect = _a.isSubSelect;
|
|
@@ -2938,6 +2960,63 @@ function normalizeSingularRequest(requestMethod, request, restModel, removedPrim
|
|
|
2938
2960
|
return __assign(__assign({}, normalized), { dataInsertMultipleRows: dataInsertMultipleRows, cacheResults: cacheResults, fetchDependencies: fetchDependencies, debug: debug, success: success, error: error });
|
|
2939
2961
|
}
|
|
2940
2962
|
|
|
2963
|
+
var allowListCache = new Map();
|
|
2964
|
+
var normalizeSql = function (sql) {
|
|
2965
|
+
return sql.replace(/\s+/g, " ").trim();
|
|
2966
|
+
};
|
|
2967
|
+
var parseAllowList = function (raw, sourcePath) {
|
|
2968
|
+
var parsed;
|
|
2969
|
+
try {
|
|
2970
|
+
parsed = JSON.parse(raw);
|
|
2971
|
+
}
|
|
2972
|
+
catch (error) {
|
|
2973
|
+
throw new Error("SQL allowlist at ".concat(sourcePath, " is not valid JSON."));
|
|
2974
|
+
}
|
|
2975
|
+
if (!Array.isArray(parsed)) {
|
|
2976
|
+
throw new Error("SQL allowlist at ".concat(sourcePath, " must be a JSON array of strings."));
|
|
2977
|
+
}
|
|
2978
|
+
var sqlEntries = parsed
|
|
2979
|
+
.filter(function (entry) { return typeof entry === "string"; })
|
|
2980
|
+
.map(normalizeSql)
|
|
2981
|
+
.filter(function (entry) { return entry.length > 0; });
|
|
2982
|
+
if (sqlEntries.length !== parsed.length) {
|
|
2983
|
+
throw new Error("SQL allowlist at ".concat(sourcePath, " must contain only string entries."));
|
|
2984
|
+
}
|
|
2985
|
+
return sqlEntries;
|
|
2986
|
+
};
|
|
2987
|
+
var loadSqlAllowList = function (allowListPath) { return __awaiter(void 0, void 0, void 0, function () {
|
|
2988
|
+
var readFile, raw, sqlEntries, allowList;
|
|
2989
|
+
return __generator(this, function (_a) {
|
|
2990
|
+
switch (_a.label) {
|
|
2991
|
+
case 0:
|
|
2992
|
+
if (allowListCache.has(allowListPath)) {
|
|
2993
|
+
return [2 /*return*/, allowListCache.get(allowListPath)];
|
|
2994
|
+
}
|
|
2995
|
+
if (!isNode()) {
|
|
2996
|
+
throw new Error("SQL allowlist validation requires a Node runtime.");
|
|
2997
|
+
}
|
|
2998
|
+
return [4 /*yield*/, import('node:fs/promises')];
|
|
2999
|
+
case 1:
|
|
3000
|
+
readFile = (_a.sent()).readFile;
|
|
3001
|
+
_a.label = 2;
|
|
3002
|
+
case 2:
|
|
3003
|
+
_a.trys.push([2, 4, , 5]);
|
|
3004
|
+
return [4 /*yield*/, readFile(allowListPath, "utf-8")];
|
|
3005
|
+
case 3:
|
|
3006
|
+
raw = _a.sent();
|
|
3007
|
+
return [3 /*break*/, 5];
|
|
3008
|
+
case 4:
|
|
3009
|
+
_a.sent();
|
|
3010
|
+
throw new Error("SQL allowlist file not found at ".concat(allowListPath, "."));
|
|
3011
|
+
case 5:
|
|
3012
|
+
sqlEntries = parseAllowList(raw, allowListPath);
|
|
3013
|
+
allowList = new Set(sqlEntries);
|
|
3014
|
+
allowListCache.set(allowListPath, allowList);
|
|
3015
|
+
return [2 /*return*/, allowList];
|
|
3016
|
+
}
|
|
3017
|
+
});
|
|
3018
|
+
}); };
|
|
3019
|
+
|
|
2941
3020
|
var SqlExecutor = /** @class */ (function (_super) {
|
|
2942
3021
|
__extends(SqlExecutor, _super);
|
|
2943
3022
|
function SqlExecutor() {
|
|
@@ -2970,10 +3049,10 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
2970
3049
|
switch (_a) {
|
|
2971
3050
|
case 'GET': return [3 /*break*/, 1];
|
|
2972
3051
|
case 'POST': return [3 /*break*/, 3];
|
|
2973
|
-
case 'PUT': return [3 /*break*/,
|
|
2974
|
-
case 'DELETE': return [3 /*break*/,
|
|
3052
|
+
case 'PUT': return [3 /*break*/, 6];
|
|
3053
|
+
case 'DELETE': return [3 /*break*/, 9];
|
|
2975
3054
|
}
|
|
2976
|
-
return [3 /*break*/,
|
|
3055
|
+
return [3 /*break*/, 12];
|
|
2977
3056
|
case 1: return [4 /*yield*/, this.runQuery()];
|
|
2978
3057
|
case 2:
|
|
2979
3058
|
rest = _b.sent();
|
|
@@ -2981,16 +3060,25 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
2981
3060
|
case 3: return [4 /*yield*/, this.runQuery()];
|
|
2982
3061
|
case 4:
|
|
2983
3062
|
result = _b.sent();
|
|
3063
|
+
return [4 /*yield*/, this.broadcastWebsocketIfConfigured()];
|
|
3064
|
+
case 5:
|
|
3065
|
+
_b.sent();
|
|
2984
3066
|
return [2 /*return*/, result];
|
|
2985
|
-
case
|
|
2986
|
-
case
|
|
3067
|
+
case 6: return [4 /*yield*/, this.runQuery()];
|
|
3068
|
+
case 7:
|
|
2987
3069
|
result = _b.sent();
|
|
2988
|
-
return [
|
|
2989
|
-
case 7: return [4 /*yield*/, this.runQuery()];
|
|
3070
|
+
return [4 /*yield*/, this.broadcastWebsocketIfConfigured()];
|
|
2990
3071
|
case 8:
|
|
3072
|
+
_b.sent();
|
|
3073
|
+
return [2 /*return*/, result];
|
|
3074
|
+
case 9: return [4 /*yield*/, this.runQuery()];
|
|
3075
|
+
case 10:
|
|
2991
3076
|
result = _b.sent();
|
|
3077
|
+
return [4 /*yield*/, this.broadcastWebsocketIfConfigured()];
|
|
3078
|
+
case 11:
|
|
3079
|
+
_b.sent();
|
|
2992
3080
|
return [2 /*return*/, result];
|
|
2993
|
-
case
|
|
3081
|
+
case 12: throw new Error("Unsupported request method: ".concat(method));
|
|
2994
3082
|
}
|
|
2995
3083
|
});
|
|
2996
3084
|
});
|
|
@@ -3051,6 +3139,149 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
3051
3139
|
return "'".concat(val.toISOString().slice(0, 19).replace('T', ' '), "'");
|
|
3052
3140
|
return "'".concat(JSON.stringify(val), "'");
|
|
3053
3141
|
};
|
|
3142
|
+
SqlExecutor.prototype.stripRequestMetadata = function (source) {
|
|
3143
|
+
var ignoredKeys = new Set([
|
|
3144
|
+
C6Constants.SELECT,
|
|
3145
|
+
C6Constants.UPDATE,
|
|
3146
|
+
C6Constants.DELETE,
|
|
3147
|
+
C6Constants.WHERE,
|
|
3148
|
+
C6Constants.JOIN,
|
|
3149
|
+
C6Constants.PAGINATION,
|
|
3150
|
+
C6Constants.INSERT,
|
|
3151
|
+
C6Constants.REPLACE,
|
|
3152
|
+
"dataInsertMultipleRows",
|
|
3153
|
+
"cacheResults",
|
|
3154
|
+
"fetchDependencies",
|
|
3155
|
+
"debug",
|
|
3156
|
+
"success",
|
|
3157
|
+
"error",
|
|
3158
|
+
]);
|
|
3159
|
+
var filtered = {};
|
|
3160
|
+
for (var _i = 0, _a = Object.entries(source); _i < _a.length; _i++) {
|
|
3161
|
+
var _b = _a[_i], key = _b[0], value = _b[1];
|
|
3162
|
+
if (!ignoredKeys.has(key)) {
|
|
3163
|
+
filtered[key] = value;
|
|
3164
|
+
}
|
|
3165
|
+
}
|
|
3166
|
+
return filtered;
|
|
3167
|
+
};
|
|
3168
|
+
SqlExecutor.prototype.normalizeRequestPayload = function (source) {
|
|
3169
|
+
var _a;
|
|
3170
|
+
var columns = this.config.restModel.COLUMNS;
|
|
3171
|
+
var validColumns = new Set(Object.values(columns));
|
|
3172
|
+
var normalized = {};
|
|
3173
|
+
for (var _i = 0, _b = Object.entries(source); _i < _b.length; _i++) {
|
|
3174
|
+
var _c = _b[_i], key = _c[0], value = _c[1];
|
|
3175
|
+
var shortKey = (_a = columns[key]) !== null && _a !== void 0 ? _a : (key.includes(".") ? key.split(".").pop() : key);
|
|
3176
|
+
if (validColumns.has(shortKey)) {
|
|
3177
|
+
normalized[shortKey] = value;
|
|
3178
|
+
}
|
|
3179
|
+
}
|
|
3180
|
+
return normalized;
|
|
3181
|
+
};
|
|
3182
|
+
SqlExecutor.prototype.extractRequestBody = function () {
|
|
3183
|
+
var _a, _b;
|
|
3184
|
+
var request = this.request;
|
|
3185
|
+
if (this.config.requestMethod === C6Constants.POST) {
|
|
3186
|
+
if (Array.isArray(request.dataInsertMultipleRows) && request.dataInsertMultipleRows.length > 0) {
|
|
3187
|
+
return request.dataInsertMultipleRows[0];
|
|
3188
|
+
}
|
|
3189
|
+
if (C6Constants.INSERT in request) {
|
|
3190
|
+
return (_a = request[C6Constants.INSERT]) !== null && _a !== void 0 ? _a : {};
|
|
3191
|
+
}
|
|
3192
|
+
if (C6Constants.REPLACE in request) {
|
|
3193
|
+
return (_b = request[C6Constants.REPLACE]) !== null && _b !== void 0 ? _b : {};
|
|
3194
|
+
}
|
|
3195
|
+
return this.stripRequestMetadata(request);
|
|
3196
|
+
}
|
|
3197
|
+
if (this.config.requestMethod === C6Constants.PUT) {
|
|
3198
|
+
if (request[C6Constants.UPDATE] && typeof request[C6Constants.UPDATE] === "object") {
|
|
3199
|
+
return request[C6Constants.UPDATE];
|
|
3200
|
+
}
|
|
3201
|
+
return this.stripRequestMetadata(request);
|
|
3202
|
+
}
|
|
3203
|
+
return {};
|
|
3204
|
+
};
|
|
3205
|
+
SqlExecutor.prototype.extractPrimaryKeyValues = function () {
|
|
3206
|
+
var _a, _b, _c;
|
|
3207
|
+
var request = this.request;
|
|
3208
|
+
var where = request === null || request === void 0 ? void 0 : request[C6Constants.WHERE];
|
|
3209
|
+
var sources = [request, (where && typeof where === "object" && !Array.isArray(where)) ? where : undefined];
|
|
3210
|
+
var columns = this.config.restModel.COLUMNS;
|
|
3211
|
+
var primaryShorts = (_a = this.config.restModel.PRIMARY_SHORT) !== null && _a !== void 0 ? _a : [];
|
|
3212
|
+
var primaryFulls = (_b = this.config.restModel.PRIMARY) !== null && _b !== void 0 ? _b : [];
|
|
3213
|
+
var pkValues = {};
|
|
3214
|
+
var _loop_1 = function (pkShort) {
|
|
3215
|
+
var value = undefined;
|
|
3216
|
+
for (var _d = 0, sources_1 = sources; _d < sources_1.length; _d++) {
|
|
3217
|
+
var source = sources_1[_d];
|
|
3218
|
+
if (source && pkShort in source) {
|
|
3219
|
+
value = source[pkShort];
|
|
3220
|
+
break;
|
|
3221
|
+
}
|
|
3222
|
+
}
|
|
3223
|
+
if (value === undefined) {
|
|
3224
|
+
var fullKey = (_c = primaryFulls.find(function (key) { return key.endsWith("." + pkShort); })) !== null && _c !== void 0 ? _c : Object.keys(columns).find(function (key) { return columns[key] === pkShort; });
|
|
3225
|
+
if (fullKey) {
|
|
3226
|
+
for (var _e = 0, sources_2 = sources; _e < sources_2.length; _e++) {
|
|
3227
|
+
var source = sources_2[_e];
|
|
3228
|
+
if (source && fullKey in source) {
|
|
3229
|
+
value = source[fullKey];
|
|
3230
|
+
break;
|
|
3231
|
+
}
|
|
3232
|
+
}
|
|
3233
|
+
}
|
|
3234
|
+
}
|
|
3235
|
+
if (value !== undefined) {
|
|
3236
|
+
pkValues[pkShort] = value;
|
|
3237
|
+
}
|
|
3238
|
+
};
|
|
3239
|
+
for (var _i = 0, primaryShorts_1 = primaryShorts; _i < primaryShorts_1.length; _i++) {
|
|
3240
|
+
var pkShort = primaryShorts_1[_i];
|
|
3241
|
+
_loop_1(pkShort);
|
|
3242
|
+
}
|
|
3243
|
+
if (primaryShorts.length > 0 && Object.keys(pkValues).length < primaryShorts.length) {
|
|
3244
|
+
return null;
|
|
3245
|
+
}
|
|
3246
|
+
return Object.keys(pkValues).length > 0 ? pkValues : null;
|
|
3247
|
+
};
|
|
3248
|
+
SqlExecutor.prototype.broadcastWebsocketIfConfigured = function () {
|
|
3249
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
3250
|
+
var broadcast, payload, error_1;
|
|
3251
|
+
var _a, _b;
|
|
3252
|
+
return __generator(this, function (_c) {
|
|
3253
|
+
switch (_c.label) {
|
|
3254
|
+
case 0:
|
|
3255
|
+
broadcast = this.config.websocketBroadcast;
|
|
3256
|
+
if (!broadcast || this.config.requestMethod === C6Constants.GET)
|
|
3257
|
+
return [2 /*return*/];
|
|
3258
|
+
payload = {
|
|
3259
|
+
REST: {
|
|
3260
|
+
TABLE_NAME: this.config.restModel.TABLE_NAME,
|
|
3261
|
+
TABLE_PREFIX: (_b = (_a = this.config.C6) === null || _a === void 0 ? void 0 : _a.PREFIX) !== null && _b !== void 0 ? _b : "",
|
|
3262
|
+
METHOD: this.config.requestMethod,
|
|
3263
|
+
REQUEST: this.normalizeRequestPayload(this.extractRequestBody()),
|
|
3264
|
+
REQUEST_PRIMARY_KEY: this.extractPrimaryKeyValues(),
|
|
3265
|
+
},
|
|
3266
|
+
};
|
|
3267
|
+
_c.label = 1;
|
|
3268
|
+
case 1:
|
|
3269
|
+
_c.trys.push([1, 3, , 4]);
|
|
3270
|
+
return [4 /*yield*/, broadcast(payload)];
|
|
3271
|
+
case 2:
|
|
3272
|
+
_c.sent();
|
|
3273
|
+
return [3 /*break*/, 4];
|
|
3274
|
+
case 3:
|
|
3275
|
+
error_1 = _c.sent();
|
|
3276
|
+
if (this.config.verbose) {
|
|
3277
|
+
console.error("[SQL EXECUTOR] websocketBroadcast failed", error_1);
|
|
3278
|
+
}
|
|
3279
|
+
return [3 /*break*/, 4];
|
|
3280
|
+
case 4: return [2 /*return*/];
|
|
3281
|
+
}
|
|
3282
|
+
});
|
|
3283
|
+
});
|
|
3284
|
+
};
|
|
3054
3285
|
SqlExecutor.prototype.runQuery = function () {
|
|
3055
3286
|
return __awaiter(this, void 0, void 0, function () {
|
|
3056
3287
|
var TABLE_NAME, method, builder, QueryResult, formatted, toUnnamed, _a, sql, values;
|
|
@@ -3082,6 +3313,9 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
3082
3313
|
this.config.verbose && console.log("[SQL EXECUTOR] \uD83E\uDDE0 Formatted ".concat(method.toUpperCase(), " SQL:"), formatted);
|
|
3083
3314
|
toUnnamed = namedPlaceholders();
|
|
3084
3315
|
_a = toUnnamed(QueryResult.sql, QueryResult.params), sql = _a[0], values = _a[1];
|
|
3316
|
+
return [4 /*yield*/, this.validateSqlAllowList(sql)];
|
|
3317
|
+
case 1:
|
|
3318
|
+
_b.sent();
|
|
3085
3319
|
return [4 /*yield*/, this.withConnection(function (conn) { return __awaiter(_this, void 0, void 0, function () {
|
|
3086
3320
|
var result;
|
|
3087
3321
|
return __generator(this, function (_a) {
|
|
@@ -3106,7 +3340,29 @@ var SqlExecutor = /** @class */ (function (_super) {
|
|
|
3106
3340
|
}
|
|
3107
3341
|
});
|
|
3108
3342
|
}); })];
|
|
3109
|
-
case
|
|
3343
|
+
case 2: return [2 /*return*/, _b.sent()];
|
|
3344
|
+
}
|
|
3345
|
+
});
|
|
3346
|
+
});
|
|
3347
|
+
};
|
|
3348
|
+
SqlExecutor.prototype.validateSqlAllowList = function (sql) {
|
|
3349
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
3350
|
+
var allowListPath, allowList, normalized;
|
|
3351
|
+
return __generator(this, function (_a) {
|
|
3352
|
+
switch (_a.label) {
|
|
3353
|
+
case 0:
|
|
3354
|
+
allowListPath = this.config.sqlAllowListPath;
|
|
3355
|
+
if (!allowListPath) {
|
|
3356
|
+
return [2 /*return*/];
|
|
3357
|
+
}
|
|
3358
|
+
return [4 /*yield*/, loadSqlAllowList(allowListPath)];
|
|
3359
|
+
case 1:
|
|
3360
|
+
allowList = _a.sent();
|
|
3361
|
+
normalized = normalizeSql(sql);
|
|
3362
|
+
if (!allowList.has(normalized)) {
|
|
3363
|
+
throw new Error("SQL statement is not permitted by allowlist (".concat(allowListPath, ")."));
|
|
3364
|
+
}
|
|
3365
|
+
return [2 /*return*/];
|
|
3110
3366
|
}
|
|
3111
3367
|
});
|
|
3112
3368
|
});
|
|
@@ -3123,7 +3379,7 @@ var SqlExecutor$1 = /*#__PURE__*/Object.freeze({
|
|
|
3123
3379
|
// note sure how it would help anyone actually...
|
|
3124
3380
|
function ExpressHandler(_a) {
|
|
3125
3381
|
var _this = this;
|
|
3126
|
-
var C6 = _a.C6, mysqlPool = _a.mysqlPool;
|
|
3382
|
+
var C6 = _a.C6, mysqlPool = _a.mysqlPool, sqlAllowListPath = _a.sqlAllowListPath;
|
|
3127
3383
|
return function (req, res, next) { return __awaiter(_this, void 0, void 0, function () {
|
|
3128
3384
|
var incomingMethod, table, primary, methodOverrideRaw, methodOverride, treatAsGet, method, payload, restModel, primaryKeys_1, primaryShortKeys_1, columnMap_1, resolveShortKey_1, hasPrimaryKeyValues, primaryKeyName, response, err_1;
|
|
3129
3385
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
@@ -3209,6 +3465,7 @@ function ExpressHandler(_a) {
|
|
|
3209
3465
|
return [4 /*yield*/, restRequest({
|
|
3210
3466
|
C6: C6,
|
|
3211
3467
|
mysqlPool: mysqlPool,
|
|
3468
|
+
sqlAllowListPath: sqlAllowListPath,
|
|
3212
3469
|
requestMethod: method,
|
|
3213
3470
|
restModel: C6.TABLES[table]
|
|
3214
3471
|
})(payload)];
|
|
@@ -3327,5 +3584,5 @@ function isVerbose () {
|
|
|
3327
3584
|
return ['true', '1', 'yes', 'on'].includes(envVerbose.toLowerCase());
|
|
3328
3585
|
}
|
|
3329
3586
|
|
|
3330
|
-
export { A, AggregateBuilder, C6C, C6Constants, ConditionBuilder, DELETE, DeleteQueryBuilder, Executor, ExpressHandler, F, GET, HttpExecutor, JoinBuilder, POST, PUT, PaginationBuilder, PostQueryBuilder, SelectQueryBuilder, SqlExecutor, TestRestfulResponse, UpdateQueryBuilder, apiRequestCache, axiosInstance, bbox, carbonNodeQsStringify, checkAllRequestsComplete, checkCache, clearCache, convertForRequestBody, convertHexIfBinary, derivedTable, determineRuntimeJsType, distSphere, eFetchDependencies, error, fieldEq, getEnvVar, getPrimaryKeyTypes, group, info, isDerivedTableKey, isLocal, isNode, isTest, isVerbose, normalizeSingularRequest, onError, onSuccess, removeInvalidKeys, removePrefixIfExists, resolveDerivedTable, restOrm, restRequest, setCache, sortAndSerializeQueryObject, stContains, timeout, toastOptions, toastOptionsDevs, userCustomClearCache, warn };
|
|
3587
|
+
export { A, AggregateBuilder, C6C, C6Constants, ConditionBuilder, DELETE, DeleteQueryBuilder, Executor, ExpressHandler, F, GET, HttpExecutor, JoinBuilder, POST, PUT, PaginationBuilder, PostQueryBuilder, SelectQueryBuilder, SqlExecutor, TestRestfulResponse, UpdateQueryBuilder, apiRequestCache, axiosInstance, bbox, carbonNodeQsStringify, checkAllRequestsComplete, checkCache, clearCache, convertForRequestBody, convertHexIfBinary, derivedTable, determineRuntimeJsType, distSphere, eFetchDependencies, error, fieldEq, getEnvVar, getPrimaryKeyTypes, group, info, isDerivedTableKey, isLocal, isNode, isTest, isVerbose, loadSqlAllowList, normalizeSingularRequest, normalizeSql, onError, onSuccess, removeInvalidKeys, removePrefixIfExists, resolveDerivedTable, restOrm, restRequest, setCache, sortAndSerializeQueryObject, stContains, timeout, toastOptions, toastOptionsDevs, userCustomClearCache, warn };
|
|
3331
3588
|
//# sourceMappingURL=index.esm.js.map
|