@carbonorm/carbonnode 6.0.12 → 6.0.14

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.
Files changed (75) hide show
  1. package/dist/executors/SqlExecutor.d.ts +1 -0
  2. package/dist/handlers/ExpressHandler.d.ts +6 -14
  3. package/dist/index.cjs.js +167 -41
  4. package/dist/index.cjs.js.map +1 -1
  5. package/dist/index.esm.js +167 -41
  6. package/dist/index.esm.js.map +1 -1
  7. package/dist/types/ormInterfaces.d.ts +13 -3
  8. package/dist/utils/cacheManager.d.ts +2 -3
  9. package/package.json +1 -1
  10. package/src/__tests__/convertForRequestBody.test.ts +58 -0
  11. package/src/__tests__/expressServer.e2e.test.ts +62 -38
  12. package/src/__tests__/fixtures/createTestServer.ts +7 -3
  13. package/src/__tests__/httpExecutor.multiRowUpsert.test.ts +50 -0
  14. package/src/__tests__/httpExecutorSingular.e2e.test.ts +97 -60
  15. package/src/__tests__/logSql.test.ts +13 -0
  16. package/src/__tests__/sakila-db/C6.js +1 -1
  17. package/src/__tests__/sakila-db/C6.mysqldump.json +1 -1
  18. package/src/__tests__/sakila-db/C6.mysqldump.sql +1 -1
  19. package/src/__tests__/sakila-db/C6.sqlAllowList.json +11 -11
  20. package/src/__tests__/sakila-db/C6.ts +1 -1
  21. package/src/__tests__/sakila-db/sqlResponses/C6.actor.post.json +4 -4
  22. package/src/__tests__/sakila-db/sqlResponses/C6.actor.post.latest.json +3 -3
  23. package/src/__tests__/sakila-db/sqlResponses/C6.actor.put.json +1 -1
  24. package/src/__tests__/sakila-db/sqlResponses/C6.actor.put.lookup.json +3 -3
  25. package/src/__tests__/sakila-db/sqlResponses/C6.address.post.json +6 -6
  26. package/src/__tests__/sakila-db/sqlResponses/C6.address.post.latest.json +5 -5
  27. package/src/__tests__/sakila-db/sqlResponses/C6.address.put.json +1 -1
  28. package/src/__tests__/sakila-db/sqlResponses/C6.address.put.lookup.json +5 -5
  29. package/src/__tests__/sakila-db/sqlResponses/C6.category.post.json +3 -3
  30. package/src/__tests__/sakila-db/sqlResponses/C6.category.post.latest.json +2 -2
  31. package/src/__tests__/sakila-db/sqlResponses/C6.category.put.json +1 -1
  32. package/src/__tests__/sakila-db/sqlResponses/C6.category.put.lookup.json +2 -2
  33. package/src/__tests__/sakila-db/sqlResponses/C6.city.post.json +3 -3
  34. package/src/__tests__/sakila-db/sqlResponses/C6.city.post.latest.json +2 -2
  35. package/src/__tests__/sakila-db/sqlResponses/C6.city.put.json +1 -1
  36. package/src/__tests__/sakila-db/sqlResponses/C6.city.put.lookup.json +2 -2
  37. package/src/__tests__/sakila-db/sqlResponses/C6.country.post.json +3 -3
  38. package/src/__tests__/sakila-db/sqlResponses/C6.country.post.latest.json +2 -2
  39. package/src/__tests__/sakila-db/sqlResponses/C6.country.put.json +1 -1
  40. package/src/__tests__/sakila-db/sqlResponses/C6.country.put.lookup.json +2 -2
  41. package/src/__tests__/sakila-db/sqlResponses/C6.customer.post.json +6 -6
  42. package/src/__tests__/sakila-db/sqlResponses/C6.customer.post.latest.json +5 -5
  43. package/src/__tests__/sakila-db/sqlResponses/C6.customer.put.json +1 -1
  44. package/src/__tests__/sakila-db/sqlResponses/C6.customer.put.lookup.json +5 -5
  45. package/src/__tests__/sakila-db/sqlResponses/C6.film.post.json +3 -3
  46. package/src/__tests__/sakila-db/sqlResponses/C6.film.post.latest.json +2 -2
  47. package/src/__tests__/sakila-db/sqlResponses/C6.film.put.json +1 -1
  48. package/src/__tests__/sakila-db/sqlResponses/C6.film.put.lookup.json +2 -2
  49. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.post.json +2 -2
  50. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.post.latest.json +1 -1
  51. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.put.json +1 -1
  52. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.put.lookup.json +1 -1
  53. package/src/__tests__/sakila-db/sqlResponses/C6.language.post.json +3 -3
  54. package/src/__tests__/sakila-db/sqlResponses/C6.language.post.latest.json +2 -2
  55. package/src/__tests__/sakila-db/sqlResponses/C6.language.put.json +1 -1
  56. package/src/__tests__/sakila-db/sqlResponses/C6.language.put.lookup.json +2 -2
  57. package/src/__tests__/sakila-db/sqlResponses/C6.payment.post.json +3 -3
  58. package/src/__tests__/sakila-db/sqlResponses/C6.payment.post.latest.json +2 -2
  59. package/src/__tests__/sakila-db/sqlResponses/C6.payment.put.lookup.json +2 -2
  60. package/src/__tests__/sakila-db/sqlResponses/C6.rental.join.json +10 -10
  61. package/src/__tests__/sakila-db/sqlResponses/C6.rental.post.json +4 -4
  62. package/src/__tests__/sakila-db/sqlResponses/C6.rental.post.latest.json +3 -3
  63. package/src/__tests__/sakila-db/sqlResponses/C6.rental.put.json +1 -1
  64. package/src/__tests__/sakila-db/sqlResponses/C6.rental.put.lookup.json +3 -3
  65. package/src/__tests__/sqlBuilders.test.ts +46 -0
  66. package/src/api/convertForRequestBody.ts +9 -2
  67. package/src/api/restRequest.ts +1 -0
  68. package/src/executors/HttpExecutor.ts +7 -2
  69. package/src/executors/SqlExecutor.ts +64 -2
  70. package/src/handlers/ExpressHandler.ts +50 -39
  71. package/src/orm/builders/ConditionBuilder.ts +43 -1
  72. package/src/orm/queries/PostQueryBuilder.ts +24 -12
  73. package/src/types/ormInterfaces.ts +15 -3
  74. package/src/utils/cacheManager.ts +3 -4
  75. package/src/utils/colorSql.ts +18 -0
