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