@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
@@ -22,6 +22,7 @@ export declare class SqlExecutor<G extends OrmGenerics> extends Executor<G> {
22
22
  private buildSqlExecutionContext;
23
23
  private createResponseFromQueryResult;
24
24
  private createLifecycleHookResponse;
25
+ private createCacheResponseEnvelope;
25
26
  private executeQueryWithLifecycle;
26
27
  private validateSqlAllowList;
27
28
  }
@@ -1,16 +1,8 @@
1
- import type { Request, Response, NextFunction, Router } from "express";
2
- import type { Pool } from "mysql2/promise";
3
- import type { iC6Object, tWebsocketBroadcast } from "../types/ormInterfaces";
4
- type iExpressHandlerConfig = {
5
- C6: iC6Object;
6
- mysqlPool: Pool;
7
- sqlAllowListPath?: string;
8
- websocketBroadcast?: tWebsocketBroadcast;
9
- };
10
- type iRestExpressRequestConfig = iExpressHandlerConfig & {
1
+ import type { Request, Response, Router } from "express";
2
+ import { iRest } from "../types/ormInterfaces";
3
+ import { OrmGenerics } from "../types/ormGenerics";
4
+ export declare function restExpressRequest<G extends OrmGenerics>(routerConfig: {
11
5
  router: Pick<Router, "all">;
12
6
  routePath?: string;
13
- };
14
- export declare function restExpressRequest({ router, routePath, ...handlerConfig }: iRestExpressRequestConfig): void;
15
- export declare function ExpressHandler({ C6, mysqlPool, sqlAllowListPath, websocketBroadcast, }: iExpressHandlerConfig): (req: Request, res: Response, next: NextFunction) => Promise<void>;
16
- export {};
7
+ } & Omit<iRest<G['RestShortTableName'], G['RestTableInterface']>, "requestMethod" | "restModel">): void;
8
+ export declare function ExpressHandler<G extends OrmGenerics>(configX: (() => Omit<iRest<G['RestShortTableName'], G['RestTableInterface']>, "requestMethod" | "restModel">) | Omit<iRest<G['RestShortTableName'], G['RestTableInterface']>, "requestMethod" | "restModel">): (req: Request, res: Response) => Promise<void>;
package/dist/index.cjs.js CHANGED
@@ -536,7 +536,11 @@ var logWithLevel = function (requiredLevel, context, logger) {
536
536
  };
537
537
 
538
538
  function convertForRequestBody (restfulObject, tableName, C6, regexErrorHandler) {
539
- if (regexErrorHandler === void 0) { regexErrorHandler = alert; }
539
+ if (regexErrorHandler === void 0) { regexErrorHandler = function (message) {
540
+ if (typeof globalThis !== "undefined" && typeof globalThis.alert === "function") {
541
+ globalThis.alert(message);
542
+ }
543
+ }; }
540
544
  var payload = {};
541
545
  var tableNames = Array.isArray(tableName) ? tableName : [tableName];
542
546
  var tableDefinitions = tableNames.map(function (name) {
@@ -559,7 +563,8 @@ function convertForRequestBody (restfulObject, tableName, C6, regexErrorHandler)
559
563
  C6Constants.DELETE,
560
564
  C6Constants.WHERE,
561
565
  C6Constants.JOIN,
562
- C6Constants.PAGINATION
566
+ C6Constants.PAGINATION,
567
+ "cacheResults",
563
568
  ].includes(value)) {
564
569
  var val_1 = restfulObject[value];
565
570
  if (Array.isArray(val_1)) {
@@ -573,6 +578,9 @@ function convertForRequestBody (restfulObject, tableName, C6, regexErrorHandler)
573
578
  return (tslib.__assign(tslib.__assign({}, acc), (_a = {}, _a[key] = val_1[key], _a)));
574
579
  }, {});
575
580
  }
581
+ else {
582
+ payload[value] = val_1;
583
+ }
576
584
  return "continue";
577
585
  }