package/dist/index.esm.js CHANGED
@@ -533,7 +533,11 @@ var logWithLevel = function (requiredLevel, context, logger) {
533
533
  };
534
534
 
535
535
  function convertForRequestBody (restfulObject, tableName, C6, regexErrorHandler) {
536
- if (regexErrorHandler === void 0) { regexErrorHandler = alert; }
536
+ if (regexErrorHandler === void 0) { regexErrorHandler = function (message) {
537
+ if (typeof globalThis !== "undefined" && typeof globalThis.alert === "function") {
538
+ globalThis.alert(message);
539
+ }
540
+ }; }
537
541
  var payload = {};
538
542
  var tableNames = Array.isArray(tableName) ? tableName : [tableName];
539
543
  var tableDefinitions = tableNames.map(function (name) {
@@ -556,7 +560,8 @@ function convertForRequestBody (restfulObject, tableName, C6, regexErrorHandler)
556
560
  C6Constants.DELETE,
557
561
  C6Constants.WHERE,
558
562
  C6Constants.JOIN,
559
- C6Constants.PAGINATION
563
+ C6Constants.PAGINATION,
564
+ "cacheResults",
560
565
  ].includes(value)) {
561
566
  var val_1 = restfulObject[value];
562
567
  if (Array.isArray(val_1)) {
@@ -570,6 +575,9 @@ function convertForRequestBody (restfulObject, tableName, C6, regexErrorHandler)
570
575
  return (__assign(__assign({}, acc), (_a = {}, _a[key] = val_1[key], _a)));
571
576
  }, {});
572
577
  }
