@carbonorm/carbonnode 3.5.7 → 3.5.8
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/dist/index.cjs.js +1006 -1222
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +1008 -1224
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/api/convertForRequestBody.ts +23 -1
- package/src/api/executors/HttpExecutor.ts +3 -1
package/dist/index.esm.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
2
|
import Qs from 'qs';
|
|
3
|
-
import { __assign, __awaiter, __generator, __extends, __spreadArray } from 'tslib';
|
|
4
3
|
import { toast } from 'react-toastify';
|
|
5
4
|
import namedPlaceholders from 'named-placeholders';
|
|
6
5
|
import { Buffer as Buffer$1 } from 'buffer';
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
const C6Constants = {
|
|
9
8
|
// try to 1=1 match the Rest abstract class
|
|
10
9
|
ADDDATE: 'ADDDATE',
|
|
11
10
|
ADDTIME: 'ADDTIME',
|
|
@@ -163,7 +162,7 @@ var C6Constants = {
|
|
|
163
162
|
FINISH: 'FINISH',
|
|
164
163
|
VALIDATE_C6_ENTITY_ID_REGEX: '#^([a-fA-F0-9]{20,35})$#',
|
|
165
164
|
};
|
|
166
|
-
|
|
165
|
+
const C6C = C6Constants;
|
|
167
166
|
|
|
168
167
|
// @link https://www.npmjs.com/package/axios-cache-adapter
|
|
169
168
|
// updating these values
|
|
@@ -268,22 +267,20 @@ var axiosInstance = (axios.create({
|
|
|
268
267
|
*/
|
|
269
268
|
}));
|
|
270
269
|
|
|
271
|
-
function convertForRequestBody (restfulObject, tableName, C6, regexErrorHandler) {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
var tableDefinition = Object.values(C6.TABLES).find(function (t) { return t.TABLE_NAME === name; });
|
|
270
|
+
function convertForRequestBody (restfulObject, tableName, C6, regexErrorHandler = alert) {
|
|
271
|
+
const payload = {};
|
|
272
|
+
const tableNames = Array.isArray(tableName) ? tableName : [tableName];
|
|
273
|
+
const tableDefinitions = tableNames.map((name) => {
|
|
274
|
+
const tableDefinition = Object.values(C6.TABLES).find((t) => t.TABLE_NAME === name);
|
|
277
275
|
if (!tableDefinition) {
|
|
278
|
-
console.error(
|
|
279
|
-
throw new Error(
|
|
276
|
+
console.error(`Table name (${name}) is not found in the C6.TABLES object.`, C6.TABLES);
|
|
277
|
+
throw new Error(`Table name (${name}) is not found in the C6.TABLES object.`);
|
|
280
278
|
}
|
|
281
279
|
return tableDefinition;
|
|
282
280
|
});
|
|
283
|
-
for (
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
var shortReference = value.toUpperCase();
|
|
281
|
+
for (const tableDefinition of tableDefinitions) {
|
|
282
|
+
for (const value of Object.keys(restfulObject)) {
|
|
283
|
+
const shortReference = value.toUpperCase();
|
|
287
284
|
if ([
|
|
288
285
|
C6Constants.GET,
|
|
289
286
|
C6Constants.POST,
|
|
@@ -294,61 +291,72 @@ function convertForRequestBody (restfulObject, tableName, C6, regexErrorHandler)
|
|
|
294
291
|
C6Constants.JOIN,
|
|
295
292
|
C6Constants.PAGINATION
|
|
296
293
|
].includes(value)) {
|
|
297
|
-
|
|
298
|
-
if (Array.isArray(
|
|
299
|
-
payload[value] =
|
|
294
|
+
const val = restfulObject[value];
|
|
295
|
+
if (Array.isArray(val)) {
|
|
296
|
+
payload[value] = val.sort();
|
|
300
297
|
}
|
|
301
|
-
else if (typeof
|
|
302
|
-
payload[value] = Object.keys(
|
|
298
|
+
else if (typeof val === 'object' && val !== null) {
|
|
299
|
+
payload[value] = Object.keys(val)
|
|
303
300
|
.sort()
|
|
304
|
-
.reduce(
|
|
305
|
-
var _a;
|
|
306
|
-
return (__assign(__assign({}, acc), (_a = {}, _a[key] = val_1[key], _a)));
|
|
307
|
-
}, {});
|
|
301
|
+
.reduce((acc, key) => ({ ...acc, [key]: val[key] }), {});
|
|
308
302
|
}
|
|
309
|
-
|
|
303
|
+
continue;
|
|
310
304
|
}
|
|
311
305
|
if (shortReference in tableDefinition) {
|
|
312
|
-
|
|
313
|
-
|
|
306
|
+
const longName = tableDefinition[shortReference];
|
|
307
|
+
const columnValue = restfulObject[value];
|
|
314
308
|
payload[longName] = columnValue;
|
|
315
|
-
|
|
309
|
+
const regexValidations = tableDefinition.REGEX_VALIDATION[longName];
|
|
316
310
|
if (regexValidations instanceof RegExp) {
|
|
317
311
|
if (!regexValidations.test(columnValue)) {
|
|
318
|
-
regexErrorHandler(
|
|
319
|
-
throw new Error(
|
|
312
|
+
regexErrorHandler(`Failed to match regex (${regexValidations}) for column (${longName})`);
|
|
313
|
+
throw new Error(`Failed to match regex (${regexValidations}) for column (${longName})`);
|
|
320
314
|
}
|
|
321
315
|
}
|
|
322
316
|
else if (typeof regexValidations === 'object' && regexValidations !== null) {
|
|
323
|
-
for (
|
|
324
|
-
|
|
317
|
+
for (const errorMessage in regexValidations) {
|
|
318
|
+
const regex = regexValidations[errorMessage];
|
|
325
319
|
if (!regex.test(columnValue)) {
|
|
326
|
-
|
|
320
|
+
const devErrorMessage = `Failed to match regex (${regex}) for column (${longName})`;
|
|
321
|
+
regexErrorHandler(errorMessage || devErrorMessage);
|
|
322
|
+
throw new Error(devErrorMessage);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
else if (Object.values(tableDefinition.COLUMNS).includes(value)) {
|
|
328
|
+
// Already a fully qualified column name
|
|
329
|
+
const columnValue = restfulObject[value];
|
|
330
|
+
payload[value] = columnValue;
|
|
331
|
+
const regexValidations = tableDefinition.REGEX_VALIDATION[value];
|
|
332
|
+
if (regexValidations instanceof RegExp) {
|
|
333
|
+
if (!regexValidations.test(columnValue)) {
|
|
334
|
+
regexErrorHandler(`Failed to match regex (${regexValidations}) for column (${value})`);
|
|
335
|
+
throw new Error(`Failed to match regex (${regexValidations}) for column (${value})`);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
else if (typeof regexValidations === 'object' && regexValidations !== null) {
|
|
339
|
+
for (const errorMessage in regexValidations) {
|
|
340
|
+
const regex = regexValidations[errorMessage];
|
|
341
|
+
if (!regex.test(columnValue)) {
|
|
342
|
+
const devErrorMessage = `Failed to match regex (${regex}) for column (${value})`;
|
|
327
343
|
regexErrorHandler(errorMessage || devErrorMessage);
|
|
328
344
|
throw new Error(devErrorMessage);
|
|
329
345
|
}
|
|
330
346
|
}
|
|
331
347
|
}
|
|
332
348
|
}
|
|
333
|
-
};
|
|
334
|
-
for (var _a = 0, _b = Object.keys(restfulObject); _a < _b.length; _a++) {
|
|
335
|
-
var value = _b[_a];
|
|
336
|
-
_loop_1(value);
|
|
337
349
|
}
|
|
338
350
|
}
|
|
339
351
|
return Object.keys(payload)
|
|
340
352
|
.sort()
|
|
341
|
-
.reduce(
|
|
342
|
-
var _a;
|
|
343
|
-
return (__assign(__assign({}, acc), (_a = {}, _a[key] = payload[key], _a)));
|
|
344
|
-
}, {});
|
|
353
|
+
.reduce((acc, key) => ({ ...acc, [key]: payload[key] }), {});
|
|
345
354
|
}
|
|
346
355
|
|
|
347
|
-
|
|
348
|
-
var _a;
|
|
356
|
+
const isNode = () => {
|
|
349
357
|
console.log('Checking if running in Node.js environment...');
|
|
350
|
-
|
|
351
|
-
console.log(
|
|
358
|
+
const isNodeEnv = typeof process !== 'undefined' && !!process.versions?.node;
|
|
359
|
+
console.log(`Is Node.js environment: ${isNodeEnv}`);
|
|
352
360
|
return isNodeEnv;
|
|
353
361
|
};
|
|
354
362
|
|
|
@@ -356,112 +364,94 @@ var isNode = function () {
|
|
|
356
364
|
* Facade: routes API calls to SQL or HTTP executors based on runtime context.
|
|
357
365
|
*/
|
|
358
366
|
function restRequest(configX) {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
return [2 /*return*/, executor.execute()];
|
|
374
|
-
case 2: return [4 /*yield*/, Promise.resolve().then(function () { return HttpExecutor$1; })];
|
|
375
|
-
case 3:
|
|
376
|
-
HttpExecutor = (_b.sent()).HttpExecutor;
|
|
377
|
-
http = new HttpExecutor(config, request);
|
|
378
|
-
return [2 /*return*/, http.execute()];
|
|
379
|
-
}
|
|
380
|
-
});
|
|
381
|
-
}); };
|
|
367
|
+
return async (request) => {
|
|
368
|
+
const config = typeof configX === "function" ? configX() : configX;
|
|
369
|
+
config.verbose ??= true; // Default to verbose logging if not set
|
|
370
|
+
// SQL path if on Node with a provided pool
|
|
371
|
+
if (isNode() && config.mysqlPool) {
|
|
372
|
+
const { SqlExecutor } = await Promise.resolve().then(function () { return SqlExecutor$1; });
|
|
373
|
+
const executor = new SqlExecutor(config, request);
|
|
374
|
+
return executor.execute();
|
|
375
|
+
}
|
|
376
|
+
// HTTP path fallback
|
|
377
|
+
const { HttpExecutor } = await Promise.resolve().then(function () { return HttpExecutor$1; });
|
|
378
|
+
const http = new HttpExecutor(config, request);
|
|
379
|
+
return http.execute();
|
|
380
|
+
};
|
|
382
381
|
}
|
|
383
382
|
|
|
384
383
|
function restOrm(configFn) {
|
|
385
384
|
return {
|
|
386
|
-
Get: restRequest(
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
385
|
+
Get: restRequest(() => ({
|
|
386
|
+
...configFn(),
|
|
387
|
+
requestMethod: "GET"
|
|
388
|
+
})),
|
|
389
|
+
Put: restRequest(() => ({
|
|
390
|
+
...configFn(),
|
|
391
|
+
requestMethod: "PUT"
|
|
392
|
+
})),
|
|
393
|
+
Post: restRequest(() => ({
|
|
394
|
+
...configFn(),
|
|
395
|
+
requestMethod: "POST"
|
|
396
|
+
})),
|
|
397
|
+
Delete: restRequest(() => ({
|
|
398
|
+
...configFn(),
|
|
399
|
+
requestMethod: "DELETE"
|
|
400
|
+
}))
|
|
390
401
|
};
|
|
391
402
|
}
|
|
392
403
|
|
|
393
|
-
function timeout(shouldContinueAfterTimeout, cb, timeoutMs) {
|
|
394
|
-
|
|
395
|
-
var timer = function () { return setTimeout(function () {
|
|
404
|
+
function timeout(shouldContinueAfterTimeout, cb, timeoutMs = 3000) {
|
|
405
|
+
const timer = () => setTimeout(() => {
|
|
396
406
|
if (false === shouldContinueAfterTimeout()) {
|
|
397
407
|
return;
|
|
398
408
|
}
|
|
399
409
|
cb();
|
|
400
|
-
}, timeoutMs);
|
|
401
|
-
|
|
402
|
-
return
|
|
410
|
+
}, timeoutMs);
|
|
411
|
+
const timerId = timer();
|
|
412
|
+
return () => {
|
|
403
413
|
clearTimeout(timerId);
|
|
404
414
|
};
|
|
405
415
|
}
|
|
406
416
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
417
|
+
class Executor {
|
|
418
|
+
config;
|
|
419
|
+
request;
|
|
420
|
+
useNamedParams;
|
|
421
|
+
constructor(config, request, useNamedParams = false) {
|
|
410
422
|
this.config = config;
|
|
411
423
|
this.request = request;
|
|
412
424
|
this.useNamedParams = useNamedParams;
|
|
413
425
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
_b = _a[_i], key = _b[0], fn = _b[1];
|
|
429
|
-
if (!(typeof fn === "function")) return [3 /*break*/, 5];
|
|
430
|
-
if (this.config.verbose || args.request.debug) {
|
|
431
|
-
console.groupCollapsed("[LIFECYCLE] ".concat(this.config.requestMethod, ".").concat(String(phase), ":").concat(key));
|
|
432
|
-
console.log("config:", args.config);
|
|
433
|
-
console.log("request:", args.request);
|
|
434
|
-
if ("response" in args) {
|
|
435
|
-
console.log("response:", args.response);
|
|
436
|
-
}
|
|
437
|
-
console.groupEnd();
|
|
438
|
-
}
|
|
439
|
-
_d.label = 2;
|
|
440
|
-
case 2:
|
|
441
|
-
_d.trys.push([2, 4, , 5]);
|
|
442
|
-
// todo - this
|
|
443
|
-
return [4 /*yield*/, fn(args)];
|
|
444
|
-
case 3:
|
|
445
|
-
// todo - this
|
|
446
|
-
_d.sent();
|
|
447
|
-
return [3 /*break*/, 5];
|
|
448
|
-
case 4:
|
|
449
|
-
err_1 = _d.sent();
|
|
450
|
-
console.error("[LIFECYCLE ERROR] ".concat(this.config.requestMethod, ".").concat(String(phase), ":").concat(key), err_1);
|
|
451
|
-
throw err_1;
|
|
452
|
-
case 5:
|
|
453
|
-
_i++;
|
|
454
|
-
return [3 /*break*/, 1];
|
|
455
|
-
case 6: return [2 /*return*/];
|
|
426
|
+
async runLifecycleHooks(phase, args) {
|
|
427
|
+
const lifecycleGroup = this.config.restModel.LIFECYCLE_HOOKS[this.config.requestMethod]?.[phase];
|
|
428
|
+
if (!lifecycleGroup)
|
|
429
|
+
return;
|
|
430
|
+
for (const [key, fn] of Object.entries(lifecycleGroup)) {
|
|
431
|
+
if (typeof fn === "function") {
|
|
432
|
+
if (this.config.verbose || args.request.debug) {
|
|
433
|
+
console.groupCollapsed(`[LIFECYCLE] ${this.config.requestMethod}.${String(phase)}:${key}`);
|
|
434
|
+
console.log("config:", args.config);
|
|
435
|
+
console.log("request:", args.request);
|
|
436
|
+
if ("response" in args) {
|
|
437
|
+
console.log("response:", args.response);
|
|
438
|
+
}
|
|
439
|
+
console.groupEnd();
|
|
456
440
|
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
441
|
+
try {
|
|
442
|
+
// todo - this
|
|
443
|
+
await fn(args);
|
|
444
|
+
}
|
|
445
|
+
catch (err) {
|
|
446
|
+
console.error(`[LIFECYCLE ERROR] ${this.config.requestMethod}.${String(phase)}:${key}`, err);
|
|
447
|
+
throw err;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
462
453
|
|
|
463
|
-
function getEnvVar(key, fallback) {
|
|
464
|
-
if (fallback === void 0) { fallback = ''; }
|
|
454
|
+
function getEnvVar(key, fallback = '') {
|
|
465
455
|
// Vite-style injection
|
|
466
456
|
// @ts-ignore
|
|
467
457
|
if (typeof import.meta !== 'undefined' && import.meta.env && key in import.meta.env) {
|
|
@@ -498,12 +488,12 @@ var eFetchDependencies;
|
|
|
498
488
|
})(eFetchDependencies || (eFetchDependencies = {}));
|
|
499
489
|
|
|
500
490
|
// Refined TypeScript types for CarbonORM
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
491
|
+
const POST = 'POST';
|
|
492
|
+
const PUT = 'PUT';
|
|
493
|
+
const GET = 'GET';
|
|
494
|
+
const DELETE = 'DELETE';
|
|
505
495
|
|
|
506
|
-
|
|
496
|
+
const toastOptions = {
|
|
507
497
|
position: "bottom-left",
|
|
508
498
|
autoClose: 10000,
|
|
509
499
|
hideProgressBar: false,
|
|
@@ -512,7 +502,7 @@ var toastOptions = {
|
|
|
512
502
|
draggable: true,
|
|
513
503
|
theme: "dark",
|
|
514
504
|
};
|
|
515
|
-
|
|
505
|
+
const toastOptionsDevs = {
|
|
516
506
|
position: "bottom-right",
|
|
517
507
|
autoClose: 3000,
|
|
518
508
|
hideProgressBar: false,
|
|
@@ -524,20 +514,19 @@ var toastOptionsDevs = {
|
|
|
524
514
|
|
|
525
515
|
// When we capture DropExceptions and display them as a custom page, this will change.
|
|
526
516
|
function TestRestfulResponse(response, success, error) {
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|| undefined !==
|
|
531
|
-
|| undefined !==
|
|
532
|
-
|
|
533
|
-
var successReturn = 'function' === typeof success ? success === null || success === void 0 ? void 0 : success(response) : success;
|
|
517
|
+
if (undefined === response.data?.['ERROR TYPE']
|
|
518
|
+
&& (undefined !== response?.data?.rest
|
|
519
|
+
|| undefined !== response.data?.created
|
|
520
|
+
|| undefined !== response.data?.updated
|
|
521
|
+
|| undefined !== response.data?.deleted)) {
|
|
522
|
+
let successReturn = 'function' === typeof success ? success?.(response) : success;
|
|
534
523
|
if (typeof successReturn === 'string') {
|
|
535
524
|
toast.success(successReturn, toastOptions);
|
|
536
525
|
}
|
|
537
526
|
// this could end up with bad results for deleting id's === 0
|
|
538
|
-
return
|
|
527
|
+
return response.data.created ?? response.data.updated ?? response.data.deleted ?? true;
|
|
539
528
|
}
|
|
540
|
-
|
|
529
|
+
let errorReturn = 'function' === typeof error ? error?.(response) : error;
|
|
541
530
|
if (typeof errorReturn === 'string') {
|
|
542
531
|
toast.error(errorReturn, toastOptions);
|
|
543
532
|
}
|
|
@@ -550,15 +539,15 @@ function removePrefixIfExists(tableName, prefix) {
|
|
|
550
539
|
return tableName;
|
|
551
540
|
}
|
|
552
541
|
function removeInvalidKeys(request, c6Tables) {
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
tableList.forEach(
|
|
542
|
+
let intersection = {};
|
|
543
|
+
let restfulObjectKeys = [];
|
|
544
|
+
const tableList = Object.values(c6Tables);
|
|
545
|
+
tableList.forEach(table => Object.values(table.COLUMNS).forEach(column => {
|
|
557
546
|
if (false === restfulObjectKeys.includes(column)) {
|
|
558
547
|
restfulObjectKeys.push(column);
|
|
559
548
|
}
|
|
560
|
-
})
|
|
561
|
-
Object.keys(request).forEach(
|
|
549
|
+
}));
|
|
550
|
+
Object.keys(request).forEach(key => {
|
|
562
551
|
if (restfulObjectKeys.includes(key)) {
|
|
563
552
|
intersection[key] = request[key];
|
|
564
553
|
}
|
|
@@ -569,13 +558,13 @@ function removeInvalidKeys(request, c6Tables) {
|
|
|
569
558
|
|
|
570
559
|
// do not remove entries from this array. It is used to track the progress of API requests.
|
|
571
560
|
// position in array is important. Do not sort. To not add to begging.
|
|
572
|
-
|
|
573
|
-
|
|
561
|
+
let apiRequestCache = [];
|
|
562
|
+
let userCustomClearCache = [];
|
|
574
563
|
function clearCache(props) {
|
|
575
|
-
if (false ===
|
|
564
|
+
if (false === props?.ignoreWarning) {
|
|
576
565
|
console.warn('The rest api clearCache should only be used with extreme care! Avoid using this in favor of using `cacheResults : boolean`.');
|
|
577
566
|
}
|
|
578
|
-
userCustomClearCache.map(
|
|
567
|
+
userCustomClearCache.map((f) => 'function' === typeof f && f());
|
|
579
568
|
userCustomClearCache = apiRequestCache = [];
|
|
580
569
|
}
|
|
581
570
|
function checkCache(cacheResult, requestMethod, tableName, request) {
|
|
@@ -590,601 +579,551 @@ function checkCache(cacheResult, requestMethod, tableName, request) {
|
|
|
590
579
|
}
|
|
591
580
|
|
|
592
581
|
function sortAndSerializeQueryObject(tables, query) {
|
|
593
|
-
|
|
582
|
+
const orderedQuery = Object.keys(query).sort().reduce((obj, key) => {
|
|
594
583
|
obj[key] = query[key];
|
|
595
584
|
return obj;
|
|
596
585
|
}, {});
|
|
597
586
|
return tables + ' ' + JSON.stringify(orderedQuery);
|
|
598
587
|
}
|
|
599
588
|
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
}
|
|
605
|
-
HttpExecutor.prototype.putState = function (response, request, callback) {
|
|
606
|
-
var _a, _b;
|
|
607
|
-
(_a = this.config.reactBootstrap) === null || _a === void 0 ? void 0 : _a.updateRestfulObjectArrays({
|
|
608
|
-
callback: callback,
|
|
589
|
+
class HttpExecutor extends Executor {
|
|
590
|
+
putState(response, request, callback) {
|
|
591
|
+
this.config.reactBootstrap?.updateRestfulObjectArrays({
|
|
592
|
+
callback,
|
|
609
593
|
dataOrCallback: [
|
|
610
|
-
removeInvalidKeys(
|
|
594
|
+
removeInvalidKeys({
|
|
595
|
+
...request,
|
|
596
|
+
...response?.data?.rest,
|
|
597
|
+
}, this.config.C6.TABLES)
|
|
611
598
|
],
|
|
612
599
|
stateKey: this.config.restModel.TABLE_NAME,
|
|
613
600
|
uniqueObjectId: this.config.restModel.PRIMARY_SHORT
|
|
614
601
|
});
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
var _this = this;
|
|
618
|
-
var _a, _b, _c;
|
|
602
|
+
}
|
|
603
|
+
postState(response, request, callback) {
|
|
619
604
|
if (1 !== this.config.restModel.PRIMARY_SHORT.length) {
|
|
620
605
|
console.error("C6 received unexpected result's given the primary key length");
|
|
621
606
|
}
|
|
622
607
|
else {
|
|
623
|
-
|
|
608
|
+
const pk = this.config.restModel.PRIMARY_SHORT[0];
|
|
624
609
|
// TODO - should overrides be handled differently? Why override: (react/php), driver missmatches, aux data..
|
|
625
610
|
// @ts-ignore - this is technically a correct error, but we allow it anyway...
|
|
626
|
-
request[pk] =
|
|
611
|
+
request[pk] = response.data?.created;
|
|
627
612
|
}
|
|
628
|
-
|
|
629
|
-
callback
|
|
613
|
+
this.config.reactBootstrap?.updateRestfulObjectArrays({
|
|
614
|
+
callback,
|
|
630
615
|
dataOrCallback: undefined !== request.dataInsertMultipleRows
|
|
631
|
-
? request.dataInsertMultipleRows.map(
|
|
632
|
-
|
|
633
|
-
|
|
616
|
+
? request.dataInsertMultipleRows.map((request, index) => {
|
|
617
|
+
return removeInvalidKeys({
|
|
618
|
+
...request,
|
|
619
|
+
...(index === 0 ? response?.data?.rest : {}),
|
|
620
|
+
}, this.config.C6.TABLES);
|
|
634
621
|
})
|
|
635
622
|
: [
|
|
636
|
-
removeInvalidKeys(
|
|
623
|
+
removeInvalidKeys({
|
|
624
|
+
...request,
|
|
625
|
+
...response?.data?.rest,
|
|
626
|
+
}, this.config.C6.TABLES)
|
|
637
627
|
],
|
|
638
628
|
stateKey: this.config.restModel.TABLE_NAME,
|
|
639
629
|
uniqueObjectId: this.config.restModel.PRIMARY_SHORT
|
|
640
630
|
});
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
callback: callback,
|
|
631
|
+
}
|
|
632
|
+
deleteState(_response, request, callback) {
|
|
633
|
+
this.config.reactBootstrap?.deleteRestfulObjectArrays({
|
|
634
|
+
callback,
|
|
646
635
|
dataOrCallback: [
|
|
647
636
|
request,
|
|
648
637
|
],
|
|
649
638
|
stateKey: this.config.restModel.TABLE_NAME,
|
|
650
639
|
uniqueObjectId: this.config.restModel.PRIMARY_SHORT
|
|
651
640
|
});
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
641
|
+
}
|
|
642
|
+
async execute() {
|
|
643
|
+
const { C6, axios, restURL, withCredentials, restModel, reactBootstrap, requestMethod, skipPrimaryCheck, clearCache, } = this.config;
|
|
644
|
+
console.log('this.config', this.config);
|
|
645
|
+
await this.runLifecycleHooks("beforeProcessing", {
|
|
646
|
+
config: this.config,
|
|
647
|
+
request: this.request,
|
|
648
|
+
});
|
|
649
|
+
const tableName = restModel.TABLE_NAME;
|
|
650
|
+
const fullTableList = Array.isArray(tableName) ? tableName : [tableName];
|
|
651
|
+
const operatingTableFullName = fullTableList[0];
|
|
652
|
+
const operatingTable = removePrefixIfExists(operatingTableFullName, C6.PREFIX);
|
|
653
|
+
const tables = fullTableList.join(',');
|
|
654
|
+
switch (requestMethod) {
|
|
655
|
+
case GET:
|
|
656
|
+
case POST:
|
|
657
|
+
case PUT:
|
|
658
|
+
case DELETE:
|
|
659
|
+
break;
|
|
660
|
+
default:
|
|
661
|
+
throw Error('Bad request method passed to getApi');
|
|
662
|
+
}
|
|
663
|
+
if (null !== clearCache || undefined !== clearCache) {
|
|
664
|
+
userCustomClearCache[tables + requestMethod] = clearCache;
|
|
665
|
+
}
|
|
666
|
+
console.groupCollapsed('%c API: (' + requestMethod + ') Request for (' + tableName + ')', 'color: #0c0');
|
|
667
|
+
console.log('request', this.request);
|
|
668
|
+
console.groupEnd();
|
|
669
|
+
// an undefined query would indicate queryCallback returned undefined,
|
|
670
|
+
// thus the request shouldn't fire as is in custom cache
|
|
671
|
+
if (undefined === this.request || null === this.request) {
|
|
672
|
+
console.groupCollapsed('%c API: (' + requestMethod + ') Request Query for (' + tableName + ') undefined, returning null (will not fire)!', 'color: #c00');
|
|
673
|
+
console.log('request', this.request);
|
|
674
|
+
console.log('%c Returning (undefined|null) for a query would indicate a custom cache hit (outside API.tsx), thus the request should not fire.', 'color: #c00');
|
|
675
|
+
console.trace();
|
|
676
|
+
console.groupEnd();
|
|
677
|
+
return null;
|
|
678
|
+
}
|
|
679
|
+
let query = this.request;
|
|
680
|
+
if (C6.GET === requestMethod) {
|
|
681
|
+
if (undefined === query[C6.PAGINATION]) {
|
|
682
|
+
query[C6.PAGINATION] = {};
|
|
683
|
+
}
|
|
684
|
+
query[C6.PAGINATION][C6.PAGE] = query[C6.PAGINATION][C6.PAGE] || 1;
|
|
685
|
+
query[C6.PAGINATION][C6.LIMIT] = query[C6.PAGINATION][C6.LIMIT] || 100;
|
|
686
|
+
}
|
|
687
|
+
// this is parameterless and could return itself with a new page number, or undefined if the end is reached
|
|
688
|
+
const apiRequest = async () => {
|
|
689
|
+
const { debug, cacheResults = (C6.GET === requestMethod), dataInsertMultipleRows, success, fetchDependencies = eFetchDependencies.NONE, error = "An unexpected API error occurred!" } = this.request;
|
|
690
|
+
if (C6.GET === requestMethod
|
|
691
|
+
&& undefined !== query?.[C6.PAGINATION]?.[C6.PAGE]
|
|
692
|
+
&& 1 !== query[C6.PAGINATION][C6.PAGE]) {
|
|
693
|
+
console.groupCollapsed('Request on table (' + tableName + ') is firing for page (' + query[C6.PAGINATION][C6.PAGE] + '), please wait!');
|
|
694
|
+
console.log('Request Data (note you may see the success and/or error prompt):', this.request);
|
|
695
|
+
console.trace();
|
|
696
|
+
console.groupEnd();
|
|
697
|
+
}
|
|
698
|
+
// The problem with creating cache keys with a stringified object is the order of keys matters and it's possible for the same query to be stringified differently.
|
|
699
|
+
// Here we ensure the key order will be identical between two of the same requests. https://stackoverflow.com/questions/5467129/sort-javascript-object-by-key
|
|
700
|
+
// literally impossible for query to be undefined or null here but the editor is too busy licking windows to understand that
|
|
701
|
+
let querySerialized = sortAndSerializeQueryObject(tables, query ?? {});
|
|
702
|
+
let cacheResult = apiRequestCache.find(cache => cache.requestArgumentsSerialized === querySerialized);
|
|
703
|
+
let cachingConfirmed = false;
|
|
704
|
+
// determine if we need to paginate.
|
|
705
|
+
if (requestMethod === C6.GET) {
|
|
706
|
+
if (undefined === query?.[C6.PAGINATION]) {
|
|
707
|
+
if (undefined === query || null === query) {
|
|
708
|
+
query = {};
|
|
709
|
+
}
|
|
710
|
+
query[C6.PAGINATION] = {};
|
|
711
|
+
}
|
|
712
|
+
query[C6.PAGINATION][C6.PAGE] = query[C6.PAGINATION][C6.PAGE] || 1;
|
|
713
|
+
query[C6.PAGINATION][C6.LIMIT] = query[C6.PAGINATION][C6.LIMIT] || 100;
|
|
714
|
+
// this will evaluate true most the time
|
|
715
|
+
if (true === cacheResults) {
|
|
716
|
+
// just find the next, non-fetched, page and return a function to request it
|
|
717
|
+
if (undefined !== cacheResult) { // we will return in this loop
|
|
718
|
+
do {
|
|
719
|
+
const cacheCheck = checkCache(cacheResult, requestMethod, tableName, this.request);
|
|
720
|
+
if (false !== cacheCheck) {
|
|
721
|
+
return (await cacheCheck).data;
|
|
722
|
+
}
|
|
723
|
+
// this line incrementing page is why we return recursively
|
|
724
|
+
++query[C6.PAGINATION][C6.PAGE];
|
|
725
|
+
// this json stringify is to capture the new page number
|
|
726
|
+
querySerialized = sortAndSerializeQueryObject(tables, query ?? {});
|
|
727
|
+
cacheResult = apiRequestCache.find(cache => cache.requestArgumentsSerialized === querySerialized);
|
|
728
|
+
} while (undefined !== cacheResult);
|
|
729
|
+
if (debug && isLocal()) {
|
|
730
|
+
toast.warning("DEVS: Request in cache. (" + apiRequestCache.findIndex(cache => cache.requestArgumentsSerialized === querySerialized) + "). Returning function to request page (" + query[C6.PAGINATION][C6.PAGE] + ")", toastOptionsDevs);
|
|
731
|
+
}
|
|
732
|
+
// @ts-ignore - this is an incorrect warning on TS, it's well typed
|
|
733
|
+
return apiRequest;
|
|
734
|
+
}
|
|
735
|
+
cachingConfirmed = true;
|
|
736
|
+
}
|
|
737
|
+
else {
|
|
738
|
+
if (debug && isLocal()) {
|
|
739
|
+
toast.info("DEVS: Ignore cache was set to true.", toastOptionsDevs);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
if (debug && isLocal()) {
|
|
743
|
+
toast.success("DEVS: Request not in cache." + (requestMethod === C6.GET ? "Page (" + query[C6.PAGINATION][C6.PAGE] + ")." : '') + " Logging cache 2 console.", toastOptionsDevs);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
else if (cacheResults) { // if we are not getting, we are updating, deleting, or inserting
|
|
747
|
+
if (cacheResult) {
|
|
748
|
+
const cacheCheck = checkCache(cacheResult, requestMethod, tableName, this.request);
|
|
749
|
+
if (false !== cacheCheck) {
|
|
750
|
+
return (await cacheCheck).data;
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
cachingConfirmed = true;
|
|
754
|
+
// push to cache so we do not repeat the request
|
|
755
|
+
}
|
|
756
|
+
let addBackPK;
|
|
757
|
+
let apiResponse;
|
|
758
|
+
let returnGetNextPageFunction = false;
|
|
759
|
+
let restRequestUri = restURL + operatingTable + '/';
|
|
760
|
+
const needsConditionOrPrimaryCheck = (PUT === requestMethod || DELETE === requestMethod)
|
|
761
|
+
&& false === skipPrimaryCheck;
|
|
762
|
+
const TABLES = C6.TABLES;
|
|
763
|
+
// todo - aggregate primary key check with condition check
|
|
764
|
+
// check if PK exists in query, clone so pop does not affect the real data
|
|
765
|
+
const primaryKey = structuredClone(TABLES[operatingTable]?.PRIMARY)?.pop()?.split('.')?.pop();
|
|
766
|
+
if (needsConditionOrPrimaryCheck) {
|
|
767
|
+
if (undefined === primaryKey) {
|
|
768
|
+
if (null === query
|
|
769
|
+
|| undefined === query
|
|
770
|
+
|| undefined === query?.[C6.WHERE]
|
|
771
|
+
|| (true === Array.isArray(query[C6.WHERE])
|
|
772
|
+
|| query[C6.WHERE].length === 0)
|
|
773
|
+
|| (Object.keys(query?.[C6.WHERE]).length === 0)) {
|
|
774
|
+
console.error(query);
|
|
775
|
+
throw Error('Failed to parse primary key information. Query: (' + JSON.stringify(query) + ') Primary Key: (' + JSON.stringify(primaryKey) + ') TABLES[operatingTable]?.PRIMARY: (' + JSON.stringify(TABLES[operatingTable]?.PRIMARY) + ') for operatingTable (' + operatingTable + ').');
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
else {
|
|
779
|
+
if (undefined === query
|
|
780
|
+
|| null === query
|
|
781
|
+
|| false === primaryKey in query) {
|
|
782
|
+
if (true === debug && isLocal()) {
|
|
783
|
+
toast.error('DEVS: The primary key (' + primaryKey + ') was not provided!!');
|
|
784
|
+
}
|
|
785
|
+
throw Error('You must provide the primary key (' + primaryKey + ') for table (' + operatingTable + '). Request (' + JSON.stringify(this.request, undefined, 4) + ') Query (' + JSON.stringify(query) + ')');
|
|
786
|
+
}
|
|
787
|
+
if (undefined === query?.[primaryKey]
|
|
788
|
+
|| null === query?.[primaryKey]) {
|
|
789
|
+
toast.error('The primary key (' + primaryKey + ') provided is undefined or null explicitly!!');
|
|
790
|
+
throw Error('The primary key (' + primaryKey + ') provided in the request was exactly equal to undefined.');
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
// A part of me exists that wants to remove this, but it's a good feature
|
|
795
|
+
// this allows developers the ability to cache requests based on primary key
|
|
796
|
+
// for tables like `photos` this can be a huge performance boost
|
|
797
|
+
if (undefined !== query
|
|
798
|
+
&& null !== query
|
|
799
|
+
&& undefined !== primaryKey
|
|
800
|
+
&& primaryKey in query) {
|
|
801
|
+
restRequestUri += query[primaryKey] + '/';
|
|
802
|
+
const removedPkValue = query[primaryKey];
|
|
803
|
+
addBackPK = () => {
|
|
804
|
+
query ??= {};
|
|
805
|
+
query[primaryKey] = removedPkValue;
|
|
806
|
+
};
|
|
807
|
+
delete query[primaryKey];
|
|
808
|
+
console.log('query', query, 'primaryKey', primaryKey, 'removedPkValue', removedPkValue);
|
|
809
|
+
}
|
|
810
|
+
else {
|
|
811
|
+
console.log('query', query);
|
|
812
|
+
}
|
|
813
|
+
try {
|
|
814
|
+
console.groupCollapsed('%c API: (' + requestMethod + ') Request Query for (' + operatingTable + ') is about to fire, will return with promise!', 'color: #A020F0');
|
|
815
|
+
console.log(this.request);
|
|
816
|
+
console.log('%c If this is the first request for this datatype; thus the value being set is currently undefined, please remember to update the state to null.', 'color: #A020F0');
|
|
817
|
+
console.log('%c Remember undefined indicated the request has not fired, null indicates the request is firing, an empty array would signal no data was returned for the sql stmt.', 'color: #A020F0');
|
|
818
|
+
console.trace();
|
|
819
|
+
console.groupEnd();
|
|
820
|
+
this.runLifecycleHooks("beforeExecution", {
|
|
821
|
+
config: this.config,
|
|
822
|
+
request: this.request
|
|
823
|
+
});
|
|
824
|
+
const axiosActiveRequest = axios[requestMethod.toLowerCase()](restRequestUri, ...(() => {
|
|
825
|
+
const convert = (data) => convertForRequestBody(data, fullTableList, C6, (message) => toast.error(message, toastOptions));
|
|
826
|
+
const baseConfig = {
|
|
827
|
+
withCredentials: withCredentials,
|
|
828
|
+
};
|
|
829
|
+
switch (requestMethod) {
|
|
830
|
+
case GET:
|
|
831
|
+
return [{
|
|
832
|
+
...baseConfig,
|
|
833
|
+
params: query
|
|
834
|
+
}];
|
|
835
|
+
case POST:
|
|
836
|
+
if (dataInsertMultipleRows !== undefined) {
|
|
837
|
+
return [
|
|
838
|
+
dataInsertMultipleRows.map(convert),
|
|
839
|
+
baseConfig
|
|
840
|
+
];
|
|
841
|
+
}
|
|
842
|
+
return [convert(query), baseConfig];
|
|
843
|
+
case PUT:
|
|
844
|
+
return [convert(query), baseConfig];
|
|
845
|
+
case DELETE:
|
|
846
|
+
return [{
|
|
847
|
+
...baseConfig,
|
|
848
|
+
data: convert(query)
|
|
849
|
+
}];
|
|
850
|
+
default:
|
|
851
|
+
throw new Error(`The request method (${requestMethod}) was not recognized.`);
|
|
852
|
+
}
|
|
853
|
+
})());
|
|
854
|
+
if (cachingConfirmed) {
|
|
855
|
+
// push to cache so we do not repeat the request
|
|
856
|
+
apiRequestCache.push({
|
|
857
|
+
requestArgumentsSerialized: querySerialized,
|
|
858
|
+
request: axiosActiveRequest
|
|
859
|
+
});
|
|
860
|
+
}
|
|
861
|
+
// todo - wip verify this works
|
|
862
|
+
// we had removed the value from the request to add to the URI.
|
|
863
|
+
addBackPK?.(); // adding back so post-processing methods work
|
|
864
|
+
// returning the promise with this then is important for tests. todo - we could make that optional.
|
|
865
|
+
// https://rapidapi.com/guides/axios-async-await
|
|
866
|
+
return axiosActiveRequest.then(async (response) => {
|
|
867
|
+
// noinspection SuspiciousTypeOfGuard
|
|
868
|
+
if (typeof response.data === 'string') {
|
|
869
|
+
if (isTest()) {
|
|
870
|
+
console.trace();
|
|
871
|
+
throw new Error('The response data was a string this typically indicated html was sent. Make sure all cookies (' + JSON.stringify(response.config.headers) + ') needed are present! (' + response.data + ')');
|
|
872
|
+
}
|
|
873
|
+
return Promise.reject(response);
|
|
874
|
+
}
|
|
875
|
+
if (cachingConfirmed) {
|
|
876
|
+
const cacheIndex = apiRequestCache.findIndex(cache => cache.requestArgumentsSerialized === querySerialized);
|
|
877
|
+
// TODO - currently nonthing is setting this correctly
|
|
878
|
+
apiRequestCache[cacheIndex].final = false === returnGetNextPageFunction;
|
|
879
|
+
// only cache get method requests
|
|
880
|
+
apiRequestCache[cacheIndex].response = response;
|
|
881
|
+
}
|
|
882
|
+
this.runLifecycleHooks("afterExecution", {
|
|
883
|
+
config: this.config,
|
|
884
|
+
request: this.request,
|
|
885
|
+
response
|
|
886
|
+
});
|
|
887
|
+
// todo - this feels dumb now, but i digress
|
|
888
|
+
apiResponse = TestRestfulResponse(response, success, error);
|
|
889
|
+
if (false === apiResponse) {
|
|
890
|
+
if (debug && isLocal()) {
|
|
891
|
+
toast.warning("DEVS: TestRestfulResponse returned false for (" + operatingTable + ").", toastOptionsDevs);
|
|
892
|
+
}
|
|
893
|
+
return response;
|
|
894
|
+
}
|
|
895
|
+
const callback = () => this.runLifecycleHooks("afterCommit", {
|
|
896
|
+
config: this.config,
|
|
897
|
+
request: this.request,
|
|
898
|
+
response
|
|
899
|
+
});
|
|
900
|
+
if (undefined !== reactBootstrap && response) {
|
|
673
901
|
switch (requestMethod) {
|
|
674
902
|
case GET:
|
|
903
|
+
response.data && reactBootstrap.updateRestfulObjectArrays({
|
|
904
|
+
dataOrCallback: Array.isArray(response.data.rest) ? response.data.rest : [response.data.rest],
|
|
905
|
+
stateKey: this.config.restModel.TABLE_NAME,
|
|
906
|
+
uniqueObjectId: this.config.restModel.PRIMARY_SHORT,
|
|
907
|
+
callback
|
|
908
|
+
});
|
|
909
|
+
break;
|
|
675
910
|
case POST:
|
|
911
|
+
this.postState(response, this.request, callback);
|
|
912
|
+
break;
|
|
676
913
|
case PUT:
|
|
914
|
+
this.putState(response, this.request, callback);
|
|
915
|
+
break;
|
|
677
916
|
case DELETE:
|
|
917
|
+
this.deleteState(response, this.request, callback);
|
|
678
918
|
break;
|
|
679
|
-
default:
|
|
680
|
-
throw Error('Bad request method passed to getApi');
|
|
681
919
|
}
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
if (
|
|
691
|
-
console.groupCollapsed('%c API: (' + requestMethod + ')
|
|
692
|
-
console.log('
|
|
693
|
-
console.log('%c
|
|
920
|
+
}
|
|
921
|
+
else {
|
|
922
|
+
callback();
|
|
923
|
+
}
|
|
924
|
+
if (C6.GET === requestMethod) {
|
|
925
|
+
const responseData = response.data;
|
|
926
|
+
returnGetNextPageFunction = 1 !== query?.[C6.PAGINATION]?.[C6.LIMIT] &&
|
|
927
|
+
query?.[C6.PAGINATION]?.[C6.LIMIT] === responseData.rest.length;
|
|
928
|
+
if (false === isTest() || this.config.verbose) {
|
|
929
|
+
console.groupCollapsed('%c API: Response (' + requestMethod + ' ' + tableName + ') returned length (' + responseData.rest?.length + ') of possible (' + query?.[C6.PAGINATION]?.[C6.LIMIT] + ') limit!', 'color: #0c0');
|
|
930
|
+
console.log('%c ' + requestMethod + ' ' + tableName, 'color: #0c0');
|
|
931
|
+
console.log('%c Request Data (note you may see the success and/or error prompt):', 'color: #0c0', this.request);
|
|
932
|
+
console.log('%c Response Data:', 'color: #0c0', responseData.rest);
|
|
933
|
+
console.log('%c Will return get next page function:' + (returnGetNextPageFunction ? '' : ' (Will not return with explicit limit 1 set)'), 'color: #0c0', true === returnGetNextPageFunction);
|
|
694
934
|
console.trace();
|
|
695
935
|
console.groupEnd();
|
|
696
|
-
return [2 /*return*/, null];
|
|
697
936
|
}
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
937
|
+
if (false === returnGetNextPageFunction) {
|
|
938
|
+
responseData.next = apiRequest;
|
|
939
|
+
}
|
|
940
|
+
else {
|
|
941
|
+
responseData.next = undefined;
|
|
942
|
+
if (true === debug
|
|
943
|
+
&& isLocal()) {
|
|
944
|
+
toast.success("DEVS: Response returned length (" + responseData.rest?.length + ") less than limit (" + query?.[C6.PAGINATION]?.[C6.LIMIT] + ").", toastOptionsDevs);
|
|
702
945
|
}
|
|
703
|
-
query[C6.PAGINATION][C6.PAGE] = query[C6.PAGINATION][C6.PAGE] || 1;
|
|
704
|
-
query[C6.PAGINATION][C6.LIMIT] = query[C6.PAGINATION][C6.LIMIT] || 100;
|
|
705
946
|
}
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
_m.label = 1;
|
|
738
|
-
case 1:
|
|
739
|
-
cacheCheck = checkCache(cacheResult, requestMethod, tableName, this.request);
|
|
740
|
-
if (!(false !== cacheCheck)) return [3 /*break*/, 3];
|
|
741
|
-
return [4 /*yield*/, cacheCheck];
|
|
742
|
-
case 2: return [2 /*return*/, (_m.sent()).data];
|
|
743
|
-
case 3:
|
|
744
|
-
// this line incrementing page is why we return recursively
|
|
745
|
-
++query[C6.PAGINATION][C6.PAGE];
|
|
746
|
-
// this json stringify is to capture the new page number
|
|
747
|
-
querySerialized = sortAndSerializeQueryObject(tables, query !== null && query !== void 0 ? query : {});
|
|
748
|
-
cacheResult = apiRequestCache.find(function (cache) { return cache.requestArgumentsSerialized === querySerialized; });
|
|
749
|
-
_m.label = 4;
|
|
750
|
-
case 4:
|
|
751
|
-
if (undefined !== cacheResult) return [3 /*break*/, 1];
|
|
752
|
-
_m.label = 5;
|
|
753
|
-
case 5:
|
|
754
|
-
if (debug && isLocal()) {
|
|
755
|
-
toast.warning("DEVS: Request in cache. (" + apiRequestCache.findIndex(function (cache) { return cache.requestArgumentsSerialized === querySerialized; }) + "). Returning function to request page (" + query[C6.PAGINATION][C6.PAGE] + ")", toastOptionsDevs);
|
|
756
|
-
}
|
|
757
|
-
// @ts-ignore - this is an incorrect warning on TS, it's well typed
|
|
758
|
-
return [2 /*return*/, apiRequest];
|
|
759
|
-
case 6:
|
|
760
|
-
cachingConfirmed = true;
|
|
761
|
-
return [3 /*break*/, 8];
|
|
762
|
-
case 7:
|
|
763
|
-
if (debug && isLocal()) {
|
|
764
|
-
toast.info("DEVS: Ignore cache was set to true.", toastOptionsDevs);
|
|
765
|
-
}
|
|
766
|
-
_m.label = 8;
|
|
767
|
-
case 8:
|
|
768
|
-
if (debug && isLocal()) {
|
|
769
|
-
toast.success("DEVS: Request not in cache." + (requestMethod === C6.GET ? "Page (" + query[C6.PAGINATION][C6.PAGE] + ")." : '') + " Logging cache 2 console.", toastOptionsDevs);
|
|
770
|
-
}
|
|
771
|
-
return [3 /*break*/, 12];
|
|
772
|
-
case 9:
|
|
773
|
-
if (!cacheResults) return [3 /*break*/, 12];
|
|
774
|
-
if (!cacheResult) return [3 /*break*/, 11];
|
|
775
|
-
cacheCheck = checkCache(cacheResult, requestMethod, tableName, this.request);
|
|
776
|
-
if (!(false !== cacheCheck)) return [3 /*break*/, 11];
|
|
777
|
-
return [4 /*yield*/, cacheCheck];
|
|
778
|
-
case 10: return [2 /*return*/, (_m.sent()).data];
|
|
779
|
-
case 11:
|
|
780
|
-
cachingConfirmed = true;
|
|
781
|
-
_m.label = 12;
|
|
782
|
-
case 12:
|
|
783
|
-
returnGetNextPageFunction = false;
|
|
784
|
-
restRequestUri = restURL + operatingTable + '/';
|
|
785
|
-
needsConditionOrPrimaryCheck = (PUT === requestMethod || DELETE === requestMethod)
|
|
786
|
-
&& false === skipPrimaryCheck;
|
|
787
|
-
TABLES = C6.TABLES;
|
|
788
|
-
primaryKey = (_k = (_j = (_h = structuredClone((_g = TABLES[operatingTable]) === null || _g === void 0 ? void 0 : _g.PRIMARY)) === null || _h === void 0 ? void 0 : _h.pop()) === null || _j === void 0 ? void 0 : _j.split('.')) === null || _k === void 0 ? void 0 : _k.pop();
|
|
789
|
-
if (needsConditionOrPrimaryCheck) {
|
|
790
|
-
if (undefined === primaryKey) {
|
|
791
|
-
if (null === query
|
|
792
|
-
|| undefined === query
|
|
793
|
-
|| undefined === (query === null || query === void 0 ? void 0 : query[C6.WHERE])
|
|
794
|
-
|| (true === Array.isArray(query[C6.WHERE])
|
|
795
|
-
|| query[C6.WHERE].length === 0)
|
|
796
|
-
|| (Object.keys(query === null || query === void 0 ? void 0 : query[C6.WHERE]).length === 0)) {
|
|
797
|
-
console.error(query);
|
|
798
|
-
throw Error('Failed to parse primary key information. Query: (' + JSON.stringify(query) + ') Primary Key: (' + JSON.stringify(primaryKey) + ') TABLES[operatingTable]?.PRIMARY: (' + JSON.stringify((_l = TABLES[operatingTable]) === null || _l === void 0 ? void 0 : _l.PRIMARY) + ') for operatingTable (' + operatingTable + ').');
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
else {
|
|
802
|
-
if (undefined === query
|
|
803
|
-
|| null === query
|
|
804
|
-
|| false === primaryKey in query) {
|
|
805
|
-
if (true === debug && isLocal()) {
|
|
806
|
-
toast.error('DEVS: The primary key (' + primaryKey + ') was not provided!!');
|
|
807
|
-
}
|
|
808
|
-
throw Error('You must provide the primary key (' + primaryKey + ') for table (' + operatingTable + '). Request (' + JSON.stringify(this.request, undefined, 4) + ') Query (' + JSON.stringify(query) + ')');
|
|
809
|
-
}
|
|
810
|
-
if (undefined === (query === null || query === void 0 ? void 0 : query[primaryKey])
|
|
811
|
-
|| null === (query === null || query === void 0 ? void 0 : query[primaryKey])) {
|
|
812
|
-
toast.error('The primary key (' + primaryKey + ') provided is undefined or null explicitly!!');
|
|
813
|
-
throw Error('The primary key (' + primaryKey + ') provided in the request was exactly equal to undefined.');
|
|
947
|
+
if (fetchDependencies
|
|
948
|
+
&& 'number' === typeof fetchDependencies
|
|
949
|
+
&& responseData.rest.length > 0) {
|
|
950
|
+
console.groupCollapsed('%c API: Fetch Dependencies segment (' + requestMethod + ' ' + tableName + ')'
|
|
951
|
+
+ (fetchDependencies & eFetchDependencies.CHILDREN ? ' | (CHILDREN|REFERENCED) ' : '')
|
|
952
|
+
+ (fetchDependencies & eFetchDependencies.PARENTS ? ' | (PARENTS|REFERENCED_BY)' : '')
|
|
953
|
+
+ (fetchDependencies & eFetchDependencies.C6ENTITY ? ' | (C6ENTITY)' : '')
|
|
954
|
+
+ (fetchDependencies & eFetchDependencies.RECURSIVE ? ' | (RECURSIVE)' : ''), 'color: #33ccff');
|
|
955
|
+
console.groupCollapsed('Collapsed JS Trace');
|
|
956
|
+
console.trace(); // hidden in collapsed group
|
|
957
|
+
console.groupEnd();
|
|
958
|
+
// noinspection JSBitwiseOperatorUsage
|
|
959
|
+
let dependencies = {};
|
|
960
|
+
// Remember this is a binary bitwise operation, so we can check for multiple dependencies at once
|
|
961
|
+
if (fetchDependencies & eFetchDependencies.C6ENTITY) {
|
|
962
|
+
dependencies = operatingTable.endsWith("carbon_carbons")
|
|
963
|
+
? {
|
|
964
|
+
// the context of the entity system is a bit different
|
|
965
|
+
...fetchDependencies & eFetchDependencies.CHILDREN // REFERENCED === CHILDREN
|
|
966
|
+
? C6.TABLES[operatingTable].TABLE_REFERENCED_BY
|
|
967
|
+
: {},
|
|
968
|
+
...fetchDependencies & eFetchDependencies.PARENTS // REFERENCES === PARENTS
|
|
969
|
+
? C6.TABLES[operatingTable].TABLE_REFERENCES
|
|
970
|
+
: {}
|
|
971
|
+
} : {
|
|
972
|
+
// the context of the entity system is a bit different
|
|
973
|
+
...fetchDependencies & eFetchDependencies.CHILDREN // REFERENCED === CHILDREN
|
|
974
|
+
? {
|
|
975
|
+
...Object.keys(C6.TABLES[operatingTable].TABLE_REFERENCES).reduce((accumulator, columnName) => {
|
|
976
|
+
if (!C6.TABLES[operatingTable].PRIMARY_SHORT.includes(columnName)) {
|
|
977
|
+
accumulator[columnName] = C6.TABLES[operatingTable].TABLE_REFERENCES[columnName];
|
|
814
978
|
}
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
// this allows developers the ability to cache requests based on primary key
|
|
819
|
-
// for tables like `photos` this can be a huge performance boost
|
|
820
|
-
if (undefined !== query
|
|
821
|
-
&& null !== query
|
|
822
|
-
&& undefined !== primaryKey
|
|
823
|
-
&& primaryKey in query) {
|
|
824
|
-
restRequestUri += query[primaryKey] + '/';
|
|
825
|
-
removedPkValue_1 = query[primaryKey];
|
|
826
|
-
addBackPK = function () {
|
|
827
|
-
query !== null && query !== void 0 ? query : (query = {});
|
|
828
|
-
query[primaryKey] = removedPkValue_1;
|
|
829
|
-
};
|
|
830
|
-
delete query[primaryKey];
|
|
831
|
-
console.log('query', query, 'primaryKey', primaryKey, 'removedPkValue', removedPkValue_1);
|
|
832
|
-
}
|
|
833
|
-
else {
|
|
834
|
-
console.log('query', query);
|
|
979
|
+
return accumulator;
|
|
980
|
+
}, {}),
|
|
981
|
+
...C6.TABLES[operatingTable].TABLE_REFERENCED_BY // it is unlikely that a C6 table will have any TABLE_REFERENCED_BY
|
|
835
982
|
}
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
console.trace();
|
|
842
|
-
console.groupEnd();
|
|
843
|
-
this.runLifecycleHooks("beforeExecution", {
|
|
844
|
-
config: this.config,
|
|
845
|
-
request: this.request
|
|
846
|
-
});
|
|
847
|
-
axiosActiveRequest = (_e = axios)[requestMethod.toLowerCase()].apply(_e, __spreadArray([restRequestUri], (function () {
|
|
848
|
-
var convert = function (data) {
|
|
849
|
-
return convertForRequestBody(data, fullTableList, C6, function (message) { return toast.error(message, toastOptions); });
|
|
850
|
-
};
|
|
851
|
-
var baseConfig = {
|
|
852
|
-
withCredentials: withCredentials,
|
|
853
|
-
};
|
|
854
|
-
switch (requestMethod) {
|
|
855
|
-
case GET:
|
|
856
|
-
return [__assign(__assign({}, baseConfig), { params: query })];
|
|
857
|
-
case POST:
|
|
858
|
-
if (dataInsertMultipleRows !== undefined) {
|
|
859
|
-
return [
|
|
860
|
-
dataInsertMultipleRows.map(convert),
|
|
861
|
-
baseConfig
|
|
862
|
-
];
|
|
863
|
-
}
|
|
864
|
-
return [convert(query), baseConfig];
|
|
865
|
-
case PUT:
|
|
866
|
-
return [convert(query), baseConfig];
|
|
867
|
-
case DELETE:
|
|
868
|
-
return [__assign(__assign({}, baseConfig), { data: convert(query) })];
|
|
869
|
-
default:
|
|
870
|
-
throw new Error("The request method (".concat(requestMethod, ") was not recognized."));
|
|
871
|
-
}
|
|
872
|
-
})(), false));
|
|
873
|
-
if (cachingConfirmed) {
|
|
874
|
-
// push to cache so we do not repeat the request
|
|
875
|
-
apiRequestCache.push({
|
|
876
|
-
requestArgumentsSerialized: querySerialized,
|
|
877
|
-
request: axiosActiveRequest
|
|
878
|
-
});
|
|
983
|
+
: {},
|
|
984
|
+
...fetchDependencies & eFetchDependencies.PARENTS // REFERENCES === PARENTS
|
|
985
|
+
? C6.TABLES[operatingTable].PRIMARY_SHORT.reduce((accumulator, primaryKey) => {
|
|
986
|
+
if (primaryKey in C6.TABLES[operatingTable].TABLE_REFERENCES) {
|
|
987
|
+
accumulator[primaryKey] = C6.TABLES[operatingTable].TABLE_REFERENCES[primaryKey];
|
|
879
988
|
}
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
callback: callback
|
|
933
|
-
});
|
|
934
|
-
break;
|
|
935
|
-
case POST:
|
|
936
|
-
this.postState(response, this.request, callback);
|
|
937
|
-
break;
|
|
938
|
-
case PUT:
|
|
939
|
-
this.putState(response, this.request, callback);
|
|
940
|
-
break;
|
|
941
|
-
case DELETE:
|
|
942
|
-
this.deleteState(response, this.request, callback);
|
|
943
|
-
break;
|
|
944
|
-
}
|
|
945
|
-
}
|
|
946
|
-
else {
|
|
947
|
-
callback();
|
|
948
|
-
}
|
|
949
|
-
if (!(C6.GET === requestMethod)) return [3 /*break*/, 6];
|
|
950
|
-
responseData_1 = response.data;
|
|
951
|
-
returnGetNextPageFunction = 1 !== ((_d = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _d === void 0 ? void 0 : _d[C6.LIMIT]) &&
|
|
952
|
-
((_e = query === null || query === void 0 ? void 0 : query[C6.PAGINATION]) === null || _e === void 0 ? void 0 : _e[C6.LIMIT]) === responseData_1.rest.length;
|
|
953
|
-
if (false === isTest() || this.config.verbose) {
|
|
954
|
-
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');
|
|
955
|
-
console.log('%c ' + requestMethod + ' ' + tableName, 'color: #0c0');
|
|
956
|
-
console.log('%c Request Data (note you may see the success and/or error prompt):', 'color: #0c0', this.request);
|
|
957
|
-
console.log('%c Response Data:', 'color: #0c0', responseData_1.rest);
|
|
958
|
-
console.log('%c Will return get next page function:' + (returnGetNextPageFunction ? '' : ' (Will not return with explicit limit 1 set)'), 'color: #0c0', true === returnGetNextPageFunction);
|
|
959
|
-
console.trace();
|
|
960
|
-
console.groupEnd();
|
|
961
|
-
}
|
|
962
|
-
if (false === returnGetNextPageFunction) {
|
|
963
|
-
responseData_1.next = apiRequest;
|
|
964
|
-
}
|
|
965
|
-
else {
|
|
966
|
-
responseData_1.next = undefined;
|
|
967
|
-
if (true === debug
|
|
968
|
-
&& isLocal()) {
|
|
969
|
-
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);
|
|
970
|
-
}
|
|
971
|
-
}
|
|
972
|
-
if (!(fetchDependencies
|
|
973
|
-
&& 'number' === typeof fetchDependencies
|
|
974
|
-
&& responseData_1.rest.length > 0)) return [3 /*break*/, 6];
|
|
975
|
-
console.groupCollapsed('%c API: Fetch Dependencies segment (' + requestMethod + ' ' + tableName + ')'
|
|
976
|
-
+ (fetchDependencies & eFetchDependencies.CHILDREN ? ' | (CHILDREN|REFERENCED) ' : '')
|
|
977
|
-
+ (fetchDependencies & eFetchDependencies.PARENTS ? ' | (PARENTS|REFERENCED_BY)' : '')
|
|
978
|
-
+ (fetchDependencies & eFetchDependencies.C6ENTITY ? ' | (C6ENTITY)' : '')
|
|
979
|
-
+ (fetchDependencies & eFetchDependencies.RECURSIVE ? ' | (RECURSIVE)' : ''), 'color: #33ccff');
|
|
980
|
-
console.groupCollapsed('Collapsed JS Trace');
|
|
981
|
-
console.trace(); // hidden in collapsed group
|
|
982
|
-
console.groupEnd();
|
|
983
|
-
dependencies_1 = {};
|
|
984
|
-
// Remember this is a binary bitwise operation, so we can check for multiple dependencies at once
|
|
985
|
-
if (fetchDependencies & eFetchDependencies.C6ENTITY) {
|
|
986
|
-
dependencies_1 = operatingTable.endsWith("carbon_carbons")
|
|
987
|
-
? __assign(__assign({}, fetchDependencies & eFetchDependencies.CHILDREN // REFERENCED === CHILDREN
|
|
988
|
-
? C6.TABLES[operatingTable].TABLE_REFERENCED_BY
|
|
989
|
-
: {}), fetchDependencies & eFetchDependencies.PARENTS // REFERENCES === PARENTS
|
|
990
|
-
? C6.TABLES[operatingTable].TABLE_REFERENCES
|
|
991
|
-
: {}) : __assign(__assign({}, fetchDependencies & eFetchDependencies.CHILDREN // REFERENCED === CHILDREN
|
|
992
|
-
? __assign(__assign({}, Object.keys(C6.TABLES[operatingTable].TABLE_REFERENCES).reduce(function (accumulator, columnName) {
|
|
993
|
-
if (!C6.TABLES[operatingTable].PRIMARY_SHORT.includes(columnName)) {
|
|
994
|
-
accumulator[columnName] = C6.TABLES[operatingTable].TABLE_REFERENCES[columnName];
|
|
995
|
-
}
|
|
996
|
-
return accumulator;
|
|
997
|
-
}, {})), C6.TABLES[operatingTable].TABLE_REFERENCED_BY // it is unlikely that a C6 table will have any TABLE_REFERENCED_BY
|
|
998
|
-
) : {}), fetchDependencies & eFetchDependencies.PARENTS // REFERENCES === PARENTS
|
|
999
|
-
? C6.TABLES[operatingTable].PRIMARY_SHORT.reduce(function (accumulator, primaryKey) {
|
|
1000
|
-
if (primaryKey in C6.TABLES[operatingTable].TABLE_REFERENCES) {
|
|
1001
|
-
accumulator[primaryKey] = C6.TABLES[operatingTable].TABLE_REFERENCES[primaryKey];
|
|
1002
|
-
}
|
|
1003
|
-
return accumulator;
|
|
1004
|
-
}, {})
|
|
1005
|
-
: {});
|
|
1006
|
-
}
|
|
1007
|
-
else {
|
|
1008
|
-
// this is the natural mysql context
|
|
1009
|
-
dependencies_1 = __assign(__assign({}, fetchDependencies & eFetchDependencies.REFERENCED // REFERENCED === CHILDREN
|
|
1010
|
-
? C6.TABLES[operatingTable].TABLE_REFERENCED_BY
|
|
1011
|
-
: {}), fetchDependencies & eFetchDependencies.REFERENCES // REFERENCES === PARENTS
|
|
1012
|
-
? C6.TABLES[operatingTable].TABLE_REFERENCES
|
|
1013
|
-
: {});
|
|
1014
|
-
}
|
|
1015
|
-
fetchReferences_1 = {};
|
|
1016
|
-
apiRequestPromises = [];
|
|
1017
|
-
console.log('%c Dependencies', 'color: #005555', dependencies_1);
|
|
1018
|
-
Object.keys(dependencies_1)
|
|
1019
|
-
.forEach(function (column) { return dependencies_1[column]
|
|
1020
|
-
.forEach(function (constraint) {
|
|
1021
|
-
var _a, _b, _c, _d;
|
|
1022
|
-
var _e, _f, _g;
|
|
1023
|
-
var columnValues = (_b = (_a = responseData_1.rest[column]) !== null && _a !== void 0 ? _a : responseData_1.rest.map(function (row) {
|
|
1024
|
-
if (operatingTable.endsWith("carbons")
|
|
1025
|
-
&& 'entity_tag' in row
|
|
1026
|
-
&& !constraint.TABLE.endsWith(row['entity_tag'].split('\\').pop().toLowerCase())) {
|
|
1027
|
-
return false; // map
|
|
1028
|
-
}
|
|
1029
|
-
if (!(column in row)) {
|
|
1030
|
-
return false;
|
|
1031
|
-
}
|
|
1032
|
-
// todo - row[column] is a FK value, we should optionally remove values that are already in state
|
|
1033
|
-
// this could be any column in the table constraint.TABLE, not just the primary key
|
|
1034
|
-
return row[column];
|
|
1035
|
-
}).filter(function (n) { return n; })) !== null && _b !== void 0 ? _b : [];
|
|
1036
|
-
if (columnValues.length === 0) {
|
|
1037
|
-
return; // forEach
|
|
1038
|
-
}
|
|
1039
|
-
(_c = fetchReferences_1[_e = constraint.TABLE]) !== null && _c !== void 0 ? _c : (fetchReferences_1[_e] = {});
|
|
1040
|
-
(_d = (_f = fetchReferences_1[constraint.TABLE])[_g = constraint.COLUMN]) !== null && _d !== void 0 ? _d : (_f[_g] = []);
|
|
1041
|
-
fetchReferences_1[constraint.TABLE][constraint.COLUMN].push(columnValues);
|
|
1042
|
-
}); });
|
|
1043
|
-
console.log('fetchReferences', fetchReferences_1);
|
|
1044
|
-
_loop_1 = function (tableToFetch) {
|
|
1045
|
-
var referencesTables, shouldContinue, fetchTable, RestApi, nextFetchDependencies;
|
|
1046
|
-
var _l;
|
|
1047
|
-
return __generator(this, function (_m) {
|
|
1048
|
-
switch (_m.label) {
|
|
1049
|
-
case 0:
|
|
1050
|
-
if (fetchDependencies & eFetchDependencies.C6ENTITY
|
|
1051
|
-
&& 'string' === typeof tableName
|
|
1052
|
-
&& tableName.endsWith("carbon_carbons")) {
|
|
1053
|
-
referencesTables = responseData_1.rest.reduce(function (accumulator, row) {
|
|
1054
|
-
if ('entity_tag' in row && !accumulator.includes(row['entity_tag'])) {
|
|
1055
|
-
accumulator.push(row['entity_tag']);
|
|
1056
|
-
}
|
|
1057
|
-
return accumulator;
|
|
1058
|
-
}, []).map(function (entityTag) { return entityTag.split('\\').pop().toLowerCase(); });
|
|
1059
|
-
shouldContinue = referencesTables.find(function (referencesTable) { return tableToFetch.endsWith(referencesTable); });
|
|
1060
|
-
if (!shouldContinue) {
|
|
1061
|
-
console.log('%c C6ENTITY: The constraintTableName (' + tableToFetch + ') did not end with any value in referencesTables', 'color: #c00', referencesTables);
|
|
1062
|
-
return [2 /*return*/, "continue"];
|
|
1063
|
-
}
|
|
1064
|
-
console.log('%c C6ENTITY: The constraintTableName (' + tableToFetch + ') will be fetched.', 'color: #0c0');
|
|
1065
|
-
}
|
|
1066
|
-
return [4 /*yield*/, C6.IMPORT(tableToFetch)];
|
|
1067
|
-
case 1:
|
|
1068
|
-
fetchTable = _m.sent();
|
|
1069
|
-
RestApi = fetchTable.default;
|
|
1070
|
-
console.log('%c Fetch Dependencies will select (' + tableToFetch + ') using GET request', 'color: #33ccff');
|
|
1071
|
-
nextFetchDependencies = eFetchDependencies.NONE;
|
|
1072
|
-
if (fetchDependencies & eFetchDependencies.RECURSIVE) {
|
|
1073
|
-
if (fetchDependencies & eFetchDependencies.ALL) {
|
|
1074
|
-
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.');
|
|
1075
|
-
}
|
|
1076
|
-
nextFetchDependencies = fetchDependencies;
|
|
1077
|
-
}
|
|
1078
|
-
else if (fetchDependencies & eFetchDependencies.C6ENTITY) {
|
|
1079
|
-
if (tableToFetch === "carbon_carbons") {
|
|
1080
|
-
nextFetchDependencies = fetchDependencies;
|
|
1081
|
-
}
|
|
1082
|
-
else {
|
|
1083
|
-
nextFetchDependencies = fetchDependencies ^ eFetchDependencies.C6ENTITY;
|
|
1084
|
-
}
|
|
1085
|
-
}
|
|
1086
|
-
console.log('fetchReferences', fetchReferences_1[tableToFetch], "Current fetchDependencies for (" + operatingTable + "):", fetchDependencies, "New fetchDependencies for (" + tableToFetch + "): ", nextFetchDependencies);
|
|
1087
|
-
// 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
|
|
1088
|
-
// it not certain that they are using carbons' entities either
|
|
1089
|
-
// this is a dynamic call to the rest api, any generated table may resolve with (RestApi)
|
|
1090
|
-
// todo - using value to avoid joins.... but. maybe this should be a parameterizable option -- think race conditions; its safer to join
|
|
1091
|
-
apiRequestPromises.push(RestApi.Get((_l = {},
|
|
1092
|
-
_l[C6.WHERE] = {
|
|
1093
|
-
0: Object.keys(fetchReferences_1[tableToFetch]).reduce(function (sum, column) {
|
|
1094
|
-
fetchReferences_1[tableToFetch][column] = fetchReferences_1[tableToFetch][column].flat(Infinity);
|
|
1095
|
-
if (0 === fetchReferences_1[tableToFetch][column].length) {
|
|
1096
|
-
console.warn('The column (' + column + ') was not found in the response data. We will not fetch.', responseData_1);
|
|
1097
|
-
return false;
|
|
1098
|
-
}
|
|
1099
|
-
sum[column] = fetchReferences_1[tableToFetch][column].length === 1
|
|
1100
|
-
? fetchReferences_1[tableToFetch][column][0]
|
|
1101
|
-
: [
|
|
1102
|
-
C6.IN, fetchReferences_1[tableToFetch][column]
|
|
1103
|
-
];
|
|
1104
|
-
return sum;
|
|
1105
|
-
}, {})
|
|
1106
|
-
},
|
|
1107
|
-
_l.fetchDependencies = nextFetchDependencies,
|
|
1108
|
-
_l)));
|
|
1109
|
-
return [2 /*return*/];
|
|
1110
|
-
}
|
|
1111
|
-
});
|
|
1112
|
-
};
|
|
1113
|
-
_a = fetchReferences_1;
|
|
1114
|
-
_b = [];
|
|
1115
|
-
for (_c in _a)
|
|
1116
|
-
_b.push(_c);
|
|
1117
|
-
_i = 0;
|
|
1118
|
-
_k.label = 1;
|
|
1119
|
-
case 1:
|
|
1120
|
-
if (!(_i < _b.length)) return [3 /*break*/, 4];
|
|
1121
|
-
_c = _b[_i];
|
|
1122
|
-
if (!(_c in _a)) return [3 /*break*/, 3];
|
|
1123
|
-
tableToFetch = _c;
|
|
1124
|
-
return [5 /*yield**/, _loop_1(tableToFetch)];
|
|
1125
|
-
case 2:
|
|
1126
|
-
_k.sent();
|
|
1127
|
-
_k.label = 3;
|
|
1128
|
-
case 3:
|
|
1129
|
-
_i++;
|
|
1130
|
-
return [3 /*break*/, 1];
|
|
1131
|
-
case 4:
|
|
1132
|
-
console.groupEnd();
|
|
1133
|
-
return [4 /*yield*/, Promise.all(apiRequestPromises)];
|
|
1134
|
-
case 5:
|
|
1135
|
-
_k.sent();
|
|
1136
|
-
apiRequestPromises.map(function (promise) { return __awaiter(_this, void 0, void 0, function () {
|
|
1137
|
-
var _a, _b;
|
|
1138
|
-
return __generator(this, function (_c) {
|
|
1139
|
-
switch (_c.label) {
|
|
1140
|
-
case 0:
|
|
1141
|
-
if (!Array.isArray(this.request.fetchDependencies)) {
|
|
1142
|
-
// to reassign value we must ref the root
|
|
1143
|
-
this.request.fetchDependencies = [];
|
|
1144
|
-
}
|
|
1145
|
-
_b = (_a = this.request.fetchDependencies).push;
|
|
1146
|
-
return [4 /*yield*/, promise];
|
|
1147
|
-
case 1:
|
|
1148
|
-
_b.apply(_a, [_c.sent()]);
|
|
1149
|
-
return [2 /*return*/];
|
|
1150
|
-
}
|
|
1151
|
-
});
|
|
1152
|
-
}); });
|
|
1153
|
-
_k.label = 6;
|
|
1154
|
-
case 6:
|
|
1155
|
-
if (debug && isLocal()) {
|
|
1156
|
-
toast.success("DEVS: (" + requestMethod + ") request complete.", toastOptionsDevs);
|
|
1157
|
-
}
|
|
1158
|
-
// this is the literal axios return
|
|
1159
|
-
return [2 /*return*/, response];
|
|
1160
|
-
}
|
|
1161
|
-
});
|
|
1162
|
-
}); }).then(function (response) { return response.data; })]; // this escapes from axios context
|
|
989
|
+
return accumulator;
|
|
990
|
+
}, {})
|
|
991
|
+
: {}
|
|
992
|
+
};
|
|
993
|
+
}
|
|
994
|
+
else {
|
|
995
|
+
// this is the natural mysql context
|
|
996
|
+
dependencies = {
|
|
997
|
+
...fetchDependencies & eFetchDependencies.REFERENCED // REFERENCED === CHILDREN
|
|
998
|
+
? C6.TABLES[operatingTable].TABLE_REFERENCED_BY
|
|
999
|
+
: {},
|
|
1000
|
+
...fetchDependencies & eFetchDependencies.REFERENCES // REFERENCES === PARENTS
|
|
1001
|
+
? C6.TABLES[operatingTable].TABLE_REFERENCES
|
|
1002
|
+
: {}
|
|
1003
|
+
};
|
|
1004
|
+
}
|
|
1005
|
+
let fetchReferences = {};
|
|
1006
|
+
let apiRequestPromises = [];
|
|
1007
|
+
console.log('%c Dependencies', 'color: #005555', dependencies);
|
|
1008
|
+
Object.keys(dependencies)
|
|
1009
|
+
.forEach(column => dependencies[column]
|
|
1010
|
+
.forEach((constraint) => {
|
|
1011
|
+
const columnValues = responseData.rest[column] ?? responseData.rest.map((row) => {
|
|
1012
|
+
if (operatingTable.endsWith("carbons")
|
|
1013
|
+
&& 'entity_tag' in row
|
|
1014
|
+
&& !constraint.TABLE.endsWith(row['entity_tag'].split('\\').pop().toLowerCase())) {
|
|
1015
|
+
return false; // map
|
|
1016
|
+
}
|
|
1017
|
+
if (!(column in row)) {
|
|
1018
|
+
return false;
|
|
1019
|
+
}
|
|
1020
|
+
// todo - row[column] is a FK value, we should optionally remove values that are already in state
|
|
1021
|
+
// this could be any column in the table constraint.TABLE, not just the primary key
|
|
1022
|
+
return row[column];
|
|
1023
|
+
}).filter(n => n) ?? [];
|
|
1024
|
+
if (columnValues.length === 0) {
|
|
1025
|
+
return; // forEach
|
|
1026
|
+
}
|
|
1027
|
+
fetchReferences[constraint.TABLE] ??= {};
|
|
1028
|
+
fetchReferences[constraint.TABLE][constraint.COLUMN] ??= [];
|
|
1029
|
+
fetchReferences[constraint.TABLE][constraint.COLUMN].push(columnValues);
|
|
1030
|
+
}));
|
|
1031
|
+
console.log('fetchReferences', fetchReferences);
|
|
1032
|
+
for (const tableToFetch in fetchReferences) {
|
|
1033
|
+
if (fetchDependencies & eFetchDependencies.C6ENTITY
|
|
1034
|
+
&& 'string' === typeof tableName
|
|
1035
|
+
&& tableName.endsWith("carbon_carbons")) {
|
|
1036
|
+
// todo - rethink the table ref entity system - when tables are renamed? no hooks exist in mysql
|
|
1037
|
+
// since were already filtering on column, we can assume the first row constraint is the same as the rest
|
|
1038
|
+
const referencesTables = responseData.rest.reduce((accumulator, row) => {
|
|
1039
|
+
if ('entity_tag' in row && !accumulator.includes(row['entity_tag'])) {
|
|
1040
|
+
accumulator.push(row['entity_tag']);
|
|
1163
1041
|
}
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1042
|
+
return accumulator;
|
|
1043
|
+
}, []).map((entityTag) => entityTag.split('\\').pop().toLowerCase());
|
|
1044
|
+
const shouldContinue = referencesTables.find((referencesTable) => tableToFetch.endsWith(referencesTable));
|
|
1045
|
+
if (!shouldContinue) {
|
|
1046
|
+
console.log('%c C6ENTITY: The constraintTableName (' + tableToFetch + ') did not end with any value in referencesTables', 'color: #c00', referencesTables);
|
|
1047
|
+
continue;
|
|
1048
|
+
}
|
|
1049
|
+
console.log('%c C6ENTITY: The constraintTableName (' + tableToFetch + ') will be fetched.', 'color: #0c0');
|
|
1050
|
+
}
|
|
1051
|
+
const fetchTable = await C6.IMPORT(tableToFetch);
|
|
1052
|
+
const RestApi = fetchTable.default;
|
|
1053
|
+
console.log('%c Fetch Dependencies will select (' + tableToFetch + ') using GET request', 'color: #33ccff');
|
|
1054
|
+
let nextFetchDependencies = eFetchDependencies.NONE;
|
|
1055
|
+
if (fetchDependencies & eFetchDependencies.RECURSIVE) {
|
|
1056
|
+
if (fetchDependencies & eFetchDependencies.ALL) {
|
|
1057
|
+
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.');
|
|
1058
|
+
}
|
|
1059
|
+
nextFetchDependencies = fetchDependencies;
|
|
1060
|
+
}
|
|
1061
|
+
else if (fetchDependencies & eFetchDependencies.C6ENTITY) {
|
|
1062
|
+
if (tableToFetch === "carbon_carbons") {
|
|
1063
|
+
nextFetchDependencies = fetchDependencies;
|
|
1064
|
+
}
|
|
1065
|
+
else {
|
|
1066
|
+
nextFetchDependencies = fetchDependencies ^ eFetchDependencies.C6ENTITY;
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
console.log('fetchReferences', fetchReferences[tableToFetch], "Current fetchDependencies for (" + operatingTable + "):", fetchDependencies, "New fetchDependencies for (" + tableToFetch + "): ", nextFetchDependencies);
|
|
1070
|
+
// 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
|
|
1071
|
+
// it not certain that they are using carbons' entities either
|
|
1072
|
+
// this is a dynamic call to the rest api, any generated table may resolve with (RestApi)
|
|
1073
|
+
// todo - using value to avoid joins.... but. maybe this should be a parameterizable option -- think race conditions; its safer to join
|
|
1074
|
+
apiRequestPromises.push(RestApi.Get({
|
|
1075
|
+
[C6.WHERE]: {
|
|
1076
|
+
0: Object.keys(fetchReferences[tableToFetch]).reduce((sum, column) => {
|
|
1077
|
+
fetchReferences[tableToFetch][column] = fetchReferences[tableToFetch][column].flat(Infinity);
|
|
1078
|
+
if (0 === fetchReferences[tableToFetch][column].length) {
|
|
1079
|
+
console.warn('The column (' + column + ') was not found in the response data. We will not fetch.', responseData);
|
|
1080
|
+
return false;
|
|
1167
1081
|
}
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1082
|
+
sum[column] = fetchReferences[tableToFetch][column].length === 1
|
|
1083
|
+
? fetchReferences[tableToFetch][column][0]
|
|
1084
|
+
: [
|
|
1085
|
+
C6.IN, fetchReferences[tableToFetch][column]
|
|
1086
|
+
];
|
|
1087
|
+
return sum;
|
|
1088
|
+
}, {})
|
|
1089
|
+
},
|
|
1090
|
+
fetchDependencies: nextFetchDependencies
|
|
1091
|
+
}));
|
|
1092
|
+
}
|
|
1093
|
+
console.groupEnd();
|
|
1094
|
+
await Promise.all(apiRequestPromises);
|
|
1095
|
+
apiRequestPromises.map(async (promise) => {
|
|
1096
|
+
if (!Array.isArray(this.request.fetchDependencies)) {
|
|
1097
|
+
// to reassign value we must ref the root
|
|
1098
|
+
this.request.fetchDependencies = [];
|
|
1177
1099
|
}
|
|
1100
|
+
this.request.fetchDependencies.push(await promise);
|
|
1178
1101
|
});
|
|
1179
|
-
}
|
|
1180
|
-
|
|
1181
|
-
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
if (debug && isLocal()) {
|
|
1105
|
+
toast.success("DEVS: (" + requestMethod + ") request complete.", toastOptionsDevs);
|
|
1106
|
+
}
|
|
1107
|
+
// this is the literal axios return
|
|
1108
|
+
return response;
|
|
1109
|
+
}).then(response => response.data); // this escapes from axios context
|
|
1110
|
+
}
|
|
1111
|
+
catch (throwableError) {
|
|
1112
|
+
if (isTest()) {
|
|
1113
|
+
throw new Error(JSON.stringify(throwableError));
|
|
1182
1114
|
}
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1115
|
+
console.groupCollapsed('%c API: An error occurred in the try catch block. returning null!', 'color: #ff0000');
|
|
1116
|
+
console.log('%c ' + requestMethod + ' ' + tableName, 'color: #A020F0');
|
|
1117
|
+
console.warn(throwableError);
|
|
1118
|
+
console.trace();
|
|
1119
|
+
console.groupEnd();
|
|
1120
|
+
TestRestfulResponse(throwableError, success, error);
|
|
1121
|
+
return null;
|
|
1122
|
+
}
|
|
1123
|
+
};
|
|
1124
|
+
return await apiRequest();
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1188
1127
|
|
|
1189
1128
|
var HttpExecutor$1 = /*#__PURE__*/Object.freeze({
|
|
1190
1129
|
__proto__: null,
|
|
@@ -1201,210 +1140,188 @@ function convertHexIfBinary(_col, val, columnDef) {
|
|
|
1201
1140
|
return val;
|
|
1202
1141
|
}
|
|
1203
1142
|
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
function AggregateBuilder() {
|
|
1207
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
1208
|
-
}
|
|
1209
|
-
AggregateBuilder.prototype.buildAggregateField = function (field) {
|
|
1210
|
-
var _this = this;
|
|
1143
|
+
class AggregateBuilder extends Executor {
|
|
1144
|
+
buildAggregateField(field) {
|
|
1211
1145
|
if (typeof field === 'string') {
|
|
1212
1146
|
return field;
|
|
1213
1147
|
}
|
|
1214
1148
|
if (!Array.isArray(field) || field.length === 0) {
|
|
1215
1149
|
throw new Error('Invalid SELECT field entry');
|
|
1216
1150
|
}
|
|
1217
|
-
|
|
1218
|
-
|
|
1151
|
+
let [fn, ...args] = field;
|
|
1152
|
+
let alias;
|
|
1219
1153
|
if (args.length >= 2 && String(args[args.length - 2]).toUpperCase() === 'AS') {
|
|
1220
1154
|
alias = String(args.pop());
|
|
1221
1155
|
args.pop();
|
|
1222
1156
|
}
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
}).join(', ');
|
|
1227
|
-
var expr = "".concat(F, "(").concat(argList, ")");
|
|
1157
|
+
const F = String(fn).toUpperCase();
|
|
1158
|
+
const argList = args.map(arg => Array.isArray(arg) ? this.buildAggregateField(arg) : arg).join(', ');
|
|
1159
|
+
let expr = `${F}(${argList})`;
|
|
1228
1160
|
if (alias) {
|
|
1229
|
-
expr +=
|
|
1161
|
+
expr += ` AS ${alias}`;
|
|
1230
1162
|
}
|
|
1231
|
-
this.config.verbose && console.log(
|
|
1163
|
+
this.config.verbose && console.log(`[SELECT] ${expr}`);
|
|
1232
1164
|
return expr;
|
|
1233
|
-
};
|
|
1234
|
-
return AggregateBuilder;
|
|
1235
|
-
}(Executor));
|
|
1236
|
-
|
|
1237
|
-
var ConditionBuilder = /** @class */ (function (_super) {
|
|
1238
|
-
__extends(ConditionBuilder, _super);
|
|
1239
|
-
function ConditionBuilder() {
|
|
1240
|
-
var _this = _super !== null && _super.apply(this, arguments) || this;
|
|
1241
|
-
_this.aliasMap = {};
|
|
1242
|
-
_this.OPERATORS = new Set([
|
|
1243
|
-
C6C.EQUAL, C6C.NOT_EQUAL, C6C.LESS_THAN, C6C.LESS_THAN_OR_EQUAL_TO,
|
|
1244
|
-
C6C.GREATER_THAN, C6C.GREATER_THAN_OR_EQUAL_TO,
|
|
1245
|
-
C6C.LIKE, C6C.NOT_LIKE,
|
|
1246
|
-
C6C.IN, C6C.NOT_IN, 'NOT IN',
|
|
1247
|
-
C6C.IS, C6C.IS_NOT,
|
|
1248
|
-
C6C.BETWEEN, 'NOT BETWEEN',
|
|
1249
|
-
C6C.MATCH_AGAINST,
|
|
1250
|
-
C6C.ST_DISTANCE_SPHERE
|
|
1251
|
-
]);
|
|
1252
|
-
return _this;
|
|
1253
1165
|
}
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
class ConditionBuilder extends AggregateBuilder {
|
|
1169
|
+
aliasMap = {};
|
|
1170
|
+
initAlias(baseTable, joins) {
|
|
1171
|
+
this.aliasMap = { [baseTable]: baseTable };
|
|
1257
1172
|
if (!joins)
|
|
1258
1173
|
return;
|
|
1259
|
-
for (
|
|
1260
|
-
for (
|
|
1261
|
-
|
|
1174
|
+
for (const joinType in joins) {
|
|
1175
|
+
for (const raw in joins[joinType]) {
|
|
1176
|
+
const [table, alias] = raw.split(' ');
|
|
1262
1177
|
this.aliasMap[alias || table] = table;
|
|
1263
1178
|
}
|
|
1264
1179
|
}
|
|
1265
|
-
}
|
|
1266
|
-
|
|
1267
|
-
var _a, _b;
|
|
1180
|
+
}
|
|
1181
|
+
isColumnRef(ref) {
|
|
1268
1182
|
if (typeof ref !== 'string' || !ref.includes('.'))
|
|
1269
1183
|
return false;
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1184
|
+
const [prefix, column] = ref.split('.', 2);
|
|
1185
|
+
const tableName = this.aliasMap[prefix] || prefix;
|
|
1186
|
+
const table = this.config.C6?.TABLES?.[tableName];
|
|
1273
1187
|
if (!table)
|
|
1274
1188
|
return false;
|
|
1275
|
-
|
|
1189
|
+
const fullKey = `${tableName}.${column}`;
|
|
1276
1190
|
if (table.COLUMNS && (fullKey in table.COLUMNS))
|
|
1277
1191
|
return true;
|
|
1278
1192
|
if (table.COLUMNS && Object.values(table.COLUMNS).includes(ref))
|
|
1279
1193
|
return true;
|
|
1280
|
-
this.config.verbose && console.log(
|
|
1194
|
+
this.config.verbose && console.log(`[COLUMN REF] ${ref} is not a valid column reference`);
|
|
1281
1195
|
return false;
|
|
1282
|
-
}
|
|
1283
|
-
|
|
1196
|
+
}
|
|
1197
|
+
execute() {
|
|
1284
1198
|
throw new Error("Method not implemented.");
|
|
1285
|
-
}
|
|
1286
|
-
|
|
1199
|
+
}
|
|
1200
|
+
OPERATORS = new Set([
|
|
1201
|
+
C6C.EQUAL, C6C.NOT_EQUAL, C6C.LESS_THAN, C6C.LESS_THAN_OR_EQUAL_TO,
|
|
1202
|
+
C6C.GREATER_THAN, C6C.GREATER_THAN_OR_EQUAL_TO,
|
|
1203
|
+
C6C.LIKE, C6C.NOT_LIKE,
|
|
1204
|
+
C6C.IN, C6C.NOT_IN, 'NOT IN',
|
|
1205
|
+
C6C.IS, C6C.IS_NOT,
|
|
1206
|
+
C6C.BETWEEN, 'NOT BETWEEN',
|
|
1207
|
+
C6C.MATCH_AGAINST,
|
|
1208
|
+
C6C.ST_DISTANCE_SPHERE
|
|
1209
|
+
]);
|
|
1210
|
+
validateOperator(op) {
|
|
1287
1211
|
if (!this.OPERATORS.has(op)) {
|
|
1288
|
-
throw new Error(
|
|
1212
|
+
throw new Error(`Invalid or unsupported SQL operator detected: '${op}'`);
|
|
1289
1213
|
}
|
|
1290
|
-
}
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
var val = convertHexIfBinary(column, value, columnDef);
|
|
1214
|
+
}
|
|
1215
|
+
addParam(params, column, value) {
|
|
1216
|
+
const columnDef = this.config.C6[column.split('.')[0]]?.TYPE_VALIDATION?.[column];
|
|
1217
|
+
const val = convertHexIfBinary(column, value, columnDef);
|
|
1295
1218
|
if (this.useNamedParams) {
|
|
1296
|
-
|
|
1219
|
+
const key = `param${Object.keys(params).length}`;
|
|
1297
1220
|
params[key] = val;
|
|
1298
|
-
return
|
|
1221
|
+
return `:${key}`;
|
|
1299
1222
|
}
|
|
1300
1223
|
else {
|
|
1301
1224
|
params.push(val);
|
|
1302
1225
|
return '?';
|
|
1303
1226
|
}
|
|
1304
|
-
}
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
if (params === void 0) { params = []; }
|
|
1309
|
-
var booleanOperator = andMode ? 'AND' : 'OR';
|
|
1310
|
-
var addCondition = function (column, op, value) {
|
|
1227
|
+
}
|
|
1228
|
+
buildBooleanJoinedConditions(set, andMode = true, params = []) {
|
|
1229
|
+
const booleanOperator = andMode ? 'AND' : 'OR';
|
|
1230
|
+
const addCondition = (column, op, value) => {
|
|
1311
1231
|
// Support function-based expressions like [C6C.ST_DISTANCE_SPHERE, col1, col2]
|
|
1312
1232
|
if (typeof column === 'string' &&
|
|
1313
|
-
|
|
1233
|
+
this.OPERATORS.has(column) &&
|
|
1314
1234
|
Array.isArray(op)) {
|
|
1315
1235
|
if (column === C6C.ST_DISTANCE_SPHERE) {
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
return
|
|
1236
|
+
const [col1, col2] = op;
|
|
1237
|
+
const threshold = Array.isArray(value) ? value[0] : value;
|
|
1238
|
+
return `ST_Distance_Sphere(${col1}, ${col2}) < ${this.addParam(params, '', threshold)}`;
|
|
1319
1239
|
}
|
|
1320
1240
|
}
|
|
1321
|
-
|
|
1322
|
-
|
|
1241
|
+
const leftIsCol = this.isColumnRef(column);
|
|
1242
|
+
const rightIsCol = typeof value === 'string' && this.isColumnRef(value);
|
|
1323
1243
|
if (!leftIsCol && !rightIsCol) {
|
|
1324
|
-
throw new Error(
|
|
1244
|
+
throw new Error(`Potential SQL injection detected: '${column} ${op} ${value}'`);
|
|
1325
1245
|
}
|
|
1326
|
-
|
|
1246
|
+
this.validateOperator(op);
|
|
1327
1247
|
if (op === C6C.MATCH_AGAINST && Array.isArray(value)) {
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
if (
|
|
1248
|
+
const [search, mode] = value;
|
|
1249
|
+
const paramName = this.useNamedParams ? `param${Object.keys(params).length}` : null;
|
|
1250
|
+
if (this.useNamedParams) {
|
|
1331
1251
|
params[paramName] = search;
|
|
1332
1252
|
}
|
|
1333
1253
|
else {
|
|
1334
1254
|
params.push(search);
|
|
1335
1255
|
}
|
|
1336
|
-
|
|
1256
|
+
let againstClause;
|
|
1337
1257
|
switch ((mode || '').toUpperCase()) {
|
|
1338
1258
|
case 'BOOLEAN':
|
|
1339
|
-
againstClause =
|
|
1259
|
+
againstClause = this.useNamedParams ? `AGAINST(:${paramName} IN BOOLEAN MODE)` : `AGAINST(? IN BOOLEAN MODE)`;
|
|
1340
1260
|
break;
|
|
1341
1261
|
case 'WITH QUERY EXPANSION':
|
|
1342
|
-
againstClause =
|
|
1262
|
+
againstClause = this.useNamedParams ? `AGAINST(:${paramName} WITH QUERY EXPANSION)` : `AGAINST(? WITH QUERY EXPANSION)`;
|
|
1343
1263
|
break;
|
|
1344
1264
|
default: // NATURAL or undefined
|
|
1345
|
-
againstClause =
|
|
1265
|
+
againstClause = this.useNamedParams ? `AGAINST(:${paramName})` : `AGAINST(?)`;
|
|
1346
1266
|
break;
|
|
1347
1267
|
}
|
|
1348
1268
|
if (!leftIsCol) {
|
|
1349
|
-
throw new Error(
|
|
1269
|
+
throw new Error(`MATCH_AGAINST requires a table reference as the left operand. Column '${column}' is not a valid table reference.`);
|
|
1350
1270
|
}
|
|
1351
|
-
|
|
1352
|
-
|
|
1271
|
+
const matchClause = `(MATCH(${column}) ${againstClause})`;
|
|
1272
|
+
this.config.verbose && console.log(`[MATCH_AGAINST] ${matchClause}`);
|
|
1353
1273
|
return matchClause;
|
|
1354
1274
|
}
|
|
1355
1275
|
if ((op === C6C.IN || op === C6C.NOT_IN) && Array.isArray(value)) {
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
}).join(', ');
|
|
1359
|
-
var normalized = op.replace('_', ' ');
|
|
1276
|
+
const placeholders = value.map(v => this.isColumnRef(v) ? v : this.addParam(params, column, v)).join(', ');
|
|
1277
|
+
const normalized = op.replace('_', ' ');
|
|
1360
1278
|
if (!leftIsCol) {
|
|
1361
|
-
throw new Error(
|
|
1279
|
+
throw new Error(`IN operator requires a table reference as the left operand. Column '${column}' is not a valid table reference.`);
|
|
1362
1280
|
}
|
|
1363
|
-
return
|
|
1281
|
+
return `( ${column} ${normalized} (${placeholders}) )`;
|
|
1364
1282
|
}
|
|
1365
1283
|
if (op === C6C.BETWEEN || op === 'NOT BETWEEN') {
|
|
1366
1284
|
if (!Array.isArray(value) || value.length !== 2) {
|
|
1367
|
-
throw new Error(
|
|
1285
|
+
throw new Error(`BETWEEN operator requires an array of two values. Received: ${JSON.stringify(value)}`);
|
|
1368
1286
|
}
|
|
1369
|
-
|
|
1287
|
+
const [start, end] = value;
|
|
1370
1288
|
if (!leftIsCol) {
|
|
1371
|
-
throw new Error(
|
|
1289
|
+
throw new Error(`BETWEEN operator requires a table reference as the left operand. Column '${column}' is not a valid table reference.`);
|
|
1372
1290
|
}
|
|
1373
|
-
return
|
|
1291
|
+
return `(${column}) ${op.replace('_', ' ')} ${this.addParam(params, column, start)} AND ${this.addParam(params, column, end)}`;
|
|
1374
1292
|
}
|
|
1375
1293
|
if (leftIsCol && rightIsCol) {
|
|
1376
|
-
return
|
|
1294
|
+
return `(${column}) ${op} ${value}`;
|
|
1377
1295
|
}
|
|
1378
1296
|
if (leftIsCol && !rightIsCol) {
|
|
1379
|
-
return
|
|
1297
|
+
return `(${column}) ${op} ${this.addParam(params, column, value)}`;
|
|
1380
1298
|
}
|
|
1381
1299
|
if (rightIsCol) {
|
|
1382
|
-
return
|
|
1300
|
+
return `(${this.addParam(params, column, column)}) ${op} ${value}`;
|
|
1383
1301
|
}
|
|
1384
|
-
throw new Error(
|
|
1302
|
+
throw new Error(`Neither operand appears to be a table reference`);
|
|
1385
1303
|
};
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
for (
|
|
1390
|
-
var _b = _a[_i], k = _b[0], v = _b[1];
|
|
1304
|
+
const parts = [];
|
|
1305
|
+
const buildFromObject = (obj, mode) => {
|
|
1306
|
+
const subParts = [];
|
|
1307
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
1391
1308
|
// numeric keys represent nested OR groups
|
|
1392
1309
|
if (!isNaN(Number(k))) {
|
|
1393
|
-
|
|
1310
|
+
const sub = this.buildBooleanJoinedConditions(v, false, params);
|
|
1394
1311
|
if (sub)
|
|
1395
1312
|
subParts.push(sub);
|
|
1396
1313
|
continue;
|
|
1397
1314
|
}
|
|
1398
1315
|
if (typeof v === 'object' && v !== null && Object.keys(v).length === 1) {
|
|
1399
|
-
|
|
1316
|
+
const [op, val] = Object.entries(v)[0];
|
|
1400
1317
|
subParts.push(addCondition(k, op, val));
|
|
1401
1318
|
}
|
|
1402
1319
|
else if (Array.isArray(v) && v.length >= 2 && typeof v[0] === 'string') {
|
|
1403
|
-
|
|
1320
|
+
const [op, val] = v;
|
|
1404
1321
|
subParts.push(addCondition(k, op, val));
|
|
1405
1322
|
}
|
|
1406
1323
|
else if (typeof v === 'object' && v !== null) {
|
|
1407
|
-
|
|
1324
|
+
const sub = this.buildBooleanJoinedConditions(v, mode, params);
|
|
1408
1325
|
if (sub)
|
|
1409
1326
|
subParts.push(sub);
|
|
1410
1327
|
}
|
|
@@ -1412,124 +1329,105 @@ var ConditionBuilder = /** @class */ (function (_super) {
|
|
|
1412
1329
|
subParts.push(addCondition(k, '=', v));
|
|
1413
1330
|
}
|
|
1414
1331
|
}
|
|
1415
|
-
return subParts.join(
|
|
1332
|
+
return subParts.join(` ${mode ? 'AND' : 'OR'} `);
|
|
1416
1333
|
};
|
|
1417
1334
|
if (Array.isArray(set)) {
|
|
1418
|
-
for (
|
|
1419
|
-
|
|
1420
|
-
var sub = this.buildBooleanJoinedConditions(item, false, params);
|
|
1335
|
+
for (const item of set) {
|
|
1336
|
+
const sub = this.buildBooleanJoinedConditions(item, false, params);
|
|
1421
1337
|
if (sub)
|
|
1422
1338
|
parts.push(sub);
|
|
1423
1339
|
}
|
|
1424
1340
|
}
|
|
1425
1341
|
else if (typeof set === 'object' && set !== null) {
|
|
1426
|
-
|
|
1342
|
+
const sub = buildFromObject(set, andMode);
|
|
1427
1343
|
if (sub)
|
|
1428
1344
|
parts.push(sub);
|
|
1429
1345
|
}
|
|
1430
|
-
|
|
1431
|
-
return clause ?
|
|
1432
|
-
}
|
|
1433
|
-
|
|
1434
|
-
|
|
1346
|
+
const clause = parts.join(` ${booleanOperator} `);
|
|
1347
|
+
return clause ? `(${clause})` : '';
|
|
1348
|
+
}
|
|
1349
|
+
buildWhereClause(whereArg, params) {
|
|
1350
|
+
const clause = this.buildBooleanJoinedConditions(whereArg, true, params);
|
|
1435
1351
|
if (!clause)
|
|
1436
1352
|
return '';
|
|
1437
|
-
|
|
1438
|
-
this.config.verbose && console.log(
|
|
1439
|
-
return
|
|
1440
|
-
};
|
|
1441
|
-
return ConditionBuilder;
|
|
1442
|
-
}(AggregateBuilder));
|
|
1443
|
-
|
|
1444
|
-
var JoinBuilder = /** @class */ (function (_super) {
|
|
1445
|
-
__extends(JoinBuilder, _super);
|
|
1446
|
-
function JoinBuilder() {
|
|
1447
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
1353
|
+
const trimmed = clause.replace(/^\((.*)\)$/, '$1');
|
|
1354
|
+
this.config.verbose && console.log(`[WHERE] ${trimmed}`);
|
|
1355
|
+
return ` WHERE ${trimmed}`;
|
|
1448
1356
|
}
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
class JoinBuilder extends ConditionBuilder {
|
|
1360
|
+
buildJoinClauses(joinArgs, params) {
|
|
1361
|
+
let sql = '';
|
|
1362
|
+
for (const joinType in joinArgs) {
|
|
1363
|
+
const joinKind = joinType.replace('_', ' ').toUpperCase();
|
|
1364
|
+
for (const raw in joinArgs[joinType]) {
|
|
1365
|
+
const [table, alias] = raw.split(' ');
|
|
1455
1366
|
this.aliasMap[alias || table] = table;
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
sql +=
|
|
1367
|
+
const onClause = this.buildBooleanJoinedConditions(joinArgs[joinType][raw], true, params);
|
|
1368
|
+
const joinSql = alias ? `\`${table}\` AS \`${alias}\`` : `\`${table}\``;
|
|
1369
|
+
sql += ` ${joinKind} JOIN ${joinSql} ON ${onClause}`;
|
|
1459
1370
|
}
|
|
1460
1371
|
}
|
|
1461
|
-
this.config.verbose && console.log(
|
|
1372
|
+
this.config.verbose && console.log(`[JOIN] ${sql.trim()}`);
|
|
1462
1373
|
return sql;
|
|
1463
|
-
};
|
|
1464
|
-
return JoinBuilder;
|
|
1465
|
-
}(ConditionBuilder));
|
|
1466
|
-
|
|
1467
|
-
var DeleteQueryBuilder = /** @class */ (function (_super) {
|
|
1468
|
-
__extends(DeleteQueryBuilder, _super);
|
|
1469
|
-
function DeleteQueryBuilder() {
|
|
1470
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
1471
1374
|
}
|
|
1472
|
-
|
|
1473
|
-
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
class DeleteQueryBuilder extends JoinBuilder {
|
|
1378
|
+
build(table) {
|
|
1379
|
+
const params = this.useNamedParams ? {} : [];
|
|
1474
1380
|
this.initAlias(table, this.request.JOIN);
|
|
1475
|
-
|
|
1381
|
+
let sql = `DELETE \`${table}\` FROM \`${table}\``;
|
|
1476
1382
|
if (this.request.JOIN) {
|
|
1477
1383
|
sql += this.buildJoinClauses(this.request.JOIN, params);
|
|
1478
1384
|
}
|
|
1479
1385
|
if (this.request.WHERE) {
|
|
1480
1386
|
sql += this.buildWhereClause(this.request.WHERE, params);
|
|
1481
1387
|
}
|
|
1482
|
-
return { sql
|
|
1483
|
-
};
|
|
1484
|
-
return DeleteQueryBuilder;
|
|
1485
|
-
}(JoinBuilder));
|
|
1486
|
-
|
|
1487
|
-
var PostQueryBuilder = /** @class */ (function (_super) {
|
|
1488
|
-
__extends(PostQueryBuilder, _super);
|
|
1489
|
-
function PostQueryBuilder() {
|
|
1490
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
1388
|
+
return { sql, params };
|
|
1491
1389
|
}
|
|
1492
|
-
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
class PostQueryBuilder extends ConditionBuilder {
|
|
1393
|
+
trimTablePrefix(table, column) {
|
|
1493
1394
|
if (!column.includes('.'))
|
|
1494
1395
|
return column;
|
|
1495
|
-
|
|
1396
|
+
const [prefix, col] = column.split('.', 2);
|
|
1496
1397
|
if (prefix !== table) {
|
|
1497
|
-
throw new Error(
|
|
1398
|
+
throw new Error(`Invalid prefixed column: '${column}'. Expected prefix '${table}.'`);
|
|
1498
1399
|
}
|
|
1499
1400
|
return col;
|
|
1500
|
-
}
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
var value = body[key];
|
|
1511
|
-
var placeholder = this.addParam(params, key, value);
|
|
1401
|
+
}
|
|
1402
|
+
build(table) {
|
|
1403
|
+
const verb = C6C.REPLACE in this.request ? C6C.REPLACE : C6C.INSERT;
|
|
1404
|
+
const body = verb in this.request ? this.request[verb] : this.request;
|
|
1405
|
+
const keys = Object.keys(body);
|
|
1406
|
+
const params = [];
|
|
1407
|
+
const placeholders = [];
|
|
1408
|
+
for (const key of keys) {
|
|
1409
|
+
const value = body[key];
|
|
1410
|
+
const placeholder = this.addParam(params, key, value);
|
|
1512
1411
|
placeholders.push(placeholder);
|
|
1513
1412
|
}
|
|
1514
|
-
|
|
1413
|
+
let sql = `${verb} INTO \`${table}\` (
|
|
1414
|
+
${keys.map(k => `\`${this.trimTablePrefix(table, k)}\``).join(', ')}
|
|
1415
|
+
) VALUES (
|
|
1416
|
+
${placeholders.join(', ')}
|
|
1417
|
+
)`;
|
|
1515
1418
|
if (C6C.UPDATE in this.request) {
|
|
1516
|
-
|
|
1419
|
+
const updateData = this.request[C6C.UPDATE];
|
|
1517
1420
|
if (!Array.isArray(updateData)) {
|
|
1518
|
-
throw new Error(
|
|
1421
|
+
throw new Error(`Update data must be an array of keys to update, got: ${JSON.stringify(updateData)}`);
|
|
1519
1422
|
}
|
|
1520
|
-
|
|
1521
|
-
sql +=
|
|
1423
|
+
const updateClause = updateData.map(k => `\`${k}\` = VALUES(\`${k}\`)`).join(', ');
|
|
1424
|
+
sql += ` ON DUPLICATE KEY UPDATE ${updateClause}`;
|
|
1522
1425
|
}
|
|
1523
|
-
return { sql
|
|
1524
|
-
};
|
|
1525
|
-
return PostQueryBuilder;
|
|
1526
|
-
}(ConditionBuilder));
|
|
1527
|
-
|
|
1528
|
-
var PaginationBuilder = /** @class */ (function (_super) {
|
|
1529
|
-
__extends(PaginationBuilder, _super);
|
|
1530
|
-
function PaginationBuilder() {
|
|
1531
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
1426
|
+
return { sql, params };
|
|
1532
1427
|
}
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
class PaginationBuilder extends JoinBuilder {
|
|
1533
1431
|
/**
|
|
1534
1432
|
* MySQL ORDER/LIMIT/OFFSET generator.
|
|
1535
1433
|
*
|
|
@@ -1543,60 +1441,49 @@ var PaginationBuilder = /** @class */ (function (_super) {
|
|
|
1543
1441
|
* }
|
|
1544
1442
|
* ```
|
|
1545
1443
|
*/
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
var _a;
|
|
1549
|
-
var sql = "";
|
|
1444
|
+
buildPaginationClause(pagination) {
|
|
1445
|
+
let sql = "";
|
|
1550
1446
|
/* -------- ORDER BY -------- */
|
|
1551
|
-
if (pagination
|
|
1552
|
-
|
|
1553
|
-
for (
|
|
1554
|
-
var _c = _b[_i], key = _c[0], val = _c[1];
|
|
1447
|
+
if (pagination?.[C6Constants.ORDER]) {
|
|
1448
|
+
const orderParts = [];
|
|
1449
|
+
for (const [key, val] of Object.entries(pagination[C6Constants.ORDER])) {
|
|
1555
1450
|
// FUNCTION CALL: val is an array of args
|
|
1556
1451
|
if (Array.isArray(val)) {
|
|
1557
|
-
|
|
1558
|
-
.map(
|
|
1452
|
+
const args = val
|
|
1453
|
+
.map((arg) => Array.isArray(arg) ? this.buildAggregateField(arg) : String(arg))
|
|
1559
1454
|
.join(", ");
|
|
1560
|
-
orderParts.push(
|
|
1455
|
+
orderParts.push(`${key}(${args})`);
|
|
1561
1456
|
}
|
|
1562
1457
|
// SIMPLE COLUMN + DIR (ASC/DESC)
|
|
1563
1458
|
else {
|
|
1564
|
-
orderParts.push(
|
|
1459
|
+
orderParts.push(`${key} ${String(val).toUpperCase()}`);
|
|
1565
1460
|
}
|
|
1566
1461
|
}
|
|
1567
1462
|
if (orderParts.length)
|
|
1568
|
-
sql +=
|
|
1463
|
+
sql += ` ORDER BY ${orderParts.join(", ")}`;
|
|
1569
1464
|
}
|
|
1570
1465
|
/* -------- LIMIT / OFFSET -------- */
|
|
1571
|
-
if (
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
sql +=
|
|
1466
|
+
if (pagination?.[C6Constants.LIMIT] != null) {
|
|
1467
|
+
const lim = parseInt(pagination[C6Constants.LIMIT], 10);
|
|
1468
|
+
const page = parseInt(pagination[C6Constants.PAGE] ?? 1, 10);
|
|
1469
|
+
const offset = (page - 1) * lim;
|
|
1470
|
+
sql += ` LIMIT ${offset}, ${lim}`;
|
|
1576
1471
|
}
|
|
1577
|
-
this.config.verbose && console.log(
|
|
1472
|
+
this.config.verbose && console.log(`[PAGINATION] ${sql.trim()}`);
|
|
1578
1473
|
return sql;
|
|
1579
|
-
};
|
|
1580
|
-
return PaginationBuilder;
|
|
1581
|
-
}(JoinBuilder));
|
|
1582
|
-
|
|
1583
|
-
var SelectQueryBuilder = /** @class */ (function (_super) {
|
|
1584
|
-
__extends(SelectQueryBuilder, _super);
|
|
1585
|
-
function SelectQueryBuilder() {
|
|
1586
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
1587
1474
|
}
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
class SelectQueryBuilder extends PaginationBuilder {
|
|
1478
|
+
build(table, isSubSelect = false) {
|
|
1479
|
+
const args = this.request;
|
|
1593
1480
|
this.initAlias(table, args.JOIN);
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
.map(
|
|
1481
|
+
const params = this.useNamedParams ? {} : [];
|
|
1482
|
+
const selectList = args.SELECT ?? ['*'];
|
|
1483
|
+
const selectFields = selectList
|
|
1484
|
+
.map((f) => this.buildAggregateField(f))
|
|
1598
1485
|
.join(', ');
|
|
1599
|
-
|
|
1486
|
+
let sql = `SELECT ${selectFields} FROM \`${table}\``;
|
|
1600
1487
|
if (args.JOIN) {
|
|
1601
1488
|
sql += this.buildJoinClauses(args.JOIN, params);
|
|
1602
1489
|
}
|
|
@@ -1604,227 +1491,165 @@ var SelectQueryBuilder = /** @class */ (function (_super) {
|
|
|
1604
1491
|
sql += this.buildWhereClause(args.WHERE, params);
|
|
1605
1492
|
}
|
|
1606
1493
|
if (args.GROUP_BY) {
|
|
1607
|
-
|
|
1494
|
+
const groupBy = Array.isArray(args.GROUP_BY)
|
|
1608
1495
|
? args.GROUP_BY.join(', ')
|
|
1609
1496
|
: args.GROUP_BY;
|
|
1610
|
-
sql +=
|
|
1497
|
+
sql += ` GROUP BY ${groupBy}`;
|
|
1611
1498
|
}
|
|
1612
1499
|
if (args.HAVING) {
|
|
1613
|
-
sql +=
|
|
1500
|
+
sql += ` HAVING ${this.buildBooleanJoinedConditions(args.HAVING, true, params)}`;
|
|
1614
1501
|
}
|
|
1615
1502
|
if (args.PAGINATION) {
|
|
1616
1503
|
sql += this.buildPaginationClause(args.PAGINATION);
|
|
1617
1504
|
}
|
|
1618
1505
|
else if (!isSubSelect) {
|
|
1619
|
-
sql +=
|
|
1506
|
+
sql += ` LIMIT 100`;
|
|
1620
1507
|
}
|
|
1621
|
-
console.log(
|
|
1622
|
-
return { sql
|
|
1623
|
-
};
|
|
1624
|
-
return SelectQueryBuilder;
|
|
1625
|
-
}(PaginationBuilder));
|
|
1626
|
-
|
|
1627
|
-
var UpdateQueryBuilder = /** @class */ (function (_super) {
|
|
1628
|
-
__extends(UpdateQueryBuilder, _super);
|
|
1629
|
-
function UpdateQueryBuilder() {
|
|
1630
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
1508
|
+
console.log(`[SELECT] ${sql.trim()}`);
|
|
1509
|
+
return { sql, params };
|
|
1631
1510
|
}
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
class UpdateQueryBuilder extends PaginationBuilder {
|
|
1514
|
+
build(table) {
|
|
1515
|
+
const args = this.request;
|
|
1516
|
+
const params = this.useNamedParams ? {} : [];
|
|
1636
1517
|
this.initAlias(table, args.JOIN);
|
|
1637
|
-
|
|
1518
|
+
let sql = `UPDATE \`${table}\``;
|
|
1638
1519
|
if (args.JOIN) {
|
|
1639
1520
|
sql += this.buildJoinClauses(args.JOIN, params);
|
|
1640
1521
|
}
|
|
1641
1522
|
if (!(C6C.UPDATE in this.request)) {
|
|
1642
1523
|
throw new Error("No update data provided in the request.");
|
|
1643
1524
|
}
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
return _this.addParam(params, col, val);
|
|
1647
|
-
});
|
|
1648
|
-
sql += " SET ".concat(setClauses.join(', '));
|
|
1525
|
+
const setClauses = Object.entries(this.request[C6C.UPDATE]).map(([col, val]) => this.addParam(params, col, val));
|
|
1526
|
+
sql += ` SET ${setClauses.join(', ')}`;
|
|
1649
1527
|
if (args.WHERE) {
|
|
1650
1528
|
sql += this.buildWhereClause(args.WHERE, params);
|
|
1651
1529
|
}
|
|
1652
1530
|
if (args.PAGINATION) {
|
|
1653
1531
|
sql += this.buildPaginationClause(args.PAGINATION);
|
|
1654
1532
|
}
|
|
1655
|
-
return { sql
|
|
1656
|
-
}
|
|
1657
|
-
|
|
1658
|
-
}(PaginationBuilder));
|
|
1533
|
+
return { sql, params };
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1659
1536
|
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1537
|
+
class SqlExecutor extends Executor {
|
|
1538
|
+
async execute() {
|
|
1539
|
+
const { TABLE_NAME } = this.config.restModel;
|
|
1540
|
+
const method = this.config.requestMethod;
|
|
1541
|
+
this.config.verbose && console.log(`[SQL EXECUTOR] ▶️ Executing ${method} on table "${TABLE_NAME}"`);
|
|
1542
|
+
this.config.verbose && console.log(`[SQL EXECUTOR] 🧩 Request:`, JSON.stringify(this.request, undefined, 2));
|
|
1543
|
+
switch (method) {
|
|
1544
|
+
case 'GET': {
|
|
1545
|
+
const rest = await this.runQuery();
|
|
1546
|
+
return rest;
|
|
1547
|
+
}
|
|
1548
|
+
case 'POST': {
|
|
1549
|
+
const result = await this.runQuery();
|
|
1550
|
+
return result;
|
|
1551
|
+
}
|
|
1552
|
+
case 'PUT': {
|
|
1553
|
+
const result = await this.runQuery();
|
|
1554
|
+
return result;
|
|
1555
|
+
}
|
|
1556
|
+
case 'DELETE': {
|
|
1557
|
+
const result = await this.runQuery();
|
|
1558
|
+
return result;
|
|
1559
|
+
}
|
|
1560
|
+
default:
|
|
1561
|
+
throw new Error(`Unsupported request method: ${method}`);
|
|
1562
|
+
}
|
|
1669
1563
|
}
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
case 'PUT': return [3 /*break*/, 5];
|
|
1685
|
-
case 'DELETE': return [3 /*break*/, 7];
|
|
1686
|
-
}
|
|
1687
|
-
return [3 /*break*/, 9];
|
|
1688
|
-
case 1: return [4 /*yield*/, this.runQuery()];
|
|
1689
|
-
case 2:
|
|
1690
|
-
rest = _b.sent();
|
|
1691
|
-
return [2 /*return*/, rest];
|
|
1692
|
-
case 3: return [4 /*yield*/, this.runQuery()];
|
|
1693
|
-
case 4:
|
|
1694
|
-
result = _b.sent();
|
|
1695
|
-
return [2 /*return*/, result];
|
|
1696
|
-
case 5: return [4 /*yield*/, this.runQuery()];
|
|
1697
|
-
case 6:
|
|
1698
|
-
result = _b.sent();
|
|
1699
|
-
return [2 /*return*/, result];
|
|
1700
|
-
case 7: return [4 /*yield*/, this.runQuery()];
|
|
1701
|
-
case 8:
|
|
1702
|
-
result = _b.sent();
|
|
1703
|
-
return [2 /*return*/, result];
|
|
1704
|
-
case 9: throw new Error("Unsupported request method: ".concat(method));
|
|
1705
|
-
}
|
|
1706
|
-
});
|
|
1707
|
-
});
|
|
1708
|
-
};
|
|
1709
|
-
SqlExecutor.prototype.withConnection = function (cb) {
|
|
1710
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
1711
|
-
var conn;
|
|
1712
|
-
return __generator(this, function (_a) {
|
|
1713
|
-
switch (_a.label) {
|
|
1714
|
-
case 0:
|
|
1715
|
-
console.log("[SQL EXECUTOR] \uD83D\uDCE1 Getting DB connection");
|
|
1716
|
-
return [4 /*yield*/, this.config.mysqlPool.getConnection()];
|
|
1717
|
-
case 1:
|
|
1718
|
-
conn = _a.sent();
|
|
1719
|
-
_a.label = 2;
|
|
1720
|
-
case 2:
|
|
1721
|
-
_a.trys.push([2, , 4, 5]);
|
|
1722
|
-
this.config.verbose && console.log("[SQL EXECUTOR] \u2705 Connection acquired");
|
|
1723
|
-
return [4 /*yield*/, cb(conn)];
|
|
1724
|
-
case 3: return [2 /*return*/, _a.sent()];
|
|
1725
|
-
case 4:
|
|
1726
|
-
this.config.verbose && console.log("[SQL EXECUTOR] \uD83D\uDD0C Releasing DB connection");
|
|
1727
|
-
conn.release();
|
|
1728
|
-
return [7 /*endfinally*/];
|
|
1729
|
-
case 5: return [2 /*return*/];
|
|
1730
|
-
}
|
|
1731
|
-
});
|
|
1732
|
-
});
|
|
1733
|
-
};
|
|
1734
|
-
SqlExecutor.prototype.formatSQLWithParams = function (sql, params) {
|
|
1735
|
-
var _this = this;
|
|
1564
|
+
async withConnection(cb) {
|
|
1565
|
+
console.log(`[SQL EXECUTOR] 📡 Getting DB connection`);
|
|
1566
|
+
const conn = await this.config.mysqlPool.getConnection();
|
|
1567
|
+
try {
|
|
1568
|
+
this.config.verbose && console.log(`[SQL EXECUTOR] ✅ Connection acquired`);
|
|
1569
|
+
return await cb(conn);
|
|
1570
|
+
}
|
|
1571
|
+
finally {
|
|
1572
|
+
this.config.verbose && console.log(`[SQL EXECUTOR] 🔌 Releasing DB connection`);
|
|
1573
|
+
conn.release();
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
serialize = (row) => Object.fromEntries(Object.entries(row).map(([k, v]) => [k, Buffer$1.isBuffer(v) ? v.toString('hex').toUpperCase() : v]));
|
|
1577
|
+
formatSQLWithParams(sql, params) {
|
|
1736
1578
|
if (Array.isArray(params)) {
|
|
1737
|
-
|
|
1738
|
-
return sql.replace(/\?/g,
|
|
1739
|
-
if (
|
|
1579
|
+
let index = 0;
|
|
1580
|
+
return sql.replace(/\?/g, () => {
|
|
1581
|
+
if (index >= params.length)
|
|
1740
1582
|
return '?';
|
|
1741
|
-
|
|
1742
|
-
return
|
|
1583
|
+
const val = params[index++];
|
|
1584
|
+
return this.formatValue(val);
|
|
1743
1585
|
});
|
|
1744
1586
|
}
|
|
1745
1587
|
else {
|
|
1746
|
-
return sql.replace(/:([a-zA-Z0-9_]+)/g,
|
|
1747
|
-
|
|
1748
|
-
return
|
|
1588
|
+
return sql.replace(/:([a-zA-Z0-9_]+)/g, (_, key) => {
|
|
1589
|
+
const val = params[key];
|
|
1590
|
+
return this.formatValue(val);
|
|
1749
1591
|
});
|
|
1750
1592
|
}
|
|
1751
|
-
}
|
|
1752
|
-
|
|
1593
|
+
}
|
|
1594
|
+
formatValue(val) {
|
|
1753
1595
|
if (val === null || val === undefined)
|
|
1754
1596
|
return 'NULL';
|
|
1755
1597
|
if (Buffer$1.isBuffer(val))
|
|
1756
|
-
return
|
|
1598
|
+
return `UNHEX('${val.toString('hex')}')`;
|
|
1757
1599
|
if (typeof val === 'string')
|
|
1758
|
-
return
|
|
1600
|
+
return `'${val.replace(/'/g, "''")}'`;
|
|
1759
1601
|
if (typeof val === 'number')
|
|
1760
1602
|
return val.toString();
|
|
1761
1603
|
if (val instanceof Date)
|
|
1762
|
-
return
|
|
1763
|
-
return
|
|
1764
|
-
}
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
}];
|
|
1809
|
-
}
|
|
1810
|
-
else {
|
|
1811
|
-
this.config.verbose && console.log("[SQL EXECUTOR] \u270F\uFE0F Rows affected:", result.affectedRows);
|
|
1812
|
-
return [2 /*return*/, {
|
|
1813
|
-
affected: result.affectedRows,
|
|
1814
|
-
rest: [],
|
|
1815
|
-
sql: { sql: sql, values: values }
|
|
1816
|
-
}];
|
|
1817
|
-
}
|
|
1818
|
-
}
|
|
1819
|
-
});
|
|
1820
|
-
}); })];
|
|
1821
|
-
case 1: return [2 /*return*/, _b.sent()];
|
|
1822
|
-
}
|
|
1823
|
-
});
|
|
1604
|
+
return `'${val.toISOString().slice(0, 19).replace('T', ' ')}'`;
|
|
1605
|
+
return `'${JSON.stringify(val)}'`;
|
|
1606
|
+
}
|
|
1607
|
+
async runQuery() {
|
|
1608
|
+
const { TABLE_NAME } = this.config.restModel;
|
|
1609
|
+
const method = this.config.requestMethod;
|
|
1610
|
+
let builder;
|
|
1611
|
+
switch (method) {
|
|
1612
|
+
case 'GET':
|
|
1613
|
+
builder = new SelectQueryBuilder(this.config, this.request);
|
|
1614
|
+
break;
|
|
1615
|
+
case 'PUT':
|
|
1616
|
+
builder = new UpdateQueryBuilder(this.config, this.request);
|
|
1617
|
+
break;
|
|
1618
|
+
case 'DELETE':
|
|
1619
|
+
builder = new DeleteQueryBuilder(this.config, this.request);
|
|
1620
|
+
break;
|
|
1621
|
+
case 'POST':
|
|
1622
|
+
builder = new PostQueryBuilder(this.config, this.request);
|
|
1623
|
+
break;
|
|
1624
|
+
default:
|
|
1625
|
+
throw new Error(`Unsupported query method: ${method}`);
|
|
1626
|
+
}
|
|
1627
|
+
const QueryResult = builder.build(TABLE_NAME);
|
|
1628
|
+
this.config.verbose && console.log(`[SQL EXECUTOR] 🧠 Generated ${method.toUpperCase()} SQL:`, QueryResult);
|
|
1629
|
+
const formatted = this.formatSQLWithParams(QueryResult.sql, QueryResult.params);
|
|
1630
|
+
this.config.verbose && console.log(`[SQL EXECUTOR] 🧠 Formatted ${method.toUpperCase()} SQL:`, formatted);
|
|
1631
|
+
const toUnnamed = namedPlaceholders();
|
|
1632
|
+
const [sql, values] = toUnnamed(QueryResult.sql, QueryResult.params);
|
|
1633
|
+
return await this.withConnection(async (conn) => {
|
|
1634
|
+
const [result] = await conn.query(sql, values);
|
|
1635
|
+
if (method === 'GET') {
|
|
1636
|
+
this.config.verbose && console.log(`[SQL EXECUTOR] 📦 Rows fetched:`, result);
|
|
1637
|
+
return {
|
|
1638
|
+
rest: result.map(this.serialize),
|
|
1639
|
+
sql: { sql, values }
|
|
1640
|
+
};
|
|
1641
|
+
}
|
|
1642
|
+
else {
|
|
1643
|
+
this.config.verbose && console.log(`[SQL EXECUTOR] ✏️ Rows affected:`, result.affectedRows);
|
|
1644
|
+
return {
|
|
1645
|
+
affected: result.affectedRows,
|
|
1646
|
+
rest: [],
|
|
1647
|
+
sql: { sql, values }
|
|
1648
|
+
};
|
|
1649
|
+
}
|
|
1824
1650
|
});
|
|
1825
|
-
}
|
|
1826
|
-
|
|
1827
|
-
}(Executor));
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
1828
1653
|
|
|
1829
1654
|
var SqlExecutor$1 = /*#__PURE__*/Object.freeze({
|
|
1830
1655
|
__proto__: null,
|
|
@@ -1833,101 +1658,80 @@ var SqlExecutor$1 = /*#__PURE__*/Object.freeze({
|
|
|
1833
1658
|
|
|
1834
1659
|
// TODO - WE MUST make this a generic - optional, but helpful
|
|
1835
1660
|
// note sure how it would help anyone actually...
|
|
1836
|
-
function ExpressHandler(
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1661
|
+
function ExpressHandler({ C6, mysqlPool }) {
|
|
1662
|
+
return async (req, res, next) => {
|
|
1663
|
+
try {
|
|
1664
|
+
const method = req.method.toUpperCase();
|
|
1665
|
+
const table = req.params.table;
|
|
1666
|
+
const primary = req.params.primary;
|
|
1667
|
+
const payload = method === 'GET' ? req.query : req.body;
|
|
1668
|
+
if (!(table in C6.TABLES)) {
|
|
1669
|
+
res.status(400).json({ error: `Invalid table: ${table}` });
|
|
1670
|
+
return;
|
|
1671
|
+
}
|
|
1672
|
+
const primaryKeys = C6.TABLES[table].PRIMARY;
|
|
1673
|
+
if (primary && primaryKeys.length !== 1) {
|
|
1674
|
+
if (primaryKeys.length > 1) {
|
|
1675
|
+
res.status(400).json({ error: `Table ${table} has multiple primary keys. Cannot implicitly determine key.` });
|
|
1676
|
+
return;
|
|
1677
|
+
}
|
|
1678
|
+
res.status(400).json({
|
|
1679
|
+
error: `Table ${table} has no primary keys. Please specify one.`
|
|
1680
|
+
});
|
|
1681
|
+
return;
|
|
1682
|
+
}
|
|
1683
|
+
const primaryKeyName = primaryKeys[0];
|
|
1684
|
+
// 👇 Call restRequest for the resolved method
|
|
1685
|
+
// TODO - add primary conditionally based on method signature
|
|
1686
|
+
switch (method) {
|
|
1687
|
+
case 'GET':
|
|
1688
|
+
if (primary) {
|
|
1689
|
+
payload[C6C.WHERE][primaryKeyName] = primary;
|
|
1852
1690
|
}
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
}
|
|
1859
|
-
res.status(400).json({
|
|
1860
|
-
error: "Table ".concat(table, " has no primary keys. Please specify one.")
|
|
1861
|
-
});
|
|
1862
|
-
return [2 /*return*/];
|
|
1691
|
+
break;
|
|
1692
|
+
case 'PUT':
|
|
1693
|
+
case 'DELETE':
|
|
1694
|
+
if (primary) {
|
|
1695
|
+
payload[C6C.WHERE][primaryKeyName] = primary;
|
|
1863
1696
|
}
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
// TODO - add primary conditionally based on method signature
|
|
1867
|
-
switch (method) {
|
|
1868
|
-
case 'GET':
|
|
1869
|
-
if (primary) {
|
|
1870
|
-
payload[C6C.WHERE][primaryKeyName] = primary;
|
|
1871
|
-
}
|
|
1872
|
-
break;
|
|
1873
|
-
case 'PUT':
|
|
1874
|
-
case 'DELETE':
|
|
1875
|
-
if (primary) {
|
|
1876
|
-
payload[C6C.WHERE][primaryKeyName] = primary;
|
|
1877
|
-
}
|
|
1878
|
-
else {
|
|
1879
|
-
res.status(400).json({ error: "Invalid request: ".concat(method, " requires a primary key.") });
|
|
1880
|
-
}
|
|
1881
|
-
break;
|
|
1882
|
-
case 'POST':
|
|
1883
|
-
break;
|
|
1884
|
-
default:
|
|
1885
|
-
res.status(405).json({ error: "Method ".concat(method, " not allowed") });
|
|
1886
|
-
return [2 /*return*/];
|
|
1697
|
+
else {
|
|
1698
|
+
res.status(400).json({ error: `Invalid request: ${method} requires a primary key.` });
|
|
1887
1699
|
}
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
case 1:
|
|
1895
|
-
response = _a.sent();
|
|
1896
|
-
res.status(200).json(__assign({ success: true }, response));
|
|
1897
|
-
return [3 /*break*/, 3];
|
|
1898
|
-
case 2:
|
|
1899
|
-
err_1 = _a.sent();
|
|
1900
|
-
res.status(500).json({ success: false, error: err_1 });
|
|
1901
|
-
next(err_1);
|
|
1902
|
-
return [3 /*break*/, 3];
|
|
1903
|
-
case 3: return [2 /*return*/];
|
|
1700
|
+
break;
|
|
1701
|
+
case 'POST':
|
|
1702
|
+
break;
|
|
1703
|
+
default:
|
|
1704
|
+
res.status(405).json({ error: `Method ${method} not allowed` });
|
|
1705
|
+
return;
|
|
1904
1706
|
}
|
|
1905
|
-
|
|
1906
|
-
|
|
1707
|
+
const response = await restRequest({
|
|
1708
|
+
C6,
|
|
1709
|
+
mysqlPool,
|
|
1710
|
+
requestMethod: method,
|
|
1711
|
+
restModel: C6.TABLES[table]
|
|
1712
|
+
})(payload);
|
|
1713
|
+
res.status(200).json({ success: true, ...response });
|
|
1714
|
+
}
|
|
1715
|
+
catch (err) {
|
|
1716
|
+
res.status(500).json({ success: false, error: err });
|
|
1717
|
+
next(err);
|
|
1718
|
+
}
|
|
1719
|
+
};
|
|
1907
1720
|
}
|
|
1908
1721
|
|
|
1909
1722
|
// Alias a table name with a given alias
|
|
1910
|
-
|
|
1911
|
-
return "".concat(tableName, " ").concat(alias);
|
|
1912
|
-
};
|
|
1723
|
+
const A = (tableName, alias) => `${tableName} ${alias}`;
|
|
1913
1724
|
// Qualify a column constant (e.g. 'property_units.parcel_id') to an alias
|
|
1914
|
-
|
|
1915
|
-
return "".concat(alias, ".").concat(qualifiedCol.split('.').pop());
|
|
1916
|
-
};
|
|
1725
|
+
const F = (qualifiedCol, alias) => `${alias}.${qualifiedCol.split('.').pop()}`;
|
|
1917
1726
|
// Equal join condition using full-qualified column constants
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
_a[F(leftCol, leftAlias)] = F(rightCol, rightAlias),
|
|
1922
|
-
_a);
|
|
1923
|
-
};
|
|
1727
|
+
const fieldEq = (leftCol, rightCol, leftAlias, rightAlias) => ({
|
|
1728
|
+
[F(leftCol, leftAlias)]: F(rightCol, rightAlias)
|
|
1729
|
+
});
|
|
1924
1730
|
// ST_Distance_Sphere for aliased fields
|
|
1925
|
-
|
|
1926
|
-
return [C6C.ST_DISTANCE_SPHERE, F(fromCol, fromAlias), F(toCol, toAlias)];
|
|
1927
|
-
};
|
|
1731
|
+
const distSphere = (fromCol, toCol, fromAlias, toAlias) => [C6C.ST_DISTANCE_SPHERE, F(fromCol, fromAlias), F(toCol, toAlias)];
|
|
1928
1732
|
|
|
1929
1733
|
function determineRuntimeJsType(mysqlType) {
|
|
1930
|
-
|
|
1734
|
+
const base = mysqlType.toLowerCase().split('(')[0];
|
|
1931
1735
|
if ([
|
|
1932
1736
|
'binary', 'varbinary', 'blob', 'tinyblob', 'mediumblob', 'longblob'
|
|
1933
1737
|
].includes(base))
|
|
@@ -1948,23 +1752,15 @@ function determineRuntimeJsType(mysqlType) {
|
|
|
1948
1752
|
return 'string';
|
|
1949
1753
|
}
|
|
1950
1754
|
function getPrimaryKeyTypes(table) {
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
var fullKey = (_a = Object.entries(table.COLUMNS).find(function (_a) {
|
|
1955
|
-
_a[0]; var short = _a[1];
|
|
1956
|
-
return short === key;
|
|
1957
|
-
})) === null || _a === void 0 ? void 0 : _a[0];
|
|
1755
|
+
const result = {};
|
|
1756
|
+
for (const key of table.PRIMARY_SHORT) {
|
|
1757
|
+
const fullKey = Object.entries(table.COLUMNS).find(([_, short]) => short === key)?.[0];
|
|
1958
1758
|
if (typeof fullKey === 'string') {
|
|
1959
|
-
|
|
1759
|
+
const validation = table.TYPE_VALIDATION[fullKey];
|
|
1960
1760
|
if (!validation)
|
|
1961
|
-
|
|
1761
|
+
continue;
|
|
1962
1762
|
result[key] = determineRuntimeJsType(validation.MYSQL_TYPE);
|
|
1963
1763
|
}
|
|
1964
|
-
};
|
|
1965
|
-
for (var _i = 0, _b = table.PRIMARY_SHORT; _i < _b.length; _i++) {
|
|
1966
|
-
var key = _b[_i];
|
|
1967
|
-
_loop_1(key);
|
|
1968
1764
|
}
|
|
1969
1765
|
return result;
|
|
1970
1766
|
}
|
|
@@ -1973,42 +1769,30 @@ function getPrimaryKeyTypes(table) {
|
|
|
1973
1769
|
* Conditionally group a log if verbose.
|
|
1974
1770
|
*/
|
|
1975
1771
|
function group(title, data) {
|
|
1976
|
-
console.groupCollapsed(
|
|
1772
|
+
console.groupCollapsed(`%c${title}`, "color: #007acc");
|
|
1977
1773
|
if (data !== undefined)
|
|
1978
1774
|
console.log(data);
|
|
1979
1775
|
console.groupEnd();
|
|
1980
1776
|
}
|
|
1981
|
-
function info(message) {
|
|
1982
|
-
|
|
1983
|
-
for (var _i = 1; _i < arguments.length; _i++) {
|
|
1984
|
-
optional[_i - 1] = arguments[_i];
|
|
1985
|
-
}
|
|
1986
|
-
console.info.apply(console, __spreadArray(["%cINFO: ".concat(message), "color: #0a0"], optional, false));
|
|
1777
|
+
function info(message, ...optional) {
|
|
1778
|
+
console.info(`%cINFO: ${message}`, "color: #0a0", ...optional);
|
|
1987
1779
|
}
|
|
1988
|
-
function warn(message) {
|
|
1989
|
-
|
|
1990
|
-
for (var _i = 1; _i < arguments.length; _i++) {
|
|
1991
|
-
optional[_i - 1] = arguments[_i];
|
|
1992
|
-
}
|
|
1993
|
-
console.warn.apply(console, __spreadArray(["%cWARN: ".concat(message), "color: #e90"], optional, false));
|
|
1780
|
+
function warn(message, ...optional) {
|
|
1781
|
+
console.warn(`%cWARN: ${message}`, "color: #e90", ...optional);
|
|
1994
1782
|
}
|
|
1995
|
-
function error(message) {
|
|
1996
|
-
|
|
1997
|
-
for (var _i = 1; _i < arguments.length; _i++) {
|
|
1998
|
-
optional[_i - 1] = arguments[_i];
|
|
1999
|
-
}
|
|
2000
|
-
console.error.apply(console, __spreadArray(["%cERROR: ".concat(message), "color: #c00"], optional, false));
|
|
1783
|
+
function error(message, ...optional) {
|
|
1784
|
+
console.error(`%cERROR: ${message}`, "color: #c00", ...optional);
|
|
2001
1785
|
}
|
|
2002
1786
|
|
|
2003
1787
|
function checkAllRequestsComplete() {
|
|
2004
|
-
|
|
1788
|
+
const stillRunning = apiRequestCache.filter((cache) => undefined === cache.response);
|
|
2005
1789
|
if (stillRunning.length !== 0) {
|
|
2006
1790
|
if (document === null || document === undefined) {
|
|
2007
1791
|
throw new Error('document is undefined while waiting for API requests to complete (' + JSON.stringify(apiRequestCache) + ')');
|
|
2008
1792
|
}
|
|
2009
1793
|
// when requests return emtpy sets in full renders, it may not be possible to track their progress.
|
|
2010
1794
|
console.warn('stillRunning...', stillRunning);
|
|
2011
|
-
return stillRunning.map(
|
|
1795
|
+
return stillRunning.map((cache) => cache.requestArgumentsSerialized);
|
|
2012
1796
|
}
|
|
2013
1797
|
return true;
|
|
2014
1798
|
}
|
|
@@ -2021,7 +1805,7 @@ function onError(message) {
|
|
|
2021
1805
|
}
|
|
2022
1806
|
|
|
2023
1807
|
function isVerbose () {
|
|
2024
|
-
|
|
1808
|
+
const envVerbose = getEnvVar('VERBOSE') || getEnvVar('REACT_APP_VERBOSE') || getEnvVar('VITE_VERBOSE') || '';
|
|
2025
1809
|
return ['true', '1', 'yes', 'on'].includes(envVerbose.toLowerCase());
|
|
2026
1810
|
}
|
|
2027
1811
|
|