578
586
  if (shortReference in tableDefinition) {
@@ -904,7 +912,7 @@ function checkCache(method, tableName, requestData) {
904
912
  var cached = apiRequestCache.get(key);
905
913
  if (!cached)
906
914
  return false;
907
- if (shouldLog(exports.LogLevel.DEBUG, undefined)) {
915
+ if (shouldLog(exports.LogLevel.INFO, undefined)) {
908
916
  console.groupCollapsed("%c API cache hit for ".concat(method, " ").concat(tableName), "color:#0c0");
909
917
  console.log("Request Data:", requestData);
910
918
  console.groupEnd();
@@ -1172,8 +1180,10 @@ var HttpExecutor = /** @class */ (function (_super) {
1172
1180
  return [tslib.__assign(tslib.__assign({}, baseConfig), { params: query })];
1173
1181
  case POST:
1174
1182
  if (dataInsertMultipleRows !== undefined) {
1183
+ var convertedRows = dataInsertMultipleRows.map(convert);
1184
+ var convertedQuery = convert(query);
1175
1185
  return [
1176
- dataInsertMultipleRows.map(convert),
1186
+ tslib.__assign(tslib.__assign({}, convertedQuery), { dataInsertMultipleRows: convertedRows }),
1177
1187
  baseConfig
1178
1188
  ];
1179
1189
  }
@@ -2131,14 +2141,51 @@ var ConditionBuilder = /** @class */ (function (_super) {
2131
2141
  return typeof mysqlType === 'string' && mysqlType.toLowerCase().includes('json');
2132
2142
  };
2133
2143
  ConditionBuilder.prototype.serializeUpdateValue = function (value, params, contextColumn) {
2144
+ var _a;
2145
+ var _this = this;
2134
2146
  var normalized = value instanceof Map ? Object.fromEntries(value) : value;
2135
2147
  var allowColumnRefs = this.isJsonColumn(contextColumn);
2136
2148
  if (this.isPlainArrayLiteral(normalized, allowColumnRefs)
2137
2149
  || this.isPlainObjectLiteral(normalized, allowColumnRefs)) {
2138
2150
  return this.addParam(params, contextColumn !== null && contextColumn !== void 0 ? contextColumn : '', JSON.stringify(normalized));
2139
2151
  }
2140
- var _a = this.serializeOperand(normalized, params, contextColumn), sql = _a.sql, isReference = _a.isReference, isExpression = _a.isExpression, isSubSelect = _a.isSubSelect;
2152
+ var sql;
2153
+ var isReference;
2154
+ var isExpression;
2155
+ var isSubSelect;
2156
+ var shouldStringifyObjectFallback = function (candidate) {
2157
+ if (typeof candidate !== 'object'
2158
+ || candidate === null
2159
+ || candidate instanceof Date
2160
+ || (typeof Buffer !== 'undefined' && Buffer.isBuffer && Buffer.isBuffer(candidate))) {
2161
+ return false;
2162
+ }
2163
+ var normalizedCandidate = candidate instanceof Map
2164
+ ? Object.fromEntries(candidate)
2165
+ : candidate;
2166
+ var entries = Object.entries(normalizedCandidate);
2167
+ if (entries.length !== 1) {
2168
+ return true;
2169
+ }
2170
+ var key = entries[0][0];
2171
+ if (_this.isOperator(key) || _this.BOOLEAN_OPERATORS.has(key)) {
2172
+ return false;
2173
+ }
2174
+ return true;
2175
+ };
2176
+ try {
2177
+ (_a = this.serializeOperand(normalized, params, contextColumn), sql = _a.sql, isReference = _a.isReference, isExpression = _a.isExpression, isSubSelect = _a.isSubSelect);
2178
+ }
2179
+ catch (err) {
2180
+ if (shouldStringifyObjectFallback(normalized)) {
2181
+ return this.addParam(params, contextColumn !== null && contextColumn !== void 0 ? contextColumn : '', JSON.stringify(normalized));
2182
+ }
2183
+ throw err;
2184
+ }
2141
2185
  if (!isReference && !isExpression && !isSubSelect && typeof normalized === 'object' && normalized !== null) {
2186
+ if (shouldStringifyObjectFallback(normalized)) {
2187
+ return this.addParam(params, contextColumn !== null && contextColumn !== void 0 ? contextColumn : '', JSON.stringify(normalized));
2188
+ }
2142
2189
  throw new Error('Unsupported operand type in SQL expression.');
2143
2190
  }
2144
2191
  return sql;
@@ -2952,11 +2999,27 @@ function collapseBinds(sql) {
2952
2999
  return "".concat(C$1.DIM, "? \u00D7").concat(count).concat(RESET);
2953
3000
  });
2954
3001
  }
3002
+ /**
3003
+ * ( ? ×9 ), ( ? ×9 ), ( ? ×9 ) -> ( ? ×9 ) ×3
3004
+ */
3005
+ function collapseRepeatedValueRows(sql) {
3006
+ var repeatedRowPattern = /(\((?:\x1b\[[0-9;]*m)?\?\s*×\d+(?:\x1b\[[0-9;]*m)?\)|\(\s*(?:\?\s*,\s*)+\?\s*\))(?:\s*,\s*\1){2,}/g;
3007
+ return sql.replace(repeatedRowPattern, function (match, row) {
3008
+ var _a, _b;
3009
+ var rowMatches = match.match(new RegExp(row.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"));
3010
+ var count = (_a = rowMatches === null || rowMatches === void 0 ? void 0 : rowMatches.length) !== null && _a !== void 0 ? _a : 1;
3011
+ var normalizedRow = row.includes("×")
3012
+ ? row
3013
+ : "(".concat(C$1.DIM, "? \u00D7").concat(((_b = row.match(/\?/g)) !== null && _b !== void 0 ? _b : []).length).concat(RESET, ")");
3014
+ return "".concat(normalizedRow, " ").concat(C$1.DIM, "\u00D7").concat(count).concat(RESET);
3015
+ });
3016
+ }
2955
3017
  /* ---------- main formatter ---------- */
2956
3018
  function colorSql(sql) {
2957
3019
  var s = sql.trim();
2958
3020
  /* 1️⃣ collapse bind noise */
2959
3021
  s = collapseBinds(s);
3022
+ s = collapseRepeatedValueRows(s);
2960
3023
  /* 2️⃣ table.column coloring (core visual grouping) */
2961
3024
  s = s.replace(/\b(`?\w+`?)\.(\w+)\b/g, function (_, table, column) {
2962
3025
  return "".concat(tableColor(table)).concat(table).concat(RESET, ".") +
@@ -2973,7 +3036,7 @@ function colorSql(sql) {
2973
3036
  return s;
2974
3037
  }
2975
3038
 
2976
- var version = "6.0.12";
3039
+ var version = "6.0.14";
2977
3040
 
2978
3041
  var DEFAULT_STEP = 8;
2979
3042
  function parseSemver(version) {
@@ -3160,21 +3223,35 @@ var PostQueryBuilder = /** @class */ (function (_super) {
3160
3223
  };
3161
3224
  PostQueryBuilder.prototype.build = function (table) {
3162
3225
  var _this = this;
3226
+ var _a, _b;
3163
3227
  this.aliasMap = {};
3164
3228
  var verb = C6C.REPLACE in this.request ? C6C.REPLACE : C6C.INSERT;
3165
- var body = verb in this.request ? this.request[verb] : this.request;
3166
- var keys = Object.keys(body);
3229
+ var directRows = Array.isArray(this.request)
3230
+ ? this.request
3231
+ : [];
3232
+ var rows = directRows.length > 0
3233
+ ? directRows
3234
+ : Array.isArray(this.request.dataInsertMultipleRows) &&
3235
+ this.request.dataInsertMultipleRows.length > 0
3236
+ ? this.request.dataInsertMultipleRows
3237
+ : [verb in this.request ? this.request[verb] : this.request];
3238
+ var keys = Object.keys((_a = rows[0]) !== null && _a !== void 0 ? _a : {});
3167
3239
  var params = this.useNamedParams ? {} : [];
3168
- var placeholders = [];
3169
- for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
3170
- var key = keys_1[_i];
3171
- var value = body[key];
3172
- var trimmed = this.trimTablePrefix(table, key);
3173
- var qualified = "".concat(table, ".").concat(trimmed);
3174
- var placeholder = this.serializeUpdateValue(value, params, qualified);
3175
- placeholders.push(placeholder);
3240
+ var rowPlaceholders = [];
3241
+ for (var _i = 0, rows_1 = rows; _i < rows_1.length; _i++) {
3242
+ var row = rows_1[_i];
3243
+ var placeholders = [];
3244
+ for (var _c = 0, keys_1 = keys; _c < keys_1.length; _c++) {
3245
+ var key = keys_1[_c];
3246
+ var value = (_b = row[key]) !== null && _b !== void 0 ? _b : null;
3247
+ var trimmed = this.trimTablePrefix(table, key);
3248
+ var qualified = "".concat(table, ".").concat(trimmed);
3249
+ var placeholder = this.serializeUpdateValue(value, params, qualified);
3250
+ placeholders.push(placeholder);
3251
+ }
3252
+ rowPlaceholders.push("(".concat(placeholders.join(', '), ")"));
3176
3253
  }
3177
- 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 )");
3254
+ 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 '));
3178
3255
  if (C6C.UPDATE in this.request) {
3179
3256
  var updateData = this.request[C6C.UPDATE];
3180
3257
  if (!Array.isArray(updateData)) {
@@ -3863,19 +3940,55 @@ var SqlExecutor = /** @class */ (function (_super) {
3863
3940
  };
3864
3941
  SqlExecutor.prototype.runQuery = function () {
3865
3942
  return tslib.__awaiter(this, void 0, void 0, function () {
3866
- var method, tableName, logContext, sqlExecution;
3943
+ var method, tableName, logContext, cacheResults, cacheRequestData, requestArgumentsSerialized, cachedRequest, sqlExecution, queryPromise, cacheRequest, cacheResponse;
3867
3944
  var _this = this;
3868
- return tslib.__generator(this, function (_a) {
3869
- switch (_a.label) {
3945
+ var _a, _b;
3946
+ return tslib.__generator(this, function (_c) {
3947
+ switch (_c.label) {
3870
3948
  case 0:
3871
3949
  method = this.config.requestMethod;
3872
3950
  tableName = this.config.restModel.TABLE_NAME;
3873
3951
  logContext = getLogContext(this.config, this.request);
3952
+ cacheResults = method === C6Constants.GET
3953
+ && !this.config.sqlAllowListPath
3954
+ && ((_a = this.request) === null || _a === void 0 ? void 0 : _a.cacheResults) !== false;
3955
+ cacheRequestData = cacheResults
3956
+ ? JSON.parse(JSON.stringify((_b = this.request) !== null && _b !== void 0 ? _b : {}))
3957
+ : undefined;
3958
+ requestArgumentsSerialized = cacheResults
3959
+ ? sortAndSerializeQueryObject(tableName, cacheRequestData !== null && cacheRequestData !== void 0 ? cacheRequestData : {})
3960
+ : undefined;
3961
+ if (!cacheResults) return [3 /*break*/, 2];
3962
+ cachedRequest = checkCache(method, tableName, cacheRequestData);
3963
+ if (!cachedRequest) return [3 /*break*/, 2];
3964
+ return [4 /*yield*/, cachedRequest];
3965
+ case 1: return [2 /*return*/, (_c.sent()).data];
3966
+ case 2:
3874
3967
  sqlExecution = this.buildSqlExecutionContext(method, tableName, logContext);
3875
- return [4 /*yield*/, this.withConnection(function (conn) { return tslib.__awaiter(_this, void 0, void 0, function () { return tslib.__generator(this, function (_a) {
3876
- return [2 /*return*/, this.executeQueryWithLifecycle(conn, method, sqlExecution, logContext)];
3877
- }); }); })];
3878
- case 1: return [2 /*return*/, _a.sent()];
3968
+ queryPromise = this.withConnection(function (conn) { return tslib.__awaiter(_this, void 0, void 0, function () { return tslib.__generator(this, function (_a) {
3969
+ return [2 /*return*/, this.executeQueryWithLifecycle(conn, method, sqlExecution, logContext)];
3970
+ }); }); });
3971
+ if (!(!cacheResults || !cacheRequestData || !requestArgumentsSerialized)) return [3 /*break*/, 4];
3972
+ return [4 /*yield*/, queryPromise];
3973
+ case 3: return [2 /*return*/, _c.sent()];
3974
+ case 4:
3975
+ cacheRequest = queryPromise.then(function (data) {
3976
+ return _this.createCacheResponseEnvelope(method, tableName, data);
3977
+ });
3978
+ setCache(method, tableName, cacheRequestData, {
3979
+ requestArgumentsSerialized: requestArgumentsSerialized,
3980
+ request: cacheRequest,
3981
+ });
3982
+ return [4 /*yield*/, cacheRequest];
3983
+ case 5:
3984
+ cacheResponse = _c.sent();
3985
+ setCache(method, tableName, cacheRequestData, {
3986
+ requestArgumentsSerialized: requestArgumentsSerialized,
3987
+ request: cacheRequest,
3988
+ response: cacheResponse,
3989
+ final: true,
3990
+ });
3991
+ return [2 /*return*/, cacheResponse.data];
3879
3992
  }
3880
3993
  });
3881
3994
  });
@@ -3923,6 +4036,15 @@ var SqlExecutor = /** @class */ (function (_super) {
3923
4036
  var data = Object.assign({ success: true }, response);
3924
4037
  return { data: data };
3925
4038
  };
4039
+ SqlExecutor.prototype.createCacheResponseEnvelope = function (method, tableName, data) {
4040
+ return {
4041
+ data: data,
4042
+ config: {
4043
+ method: method.toLowerCase(),
4044
+ url: "/rest/".concat(tableName),
4045
+ },
4046
+ };
4047
+ };
3926
4048
  SqlExecutor.prototype.executeQueryWithLifecycle = function (conn, method, sqlExecution, logContext) {
3927
4049
  return tslib.__awaiter(this, void 0, void 0, function () {
3928
4050
  var useTransaction, committed, result, response, hookResponse, err_1, rollbackErr_1;
@@ -4028,22 +4150,23 @@ var SqlExecutor$1 = /*#__PURE__*/Object.freeze({
4028
4150
  SqlExecutor: SqlExecutor
4029
4151
  });
4030
4152
 
4031
- function restExpressRequest(_a) {
4032
- var router = _a.router, _b = _a.routePath, routePath = _b === void 0 ? "/rest/:table{/:primary}" : _b, handlerConfig = tslib.__rest(_a, ["router", "routePath"]);
4153
+ function restExpressRequest(routerConfig) {
4154
+ var router = routerConfig.router, _a = routerConfig.routePath, routePath = _a === void 0 ? "/rest/:table{/:primary}" : _a, handlerConfig = tslib.__rest(routerConfig, ["router", "routePath"]);
4033
4155
  router.all(routePath, ExpressHandler(handlerConfig));
4034
4156
  }
4035
4157
  // TODO - WE MUST make this a generic - optional, but helpful
4036
4158
  // note sure how it would help anyone actually...
4037
- function ExpressHandler(_a) {
4159
+ function ExpressHandler(configX) {
4038
4160
  var _this = this;
4039
- var C6 = _a.C6, mysqlPool = _a.mysqlPool, sqlAllowListPath = _a.sqlAllowListPath, websocketBroadcast = _a.websocketBroadcast;
4040
- return function (req, res, next) { return tslib.__awaiter(_this, void 0, void 0, function () {
4041
- var incomingMethod, table, primary, methodOverrideRaw, methodOverride, treatAsGet, method, payload, restModel, primaryKeys_1, primaryShortKeys_1, columnMap_1, resolveShortKey_1, hasPrimaryKeyValues, primaryKeyName, response, err_1;
4161
+ return function (req, res) { return tslib.__awaiter(_this, void 0, void 0, function () {
4162
+ 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;
4042
4163
  var _a, _b, _c, _d, _e, _f, _g;
4043
4164
  return tslib.__generator(this, function (_h) {
4044
4165
  switch (_h.label) {
4045
4166
  case 0:
4046
4167
  _h.trys.push([0, 2, , 3]);
4168
+ config = typeof configX === "function" ? configX() : configX;
4169
+ C6 = config.C6;
4047
4170
  incomingMethod = req.method.toUpperCase();
4048
4171
  table = req.params.table;
4049
4172
  primary = req.params.primary;
@@ -4052,12 +4175,21 @@ function ExpressHandler(_a) {
4052
4175
  treatAsGet = incomingMethod === 'POST' && methodOverride === 'GET';
4053
4176
  method = treatAsGet ? 'GET' : incomingMethod;
4054
4177
  payload = treatAsGet ? tslib.__assign({}, req.body) : (method === 'GET' ? req.query : req.body);
4178
+ // Query strings are text; coerce known boolean controls.
4179
+ if (typeof (payload === null || payload === void 0 ? void 0 : payload.cacheResults) === "string") {
4180
+ normalized = payload.cacheResults.toLowerCase();
4181
+ if (normalized === "false")
4182
+ payload.cacheResults = false;
4183
+ if (normalized === "true")
4184
+ payload.cacheResults = true;
4185
+ }
4055
4186
  // Remove transport-only METHOD flag so it never leaks into ORM parsing
4056
4187
  if (treatAsGet && 'METHOD' in payload) {
4057
4188
  try {
4058
4189
  delete payload.METHOD;
4059
4190
  }
4060
- catch ( /* noop */_j) { /* noop */ }
4191
+ catch ( /* noop */_j) { /* noop */
4192
+ }
4061
4193
  }
4062
4194
  // Warn for unsupported overrides but continue normally
4063
4195
  if (incomingMethod !== 'GET' && methodOverride && methodOverride !== 'GET') {
@@ -4119,22 +4251,16 @@ function ExpressHandler(_a) {
4119
4251
  (_g = payload[primaryKeyName]) !== null && _g !== void 0 ? _g : primary;
4120
4252
  }
4121
4253
  }
4122
- return [4 /*yield*/, restRequest({
4123
- C6: C6,
4124
- mysqlPool: mysqlPool,
4125
- sqlAllowListPath: sqlAllowListPath,
4126
- websocketBroadcast: websocketBroadcast,
4127
- requestMethod: method,
4128
- restModel: C6.TABLES[table]
4129
- })(payload)];
4254
+ return [4 /*yield*/, restRequest(tslib.__assign(tslib.__assign({}, config), { requestMethod: method, restModel: C6.TABLES[table] }))(payload)];
4130
4255
  case 1:
4131
4256
  response = _h.sent();
4132
4257
  res.status(200).json(tslib.__assign({ success: true }, response));
4133
4258
  return [3 /*break*/, 3];
4134
4259
  case 2:
4135
4260
  err_1 = _h.sent();
4136
- res.status(500).json({ success: false, error: err_1 });
4137
- next(err_1);
4261
+ message = err_1 instanceof Error ? err_1.message : String(err_1);
4262
+ logWithLevel(exports.LogLevel.ERROR, undefined, console.error, message);
4263
+ res.status(500).json({ success: false, error: message });
4138
4264
  return [3 /*break*/, 3];
4139
4265
  case 3: return [2 /*return*/];
4140
4266
  }