578
+ else {
579
+ payload[value] = val_1;
580
+ }
573
581
  return "continue";
574
582
  }
575
583
  if (shortReference in tableDefinition) {
@@ -901,7 +909,7 @@ function checkCache(method, tableName, requestData) {
901
909
  var cached = apiRequestCache.get(key);
902
910
  if (!cached)
903
911
  return false;
904
- if (shouldLog(LogLevel.DEBUG, undefined)) {
912
+ if (shouldLog(LogLevel.INFO, undefined)) {
905
913
  console.groupCollapsed("%c API cache hit for ".concat(method, " ").concat(tableName), "color:#0c0");
906
914
  console.log("Request Data:", requestData);
907
915
  console.groupEnd();
@@ -1169,8 +1177,10 @@ var HttpExecutor = /** @class */ (function (_super) {
1169
1177
  return [__assign(__assign({}, baseConfig), { params: query })];
1170
1178
  case POST:
1171
1179
  if (dataInsertMultipleRows !== undefined) {
1180
+ var convertedRows = dataInsertMultipleRows.map(convert);
1181
+ var convertedQuery = convert(query);
1172
1182
  return [
1173
- dataInsertMultipleRows.map(convert),
1183
+ __assign(__assign({}, convertedQuery), { dataInsertMultipleRows: convertedRows }),
1174
1184
  baseConfig
1175
1185
  ];
1176
1186
  }
@@ -2128,14 +2138,51 @@ var ConditionBuilder = /** @class */ (function (_super) {
2128
2138
  return typeof mysqlType === 'string' && mysqlType.toLowerCase().includes('json');
2129
2139
  };
2130
2140
  ConditionBuilder.prototype.serializeUpdateValue = function (value, params, contextColumn) {
2141
+ var _a;
2142
+ var _this = this;
2131
2143
  var normalized = value instanceof Map ? Object.fromEntries(value) : value;
2132
2144
  var allowColumnRefs = this.isJsonColumn(contextColumn);
2133
2145
  if (this.isPlainArrayLiteral(normalized, allowColumnRefs)
2134
2146
  || this.isPlainObjectLiteral(normalized, allowColumnRefs)) {
2135
2147
  return this.addParam(params, contextColumn !== null && contextColumn !== void 0 ? contextColumn : '', JSON.stringify(normalized));
2136
2148
  }
2137
- var _a = this.serializeOperand(normalized, params, contextColumn), sql = _a.sql, isReference = _a.isReference, isExpression = _a.isExpression, isSubSelect = _a.isSubSelect;
2149
+ var sql;
2150
+ var isReference;
2151
+ var isExpression;
2152
+ var isSubSelect;
2153
+ var shouldStringifyObjectFallback = function (candidate) {
2154
+ if (typeof candidate !== 'object'
2155
+ || candidate === null
2156
+ || candidate instanceof Date
2157
+ || (typeof Buffer !== 'undefined' && Buffer.isBuffer && Buffer.isBuffer(candidate))) {
2158
+ return false;
2159
+ }
2160
+ var normalizedCandidate = candidate instanceof Map
2161
+ ? Object.fromEntries(candidate)
2162
+ : candidate;
2163
+ var entries = Object.entries(normalizedCandidate);
2164
+ if (entries.length !== 1) {
2165
+ return true;
2166
+ }
2167
+ var key = entries[0][0];
2168
+ if (_this.isOperator(key) || _this.BOOLEAN_OPERATORS.has(key)) {
2169
+ return false;
2170
+ }
2171
+ return true;
2172
+ };
2173
+ try {
2174
+ (_a = this.serializeOperand(normalized, params, contextColumn), sql = _a.sql, isReference = _a.isReference, isExpression = _a.isExpression, isSubSelect = _a.isSubSelect);
2175
+ }
2176
+ catch (err) {
2177
+ if (shouldStringifyObjectFallback(normalized)) {
2178
+ return this.addParam(params, contextColumn !== null && contextColumn !== void 0 ? contextColumn : '', JSON.stringify(normalized));
2179
+ }
2180
+ throw err;
2181
+ }
2138
2182
  if (!isReference && !isExpression && !isSubSelect && typeof normalized === 'object' && normalized !== null) {
2183
+ if (shouldStringifyObjectFallback(normalized)) {
2184
+ return this.addParam(params, contextColumn !== null && contextColumn !== void 0 ? contextColumn : '', JSON.stringify(normalized));
2185
+ }
2139
2186
  throw new Error('Unsupported operand type in SQL expression.');
2140
2187
  }
2141
2188
  return sql;
@@ -2949,11 +2996,27 @@ function collapseBinds(sql) {
2949
2996
  return "".concat(C$1.DIM, "? \u00D7").concat(count).concat(RESET);
2950
2997
  });
2951
2998
  }
2999
+ /**
3000
+ * ( ? ×9 ), ( ? ×9 ), ( ? ×9 ) -> ( ? ×9 ) ×3
3001
+ */
3002
+ function collapseRepeatedValueRows(sql) {
3003
+ var repeatedRowPattern = /(\((?:\x1b\[[0-9;]*m)?\?\s*×\d+(?:\x1b\[[0-9;]*m)?\)|\(\s*(?:\?\s*,\s*)+\?\s*\))(?:\s*,\s*\1){2,}/g;
3004
+ return sql.replace(repeatedRowPattern, function (match, row) {
3005
+ var _a, _b;
3006
+ var rowMatches = match.match(new RegExp(row.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"));
3007
+ var count = (_a = rowMatches === null || rowMatches === void 0 ? void 0 : rowMatches.length) !== null && _a !== void 0 ? _a : 1;
3008
+ var normalizedRow = row.includes("×")
3009
+ ? row
3010
+ : "(".concat(C$1.DIM, "? \u00D7").concat(((_b = row.match(/\?/g)) !== null && _b !== void 0 ? _b : []).length).concat(RESET, ")");
3011
+ return "".concat(normalizedRow, " ").concat(C$1.DIM, "\u00D7").concat(count).concat(RESET);
3012
+ });
3013
+ }
2952
3014
  /* ---------- main formatter ---------- */
2953
3015
  function colorSql(sql) {
2954
3016
  var s = sql.trim();
2955
3017
  /* 1️⃣ collapse bind noise */
2956
3018
  s = collapseBinds(s);
3019
+ s = collapseRepeatedValueRows(s);
2957
3020
  /* 2️⃣ table.column coloring (core visual grouping) */
2958
3021
  s = s.replace(/\b(`?\w+`?)\.(\w+)\b/g, function (_, table, column) {
2959
3022
  return "".concat(tableColor(table)).concat(table).concat(RESET, ".") +
@@ -2970,7 +3033,7 @@ function colorSql(sql) {
2970
3033
  return s;
2971
3034
  }
2972
3035
 
2973
- var version = "6.0.12";
3036
+ var version = "6.0.14";
2974
3037
 
2975
3038
  var DEFAULT_STEP = 8;
2976
3039
  function parseSemver(version) {
@@ -3157,21 +3220,35 @@ var PostQueryBuilder = /** @class */ (function (_super) {
3157
3220
  };
3158
3221
  PostQueryBuilder.prototype.build = function (table) {
3159
3222
  var _this = this;
3223
+ var _a, _b;
3160
3224
  this.aliasMap = {};
3161
3225
  var verb = C6C.REPLACE in this.request ? C6C.REPLACE : C6C.INSERT;
3162
- var body = verb in this.request ? this.request[verb] : this.request;
3163
- var keys = Object.keys(body);
3226
+ var directRows = Array.isArray(this.request)
3227
+ ? this.request
3228
+ : [];
3229
+ var rows = directRows.length > 0
3230
+ ? directRows
3231
+ : Array.isArray(this.request.dataInsertMultipleRows) &&
3232
+ this.request.dataInsertMultipleRows.length > 0
3233
+ ? this.request.dataInsertMultipleRows
3234
+ : [verb in this.request ? this.request[verb] : this.request];
3235
+ var keys = Object.keys((_a = rows[0]) !== null && _a !== void 0 ? _a : {});
3164
3236
  var params = this.useNamedParams ? {} : [];
3165
- var placeholders = [];
3166
- for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
3167
- var key = keys_1[_i];
3168
- var value = body[key];
3169
- var trimmed = this.trimTablePrefix(table, key);
3170
- var qualified = "".concat(table, ".").concat(trimmed);
3171
- var placeholder = this.serializeUpdateValue(value, params, qualified);
3172
- placeholders.push(placeholder);
3237
+ var rowPlaceholders = [];
3238
+ for (var _i = 0, rows_1 = rows; _i < rows_1.length; _i++) {
3239
+ var row = rows_1[_i];
3240
+ var placeholders = [];
3241
+ for (var _c = 0, keys_1 = keys; _c < keys_1.length; _c++) {
3242
+ var key = keys_1[_c];
3243
+ var value = (_b = row[key]) !== null && _b !== void 0 ? _b : null;
3244
+ var trimmed = this.trimTablePrefix(table, key);
3245
+ var qualified = "".concat(table, ".").concat(trimmed);
3246
+ var placeholder = this.serializeUpdateValue(value, params, qualified);
3247
+ placeholders.push(placeholder);
3248
+ }
3249
+ rowPlaceholders.push("(".concat(placeholders.join(', '), ")"));
3173
3250
  }
3174
- var sql = "".concat(verb, " INTO `").concat(table, "` (\n ").concat(keys.map(function (k) { return "`".concat(_this.trimTablePrefix(table, k), "`"); }).join(', '), "\n ) VALUES (\n ").concat(placeholders.join(', '), "\n )");
3251
+ var sql = "".concat(verb, " INTO `").concat(table, "` (\n ").concat(keys.map(function (k) { return "`".concat(_this.trimTablePrefix(table, k), "`"); }).join(', '), "\n ) VALUES\n ").concat(rowPlaceholders.join(',\n '));
3175
3252
  if (C6C.UPDATE in this.request) {
3176
3253
  var updateData = this.request[C6C.UPDATE];
3177
3254
  if (!Array.isArray(updateData)) {
@@ -3860,19 +3937,55 @@ var SqlExecutor = /** @class */ (function (_super) {
3860
3937
  };
3861
3938
  SqlExecutor.prototype.runQuery = function () {
3862
3939
  return __awaiter(this, void 0, void 0, function () {
3863
- var method, tableName, logContext, sqlExecution;
3940
+ var method, tableName, logContext, cacheResults, cacheRequestData, requestArgumentsSerialized, cachedRequest, sqlExecution, queryPromise, cacheRequest, cacheResponse;
3864
3941
  var _this = this;
3865
- return __generator(this, function (_a) {
3866
- switch (_a.label) {
3942
+ var _a, _b;
3943
+ return __generator(this, function (_c) {
3944
+ switch (_c.label) {
3867
3945
  case 0:
3868
3946
  method = this.config.requestMethod;
3869
3947
  tableName = this.config.restModel.TABLE_NAME;
3870
3948
  logContext = getLogContext(this.config, this.request);
3949
+ cacheResults = method === C6Constants.GET
3950
+ && !this.config.sqlAllowListPath
3951
+ && ((_a = this.request) === null || _a === void 0 ? void 0 : _a.cacheResults) !== false;
3952
+ cacheRequestData = cacheResults
3953
+ ? JSON.parse(JSON.stringify((_b = this.request) !== null && _b !== void 0 ? _b : {}))
3954
+ : undefined;
3955
+ requestArgumentsSerialized = cacheResults
3956
+ ? sortAndSerializeQueryObject(tableName, cacheRequestData !== null && cacheRequestData !== void 0 ? cacheRequestData : {})
3957
+ : undefined;
3958
+ if (!cacheResults) return [3 /*break*/, 2];
3959
+ cachedRequest = checkCache(method, tableName, cacheRequestData);
3960
+ if (!cachedRequest) return [3 /*break*/, 2];
3961
+ return [4 /*yield*/, cachedRequest];
3962
+ case 1: return [2 /*return*/, (_c.sent()).data];
3963
+ case 2:
3871
3964
  sqlExecution = this.buildSqlExecutionContext(method, tableName, logContext);
3872
- return [4 /*yield*/, this.withConnection(function (conn) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
3873
- return [2 /*return*/, this.executeQueryWithLifecycle(conn, method, sqlExecution, logContext)];
3874
- }); }); })];
3875
- case 1: return [2 /*return*/, _a.sent()];
3965
+ queryPromise = this.withConnection(function (conn) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
3966
+ return [2 /*return*/, this.executeQueryWithLifecycle(conn, method, sqlExecution, logContext)];
3967
+ }); }); });
3968
+ if (!(!cacheResults || !cacheRequestData || !requestArgumentsSerialized)) return [3 /*break*/, 4];
3969
+ return [4 /*yield*/, queryPromise];
3970
+ case 3: return [2 /*return*/, _c.sent()];
3971
+ case 4:
3972
+ cacheRequest = queryPromise.then(function (data) {
3973
+ return _this.createCacheResponseEnvelope(method, tableName, data);
3974
+ });
3975
+ setCache(method, tableName, cacheRequestData, {
3976
+ requestArgumentsSerialized: requestArgumentsSerialized,
3977
+ request: cacheRequest,
3978
+ });
3979
+ return [4 /*yield*/, cacheRequest];
3980
+ case 5:
3981
+ cacheResponse = _c.sent();
3982
+ setCache(method, tableName, cacheRequestData, {
3983
+ requestArgumentsSerialized: requestArgumentsSerialized,
3984
+ request: cacheRequest,
3985
+ response: cacheResponse,
3986
+ final: true,
3987
+ });
3988
+ return [2 /*return*/, cacheResponse.data];
3876
3989
  }
3877
3990
  });
3878
3991
  });
@@ -3920,6 +4033,15 @@ var SqlExecutor = /** @class */ (function (_super) {
3920
4033
  var data = Object.assign({ success: true }, response);
3921
4034
  return { data: data };
3922
4035
  };
4036
+ SqlExecutor.prototype.createCacheResponseEnvelope = function (method, tableName, data) {
4037
+ return {
4038
+ data: data,
4039
+ config: {
4040
+ method: method.toLowerCase(),
4041
+ url: "/rest/".concat(tableName),
4042
+ },
4043
+ };
4044
+ };
3923
4045
  SqlExecutor.prototype.executeQueryWithLifecycle = function (conn, method, sqlExecution, logContext) {
3924
4046
  return __awaiter(this, void 0, void 0, function () {
3925
4047
  var useTransaction, committed, result, response, hookResponse, err_1, rollbackErr_1;
@@ -4025,22 +4147,23 @@ var SqlExecutor$1 = /*#__PURE__*/Object.freeze({
4025
4147
  SqlExecutor: SqlExecutor
4026
4148
  });
4027
4149
 
4028
- function restExpressRequest(_a) {
4029
- var router = _a.router, _b = _a.routePath, routePath = _b === void 0 ? "/rest/:table{/:primary}" : _b, handlerConfig = __rest(_a, ["router", "routePath"]);
4150
+ function restExpressRequest(routerConfig) {
4151
+ var router = routerConfig.router, _a = routerConfig.routePath, routePath = _a === void 0 ? "/rest/:table{/:primary}" : _a, handlerConfig = __rest(routerConfig, ["router", "routePath"]);
4030
4152
  router.all(routePath, ExpressHandler(handlerConfig));
4031
4153
  }
4032
4154
  // TODO - WE MUST make this a generic - optional, but helpful
4033
4155
  // note sure how it would help anyone actually...
4034
- function ExpressHandler(_a) {
4156
+ function ExpressHandler(configX) {
4035
4157
  var _this = this;
4036
- var C6 = _a.C6, mysqlPool = _a.mysqlPool, sqlAllowListPath = _a.sqlAllowListPath, websocketBroadcast = _a.websocketBroadcast;
4037
- return function (req, res, next) { return __awaiter(_this, void 0, void 0, function () {
4038
- var incomingMethod, table, primary, methodOverrideRaw, methodOverride, treatAsGet, method, payload, restModel, primaryKeys_1, primaryShortKeys_1, columnMap_1, resolveShortKey_1, hasPrimaryKeyValues, primaryKeyName, response, err_1;
4158
+ return function (req, res) { return __awaiter(_this, void 0, void 0, function () {
4159
+ var config, C6, incomingMethod, table, primary, methodOverrideRaw, methodOverride, treatAsGet, method, payload, normalized, restModel, primaryKeys_1, primaryShortKeys_1, columnMap_1, resolveShortKey_1, hasPrimaryKeyValues, primaryKeyName, response, err_1, message;
4039
4160
  var _a, _b, _c, _d, _e, _f, _g;
4040
4161
  return __generator(this, function (_h) {
4041
4162
  switch (_h.label) {
4042
4163
  case 0:
4043
4164
  _h.trys.push([0, 2, , 3]);
4165
+ config = typeof configX === "function" ? configX() : configX;
4166
+ C6 = config.C6;
4044
4167
  incomingMethod = req.method.toUpperCase();
4045
4168
  table = req.params.table;
4046
4169
  primary = req.params.primary;
@@ -4049,12 +4172,21 @@ function ExpressHandler(_a) {
4049
4172
  treatAsGet = incomingMethod === 'POST' && methodOverride === 'GET';
4050
4173
  method = treatAsGet ? 'GET' : incomingMethod;
4051
4174
  payload = treatAsGet ? __assign({}, req.body) : (method === 'GET' ? req.query : req.body);
4175
+ // Query strings are text; coerce known boolean controls.
4176
+ if (typeof (payload === null || payload === void 0 ? void 0 : payload.cacheResults) === "string") {
4177
+ normalized = payload.cacheResults.toLowerCase();
4178
+ if (normalized === "false")
4179
+ payload.cacheResults = false;
4180
+ if (normalized === "true")
4181
+ payload.cacheResults = true;
4182
+ }
4052
4183
  // Remove transport-only METHOD flag so it never leaks into ORM parsing
4053
4184
  if (treatAsGet && 'METHOD' in payload) {
4054
4185
  try {
4055
4186
  delete payload.METHOD;
4056
4187
  }
4057
- catch ( /* noop */_j) { /* noop */ }
4188
+ catch ( /* noop */_j) { /* noop */
4189
+ }
4058
4190
  }
4059
4191
  // Warn for unsupported overrides but continue normally
4060
4192
  if (incomingMethod !== 'GET' && methodOverride && methodOverride !== 'GET') {
@@ -4116,22 +4248,16 @@ function ExpressHandler(_a) {
4116
4248
  (_g = payload[primaryKeyName]) !== null && _g !== void 0 ? _g : primary;
4117
4249
  }
4118
4250
  }
4119
- return [4 /*yield*/, restRequest({
4120
- C6: C6,
4121
- mysqlPool: mysqlPool,
4122
- sqlAllowListPath: sqlAllowListPath,
4123
- websocketBroadcast: websocketBroadcast,
4124
- requestMethod: method,
4125
- restModel: C6.TABLES[table]
4126
- })(payload)];
4251
+ return [4 /*yield*/, restRequest(__assign(__assign({}, config), { requestMethod: method, restModel: C6.TABLES[table] }))(payload)];
4127
4252
  case 1:
4128
4253
  response = _h.sent();
4129
4254
  res.status(200).json(__assign({ success: true }, response));
4130
4255
  return [3 /*break*/, 3];
4131
4256
  case 2:
4132
4257
  err_1 = _h.sent();
4133
- res.status(500).json({ success: false, error: err_1 });
4134
- next(err_1);
4258
+ message = err_1 instanceof Error ? err_1.message : String(err_1);
4259
+ logWithLevel(LogLevel.ERROR, undefined, console.error, message);
4260
+ res.status(500).json({ success: false, error: message });
4135
4261
  return [3 /*break*/, 3];
4136
4262
  case 3: return [2 /*return*/];
4137
4263
  }