@carbonorm/carbonnode 3.6.7 → 3.7.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 CHANGED
@@ -562,6 +562,21 @@ export default Users;
562
562
 
563
563
 
564
564
 
565
+ # Git Hooks
566
+
567
+ This project uses Git hooks to automate certain tasks:
568
+
569
+ - **pre-commit**: Builds the project before pushing to ensure only working code is pushed
570
+ - **post-push**: Automatically publishes to npm when the version number changes
571
+
572
+ To set up the Git hooks, run:
573
+
574
+ ```bash
575
+ npm run hooks:setup
576
+ ```
577
+
578
+ This will configure Git to use the hooks in the `.githooks` directory. The hooks are automatically set up when you run `npm install` as well.
579
+
565
580
  # Support and Issues
566
581
 
567
582
  Any issues found should be reported on [GitHub](https://github.com/CarbonORM/CarbonNode/issues).
@@ -2,3 +2,4 @@ export declare const A: (tableName: string, alias: string) => string;
2
2
  export declare const F: (qualifiedCol: string, alias: string) => string;
3
3
  export declare const fieldEq: (leftCol: string, rightCol: string, leftAlias: string, rightAlias: string) => Record<string, string>;
4
4
  export declare const distSphere: (fromCol: string, toCol: string, fromAlias: string, toAlias: string) => any[];
5
+ export declare const stContains: (envelope: string, shape: string) => any[];
@@ -5,6 +5,7 @@ import { Modify } from "./modifyTypes";
5
5
  import { JoinType, OrderDirection, SQLComparisonOperator, SQLFunction } from "./mysqlTypes";
6
6
  import { CarbonReact } from "@carbonorm/carbonreact";
7
7
  import { OrmGenerics } from "./ormGenerics";
8
+ import { restOrm } from "../restOrm";
8
9
  export type iRestMethods = 'GET' | 'POST' | 'PUT' | 'DELETE';
9
10
  export declare const POST = "POST";
10
11
  export declare const PUT = "PUT";
@@ -215,7 +216,9 @@ export interface iC6Object<RestTableInterfaces extends {
215
216
  [K in Extract<keyof RestTableInterfaces, string>]: C6RestfulModel<K, RestTableInterfaces[K], keyof RestTableInterfaces[K] & string>;
216
217
  };
217
218
  PREFIX: string;
218
- IMPORT: (tableName: string) => Promise<iDynamicApiImport>;
219
+ ORM: {
220
+ [K in Extract<keyof RestTableInterfaces, string>]: C6RestfulModel<K, RestTableInterfaces[K], keyof RestTableInterfaces[K] & string> & ReturnType<typeof restOrm<OrmGenerics<any>>>;
221
+ }[];
219
222
  [key: string]: any;
220
223
  }
