@carbonorm/carbonnode 3.0.12 → 3.0.15

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 CHANGED
@@ -4,6 +4,8 @@ var axios = require('axios');
4
4
  var Qs = require('qs');
5
5
  var tslib = require('tslib');
6
6
  var reactToastify = require('react-toastify');
7
+ var namedPlaceholders = require('named-placeholders');
8
+ var buffer = require('buffer');
7
9
 
8
10
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
9
11
  var C6Constants = {
@@ -69,6 +71,7 @@ var C6Constants = {
69
71
  LOCALTIMESTAMP: 'LOCALTIMESTAMP',
70
72
  MAKEDATE: 'MAKEDATE',
71
73
  MAKETIME: 'MAKETIME',
74
+ MATCH_AGAINST: 'MATCH_AGAINST',
72
75
  MONTHNAME: 'MONTHNAME',
73
76
  MICROSECOND: 'MICROSECOND',
74
77
  MINUTE: 'MINUTE',
@@ -443,203 +446,400 @@ var Executor = /** @class */ (function () {
443
446
  var SqlBuilder = /** @class */ (function (_super) {
444
447
  tslib.__extends(SqlBuilder, _super);
445
448
  function SqlBuilder() {
446
- return _super !== null && _super.apply(this, arguments) || this;
449
+ var _this = _super !== null && _super.apply(this, arguments) || this;
450
+ /** Flag to determine if named placeholders should be used */
451
+ _this.useNamedParams = false;
452
+ return _this;
447
453
  }
448
- /** Generate nested WHERE/JOIN conditions with parameter binding */
454
+ SqlBuilder.prototype.convertHexIfBinary = function (col, val) {
455
+ var _a;
456
+ var columnDef = (_a = this.config.C6.TABLES[this.config.restModel.TABLE_NAME].TYPE_VALIDATION) === null || _a === void 0 ? void 0 : _a[col];
457
+ if (typeof val === 'string' &&
458
+ /^[0-9a-fA-F]{32}$/.test(val) &&
459
+ typeof columnDef === 'object' &&
460
+ columnDef.MYSQL_TYPE.toUpperCase().includes('BINARY')) {
461
+ return Buffer.from(val, 'hex');
462
+ }
463
+ return val;
464
+ };
465
+ /** Generate nested WHERE/ON conditions with parameter binding (supports AND/OR/NOT) */
449
466
  SqlBuilder.prototype.buildBooleanJoinedConditions = function (set, andMode, params) {
467
+ var _this = this;
450
468
  if (andMode === void 0) { andMode = true; }
451
469
  if (params === void 0) { params = []; }
452
470
  var booleanOperator = andMode ? 'AND' : 'OR';
453
- var OPERATORS = ['=', '!=', '<', '<=', '>', '>=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'IS', 'IS NOT'];
454
- var isAggregateArray = function (value) {
455
- return Array.isArray(value) && typeof value[0] === 'string' && OPERATORS.includes(value[0]);
456
- };
471
+ var OPERATORS = [
472
+ '=', '!=', '<', '<=', '>', '>=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'IS', 'IS NOT',
473
+ 'BETWEEN', 'NOT BETWEEN', C6Constants.MATCH_AGAINST
474
+ ];
457
475
  var isNumericKeyed = function (obj) {
458
476
  return Array.isArray(obj) && Object.keys(obj).every(function (k) { return /^\d+$/.test(k); });
459
477
  };
478
+ // Helper to add a single condition with proper parameter binding
460
479
  var addCondition = function (column, op, value) {
461
480
  var clause;
462
- /*if (Buffer.isBuffer(value)) { // TODO - I want this as a parameterized option, for now default to faster
463
- params.push(value.toString('hex')); // Or use UNHEX(?) in SQL
464
- clause = `(${column} = UNHEX(?))`;
465
- } else {*/
466
- params.push(value);
467
- clause = "( ".concat(column, " ").concat(op, " ? )");
468
- //}
469
- isVerbose() && console.log("[WHERE] \u2795 ".concat(clause, " ->"), value);
481
+ // If using named parameters, generate a unique key; otherwise use positional placeholder
482
+ var addParam = function (val) {
483
+ if (Array.isArray(params)) {
484
+ // Positional (unnamed) parameter
485
+ params.push(_this.convertHexIfBinary(column, val));
486
+ return '?';
487
+ }
488
+ else {
489
+ // Named parameter mode
490
+ var key = "param".concat(Object.keys(params).length);
491
+ params[key] = _this.convertHexIfBinary(column, val);
492
+ return ":".concat(key);
493
+ }
494
+ };
495
+ if ((op === 'IN' || op === 'NOT IN') && Array.isArray(value)) {
496
+ if (value.length === 0) {
497
+ // Edge case: empty IN list - use a condition that's always false
498
+ clause = "( ".concat(column, " ").concat(op, " (NULL) )");
499
+ isVerbose() && console.warn("[WHERE] Empty list for ".concat(op, " on ").concat(column));
500
+ }
501
+ else {
502
+ var placeholders = value.map(function (val) { return addParam(val); }).join(', ');
503
+ clause = "( ".concat(column, " ").concat(op, " (").concat(placeholders, ") )");
504
+ }
505
+ }
506
+ else if ((op === 'BETWEEN' || op === 'NOT BETWEEN') && Array.isArray(value) && value.length === 2) {
507
+ // BETWEEN expects exactly two values [min, max]
508
+ var minVal = value[0], maxVal = value[1];
509
+ var ph1 = addParam(minVal);
510
+ var ph2 = addParam(maxVal);
511
+ clause = "( ".concat(column, " ").concat(op, " ").concat(ph1, " AND ").concat(ph2, " )");
512
+ }
513
+ else {
514
+ // Default case for single-value operators (including IS, IS NOT, =, etc.)
515
+ // Note: If value is null and op is 'IS' or 'IS NOT', the placeholder will safely bind null.
516
+ var ph = addParam(value);
517
+ clause = "( ".concat(column, " ").concat(op, " ").concat(ph, " )");
518
+ }
519
+ isVerbose() && console.log("[WHERE] \u2795 ".concat(clause));
470
520
  return clause;
471
521
  };
472
522
  var sql;
473
523
  if (isNumericKeyed(set)) {
474
- isVerbose() && console.log("[WHERE] Numeric keyed condition:", set);
475
- switch (set.length) {
476
- case 2:
477
- sql = addCondition(set[0], '=', set[1]);
478
- break;
479
- case 3:
480
- if (!OPERATORS.includes(set[1]))
481
- throw new Error("Invalid operator: ".concat(set[1]));
482
- sql = addCondition(set[0], set[1], set[2]);
483
- break;
484
- default:
485
- throw new Error("Invalid array condition: ".concat(JSON.stringify(set)));
524
+ // Array of conditions, use opposite boolean mode for combining (AND/OR swap)
525
+ isVerbose() && console.log("[WHERE] Grouping conditions (array) in ".concat(andMode ? 'AND' : 'OR', " mode:"), set);
526
+ if (set.length === 0) {
527
+ sql = ''; // no conditions
528
+ }
529
+ else if (set.length === 1) {
530
+ // Single element array, just build it normally (no boolean operator needed)
531
+ sql = this.buildBooleanJoinedConditions(set[0], true, params);
532
+ }
533
+ else {
534
+ // Multiple conditions: join them with the opposite of current mode
535
+ var subClauses = set.map(function (item) { return _this.buildBooleanJoinedConditions(item, true, params); });
536
+ var op = andMode ? 'OR' : 'AND';
537
+ sql = subClauses.map(function (sc) { return "(".concat(sc, ")"); }).join(" ".concat(op, " "));
486
538
  }
487
539
  }
488
- else {
540
+ else if (typeof set === 'object') {
489
541
  var parts = [];
490
542
  for (var _i = 0, _a = Object.entries(set); _i < _a.length; _i++) {
491
543
  var _b = _a[_i], key = _b[0], value = _b[1];
492
544
  if (/^\d+$/.test(key)) {
545
+ // Numeric object keys (should not happen because numeric arrays handled above)
493
546
  parts.push(this.buildBooleanJoinedConditions(value, !andMode, params));
494
547
  }
495
- else if (!Array.isArray(value) || isAggregateArray(value)) {
496
- parts.push(addCondition(key, '=', value));
548
+ else if (key.toUpperCase() === 'NOT') {
549
+ // NOT operator: negate the inner condition(s)
550
+ var negated = this.buildBooleanJoinedConditions(value, true, params);
551
+ parts.push("NOT (".concat(negated, ")"));
552
+ isVerbose() && console.log("[WHERE] NOT block: (".concat(negated, ")"));
553
+ }
554
+ else if (!Array.isArray(value)) {
555
+ if (typeof value === 'object' && value !== null && Object.keys(value).length === 1) {
556
+ var _c = Object.entries(value)[0], op = _c[0], val = _c[1];
557
+ if (OPERATORS.includes(op.toUpperCase())) {
558
+ if (value !== null &&
559
+ C6Constants.MATCH_AGAINST in value &&
560
+ Array.isArray(value[C6Constants.MATCH_AGAINST])) {
561
+ var _d = value[C6Constants.MATCH_AGAINST], search = _d[0], mode = _d[1];
562
+ var paramName = "param".concat(Object.keys(params).length);
563
+ params[paramName] = search;
564
+ var againstClause = void 0;
565
+ switch (mode === null || mode === void 0 ? void 0 : mode.toUpperCase()) {
566
+ case 'BOOLEAN':
567
+ againstClause = "AGAINST(:".concat(paramName, " IN BOOLEAN MODE)");
568
+ break;
569
+ case 'WITH QUERY EXPANSION':
570
+ againstClause = "AGAINST(:".concat(paramName, " WITH QUERY EXPANSION)");
571
+ break;
572
+ case 'NATURAL':
573
+ case undefined:
574
+ case null:
575
+ againstClause = "AGAINST(:".concat(paramName, ")"); // default natural language mode
576
+ break;
577
+ default:
578
+ throw new Error("Unsupported MATCH_AGAINST mode: ".concat(mode));
579
+ }
580
+ parts.push("(MATCH(".concat(key, ") ").concat(againstClause, ")"));
581
+ continue;
582
+ }
583
+ parts.push(addCondition(key, op.toUpperCase(), val));
584
+ }
585
+ else {
586
+ throw new Error("Unsupported operator '".concat(op, "' for key '").concat(key, "'"));
587
+ }
588
+ }
589
+ else {
590
+ // Fallback: treat as simple equality
591
+ parts.push(addCondition(key, '=', value));
592
+ }
497
593
  }
498
594
  else if (value.length === 2 && OPERATORS.includes(value[0])) {
595
+ // Two-element array, first is an operator (like ['>', 5])
499
596
  parts.push(addCondition(key, value[0], value[1]));
500
597
  }
598
+ else if (value.length === 3 && OPERATORS.includes(value[0])) {
599
+ // Three-element array, e.g. ['BETWEEN', min, max]
600
+ parts.push(addCondition(key, value[0], value.slice(1)));
601
+ }
501
602
  else {
502
603
  throw new Error("Invalid condition for ".concat(key, ": ").concat(JSON.stringify(value)));
503
604
  }
504
605
  }
505
- sql = parts.join(" ".concat(booleanOperator, " "));
606
+ sql = parts.length ? parts.join(" ".concat(booleanOperator, " ")) : '';
607
+ }
608
+ else {
609
+ // Primitive type (should not happen normally), treat it as a boolean expression string
610
+ sql = String(set);
506
611
  }
507
- isVerbose() && console.log("[WHERE] Final: (".concat(sql, ")"));
508
- return "(".concat(sql, ")");
612
+ // Wrap the final combined condition in parentheses to maintain correct precedence
613
+ return sql ? "(".concat(sql, ")") : '';
509
614
  };
510
- /** Translate array or function calls into SQL expressions */
615
+ /** Translate array or function call definitions into SQL expressions (supports nested calls) */
511
616
  SqlBuilder.prototype.buildAggregateField = function (field) {
512
- if (typeof field === 'string')
617
+ var _this = this;
618
+ if (typeof field === 'string') {
513
619
  return field;
514
- if (!Array.isArray(field))
515
- throw new Error('Invalid SELECT entry');
620
+ }
621
+ if (!Array.isArray(field) || field.length === 0) {
622
+ throw new Error('Invalid SELECT field entry');
623
+ }
624
+ // e.g. field = [ 'ROUND', [ 'SQRT', 'age' ], 2, 'AS', 'roundedRootAge' ]
516
625
  var fn = field[0], args = field.slice(1);
517
626
  var alias;
518
- if (args.length >= 2 && args[args.length - 2] === 'AS') {
519
- alias = String(args.pop());
520
- args.pop();
627
+ // Handle alias if present in array (e.g. ... 'AS', 'aliasName')
628
+ if (args.length >= 2 && String(args[args.length - 2]).toUpperCase() === 'AS') {
629
+ alias = String(args.pop()); // last element is alias name
630
+ args.pop(); // remove the 'AS'
521
631
  }
522
632
  var F = String(fn).toUpperCase();
523
- var p = args.join(', ');
524
- isVerbose() && console.log("[SELECT] ".concat(F, "(").concat(p, ")").concat(alias ? " AS ".concat(alias) : ''));
633
+ // Map each argument to SQL string, handling nested function arrays recursively
634
+ var argList = args.map(function (arg) {
635
+ if (Array.isArray(arg)) {
636
+ return _this.buildAggregateField(arg);
637
+ }
638
+ else {
639
+ return arg;
640
+ }
641
+ }).join(', ');
642
+ var expr;
525
643
  switch (F) {
526
644
  case 'DATE_ADD':
527
- return "DATE_ADD(".concat(args[0], ", ").concat(args[1], ")").concat(alias ? " AS ".concat(alias) : '');
528
645
  case 'DATE_SUB':
529
- return "DATE_SUB(".concat(args[0], ", ").concat(args[1], ")").concat(alias ? " AS ".concat(alias) : '');
646
+ // Functions with comma-separated interval, assume args like [ date, interval_expression ]
647
+ expr = "".concat(F, "(").concat(argList, ")");
648
+ break;
530
649
  case 'YEAR':
531
- return "YEAR(".concat(args[0], ")").concat(alias ? " AS ".concat(alias) : '');
532
650
  case 'MONTH':
533
- return "MONTH(".concat(args[0], ")").concat(alias ? " AS ".concat(alias) : '');
534
651
  case 'DAY':
535
- return "DAY(".concat(args[0], ")").concat(alias ? " AS ".concat(alias) : '');
536
652
  case 'ROUND':
537
653
  case 'CEIL':
538
654
  case 'FLOOR':
539
655
  case 'ABS':
540
656
  case 'SQRT':
541
- return "".concat(F, "(").concat(p, ")").concat(alias ? " AS ".concat(alias) : '');
657
+ case 'UPPER':
658
+ case 'LOWER':
659
+ case 'COALESCE':
660
+ case 'CONCAT':
661
+ case 'IFNULL':
662
+ case 'IF':
663
+ case 'COUNT':
664
+ case 'SUM':
665
+ case 'MIN':
666
+ case 'MAX':
667
+ case 'AVG':
668
+ // Common SQL functions – just format as F(arg1, arg2, ...)
669
+ expr = "".concat(F, "(").concat(argList, ")");
670
+ break;
542
671
  case 'ST_DISTANCE':
543
- return "ST_Distance(".concat(p, ")").concat(alias ? " AS ".concat(alias) : '');
672
+ expr = "ST_Distance(".concat(argList, ")");
673
+ break;
544
674
  default:
545
- if (/^[A-Z_]+$/.test(F))
546
- return "".concat(F, "(").concat(p, ")").concat(alias ? " AS ".concat(alias) : '');
547
- throw new Error("Unsupported function: ".concat(F));
675
+ if (/^[A-Z_]+$/.test(F)) {
676
+ // Allow any other SQL function by name (assuming it's a valid function)
677
+ expr = "".concat(F, "(").concat(argList, ")");
678
+ }
679
+ else {
680
+ throw new Error("Unsupported function: ".concat(F));
681
+ }
682
+ }
683
+ if (alias) {
684
+ expr += " AS ".concat(alias);
685
+ }
686
+ isVerbose() && console.log("[SELECT] ".concat(expr));
687
+ return expr;
688
+ };
689
+ SqlBuilder.prototype.buildJoinClauses = function (joinArgs, params) {
690
+ var sql = '';
691
+ for (var joinType in joinArgs) {
692
+ var jk = joinType.replace('_', ' ').toUpperCase();
693
+ for (var joinTable in joinArgs[joinType]) {
694
+ var onConditions = joinArgs[joinType][joinTable];
695
+ var onClause = this.buildBooleanJoinedConditions(onConditions, true, params);
696
+ sql += " ".concat(jk, " JOIN `").concat(joinTable, "` ON ").concat(onClause);
697
+ isVerbose() && console.log("[JOIN] ".concat(jk, " JOIN ").concat(joinTable, " ON ").concat(onClause));
698
+ }
548
699
  }
700
+ return sql;
701
+ };
702
+ SqlBuilder.prototype.buildPaginationClause = function (pagination, _params) {
703
+ var _a;
704
+ var sql = '';
705
+ if (pagination === null || pagination === void 0 ? void 0 : pagination[C6Constants.ORDER]) {
706
+ var orderParts = Object.entries(pagination[C6Constants.ORDER])
707
+ .map(function (_a) {
708
+ var col = _a[0], dir = _a[1];
709
+ return "".concat(col, " ").concat(String(dir).toUpperCase());
710
+ });
711
+ sql += " ORDER BY ".concat(orderParts.join(', '));
712
+ isVerbose() && console.log("[ORDER BY] ".concat(orderParts));
713
+ }
714
+ if ((pagination === null || pagination === void 0 ? void 0 : pagination[C6Constants.LIMIT]) != null) {
715
+ var lim = parseInt(pagination[C6Constants.LIMIT], 10);
716
+ var page = parseInt((_a = pagination[C6Constants.PAGE]) !== null && _a !== void 0 ? _a : 1, 10);
717
+ var offset = (page - 1) * lim;
718
+ sql += " LIMIT ".concat(offset, ", ").concat(lim);
719
+ isVerbose() && console.log("[LIMIT] ".concat(offset, ", ").concat(lim));
720
+ }
721
+ return sql;
722
+ };
723
+ SqlBuilder.prototype.buildWhereClause = function (whereArg, params) {
724
+ var whereClause = this.buildBooleanJoinedConditions(whereArg, true, params);
725
+ if (whereClause) {
726
+ var trimmed = whereClause.replace(/^\((.*)\)$/, '$1');
727
+ isVerbose() && console.log("[WHERE] ".concat(trimmed));
728
+ return " WHERE ".concat(trimmed);
729
+ }
730
+ return '';
549
731
  };
550
- /** Compose a parameterized SELECT query with optional JOIN/WHERE/GROUP/HAVING/PAGINATION */
551
732
  SqlBuilder.prototype.buildSelectQuery = function (table, primary, args, isSubSelect) {
552
733
  var _this = this;
553
- var _a, _b, _c, _d;
734
+ var _a, _b, _c;
554
735
  if (isSubSelect === void 0) { isSubSelect = false; }
555
736
  var model = this.config.C6.TABLES[table];
556
- var params = [];
557
- // SELECT
737
+ var params = this.useNamedParams ? {} : [];
558
738
  var selectList = (_a = args === null || args === void 0 ? void 0 : args[C6Constants.SELECT]) !== null && _a !== void 0 ? _a : ['*'];
559
739
  var selectFields = Array.isArray(selectList)
560
740
  ? selectList.map(function (f) { return _this.buildAggregateField(f); }).join(', ')
561
- : '*';
741
+ : String(selectList);
562
742
  var sql = "SELECT ".concat(selectFields, " FROM ").concat(table);
563
- isVerbose() && console.log("[SELECT]", selectFields);
564
- // JOIN
565
743
  if (args === null || args === void 0 ? void 0 : args[C6Constants.JOIN]) {
566
- for (var jt in args[C6Constants.JOIN]) {
567
- var jk = jt.replace('_', ' ').toUpperCase();
568
- for (var jn in args[C6Constants.JOIN][jt]) {
569
- var on = this.buildBooleanJoinedConditions(args[C6Constants.JOIN][jt][jn], true, params);
570
- sql += " ".concat(jk, " JOIN `").concat(jn, "` ON ").concat(on);
571
- isVerbose() && console.log("[JOIN]", jk, jn, on);
572
- }
573
- }
744
+ sql += this.buildJoinClauses(args[C6Constants.JOIN], params);
574
745
  }
575
- // WHERE
576
746
  if (args === null || args === void 0 ? void 0 : args[C6Constants.WHERE]) {
577
- var wc = this.buildBooleanJoinedConditions(args[C6Constants.WHERE], true, params);
578
- // Trim leading and trailing parentheses if they fully wrap the condition
579
- while (wc.startsWith('(') && wc.endsWith(')')) {
580
- wc = wc.slice(1, -1).trim();
581
- }
582
- sql += " WHERE ".concat(wc);
747
+ sql += this.buildWhereClause(args[C6Constants.WHERE], params);
583
748
  }
584
- // GROUP BY
585
749
  if (args === null || args === void 0 ? void 0 : args[C6Constants.GROUP_BY]) {
586
750
  var gb = Array.isArray(args[C6Constants.GROUP_BY])
587
751
  ? args[C6Constants.GROUP_BY].join(', ')
588
752
  : args[C6Constants.GROUP_BY];
589
753
  sql += " GROUP BY ".concat(gb);
590
- isVerbose() && console.log("[GROUP BY]", gb);
754
+ isVerbose() && console.log("[GROUP BY] ".concat(gb));
591
755
  }
592
- // HAVING
593
756
  if (args === null || args === void 0 ? void 0 : args[C6Constants.HAVING]) {
594
- var hc = this.buildBooleanJoinedConditions(args[C6Constants.HAVING], true, params);
595
- sql += " HAVING ".concat(hc);
757
+ var havingClause = this.buildBooleanJoinedConditions(args[C6Constants.HAVING], true, params);
758
+ if (havingClause) {
759
+ sql += " HAVING ".concat(havingClause);
760
+ }
596
761
  }
597
- // PAGINATION
598
762
  if (args === null || args === void 0 ? void 0 : args[C6Constants.PAGINATION]) {
599
- var p = args[C6Constants.PAGINATION];
600
- if (p[C6Constants.ORDER]) {
601
- var ord = Object.entries(p[C6Constants.ORDER]).map(function (_a) {
602
- var c = _a[0], d = _a[1];
603
- return "".concat(c, " ").concat(String(d).toUpperCase());
604
- });
605
- sql += " ORDER BY ".concat(ord.join(', '));
606
- isVerbose() && console.log("[ORDER BY]", ord);
607
- }
608
- if (p[C6Constants.LIMIT] != null) {
609
- var lim = parseInt(p[C6Constants.LIMIT], 10);
610
- var pg = parseInt((_b = p[C6Constants.PAGE]) !== null && _b !== void 0 ? _b : 1, 10);
611
- var off = (pg - 1) * lim;
612
- sql += " LIMIT ".concat(off, ", ").concat(lim);
613
- isVerbose() && console.log("[LIMIT]", off, lim);
614
- }
763
+ sql += this.buildPaginationClause(args[C6Constants.PAGINATION], params);
615
764
  }
616
- // Fallback ORDER/LIMIT
617
765
  else if (!isSubSelect) {
618
- var ok = void 0;
619
- if (primary)
620
- ok = primary;
621
- else if ((_c = model === null || model === void 0 ? void 0 : model.PRIMARY_SHORT) === null || _c === void 0 ? void 0 : _c[0])
622
- ok = model.PRIMARY_SHORT[0];
623
- else
624
- for (var _i = 0, _e = ['created_at', 'updated_at']; _i < _e.length; _i++) {
625
- var ts = _e[_i];
626
- if ((_d = model === null || model === void 0 ? void 0 : model.COLUMNS) === null || _d === void 0 ? void 0 : _d["".concat(table, ".").concat(ts)]) {
627
- ok = ts;
766
+ var orderKey = primary || ((_b = model === null || model === void 0 ? void 0 : model.PRIMARY_SHORT) === null || _b === void 0 ? void 0 : _b[0]);
767
+ if (!orderKey) {
768
+ for (var _i = 0, _d = ['created_at', 'updated_at']; _i < _d.length; _i++) {
769
+ var ts = _d[_i];
770
+ if ((_c = model === null || model === void 0 ? void 0 : model.COLUMNS) === null || _c === void 0 ? void 0 : _c["".concat(table, ".").concat(ts)]) {
771
+ orderKey = ts;
628
772
  break;
629
773
  }
630
774
  }
631
- if (ok) {
775
+ }
776
+ if (orderKey) {
632
777
  var dir = primary ? 'ASC' : 'DESC';
633
- var lim = primary ? 1 : 100;
634
- sql += " ORDER BY ".concat(ok, " ").concat(dir, " LIMIT ").concat(lim);
635
- isVerbose() && console.log("[ORDER]", ok, dir, lim);
778
+ sql += " ORDER BY ".concat(orderKey, " ").concat(dir, " LIMIT ").concat(primary ? 1 : 100);
779
+ isVerbose() && console.log("[DEFAULT ORDER] ".concat(orderKey, " ").concat(dir));
636
780
  }
637
781
  else {
638
782
  sql += " LIMIT 100";
639
- isVerbose() && console.warn("[ORDER] fallback LIMIT 100");
783
+ isVerbose() && console.warn("[DEFAULT LIMIT] 100 (no order key found)");
784
+ }
785
+ }
786
+ isVerbose() && console.log("[SQL SELECT]", sql, params);
787
+ return { sql: sql, params: params };
788
+ };
789
+ SqlBuilder.prototype.buildUpdateQuery = function (table, data, args) {
790
+ if (args === void 0) { args = {}; }
791
+ var params = this.useNamedParams ? {} : [];
792
+ var sql = "UPDATE ".concat(table);
793
+ if (args[C6Constants.JOIN]) {
794
+ sql += this.buildJoinClauses(args[C6Constants.JOIN], params);
795
+ }
796
+ var setClauses = [];
797
+ for (var _i = 0, _a = Object.entries(data); _i < _a.length; _i++) {
798
+ var _b = _a[_i], col = _b[0], val = _b[1];
799
+ if (Array.isArray(val)) {
800
+ var expr = this.buildAggregateField(val);
801
+ setClauses.push("`".concat(col, "` = ").concat(expr));
802
+ }
803
+ else {
804
+ var key = "param".concat(Array.isArray(params) ? params.length : Object.keys(params).length);
805
+ if (Array.isArray(params)) {
806
+ params.push(val);
807
+ setClauses.push("`".concat(col, "` = ?"));
808
+ }
809
+ else {
810
+ params[key] = val;
811
+ setClauses.push("`".concat(col, "` = :").concat(key));
812
+ }
640
813
  }
641
814
  }
642
- isVerbose() && console.log("[SQL]", sql, params);
815
+ sql += " SET ".concat(setClauses.join(', '));
816
+ isVerbose() && console.log("[SET] ".concat(setClauses));
817
+ if (args[C6Constants.WHERE]) {
818
+ sql += this.buildWhereClause(args[C6Constants.WHERE], params);
819
+ }
820
+ if (args[C6Constants.PAGINATION]) {
821
+ sql += this.buildPaginationClause(args[C6Constants.PAGINATION], params);
822
+ }
823
+ isVerbose() && console.log("[SQL UPDATE]", sql, params);
824
+ return { sql: sql, params: params };
825
+ };
826
+ /** Compose a DELETE query with optional JOIN and WHERE clauses */
827
+ SqlBuilder.prototype.buildDeleteQuery = function (table, args) {
828
+ if (args === void 0) { args = {}; }
829
+ var params = this.useNamedParams ? {} : [];
830
+ var sql = args[C6Constants.JOIN]
831
+ ? "DELETE ".concat(table, " FROM ").concat(table)
832
+ : "DELETE FROM ".concat(table);
833
+ if (args[C6Constants.JOIN]) {
834
+ sql += this.buildJoinClauses(args[C6Constants.JOIN], params);
835
+ }
836
+ if (args[C6Constants.WHERE]) {
837
+ sql += this.buildWhereClause(args[C6Constants.WHERE], params);
838
+ }
839
+ if (args[C6Constants.PAGINATION]) {
840
+ sql += this.buildPaginationClause(args[C6Constants.PAGINATION], params);
841
+ }
842
+ isVerbose() && console.log("[SQL DELETE]", sql, params);
643
843
  return { sql: sql, params: params };
644
844
  };
645
845
  return SqlBuilder;
@@ -1366,7 +1566,12 @@ var HttpExecutor$1 = /*#__PURE__*/Object.freeze({
1366
1566
  var SqlExecutor = /** @class */ (function (_super) {
1367
1567
  tslib.__extends(SqlExecutor, _super);
1368
1568
  function SqlExecutor() {
1369
- return _super !== null && _super.apply(this, arguments) || this;
1569
+ var _this = _super !== null && _super.apply(this, arguments) || this;
1570
+ _this.serialize = function (row) { return Object.fromEntries(Object.entries(row).map(function (_a) {
1571
+ var k = _a[0], v = _a[1];
1572
+ return [k, buffer.Buffer.isBuffer(v) ? v.toString('hex').toUpperCase() : v];
1573
+ })); };
1574
+ return _this;
1370
1575
  }
1371
1576
  SqlExecutor.prototype.execute = function () {
1372
1577
  return tslib.__awaiter(this, void 0, void 0, function () {
@@ -1390,7 +1595,7 @@ var SqlExecutor = /** @class */ (function (_super) {
1390
1595
  case 2:
1391
1596
  rest = _b.sent();
1392
1597
  console.log("[SQL EXECUTOR] \u2705 GET result:", rest);
1393
- return [2 /*return*/, { rest: rest }];
1598
+ return [2 /*return*/, rest];
1394
1599
  case 3: return [4 /*yield*/, this.insert(TABLE_NAME, this.request)];
1395
1600
  case 4:
1396
1601
  result = _b.sent();
@@ -1401,11 +1606,7 @@ var SqlExecutor = /** @class */ (function (_super) {
1401
1606
  case 6:
1402
1607
  result = _b.sent();
1403
1608
  console.log("[SQL EXECUTOR] \u2705 PUT result:", result);
1404
- updated = {
1405
- rest: result,
1406
- updated: true,
1407
- rowCount: result.affectedRows
1408
- };
1609
+ updated = tslib.__assign(tslib.__assign({}, result), { updated: true, rowCount: result.rest.affectedRows });
1409
1610
  return [2 /*return*/, updated];
1410
1611
  case 7: return [4 /*yield*/, this.delete(TABLE_NAME, [], this.request)];
1411
1612
  case 8:
@@ -1414,7 +1615,7 @@ var SqlExecutor = /** @class */ (function (_super) {
1414
1615
  deleted = {
1415
1616
  rest: result,
1416
1617
  deleted: true,
1417
- rowCount: result.affectedRows
1618
+ rowCount: result.rest.affectedRows
1418
1619
  };
1419
1620
  return [2 /*return*/, deleted];
1420
1621
  case 9: throw new Error("Unsupported request method: ".concat(method));
@@ -1449,28 +1650,36 @@ var SqlExecutor = /** @class */ (function (_super) {
1449
1650
  };
1450
1651
  SqlExecutor.prototype.select = function (table, primary, args) {
1451
1652
  return tslib.__awaiter(this, void 0, void 0, function () {
1452
- var sql, formatted;
1653
+ var QueryResult, formatted, toUnnamed, _a, sql, values;
1453
1654
  var _this = this;
1454
- return tslib.__generator(this, function (_a) {
1455
- switch (_a.label) {
1655
+ return tslib.__generator(this, function (_b) {
1656
+ switch (_b.label) {
1456
1657
  case 0:
1457
- sql = this.buildSelectQuery(table, primary, args);
1458
- console.log("[SQL EXECUTOR] \uD83E\uDDE0 Generated SELECT SQL:", sql);
1459
- formatted = this.formatSQLWithParams(sql.sql, sql.params);
1658
+ QueryResult = this.buildSelectQuery(table, primary, args);
1659
+ console.log("[SQL EXECUTOR] \uD83E\uDDE0 Generated SELECT SQL:", QueryResult);
1660
+ formatted = this.formatSQLWithParams(QueryResult.sql, QueryResult.params);
1460
1661
  console.log("[SQL EXECUTOR] \uD83E\uDDE0 Formatted SELECT SQL:", formatted);
1662
+ toUnnamed = namedPlaceholders();
1663
+ _a = toUnnamed(QueryResult.sql, QueryResult.params), sql = _a[0], values = _a[1];
1461
1664
  return [4 /*yield*/, this.withConnection(function (conn) { return tslib.__awaiter(_this, void 0, void 0, function () {
1462
1665
  var rows;
1463
1666
  return tslib.__generator(this, function (_a) {
1464
1667
  switch (_a.label) {
1465
- case 0: return [4 /*yield*/, conn.query(sql.sql, sql.params)];
1668
+ case 0: return [4 /*yield*/, conn.query(sql, values)];
1466
1669
  case 1:
1467
1670
  rows = (_a.sent())[0];
1468
1671
  console.log("[SQL EXECUTOR] \uD83D\uDCE6 Rows fetched:", rows);
1469
- return [2 /*return*/, rows];
1672
+ return [2 /*return*/, {
1673
+ rest: rows.map(this.serialize),
1674
+ sql: {
1675
+ sql: sql,
1676
+ values: values
1677
+ }
1678
+ }];
1470
1679
  }
1471
1680
  });
1472
1681
  }); })];
1473
- case 1: return [2 /*return*/, _a.sent()];
1682
+ case 1: return [2 /*return*/, _b.sent()];
1474
1683
  }
1475
1684
  });
1476
1685
  });
@@ -1485,7 +1694,7 @@ var SqlExecutor = /** @class */ (function (_super) {
1485
1694
  keys = Object.keys(data);
1486
1695
  values = keys.map(function (k) { return data[k]; });
1487
1696
  placeholders = keys.map(function () { return '?'; }).join(', ');
1488
- sql = "INSERT INTO `".concat(table, "` (").concat(keys.join(', '), ") VALUES (").concat(placeholders, ")");
1697
+ sql = "INSERT INTO `".concat(table, "` (").concat(keys.join(', '), ")\n VALUES (").concat(placeholders, ")");
1489
1698
  console.log("[SQL EXECUTOR] \uD83E\uDDE0 Generated INSERT SQL:", sql);
1490
1699
  console.log("[SQL EXECUTOR] \uD83D\uDD22 Values:", values);
1491
1700
  return [4 /*yield*/, this.withConnection(function (conn) { return tslib.__awaiter(_this, void 0, void 0, function () {
@@ -1495,7 +1704,13 @@ var SqlExecutor = /** @class */ (function (_super) {
1495
1704
  case 0: return [4 /*yield*/, conn.execute(sql, values)];
1496
1705
  case 1:
1497
1706
  result = (_a.sent())[0];
1498
- return [2 /*return*/, result];
1707
+ return [2 /*return*/, {
1708
+ rest: result,
1709
+ sql: {
1710
+ sql: sql,
1711
+ placeholders: placeholders
1712
+ }
1713
+ }];
1499
1714
  }
1500
1715
  });
1501
1716
  }); })];
@@ -1516,7 +1731,7 @@ var SqlExecutor = /** @class */ (function (_super) {
1516
1731
  keys = Object.keys(data);
1517
1732
  values = keys.map(function (k) { return data[k]; });
1518
1733
  updates = keys.map(function (k) { return "`".concat(k, "` = ?"); }).join(', ');
1519
- sql = "UPDATE `".concat(table, "` SET ").concat(updates, " WHERE `").concat(primary[0], "` = ?");
1734
+ sql = "UPDATE `".concat(table, "`\n SET ").concat(updates, "\n WHERE `").concat(primary[0], "` = ?");
1520
1735
  values.push(data[primary[0]]);
1521
1736
  console.log("[SQL EXECUTOR] \uD83E\uDDE0 Generated UPDATE SQL:", sql);
1522
1737
  console.log("[SQL EXECUTOR] \uD83D\uDD22 Values:", values);
@@ -1527,7 +1742,13 @@ var SqlExecutor = /** @class */ (function (_super) {
1527
1742
  case 0: return [4 /*yield*/, conn.execute(sql, values)];
1528
1743
  case 1:
1529
1744
  result = (_a.sent())[0];
1530
- return [2 /*return*/, result];
1745
+ return [2 /*return*/, {
1746
+ rest: result,
1747
+ sql: {
1748
+ sql: sql,
1749
+ values: values
1750
+ }
1751
+ }];
1531
1752
  }
1532
1753
  });
1533
1754
  }); })];
@@ -1546,7 +1767,7 @@ var SqlExecutor = /** @class */ (function (_super) {
1546
1767
  key = primary === null || primary === void 0 ? void 0 : primary[0];
1547
1768
  if (!key || !(args === null || args === void 0 ? void 0 : args[key]))
1548
1769
  throw new Error('Primary key and value required for delete');
1549
- sql = "DELETE FROM `".concat(table, "` WHERE `").concat(key, "` = ?");
1770
+ sql = "DELETE\n FROM `".concat(table, "`\n WHERE `").concat(key, "` = ?");
1550
1771
  console.log("[SQL EXECUTOR] \uD83E\uDDE0 Generated DELETE SQL:", sql);
1551
1772
  console.log("[SQL EXECUTOR] \uD83D\uDD22 Value:", args[key]);
1552
1773
  return [4 /*yield*/, this.withConnection(function (conn) { return tslib.__awaiter(_this, void 0, void 0, function () {
@@ -1556,7 +1777,13 @@ var SqlExecutor = /** @class */ (function (_super) {
1556
1777
  case 0: return [4 /*yield*/, conn.execute(sql, [args[key]])];
1557
1778
  case 1:
1558
1779
  result = (_a.sent())[0];
1559
- return [2 /*return*/, result];
1780
+ return [2 /*return*/, {
1781
+ rest: result,
1782
+ sql: {
1783
+ sql: sql,
1784
+ args: args
1785
+ }
1786
+ }];
1560
1787
  }
1561
1788
  });
1562
1789
  }); })];
@@ -1566,23 +1793,35 @@ var SqlExecutor = /** @class */ (function (_super) {
1566
1793
  });
1567
1794
  };
1568
1795
  SqlExecutor.prototype.formatSQLWithParams = function (sql, params) {
1569
- var index = 0;
1570
- return sql.replace(/\?/g, function () {
1571
- if (index >= params.length)
1572
- return '?'; // fallback if params are missing
1573
- var val = params[index++];
1574
- if (val === null || val === undefined)
1575
- return 'NULL';
1576
- if (Buffer.isBuffer(val))
1577
- return "UNHEX('".concat(val.toString('hex'), "')");
1578
- if (typeof val === 'string')
1579
- return "'".concat(val.replace(/'/g, "''"), "'");
1580
- if (typeof val === 'number')
1581
- return val.toString();
1582
- if (val instanceof Date)
1583
- return "'".concat(val.toISOString().slice(0, 19).replace('T', ' '), "'");
1584
- return "'".concat(JSON.stringify(val), "'");
1585
- });
1796
+ var _this = this;
1797
+ if (Array.isArray(params)) {
1798
+ var index_1 = 0;
1799
+ return sql.replace(/\?/g, function () {
1800
+ if (index_1 >= params.length)
1801
+ return '?';
1802
+ var val = params[index_1++];
1803
+ return _this.formatValue(val);
1804
+ });
1805
+ }
1806
+ else {
1807
+ return sql.replace(/:([a-zA-Z0-9_]+)/g, function (_, key) {
1808
+ var val = params[key];
1809
+ return _this.formatValue(val);
1810
+ });
1811
+ }
1812
+ };
1813
+ SqlExecutor.prototype.formatValue = function (val) {
1814
+ if (val === null || val === undefined)
1815
+ return 'NULL';
1816
+ if (buffer.Buffer.isBuffer(val))
1817
+ return "UNHEX('".concat(val.toString('hex'), "')");
1818
+ if (typeof val === 'string')
1819
+ return "'".concat(val.replace(/'/g, "''"), "'");
1820
+ if (typeof val === 'number')
1821
+ return val.toString();
1822
+ if (val instanceof Date)
1823
+ return "'".concat(val.toISOString().slice(0, 19).replace('T', ' '), "'");
1824
+ return "'".concat(JSON.stringify(val), "'");
1586
1825
  };
1587
1826
  return SqlExecutor;
1588
1827
  }(SqlBuilder));
@@ -1636,11 +1875,11 @@ function ExpressHandler(_a) {
1636
1875
  })(payload)];
1637
1876
  case 1:
1638
1877
  response = _a.sent();
1639
- console.log('response', JSON.stringify(response));
1640
1878
  res.status(200).json(tslib.__assign({ success: true }, response));
1641
1879
  return [3 /*break*/, 3];
1642
1880
  case 2:
1643
1881
  err_1 = _a.sent();
1882
+ res.status(500).json({ success: false });
1644
1883
  next(err_1);
1645
1884
  return [3 /*break*/, 3];
1646
1885
  case 3: return [2 /*return*/];