@carbonorm/carbonnode 3.8.3 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -58,6 +58,7 @@ var C6Constants = {
58
58
  INNER: 'INNER',
59
59
  INTERVAL: 'INTERVAL',
60
60
  JOIN: 'JOIN',
61
+ FROM: 'FROM',
61
62
  LEFT: 'LEFT',
62
63
  LEFT_OUTER: 'LEFT_OUTER',
63
64
  LESS_THAN: '<',
@@ -89,6 +90,7 @@ var C6Constants = {
89
90
  SECOND: 'SECOND',
90
91
  SECOND_MICROSECOND: 'SECOND_MICROSECOND',
91
92
  SELECT: 'SELECT',
93
+ SUBSELECT: 'SUBSELECT',
92
94
  // MySQL Spatial Functions
93
95
  ST_AREA: 'ST_Area',
94
96
  ST_ASBINARY: 'ST_AsBinary',
@@ -1251,9 +1253,16 @@ var AggregateBuilder = /** @class */ (function (_super) {
1251
1253
  _this.selectAliases = new Set();
1252
1254
  return _this;
1253
1255
  }
1254
- AggregateBuilder.prototype.buildAggregateField = function (field) {
1256
+ // Overridden in ConditionBuilder where alias tracking is available.
1257
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1258
+ AggregateBuilder.prototype.assertValidIdentifier = function (_identifier, _context) {
1259
+ // no-op placeholder for subclasses that do not implement alias validation
1260
+ };
1261
+ AggregateBuilder.prototype.buildAggregateField = function (field, params) {
1255
1262
  var _this = this;
1263
+ var _a, _b;
1256
1264
  if (typeof field === 'string') {
1265
+ this.assertValidIdentifier(field, 'SELECT field');
1257
1266
  return field;
1258
1267
  }
1259
1268
  if (!Array.isArray(field) || field.length === 0) {
@@ -1266,8 +1275,33 @@ var AggregateBuilder = /** @class */ (function (_super) {
1266
1275
  args.pop();
1267
1276
  }
1268
1277
  var F = String(fn).toUpperCase();
1278
+ if (F === C6C.SUBSELECT) {
1279
+ if (!params) {
1280
+ throw new Error('Scalar subselects in SELECT require parameter tracking.');
1281
+ }
1282
+ var subRequest = args[0];
1283
+ var subSql = (_b = (_a = this).buildScalarSubSelect) === null || _b === void 0 ? void 0 : _b.call(_a, subRequest, params);
1284
+ if (!subSql) {
1285
+ throw new Error('Failed to build scalar subselect.');
1286
+ }
1287
+ var expr_1 = subSql;
1288
+ if (alias) {
1289
+ this.selectAliases.add(alias);
1290
+ expr_1 += " AS ".concat(alias);
1291
+ }
1292
+ this.config.verbose && console.log("[SELECT] ".concat(expr_1));
1293
+ return expr_1;
1294
+ }
1269
1295
  var argList = args
1270
- .map(function (arg) { return Array.isArray(arg) ? _this.buildAggregateField(arg) : arg; })
1296
+ .map(function (arg) {
1297
+ if (Array.isArray(arg))
1298
+ return _this.buildAggregateField(arg, params);
1299
+ if (typeof arg === 'string') {
1300
+ _this.assertValidIdentifier(arg, 'SELECT expression');
1301
+ return arg;
1302
+ }
1303
+ return String(arg);
1304
+ })
1271
1305
  .join(', ');
1272
1306
  var expr;
1273
1307
  if (F === 'DISTINCT') {
@@ -1286,11 +1320,91 @@ var AggregateBuilder = /** @class */ (function (_super) {
1286
1320
  return AggregateBuilder;
1287
1321
  }(Executor));
1288
1322
 
1323
+ // Alias a table name with a given alias
1324
+ var DERIVED_TABLE_PREFIX = '__c6DerivedTable__';
1325
+ var DERIVED_ID_SYMBOL = Symbol('c6DerivedTableId');
1326
+ var derivedTableLookup = new Map();
1327
+ var derivedTableReverseLookup = new WeakMap();
1328
+ var derivedTableCounter = 0;
1329
+ var isDerivedTableKey = function (key) {
1330
+ return typeof key === 'string' && key.startsWith(DERIVED_TABLE_PREFIX);
1331
+ };
1332
+ var resolveDerivedTable = function (key) {
1333
+ return derivedTableLookup.get(key);
1334
+ };
1335
+ var derivedTable = function (spec) {
1336
+ if (!spec || typeof spec !== 'object') {
1337
+ throw new Error('Derived table definition must be an object.');
1338
+ }
1339
+ var aliasRaw = spec[C6C.AS];
1340
+ if (typeof aliasRaw !== 'string' || aliasRaw.trim() === '') {
1341
+ throw new Error('Derived tables require a non-empty alias via C6C.AS.');
1342
+ }
1343
+ if (!spec[C6C.SUBSELECT] || typeof spec[C6C.SUBSELECT] !== 'object') {
1344
+ throw new Error('Derived tables require a nested SELECT payload under C6C.SUBSELECT.');
1345
+ }
1346
+ var id = derivedTableReverseLookup.get(spec);
1347
+ if (!id) {
1348
+ id = "".concat(DERIVED_TABLE_PREFIX).concat(++derivedTableCounter);
1349
+ derivedTableReverseLookup.set(spec, id);
1350
+ derivedTableLookup.set(id, spec);
1351
+ Object.defineProperty(spec, DERIVED_ID_SYMBOL, {
1352
+ value: id,
1353
+ configurable: false,
1354
+ enumerable: false,
1355
+ writable: false
1356
+ });
1357
+ }
1358
+ var alias = aliasRaw.trim();
1359
+ derivedTableLookup.set(id, spec);
1360
+ Object.defineProperty(spec, 'toString', {
1361
+ value: function () { return "".concat(id, " ").concat(alias); },
1362
+ configurable: true,
1363
+ enumerable: false,
1364
+ writable: true
1365
+ });
1366
+ return spec;
1367
+ };
1368
+ var A = function (tableName, alias) {
1369
+ return "".concat(tableName, " ").concat(alias);
1370
+ };
1371
+ // Qualify a column constant (e.g. 'property_units.parcel_id') to an alias
1372
+ var F = function (qualifiedCol, alias) {
1373
+ return "".concat(alias, ".").concat(qualifiedCol.split('.').pop());
1374
+ };
1375
+ // Equal join condition using full-qualified column constants
1376
+ var fieldEq = function (leftCol, rightCol, leftAlias, rightAlias) {
1377
+ var _a;
1378
+ return (_a = {},
1379
+ _a[F(leftCol, leftAlias)] = F(rightCol, rightAlias),
1380
+ _a);
1381
+ };
1382
+ // ST_Distance_Sphere for aliased fields
1383
+ var distSphere = function (fromCol, toCol, fromAlias, toAlias) {
1384
+ return [C6C.ST_DISTANCE_SPHERE, F(fromCol, fromAlias), F(toCol, toAlias)];
1385
+ };
1386
+ // Build a bounding-box expression.
1387
+ //
1388
+ // Arguments must be provided in `(minLng, minLat, maxLng, maxLat)` order. The
1389
+ // helper does not attempt to swap or validate coordinates; if a minimum value
1390
+ // is greater than its corresponding maximum value, MySQL's `ST_MakeEnvelope`
1391
+ // returns `NULL`.
1392
+ var bbox = function (minLng, minLat, maxLng, maxLat) {
1393
+ return [C6C.ST_SRID, [C6C.ST_MAKEENVELOPE,
1394
+ [C6C.ST_POINT, minLng, minLat],
1395
+ [C6C.ST_POINT, maxLng, maxLat]], 4326];
1396
+ };
1397
+ // ST_Contains for map envelope/shape queries
1398
+ var stContains = function (envelope, shape) {
1399
+ return [C6C.ST_CONTAINS, envelope, shape];
1400
+ };
1401
+
1289
1402
  var ConditionBuilder = /** @class */ (function (_super) {
1290
1403
  __extends(ConditionBuilder, _super);
1291
1404
  function ConditionBuilder() {
1292
1405
  var _this = _super !== null && _super.apply(this, arguments) || this;
1293
1406
  _this.aliasMap = {};
1407
+ _this.derivedAliases = new Set();
1294
1408
  _this.OPERATORS = new Set([
1295
1409
  C6C.EQUAL, C6C.NOT_EQUAL, C6C.LESS_THAN, C6C.LESS_THAN_OR_EQUAL_TO,
1296
1410
  C6C.GREATER_THAN, C6C.GREATER_THAN_OR_EQUAL_TO,
@@ -1315,21 +1429,43 @@ var ConditionBuilder = /** @class */ (function (_super) {
1315
1429
  ConditionBuilder.prototype.initAlias = function (baseTable, joins) {
1316
1430
  var _a;
1317
1431
  this.aliasMap = (_a = {}, _a[baseTable] = baseTable, _a);
1432
+ this.derivedAliases = new Set();
1318
1433
  if (!joins)
1319
1434
  return;
1320
1435
  for (var joinType in joins) {
1321
1436
  for (var raw in joins[joinType]) {
1322
- var _b = raw.split(' '), table = _b[0], alias = _b[1];
1323
- this.aliasMap[alias || table] = table;
1437
+ var _b = raw.trim().split(/\s+/, 2), table = _b[0], alias = _b[1];
1438
+ if (!table)
1439
+ continue;
1440
+ this.registerAlias(alias || table, table);
1324
1441
  }
1325
1442
  }
1326
1443
  };
1444
+ ConditionBuilder.prototype.registerAlias = function (alias, table) {
1445
+ this.aliasMap[alias] = table;
1446
+ if (isDerivedTableKey(table)) {
1447
+ this.derivedAliases.add(alias);
1448
+ }
1449
+ };
1450
+ ConditionBuilder.prototype.assertValidIdentifier = function (identifier, context) {
1451
+ if (typeof identifier !== 'string')
1452
+ return;
1453
+ if (!identifier.includes('.'))
1454
+ return;
1455
+ var alias = identifier.split('.', 2)[0];
1456
+ if (!(alias in this.aliasMap)) {
1457
+ throw new Error("Unknown table or alias '".concat(alias, "' referenced in ").concat(context, ": '").concat(identifier, "'."));
1458
+ }
1459
+ };
1327
1460
  ConditionBuilder.prototype.isColumnRef = function (ref) {
1328
1461
  var _a, _b;
1329
1462
  if (typeof ref !== 'string' || !ref.includes('.'))
1330
1463
  return false;
1331
1464
  var _c = ref.split('.', 2), prefix = _c[0], column = _c[1];
1332
1465
  var tableName = this.aliasMap[prefix] || prefix;
1466
+ if (isDerivedTableKey(tableName) || this.derivedAliases.has(prefix)) {
1467
+ return true;
1468
+ }
1333
1469
  var table = (_b = (_a = this.config.C6) === null || _a === void 0 ? void 0 : _a.TABLES) === null || _b === void 0 ? void 0 : _b[tableName];
1334
1470
  if (!table)
1335
1471
  return false;
@@ -1358,6 +1494,9 @@ var ConditionBuilder = /** @class */ (function (_super) {
1358
1494
  }
1359
1495
  var _e = val.split('.'), prefix = _e[0], column = _e[1];
1360
1496
  var tableName = (_b = this.aliasMap[prefix]) !== null && _b !== void 0 ? _b : prefix;
1497
+ if (isDerivedTableKey(tableName) || this.derivedAliases.has(prefix)) {
1498
+ return true;
1499
+ }
1361
1500
  var table = (_d = (_c = this.config.C6) === null || _c === void 0 ? void 0 : _c.TABLES) === null || _d === void 0 ? void 0 : _d[tableName];
1362
1501
  if (!table || !table.COLUMNS)
1363
1502
  return false;
@@ -1397,6 +1536,29 @@ var ConditionBuilder = /** @class */ (function (_super) {
1397
1536
  if (params === void 0) { params = []; }
1398
1537
  var booleanOperator = andMode ? 'AND' : 'OR';
1399
1538
  var addCondition = function (column, op, value) {
1539
+ // Normalize common variants
1540
+ var valueNorm = (value === C6C.NULL) ? null : value;
1541
+ var displayOp = typeof op === 'string' ? op.replace('_', ' ') : op;
1542
+ var extractSubSelect = function (input) {
1543
+ if (Array.isArray(input) && input.length >= 2 && input[0] === C6C.SUBSELECT) {
1544
+ return input[1];
1545
+ }
1546
+ if (input && typeof input === 'object' && C6C.SUBSELECT in input) {
1547
+ return input[C6C.SUBSELECT];
1548
+ }
1549
+ return undefined;
1550
+ };
1551
+ var rightSubSelectPayload = extractSubSelect(valueNorm);
1552
+ var buildSubSelect = function (payload) {
1553
+ if (!payload)
1554
+ return undefined;
1555
+ var builder = _this.buildScalarSubSelect;
1556
+ if (typeof builder !== 'function') {
1557
+ throw new Error('Scalar subselect handling requires JoinBuilder context.');
1558
+ }
1559
+ return builder.call(_this, payload, params);
1560
+ };
1561
+ var rightSubSelectSql = buildSubSelect(rightSubSelectPayload);
1400
1562
  // Support function-based expressions like [C6C.ST_DISTANCE_SPHERE, col1, col2]
1401
1563
  if (typeof column === 'string' &&
1402
1564
  _this.OPERATORS.has(column) &&
@@ -1423,7 +1585,7 @@ var ConditionBuilder = /** @class */ (function (_super) {
1423
1585
  var leftIsCol = _this.isColumnRef(column);
1424
1586
  var leftIsRef = _this.isTableReference(column);
1425
1587
  var rightIsCol = typeof value === 'string' && _this.isColumnRef(value);
1426
- if (!leftIsCol && !leftIsRef && !rightIsCol) {
1588
+ if (!leftIsCol && !leftIsRef && !rightIsCol && !rightSubSelectSql) {
1427
1589
  throw new Error("Potential SQL injection detected: '".concat(column, " ").concat(op, " ").concat(value, "'"));
1428
1590
  }
1429
1591
  _this.validateOperator(op);
@@ -1456,6 +1618,13 @@ var ConditionBuilder = /** @class */ (function (_super) {
1456
1618
  return matchClause;
1457
1619
  }
1458
1620
  if ((op === C6C.IN || op === C6C.NOT_IN) && Array.isArray(value)) {
1621
+ if (rightSubSelectSql) {
1622
+ if (!leftIsRef) {
1623
+ throw new Error("IN operator requires a table reference as the left operand. Column '".concat(column, "' is not a valid table reference."));
1624
+ }
1625
+ var normalized_1 = op.replace('_', ' ');
1626
+ return "( ".concat(column, " ").concat(normalized_1, " ").concat(rightSubSelectSql, " )");
1627
+ }
1459
1628
  var placeholders = value.map(function (v) {
1460
1629
  return _this.isColumnRef(v) ? v : _this.addParam(params, column, v);
1461
1630
  }).join(', ');
@@ -1475,15 +1644,18 @@ var ConditionBuilder = /** @class */ (function (_super) {
1475
1644
  }
1476
1645
  return "(".concat(column, ") ").concat(op.replace('_', ' '), " ").concat(_this.addParam(params, column, start), " AND ").concat(_this.addParam(params, column, end));
1477
1646
  }
1478
- var rightIsRef = _this.isTableReference(value);
1647
+ var rightIsRef = rightSubSelectSql ? false : _this.isTableReference(value);
1479
1648
  if (leftIsRef && rightIsRef) {
1480
- return "(".concat(column, ") ").concat(op, " ").concat(value);
1649
+ return "(".concat(column, ") ").concat(displayOp, " ").concat(value);
1650
+ }
1651
+ if (leftIsRef && rightSubSelectSql) {
1652
+ return "(".concat(column, ") ").concat(displayOp, " ").concat(rightSubSelectSql);
1481
1653
  }
1482
1654
  if (leftIsRef && !rightIsRef) {
1483
- return "(".concat(column, ") ").concat(op, " ").concat(_this.addParam(params, column, value));
1655
+ return "(".concat(column, ") ").concat(displayOp, " ").concat(_this.addParam(params, column, valueNorm));
1484
1656
  }
1485
1657
  if (rightIsRef) {
1486
- return "(".concat(_this.addParam(params, column, column), ") ").concat(op, " ").concat(value);
1658
+ return "(".concat(_this.addParam(params, column, column), ") ").concat(displayOp, " ").concat(value);
1487
1659
  }
1488
1660
  throw new Error("Neither operand appears to be a table reference (".concat(column, ") or (").concat(value, ")"));
1489
1661
  };
@@ -1532,12 +1704,23 @@ var ConditionBuilder = /** @class */ (function (_super) {
1532
1704
  return subParts.join(" ".concat(mode ? 'AND' : 'OR', " "));
1533
1705
  };
1534
1706
  if (Array.isArray(set)) {
1535
- for (var _i = 0, set_1 = set; _i < set_1.length; _i++) {
1536
- var item = set_1[_i];
1537
- var sub = this.buildBooleanJoinedConditions(item, false, params);
1707
+ // Detect a single condition triple: [column, op, value]
1708
+ if (set.length === 3 && typeof set[0] === 'string' && typeof set[1] === 'string') {
1709
+ var _a = set, column = _a[0], rawOp = _a[1], rawVal = _a[2];
1710
+ var op = rawOp;
1711
+ var value = rawVal === C6C.NULL ? null : rawVal;
1712
+ var sub = addCondition(column, op, value);
1538
1713
  if (sub)
1539
1714
  parts.push(sub);
1540
1715
  }
1716
+ else {
1717
+ for (var _i = 0, set_1 = set; _i < set_1.length; _i++) {
1718
+ var item = set_1[_i];
1719
+ var sub = this.buildBooleanJoinedConditions(item, false, params);
1720
+ if (sub)
1721
+ parts.push(sub);
1722
+ }
1723
+ }
1541
1724
  }
1542
1725
  else if (typeof set === 'object' && set !== null) {
1543
1726
  var sub = buildFromObject(set, andMode);
@@ -1563,85 +1746,117 @@ var JoinBuilder = /** @class */ (function (_super) {
1563
1746
  function JoinBuilder() {
1564
1747
  return _super !== null && _super.apply(this, arguments) || this;
1565
1748
  }
1749
+ JoinBuilder.prototype.createSelectBuilder = function (_request) {
1750
+ throw new Error('Subclasses must implement createSelectBuilder to support derived table serialization.');
1751
+ };
1566
1752
  JoinBuilder.prototype.buildJoinClauses = function (joinArgs, params) {
1567
1753
  var sql = '';
1568
- for (var joinType in joinArgs) {
1754
+ var _loop_1 = function (joinType) {
1569
1755
  var joinKind = joinType.replace('_', ' ').toUpperCase();
1570
- for (var raw in joinArgs[joinType]) {
1571
- var _a = raw.split(' '), table = _a[0], alias = _a[1];
1572
- this.aliasMap[alias || table] = table;
1573
- var onClause = this.buildBooleanJoinedConditions(joinArgs[joinType][raw], true, params);
1574
- var joinSql = alias ? "`".concat(table, "` AS `").concat(alias, "`") : "`".concat(table, "`");
1575
- sql += " ".concat(joinKind, " JOIN ").concat(joinSql, " ON ").concat(onClause);
1756
+ var entries = [];
1757
+ var joinSection = joinArgs[joinType];
1758
+ if (joinSection instanceof Map) {
1759
+ joinSection.forEach(function (value, key) {
1760
+ entries.push([key, value]);
1761
+ });
1762
+ }
1763
+ else {
1764
+ for (var raw in joinSection) {
1765
+ entries.push([raw, joinSection[raw]]);
1766
+ }
1767
+ }
1768
+ for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) {
1769
+ var _a = entries_1[_i], rawKey = _a[0], conditions = _a[1];
1770
+ var raw = typeof rawKey === 'string' ? rawKey : String(rawKey);
1771
+ var _b = raw.trim().split(/\s+/, 2), table = _b[0], aliasCandidate = _b[1];
1772
+ if (!table)
1773
+ continue;
1774
+ if (isDerivedTableKey(table)) {
1775
+ var derived = resolveDerivedTable(table);
1776
+ if (!derived) {
1777
+ throw new Error("Derived table '".concat(table, "' was not registered. Wrap the object with derivedTable(...) before using it in JOIN."));
1778
+ }
1779
+ var configuredAliasRaw = derived[C6C.AS];
1780
+ var configuredAlias = typeof configuredAliasRaw === 'string' ? configuredAliasRaw.trim() : '';
1781
+ var alias = (aliasCandidate !== null && aliasCandidate !== void 0 ? aliasCandidate : configuredAlias).trim();
1782
+ if (!alias) {
1783
+ throw new Error('Derived tables require an alias via C6C.AS.');
1784
+ }
1785
+ this_1.registerAlias(alias, table);
1786
+ var subRequest = derived[C6C.SUBSELECT];
1787
+ if (!subRequest || typeof subRequest !== 'object') {
1788
+ throw new Error('Derived tables must include a C6C.SUBSELECT payload.');
1789
+ }
1790
+ var fromTable = subRequest[C6C.FROM];
1791
+ if (typeof fromTable !== 'string' || fromTable.trim() === '') {
1792
+ throw new Error('Derived table subselects require a base table defined with C6C.FROM.');
1793
+ }
1794
+ var subBuilder = this_1.createSelectBuilder(subRequest);
1795
+ var _c = subBuilder.build(fromTable, true), subSql = _c.sql, subParams = _c.params;
1796
+ var normalizedSql = this_1.integrateSubSelectParams(subSql, subParams, params);
1797
+ var formatted = normalizedSql.trim().split('\n').map(function (line) { return " ".concat(line); }).join('\n');
1798
+ var joinSql = "(\n".concat(formatted, "\n) AS `").concat(alias, "`");
1799
+ var onClause = this_1.buildBooleanJoinedConditions(conditions, true, params);
1800
+ sql += " ".concat(joinKind, " JOIN ").concat(joinSql);
1801
+ if (onClause) {
1802
+ sql += " ON ".concat(onClause);
1803
+ }
1804
+ }
1805
+ else {
1806
+ var alias = aliasCandidate;
1807
+ if (alias) {
1808
+ this_1.registerAlias(alias, table);
1809
+ }
1810
+ var joinSql = alias ? "`".concat(table, "` AS `").concat(alias, "`") : "`".concat(table, "`");
1811
+ var onClause = this_1.buildBooleanJoinedConditions(conditions, true, params);
1812
+ sql += " ".concat(joinKind, " JOIN ").concat(joinSql);
1813
+ if (onClause) {
1814
+ sql += " ON ".concat(onClause);
1815
+ }
1816
+ }
1576
1817
  }
1818
+ };
1819
+ var this_1 = this;
1820
+ for (var joinType in joinArgs) {
1821
+ _loop_1(joinType);
1577
1822
  }
1578
1823
  this.config.verbose && console.log("[JOIN] ".concat(sql.trim()));
1579
1824
  return sql;
1580
1825
  };
1581
- return JoinBuilder;
1582
- }(ConditionBuilder));
1583
-
1584
- var DeleteQueryBuilder = /** @class */ (function (_super) {
1585
- __extends(DeleteQueryBuilder, _super);
1586
- function DeleteQueryBuilder() {
1587
- return _super !== null && _super.apply(this, arguments) || this;
1588
- }
1589
- DeleteQueryBuilder.prototype.build = function (table) {
1590
- this.aliasMap = {};
1591
- var params = this.useNamedParams ? {} : [];
1592
- this.initAlias(table, this.request.JOIN);
1593
- var sql = "DELETE `".concat(table, "` FROM `").concat(table, "`");
1594
- if (this.request.JOIN) {
1595
- sql += this.buildJoinClauses(this.request.JOIN, params);
1596
- }
1597
- if (this.request.WHERE) {
1598
- sql += this.buildWhereClause(this.request.WHERE, params);
1599
- }
1600
- return { sql: sql, params: params };
1601
- };
1602
- return DeleteQueryBuilder;
1603
- }(JoinBuilder));
1604
-
1605
- var PostQueryBuilder = /** @class */ (function (_super) {
1606
- __extends(PostQueryBuilder, _super);
1607
- function PostQueryBuilder() {
1608
- return _super !== null && _super.apply(this, arguments) || this;
1609
- }
1610
- PostQueryBuilder.prototype.trimTablePrefix = function (table, column) {
1611
- if (!column.includes('.'))
1612
- return column;
1613
- var _a = column.split('.', 2), prefix = _a[0], col = _a[1];
1614
- if (prefix !== table) {
1615
- throw new Error("Invalid prefixed column: '".concat(column, "'. Expected prefix '").concat(table, ".'"));
1826
+ JoinBuilder.prototype.integrateSubSelectParams = function (subSql, subParams, target) {
1827
+ var _a;
1828
+ if (!subParams)
1829
+ return subSql;
1830
+ if (this.useNamedParams) {
1831
+ var normalized = subSql;
1832
+ var extras = subParams;
1833
+ for (var _i = 0, _b = Object.keys(extras); _i < _b.length; _i++) {
1834
+ var key = _b[_i];
1835
+ var placeholder = this.addParam(target, '', extras[key]);
1836
+ var original = ":".concat(key);
1837
+ if (original !== placeholder) {
1838
+ normalized = normalized.split(original).join(placeholder);
1839
+ }
1840
+ }
1841
+ return normalized;
1616
1842
  }
1617
- return col;
1843
+ (_a = target).push.apply(_a, subParams);
1844
+ return subSql;
1618
1845
  };
1619
- PostQueryBuilder.prototype.build = function (table) {
1620
- var _this = this;
1621
- this.aliasMap = {};
1622
- var verb = C6C.REPLACE in this.request ? C6C.REPLACE : C6C.INSERT;
1623
- var body = verb in this.request ? this.request[verb] : this.request;
1624
- var keys = Object.keys(body);
1625
- var params = [];
1626
- var placeholders = [];
1627
- for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
1628
- var key = keys_1[_i];
1629
- var value = body[key];
1630
- var placeholder = this.addParam(params, key, value);
1631
- placeholders.push(placeholder);
1846
+ JoinBuilder.prototype.buildScalarSubSelect = function (subRequest, params) {
1847
+ if (!subRequest || typeof subRequest !== 'object') {
1848
+ throw new Error('Scalar subselect requires a C6C.SUBSELECT object payload.');
1632
1849
  }
1633
- var sql = "".concat(verb, " INTO `").concat(table, "` (\n ").concat(keys.map(function (k) { return "`".concat(_this.trimTablePrefix(table, k), "`"); }).join(', '), "\n ) VALUES (\n ").concat(placeholders.join(', '), "\n )");
1634
- if (C6C.UPDATE in this.request) {
1635
- var updateData = this.request[C6C.UPDATE];
1636
- if (!Array.isArray(updateData)) {
1637
- throw new Error("Update data must be an array of keys to update, got: ".concat(JSON.stringify(updateData)));
1638
- }
1639
- var updateClause = updateData.map(function (k) { return "`".concat(k, "` = VALUES(`").concat(k, "`)"); }).join(', ');
1640
- sql += " ON DUPLICATE KEY UPDATE ".concat(updateClause);
1850
+ var fromTable = subRequest[C6C.FROM];
1851
+ if (typeof fromTable !== 'string' || fromTable.trim() === '') {
1852
+ throw new Error('Scalar subselects require a base table specified with C6C.FROM.');
1641
1853
  }
1642
- return { sql: sql, params: params };
1854
+ var subBuilder = this.createSelectBuilder(subRequest);
1855
+ var _a = subBuilder.build(fromTable, true), subSql = _a.sql, subParams = _a.params;
1856
+ var normalized = this.integrateSubSelectParams(subSql, subParams, params).trim();
1857
+ return "(".concat(normalized, ")");
1643
1858
  };
1644
- return PostQueryBuilder;
1859
+ return JoinBuilder;
1645
1860
  }(ConditionBuilder));
1646
1861
 
1647
1862
  var PaginationBuilder = /** @class */ (function (_super) {
@@ -1662,7 +1877,7 @@ var PaginationBuilder = /** @class */ (function (_super) {
1662
1877
  * }
1663
1878
  * ```
1664
1879
  */
1665
- PaginationBuilder.prototype.buildPaginationClause = function (pagination) {
1880
+ PaginationBuilder.prototype.buildPaginationClause = function (pagination, params) {
1666
1881
  var _this = this;
1667
1882
  var sql = "";
1668
1883
  /* -------- ORDER BY -------- */
@@ -1670,10 +1885,21 @@ var PaginationBuilder = /** @class */ (function (_super) {
1670
1885
  var orderParts = [];
1671
1886
  for (var _i = 0, _a = Object.entries(pagination[C6Constants.ORDER]); _i < _a.length; _i++) {
1672
1887
  var _b = _a[_i], key = _b[0], val = _b[1];
1888
+ if (typeof key === 'string' && key.includes('.')) {
1889
+ this.assertValidIdentifier(key, 'ORDER BY');
1890
+ }
1673
1891
  // FUNCTION CALL: val is an array of args
1674
1892
  if (Array.isArray(val)) {
1675
1893
  var args = val
1676
- .map(function (arg) { return Array.isArray(arg) ? _this.buildAggregateField(arg) : String(arg); })
1894
+ .map(function (arg) {
1895
+ if (Array.isArray(arg))
1896
+ return _this.buildAggregateField(arg, params);
1897
+ if (typeof arg === 'string' && arg.includes('.')) {
1898
+ _this.assertValidIdentifier(arg, 'ORDER BY argument');
1899
+ return arg;
1900
+ }
1901
+ return String(arg);
1902
+ })
1677
1903
  .join(", ");
1678
1904
  orderParts.push("".concat(key, "(").concat(args, ")"));
1679
1905
  }
@@ -1710,6 +1936,9 @@ var SelectQueryBuilder = /** @class */ (function (_super) {
1710
1936
  function SelectQueryBuilder() {
1711
1937
  return _super !== null && _super.apply(this, arguments) || this;
1712
1938
  }
1939
+ SelectQueryBuilder.prototype.createSelectBuilder = function (request) {
1940
+ return new SelectQueryBuilder(this.config, request, this.useNamedParams);
1941
+ };
1713
1942
  SelectQueryBuilder.prototype.build = function (table, isSubSelect) {
1714
1943
  var _this = this;
1715
1944
  var _a;
@@ -1724,7 +1953,7 @@ var SelectQueryBuilder = /** @class */ (function (_super) {
1724
1953
  var params = this.useNamedParams ? {} : [];
1725
1954
  var selectList = (_a = args.SELECT) !== null && _a !== void 0 ? _a : ['*'];
1726
1955
  var selectFields = selectList
1727
- .map(function (f) { return _this.buildAggregateField(f); })
1956
+ .map(function (f) { return _this.buildAggregateField(f, params); })
1728
1957
  .join(', ');
1729
1958
  var sql = "SELECT ".concat(selectFields, " FROM `").concat(table, "`");
1730
1959
  if (args.JOIN) {
@@ -1743,7 +1972,7 @@ var SelectQueryBuilder = /** @class */ (function (_super) {
1743
1972
  sql += " HAVING ".concat(this.buildBooleanJoinedConditions(args.HAVING, true, params));
1744
1973
  }
1745
1974
  if (args.PAGINATION) {
1746
- sql += this.buildPaginationClause(args.PAGINATION);
1975
+ sql += this.buildPaginationClause(args.PAGINATION, params);
1747
1976
  }
1748
1977
  else if (!isSubSelect) {
1749
1978
  sql += " LIMIT 100";
@@ -1754,11 +1983,80 @@ var SelectQueryBuilder = /** @class */ (function (_super) {
1754
1983
  return SelectQueryBuilder;
1755
1984
  }(PaginationBuilder));
1756
1985
 
1986
+ var DeleteQueryBuilder = /** @class */ (function (_super) {
1987
+ __extends(DeleteQueryBuilder, _super);
1988
+ function DeleteQueryBuilder() {
1989
+ return _super !== null && _super.apply(this, arguments) || this;
1990
+ }
1991
+ DeleteQueryBuilder.prototype.createSelectBuilder = function (request) {
1992
+ return new SelectQueryBuilder(this.config, request, this.useNamedParams);
1993
+ };
1994
+ DeleteQueryBuilder.prototype.build = function (table) {
1995
+ this.aliasMap = {};
1996
+ var params = this.useNamedParams ? {} : [];
1997
+ this.initAlias(table, this.request.JOIN);
1998
+ var sql = "DELETE `".concat(table, "` FROM `").concat(table, "`");
1999
+ if (this.request.JOIN) {
2000
+ sql += this.buildJoinClauses(this.request.JOIN, params);
2001
+ }
2002
+ if (this.request.WHERE) {
2003
+ sql += this.buildWhereClause(this.request.WHERE, params);
2004
+ }
2005
+ return { sql: sql, params: params };
2006
+ };
2007
+ return DeleteQueryBuilder;
2008
+ }(JoinBuilder));
2009
+
2010
+ var PostQueryBuilder = /** @class */ (function (_super) {
2011
+ __extends(PostQueryBuilder, _super);
2012
+ function PostQueryBuilder() {
2013
+ return _super !== null && _super.apply(this, arguments) || this;
2014
+ }
2015
+ PostQueryBuilder.prototype.trimTablePrefix = function (table, column) {
2016
+ if (!column.includes('.'))
2017
+ return column;
2018
+ var _a = column.split('.', 2), prefix = _a[0], col = _a[1];
2019
+ if (prefix !== table) {
2020
+ throw new Error("Invalid prefixed column: '".concat(column, "'. Expected prefix '").concat(table, ".'"));
2021
+ }
2022
+ return col;
2023
+ };
2024
+ PostQueryBuilder.prototype.build = function (table) {
2025
+ var _this = this;
2026
+ this.aliasMap = {};
2027
+ var verb = C6C.REPLACE in this.request ? C6C.REPLACE : C6C.INSERT;
2028
+ var body = verb in this.request ? this.request[verb] : this.request;
2029
+ var keys = Object.keys(body);
2030
+ var params = [];
2031
+ var placeholders = [];
2032
+ for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
2033
+ var key = keys_1[_i];
2034
+ var value = body[key];
2035
+ var placeholder = this.addParam(params, key, value);
2036
+ placeholders.push(placeholder);
2037
+ }
2038
+ var sql = "".concat(verb, " INTO `").concat(table, "` (\n ").concat(keys.map(function (k) { return "`".concat(_this.trimTablePrefix(table, k), "`"); }).join(', '), "\n ) VALUES (\n ").concat(placeholders.join(', '), "\n )");
2039
+ if (C6C.UPDATE in this.request) {
2040
+ var updateData = this.request[C6C.UPDATE];
2041
+ if (!Array.isArray(updateData)) {
2042
+ throw new Error("Update data must be an array of keys to update, got: ".concat(JSON.stringify(updateData)));
2043
+ }
2044
+ var updateClause = updateData.map(function (k) { return "`".concat(k, "` = VALUES(`").concat(k, "`)"); }).join(', ');
2045
+ sql += " ON DUPLICATE KEY UPDATE ".concat(updateClause);
2046
+ }
2047
+ return { sql: sql, params: params };
2048
+ };
2049
+ return PostQueryBuilder;
2050
+ }(ConditionBuilder));
2051
+
1757
2052
  var UpdateQueryBuilder = /** @class */ (function (_super) {
1758
2053
  __extends(UpdateQueryBuilder, _super);
1759
2054
  function UpdateQueryBuilder() {
1760
2055
  return _super !== null && _super.apply(this, arguments) || this;
1761
2056
  }
2057
+ UpdateQueryBuilder.prototype.createSelectBuilder = function (request) {
2058
+ return new SelectQueryBuilder(this.config, request, this.useNamedParams);
2059
+ };
1762
2060
  UpdateQueryBuilder.prototype.trimTablePrefix = function (table, column) {
1763
2061
  if (!column.includes('.'))
1764
2062
  return column;
@@ -1793,7 +2091,7 @@ var UpdateQueryBuilder = /** @class */ (function (_super) {
1793
2091
  sql += this.buildWhereClause(args.WHERE, params);
1794
2092
  }
1795
2093
  if (args.PAGINATION) {
1796
- sql += this.buildPaginationClause(args.PAGINATION);
2094
+ sql += this.buildPaginationClause(args.PAGINATION, params);
1797
2095
  }
1798
2096
  return { sql: sql, params: params };
1799
2097
  };
@@ -2189,41 +2487,6 @@ function ExpressHandler(_a) {
2189
2487
  }); };
2190
2488
  }
2191
2489
 
2192
- // Alias a table name with a given alias
2193
- var A = function (tableName, alias) {
2194
- return "".concat(tableName, " ").concat(alias);
2195
- };
2196
- // Qualify a column constant (e.g. 'property_units.parcel_id') to an alias
2197
- var F = function (qualifiedCol, alias) {
2198
- return "".concat(alias, ".").concat(qualifiedCol.split('.').pop());
2199
- };
2200
- // Equal join condition using full-qualified column constants
2201
- var fieldEq = function (leftCol, rightCol, leftAlias, rightAlias) {
2202
- var _a;
2203
- return (_a = {},
2204
- _a[F(leftCol, leftAlias)] = F(rightCol, rightAlias),
2205
- _a);
2206
- };
2207
- // ST_Distance_Sphere for aliased fields
2208
- var distSphere = function (fromCol, toCol, fromAlias, toAlias) {
2209
- return [C6C.ST_DISTANCE_SPHERE, F(fromCol, fromAlias), F(toCol, toAlias)];
2210
- };
2211
- // Build a bounding-box expression.
2212
- //
2213
- // Arguments must be provided in `(minLng, minLat, maxLng, maxLat)` order. The
2214
- // helper does not attempt to swap or validate coordinates; if a minimum value
2215
- // is greater than its corresponding maximum value, MySQL's `ST_MakeEnvelope`
2216
- // returns `NULL`.
2217
- var bbox = function (minLng, minLat, maxLng, maxLat) {
2218
- return [C6C.ST_SRID, [C6C.ST_MAKEENVELOPE,
2219
- [C6C.ST_POINT, minLng, minLat],
2220
- [C6C.ST_POINT, maxLng, maxLat]], 4326];
2221
- };
2222
- // ST_Contains for map envelope/shape queries
2223
- var stContains = function (envelope, shape) {
2224
- return [C6C.ST_CONTAINS, envelope, shape];
2225
- };
2226
-
2227
2490
  function determineRuntimeJsType(mysqlType) {
2228
2491
  var base = mysqlType.toLowerCase().split('(')[0];
2229
2492
  if ([
@@ -2323,5 +2586,5 @@ function isVerbose () {
2323
2586
  return ['true', '1', 'yes', 'on'].includes(envVerbose.toLowerCase());
2324
2587
  }
2325
2588
 
2326
- export { A, AggregateBuilder, C6C, C6Constants, ConditionBuilder, DELETE, DeleteQueryBuilder, Executor, ExpressHandler, F, GET, HttpExecutor, JoinBuilder, POST, PUT, PaginationBuilder, PostQueryBuilder, SelectQueryBuilder, SqlExecutor, TestRestfulResponse, UpdateQueryBuilder, apiRequestCache, axiosInstance, bbox, carbonNodeQsStringify, checkAllRequestsComplete, checkCache, clearCache, convertForRequestBody, convertHexIfBinary, determineRuntimeJsType, distSphere, eFetchDependencies, error, fieldEq, getEnvVar, getPrimaryKeyTypes, group, info, isLocal, isNode, isTest, isVerbose, normalizeSingularRequest, onError, onSuccess, removeInvalidKeys, removePrefixIfExists, restOrm, restRequest, sortAndSerializeQueryObject, stContains, timeout, toastOptions, toastOptionsDevs, userCustomClearCache, warn };
2589
+ export { A, AggregateBuilder, C6C, C6Constants, ConditionBuilder, DELETE, DeleteQueryBuilder, Executor, ExpressHandler, F, GET, HttpExecutor, JoinBuilder, POST, PUT, PaginationBuilder, PostQueryBuilder, SelectQueryBuilder, SqlExecutor, TestRestfulResponse, UpdateQueryBuilder, apiRequestCache, axiosInstance, bbox, carbonNodeQsStringify, checkAllRequestsComplete, checkCache, clearCache, convertForRequestBody, convertHexIfBinary, derivedTable, determineRuntimeJsType, distSphere, eFetchDependencies, error, fieldEq, getEnvVar, getPrimaryKeyTypes, group, info, isDerivedTableKey, isLocal, isNode, isTest, isVerbose, normalizeSingularRequest, onError, onSuccess, removeInvalidKeys, removePrefixIfExists, resolveDerivedTable, restOrm, restRequest, sortAndSerializeQueryObject, stContains, timeout, toastOptions, toastOptionsDevs, userCustomClearCache, warn };
2327
2590
  //# sourceMappingURL=index.esm.js.map