221
224
  export interface tC6RestApi {
package/dist/index.cjs.js CHANGED
@@ -909,11 +909,11 @@ var HttpExecutor = /** @class */ (function (_super) {
909
909
  // returning the promise with this then is important for tests. todo - we could make that optional.
910
910
  // https://rapidapi.com/guides/axios-async-await
911
911
  return [2 /*return*/, axiosActiveRequest.then(function (response) { return tslib.__awaiter(_this, void 0, void 0, function () {
912
- var cacheIndex, callback, responseData_1, dependencies_1, fetchReferences_1, apiRequestPromises, _loop_1, _a, _b, _c, _i, tableToFetch;
912
+ var cacheIndex, callback, responseData_1, dependencies_1, fetchReferences_1, apiRequestPromises, _loop_1, tableToFetch;
913
913
  var _this = this;
914
- var _d, _e, _f, _g, _h, _j;
915
- return tslib.__generator(this, function (_k) {
916
- switch (_k.label) {
914
+ var _a, _b, _c, _d, _e, _f;
915
+ return tslib.__generator(this, function (_g) {
916
+ switch (_g.label) {
917
917
  case 0:
918
918
  // noinspection SuspiciousTypeOfGuard
919
919
  if (typeof response.data === 'string') {
@@ -972,12 +972,12 @@ var HttpExecutor = /** @class */ (function (_super) {
972
972
  else {
973
973
  callback();
974
974
  }
975
- if (!(C6.GET === requestMethod)) return [3 /*break*/, 6];
975
+ if (!(C6.GET === requestMethod)) return [3 /*break*/, 2];
976
976
  responseData_1 = response.data;
977
- returnGetNextPageFunction = 1 !== ((_d = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _d === void 0 ? void 0 : _d[C6.LIMIT]) &&
978
- ((_e = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _e === void 0 ? void 0 : _e[C6.LIMIT]) === responseData_1.rest.length;
977
+ returnGetNextPageFunction = 1 !== ((_a = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _a === void 0 ? void 0 : _a[C6.LIMIT]) &&
978
+ ((_b = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _b === void 0 ? void 0 : _b[C6.LIMIT]) === responseData_1.rest.length;
979
979
  if (false === isTest() || this.config.verbose) {
980
- console.groupCollapsed('%c API: Response (' + requestMethod + ' ' + tableName + ') returned length (' + ((_f = responseData_1.rest) === null || _f === void 0 ? void 0 : _f.length) + ') of possible (' + ((_g = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _g === void 0 ? void 0 : _g[C6.LIMIT]) + ') limit!', 'color: #0c0');
980
+ console.groupCollapsed('%c API: Response (' + requestMethod + ' ' + tableName + ') returned length (' + ((_c = responseData_1.rest) === null || _c === void 0 ? void 0 : _c.length) + ') of possible (' + ((_d = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _d === void 0 ? void 0 : _d[C6.LIMIT]) + ') limit!', 'color: #0c0');
981
981
  console.log('%c ' + requestMethod + ' ' + tableName, 'color: #0c0');
982
982
  console.log('%c Request Data (note you may see the success and/or error prompt):', 'color: #0c0', this.request);
983
983
  console.log('%c Response Data:', 'color: #0c0', responseData_1.rest);
@@ -992,12 +992,12 @@ var HttpExecutor = /** @class */ (function (_super) {
992
992
  responseData_1.next = undefined;
993
993
  if (true === debug
994
994
  && isLocal()) {
995
- reactToastify.toast.success("DEVS: Response returned length (" + ((_h = responseData_1.rest) === null || _h === void 0 ? void 0 : _h.length) + ") less than limit (" + ((_j = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _j === void 0 ? void 0 : _j[C6.LIMIT]) + ").", toastOptionsDevs);
995
+ reactToastify.toast.success("DEVS: Response returned length (" + ((_e = responseData_1.rest) === null || _e === void 0 ? void 0 : _e.length) + ") less than limit (" + ((_f = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _f === void 0 ? void 0 : _f[C6.LIMIT]) + ").", toastOptionsDevs);
996
996
  }
997
997
  }
998
998
  if (!(fetchDependencies
999
999
  && 'number' === typeof fetchDependencies
1000
- && responseData_1.rest.length > 0)) return [3 /*break*/, 6];
1000
+ && responseData_1.rest.length > 0)) return [3 /*break*/, 2];
1001
1001
  console.groupCollapsed('%c API: Fetch Dependencies segment (' + requestMethod + ' ' + tableName + ')'
1002
1002
  + (fetchDependencies & exports.eFetchDependencies.CHILDREN ? ' | (CHILDREN|REFERENCED) ' : '')
1003
1003
  + (fetchDependencies & exports.eFetchDependencies.PARENTS ? ' | (PARENTS|REFERENCED_BY)' : '')
@@ -1068,97 +1068,73 @@ var HttpExecutor = /** @class */ (function (_super) {
1068
1068
  }); });
1069
1069
  console.log('fetchReferences', fetchReferences_1);
1070
1070
  _loop_1 = function (tableToFetch) {
1071
- var referencesTables, shouldContinue, fetchTable, RestApi, nextFetchDependencies;
1072
- var _l;
1073
- return tslib.__generator(this, function (_m) {
1074
- switch (_m.label) {
1075
- case 0:
1076
- if (fetchDependencies & exports.eFetchDependencies.C6ENTITY
1077
- && 'string' === typeof tableName
1078
- && tableName.endsWith("carbon_carbons")) {
1079
- referencesTables = responseData_1.rest.reduce(function (accumulator, row) {
1080
- if ('entity_tag' in row && !accumulator.includes(row['entity_tag'])) {
1081
- accumulator.push(row['entity_tag']);
1082
- }
1083
- return accumulator;
1084
- }, []).map(function (entityTag) { return entityTag.split('\\').pop().toLowerCase(); });
1085
- shouldContinue = referencesTables.find(function (referencesTable) { return tableToFetch.endsWith(referencesTable); });
1086
- if (!shouldContinue) {
1087
- console.log('%c C6ENTITY: The constraintTableName (' + tableToFetch + ') did not end with any value in referencesTables', 'color: #c00', referencesTables);
1088
- return [2 /*return*/, "continue"];
1089
- }
1090
- console.log('%c C6ENTITY: The constraintTableName (' + tableToFetch + ') will be fetched.', 'color: #0c0');
1091
- }
1092
- return [4 /*yield*/, C6.IMPORT(tableToFetch)];
1093
- case 1:
1094
- fetchTable = _m.sent();
1095
- RestApi = fetchTable.default;
1096
- console.log('%c Fetch Dependencies will select (' + tableToFetch + ') using GET request', 'color: #33ccff');
1097
- nextFetchDependencies = exports.eFetchDependencies.NONE;
1098
- if (fetchDependencies & exports.eFetchDependencies.RECURSIVE) {
1099
- if (fetchDependencies & exports.eFetchDependencies.ALL) {
1100
- throw Error('Recursive fetch dependencies with both PARENT and CHILD reference will result in an infin1ite loop. As there is not real ending condition, this is not supported.');
1101
- }
1102
- nextFetchDependencies = fetchDependencies;
1103
- }
1104
- else if (fetchDependencies & exports.eFetchDependencies.C6ENTITY) {
1105
- if (tableToFetch === "carbon_carbons") {
1106
- nextFetchDependencies = fetchDependencies;
1107
- }
1108
- else {
1109
- nextFetchDependencies = fetchDependencies ^ exports.eFetchDependencies.C6ENTITY;
1110
- }
1111
- }
1112
- console.log('fetchReferences', fetchReferences_1[tableToFetch], "Current fetchDependencies for (" + operatingTable + "):", fetchDependencies, "New fetchDependencies for (" + tableToFetch + "): ", nextFetchDependencies);
1113
- // todo - filter out ids that exist in state?!? note - remember that this does not necessarily mean the pk, but only known is its an FK to somewhere
1114
- // it not certain that they are using carbons' entities either
1115
- // this is a dynamic call to the rest api, any generated table may resolve with (RestApi)
1116
- // todo - using value to avoid joins.... but. maybe this should be a parameterizable option -- think race conditions; its safer to join
1117
- apiRequestPromises.push(RestApi.Get((_l = {},
1118
- _l[C6.WHERE] = {
1119
- 0: Object.keys(fetchReferences_1[tableToFetch]).reduce(function (sum, column) {
1120
- fetchReferences_1[tableToFetch][column] = fetchReferences_1[tableToFetch][column].flat(Infinity);
1121
- if (0 === fetchReferences_1[tableToFetch][column].length) {
1122
- console.warn('The column (' + column + ') was not found in the response data. We will not fetch.', responseData_1);
1123
- return false;
1124
- }
1125
- sum[column] = fetchReferences_1[tableToFetch][column].length === 1
1126
- ? fetchReferences_1[tableToFetch][column][0]
1127
- : [
1128
- C6.IN, fetchReferences_1[tableToFetch][column]
1129
- ];
1130
- return sum;
1131
- }, {})
1132
- },
1133
- _l.fetchDependencies = nextFetchDependencies,
1134
- _l)));
1135
- return [2 /*return*/];
1071
+ var _h;
1072
+ if (fetchDependencies & exports.eFetchDependencies.C6ENTITY
1073
+ && 'string' === typeof tableName
1074
+ && tableName.endsWith("carbon_carbons")) {
1075
+ // todo - rethink the table ref entity system - when tables are renamed? no hooks exist in mysql
1076
+ // since were already filtering on column, we can assume the first row constraint is the same as the rest
1077
+ var referencesTables = responseData_1.rest.reduce(function (accumulator, row) {
1078
+ if ('entity_tag' in row && !accumulator.includes(row['entity_tag'])) {
1079
+ accumulator.push(row['entity_tag']);
1080
+ }
1081
+ return accumulator;
1082
+ }, []).map(function (entityTag) { return entityTag.split('\\').pop().toLowerCase(); });
1083
+ var shouldContinue = referencesTables.find(function (referencesTable) { return tableToFetch.endsWith(referencesTable); });
1084
+ if (!shouldContinue) {
1085
+ console.log('%c C6ENTITY: The constraintTableName (' + tableToFetch + ') did not end with any value in referencesTables', 'color: #c00', referencesTables);
1086
+ return "continue";
1136
1087
  }
1137
- });
1088
+ console.log('%c C6ENTITY: The constraintTableName (' + tableToFetch + ') will be fetched.', 'color: #0c0');
1089
+ }
1090
+ var RestApi = C6.ORM[tableToFetch];
1091
+ console.log('%c Fetch Dependencies will select (' + tableToFetch + ') using GET request', 'color: #33ccff');
1092
+ var nextFetchDependencies = exports.eFetchDependencies.NONE;
1093
+ if (fetchDependencies & exports.eFetchDependencies.RECURSIVE) {
1094
+ if (fetchDependencies & exports.eFetchDependencies.ALL) {
1095
+ throw Error('Recursive fetch dependencies with both PARENT and CHILD reference will result in an infin1ite loop. As there is not real ending condition, this is not supported.');
1096
+ }
1097
+ nextFetchDependencies = fetchDependencies;
1098
+ }
1099
+ else if (fetchDependencies & exports.eFetchDependencies.C6ENTITY) {
1100
+ if (tableToFetch === "carbon_carbons") {
1101
+ nextFetchDependencies = fetchDependencies;
1102
+ }
1103
+ else {
1104
+ nextFetchDependencies = fetchDependencies ^ exports.eFetchDependencies.C6ENTITY;
1105
+ }
1106
+ }
1107
+ console.log('fetchReferences', fetchReferences_1[tableToFetch], "Current fetchDependencies for (" + operatingTable + "):", fetchDependencies, "New fetchDependencies for (" + tableToFetch + "): ", nextFetchDependencies);
1108
+ // todo - filter out ids that exist in state?!? note - remember that this does not necessarily mean the pk, but only known is its an FK to somewhere
1109
+ // it not certain that they are using carbons' entities either
1110
+ // this is a dynamic call to the rest api, any generated table may resolve with (RestApi)
1111
+ // todo - using value to avoid joins.... but. maybe this should be a parameterizable option -- think race conditions; its safer to join
1112
+ apiRequestPromises.push(RestApi.Get((_h = {},
1113
+ _h[C6.WHERE] = {
1114
+ 0: Object.keys(fetchReferences_1[tableToFetch]).reduce(function (sum, column) {
1115
+ fetchReferences_1[tableToFetch][column] = fetchReferences_1[tableToFetch][column].flat(Infinity);
1116
+ if (0 === fetchReferences_1[tableToFetch][column].length) {
1117
+ console.warn('The column (' + column + ') was not found in the response data. We will not fetch.', responseData_1);
1118
+ return false;
1119
+ }
1120
+ sum[column] = fetchReferences_1[tableToFetch][column].length === 1
1121
+ ? fetchReferences_1[tableToFetch][column][0]
1122
+ : [
1123
+ C6.IN, fetchReferences_1[tableToFetch][column]
1124
+ ];
1125
+ return sum;
1126
+ }, {})
1127
+ },
1128
+ _h.fetchDependencies = nextFetchDependencies,
1129
+ _h)));
1138
1130
  };
1139
- _a = fetchReferences_1;
1140
- _b = [];
1141
- for (_c in _a)
1142
- _b.push(_c);
1143
- _i = 0;
1144
- _k.label = 1;
1145
- case 1:
1146
- if (!(_i < _b.length)) return [3 /*break*/, 4];
1147
- _c = _b[_i];
1148
- if (!(_c in _a)) return [3 /*break*/, 3];
1149
- tableToFetch = _c;
1150
- return [5 /*yield**/, _loop_1(tableToFetch)];
1151
- case 2:
1152
- _k.sent();
1153
- _k.label = 3;
1154
- case 3:
1155
- _i++;
1156
- return [3 /*break*/, 1];
1157
- case 4:
1131
+ for (tableToFetch in fetchReferences_1) {
1132
+ _loop_1(tableToFetch);
1133
+ }
1158
1134
  console.groupEnd();
1159
1135
  return [4 /*yield*/, Promise.all(apiRequestPromises)];
1160
- case 5:
1161
- _k.sent();
1136
+ case 1:
1137
+ _g.sent();
1162
1138
  apiRequestPromises.map(function (promise) { return tslib.__awaiter(_this, void 0, void 0, function () {
1163
1139
  var _a, _b;
1164
1140
  return tslib.__generator(this, function (_c) {
@@ -1176,8 +1152,8 @@ var HttpExecutor = /** @class */ (function (_super) {
1176
1152
  }
1177
1153
  });
1178
1154
  }); });
1179
- _k.label = 6;
1180
- case 6:
1155
+ _g.label = 2;
1156
+ case 2:
1181
1157
  if (debug && isLocal()) {
1182
1158
  reactToastify.toast.success("DEVS: (" + requestMethod + ") request complete.", toastOptionsDevs);
1183
1159
  }
@@ -1279,7 +1255,16 @@ var ConditionBuilder = /** @class */ (function (_super) {
1279
1255
  C6C.IS, C6C.IS_NOT,
1280
1256
  C6C.BETWEEN, 'NOT BETWEEN',
1281
1257
  C6C.MATCH_AGAINST,
1282
- C6C.ST_DISTANCE_SPHERE
1258
+ C6C.ST_DISTANCE_SPHERE,
1259
+ // spatial predicates
1260
+ C6C.ST_CONTAINS,
1261
+ C6C.ST_INTERSECTS,
1262
+ C6C.ST_WITHIN,
1263
+ C6C.ST_CROSSES,
1264
+ C6C.ST_DISJOINT,
1265
+ C6C.ST_EQUALS,
1266
+ C6C.ST_OVERLAPS,
1267
+ C6C.ST_TOUCHES
1283
1268
  ]);
1284
1269
  return _this;
1285
1270
  }
@@ -1361,6 +1346,19 @@ var ConditionBuilder = /** @class */ (function (_super) {
1361
1346
  var threshold = Array.isArray(value) ? value[0] : value;
1362
1347
  return "ST_Distance_Sphere(".concat(col1, ", ").concat(col2, ") < ").concat(_this.addParam(params, '', threshold));
1363
1348
  }
1349
+ if ([
1350
+ C6C.ST_CONTAINS,
1351
+ C6C.ST_INTERSECTS,
1352
+ C6C.ST_WITHIN,
1353
+ C6C.ST_CROSSES,
1354
+ C6C.ST_DISJOINT,
1355
+ C6C.ST_EQUALS,
1356
+ C6C.ST_OVERLAPS,
1357
+ C6C.ST_TOUCHES
1358
+ ].includes(column)) {
1359
+ var geom1 = op[0], geom2 = op[1];
1360
+ return "".concat(column, "(").concat(geom1, ", ").concat(geom2, ")");
1361
+ }
1364
1362
  }
1365
1363
  var leftIsCol = _this.isColumnRef(column);
1366
1364
  var leftIsRef = _this.isTableReference(column);
@@ -1925,7 +1923,7 @@ function ExpressHandler(_a) {
1925
1923
  payload[C6C.WHERE][primaryKeyName] = primary;
1926
1924
  }
1927
1925
  else {
1928
- res.status(400).json({ error: "Invalid request: ".concat(method, " requires a primary key.") });
1926
+ res.status(400).json({ error: "Invalid request: ".concat(method, " requires a primary key (").concat(primaryKeyName, ").") });
1929
1927
  }
1930
1928
  break;
1931
1929
  case 'POST':
@@ -1974,6 +1972,10 @@ var fieldEq = function (leftCol, rightCol, leftAlias, rightAlias) {
1974
1972
  var distSphere = function (fromCol, toCol, fromAlias, toAlias) {
1975
1973
  return [C6C.ST_DISTANCE_SPHERE, F(fromCol, fromAlias), F(toCol, toAlias)];
1976
1974
  };
1975
+ // ST_Contains for map envelope/shape queries
1976
+ var stContains = function (envelope, shape) {
1977
+ return [C6C.ST_CONTAINS, envelope, shape];
1978
+ };
1977
1979
 
1978
1980
  function determineRuntimeJsType(mysqlType) {
1979
1981
  var base = mysqlType.toLowerCase().split('(')[0];
@@ -2120,6 +2122,7 @@ exports.removePrefixIfExists = removePrefixIfExists;
2120
2122
  exports.restOrm = restOrm;
2121
2123
  exports.restRequest = restRequest;
2122
2124
  exports.sortAndSerializeQueryObject = sortAndSerializeQueryObject;
2125
+ exports.stContains = stContains;
2123
2126
  exports.timeout = timeout;
2124
2127
  exports.toastOptions = toastOptions;
2125
2128
  exports.toastOptionsDevs = toastOptionsDevs;