bun-query-builder 0.1.30 → 0.1.31

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/bin/cli.js CHANGED
@@ -12435,6 +12435,8 @@ function formatSubqueryValue(val) {
12435
12435
  return val ? "1" : "0";
12436
12436
  if (typeof val === "string")
12437
12437
  return `'${val.replace(/'/g, "''")}'`;
12438
+ if (val instanceof Date)
12439
+ return `'${val.toISOString()}'`;
12438
12440
  throw new TypeError(`[query-builder] subquery condition: refusing to interpolate value of type ${typeof val}`);
12439
12441
  }
12440
12442
  function buildOverClause(partitionBy, orderBy) {
@@ -13292,6 +13294,54 @@ function createQueryBuilder(state) {
13292
13294
  }
13293
13295
  return "";
13294
13296
  };
13297
+ const buildJoinConstraint = (targetTbl) => {
13298
+ if (!condition)
13299
+ return "";
13300
+ const frags = [];
13301
+ const addCmp = (col, op, val) => {
13302
+ validateIdentifier(String(col), "with() constraint column");
13303
+ const operator = assertSafeWhereOperator(op, "with() constraint operator");
13304
+ frags.push(`${targetTbl}.${String(col)} ${operator} ${formatSubqueryValue(val)}`);
13305
+ };
13306
+ const unsupported = (m) => () => {
13307
+ throw new Error(`[query-builder] with('${relationKey}', ...): ${m} is not supported inside a constraint callback on the JOIN-based builder \u2014 apply it to the outer query, or use the model layer's eager loading. (Silently ignoring it would return wrong data.)`);
13308
+ };
13309
+ const constraintQb = {
13310
+ where: (expr, op, val) => {
13311
+ if (Array.isArray(expr))
13312
+ addCmp(expr[0], expr[1], expr[2]);
13313
+ else if (expr && typeof expr === "object")
13314
+ for (const k of Object.keys(expr))
13315
+ addCmp(k, "=", expr[k]);
13316
+ else if (op !== undefined && val !== undefined)
13317
+ addCmp(expr, op, val);
13318
+ else if (op !== undefined)
13319
+ addCmp(expr, "=", op);
13320
+ return constraintQb;
13321
+ },
13322
+ whereIn: (col, vals) => {
13323
+ validateIdentifier(String(col), "with() constraint column");
13324
+ frags.push(`${targetTbl}.${String(col)} IN (${vals.map(formatSubqueryValue).join(", ")})`);
13325
+ return constraintQb;
13326
+ },
13327
+ whereNull: (col) => {
13328
+ validateIdentifier(String(col), "with() constraint column");
13329
+ frags.push(`${targetTbl}.${String(col)} IS NULL`);
13330
+ return constraintQb;
13331
+ },
13332
+ whereNotNull: (col) => {
13333
+ validateIdentifier(String(col), "with() constraint column");
13334
+ frags.push(`${targetTbl}.${String(col)} IS NOT NULL`);
13335
+ return constraintQb;
13336
+ },
13337
+ orderBy: unsupported("orderBy()"),
13338
+ limit: unsupported("limit()"),
13339
+ offset: unsupported("offset()"),
13340
+ take: unsupported("take()")
13341
+ };
13342
+ condition(constraintQb);
13343
+ return frags.length ? ` AND ${frags.join(" AND ")}` : "";
13344
+ };
13295
13345
  const resolveTarget = () => {
13296
13346
  const pick = (m) => {
13297
13347
  const modelName = m?.[relationKey];
@@ -13336,7 +13386,7 @@ function createQueryBuilder(state) {
13336
13386
  const throughPk = meta.primaryKeys[throughTable] ?? "id";
13337
13387
  const fkInThrough = `${singularize(fromTable)}_id`;
13338
13388
  const fkInFinal = `${singularize(throughTable)}_id`;
13339
- built = sql`${ensureBuilt()} LEFT JOIN ${sql(throughTable)} ON ${sql(`${throughTable}.${fkInThrough}`)} = ${sql(`${fromTable}.${fromPk}`)} LEFT JOIN ${sql(finalTable)} ON ${sql(`${finalTable}.${fkInFinal}`)} = ${sql(`${throughTable}.${throughPk}`)}`;
13389
+ insertJoin(`LEFT JOIN ${throughTable} ON ${throughTable}.${fkInThrough} = ${fromTable}.${fromPk} LEFT JOIN ${finalTable} ON ${finalTable}.${fkInFinal} = ${throughTable}.${throughPk}`);
13340
13390
  joinedTables.add(throughTable);
13341
13391
  joinedTables.add(finalTable);
13342
13392
  return finalTable;
@@ -13349,7 +13399,7 @@ function createQueryBuilder(state) {
13349
13399
  const childPk = meta.primaryKeys[childTable] ?? "id";
13350
13400
  const fkA = resolved?.fkParent ?? `${singularize(fromTable)}_id`;
13351
13401
  const fkB = resolved?.fkRelated ?? `${singularize(childTable)}_id`;
13352
- built = sql`${ensureBuilt()} LEFT JOIN ${sql(pivot)} ON ${sql(`${pivot}.${fkA}`)} = ${sql(`${fromTable}.${fromPk}`)} LEFT JOIN ${sql(childTable)} ON ${sql(`${childTable}.${childPk}`)} = ${sql(`${pivot}.${fkB}`)}`;
13402
+ insertJoin(`LEFT JOIN ${pivot} ON ${pivot}.${fkA} = ${fromTable}.${fromPk} LEFT JOIN ${childTable} ON ${childTable}.${childPk} = ${pivot}.${fkB}${buildJoinConstraint(childTable)}`);
13353
13403
  joinedTables.add(pivot);
13354
13404
  joinedTables.add(childTable);
13355
13405
  return childTable;
@@ -13363,7 +13413,8 @@ function createQueryBuilder(state) {
13363
13413
  const morphType = `${morphName}_type`;
13364
13414
  const morphId = `${morphName}_id`;
13365
13415
  const targetFk = `${singularize(childTable)}_id`;
13366
- built = sql`${ensureBuilt()} LEFT JOIN ${sql(pivotTable)} ON ${sql(`${pivotTable}.${morphId}`)} = ${sql(`${fromTable}.${fromPk}`)} AND ${sql(`${pivotTable}.${morphType}`)} = ${sql(meta.tableToModel[fromTable] || fromTable)} LEFT JOIN ${sql(childTable)} ON ${sql(`${childTable}.${childPk}`)} = ${sql(`${pivotTable}.${targetFk}`)}`;
13416
+ const morphVal = formatSubqueryValue(meta.tableToModel[fromTable] || fromTable);
13417
+ insertJoin(`LEFT JOIN ${pivotTable} ON ${pivotTable}.${morphId} = ${fromTable}.${fromPk} AND ${pivotTable}.${morphType} = ${morphVal} LEFT JOIN ${childTable} ON ${childTable}.${childPk} = ${pivotTable}.${targetFk}`);
13367
13418
  joinedTables.add(pivotTable);
13368
13419
  joinedTables.add(childTable);
13369
13420
  return childTable;
@@ -13379,7 +13430,8 @@ function createQueryBuilder(state) {
13379
13430
  const morphType = `${morphName}_type`;
13380
13431
  const morphId = `${morphName}_id`;
13381
13432
  const relatedFk = `${singularize(relatedTable)}_id`;
13382
- built = sql`${ensureBuilt()} LEFT JOIN ${sql(pivotTable)} ON ${sql(`${pivotTable}.${relatedFk}`)} = ${sql(`${fromTable}.${fromPk}`)} LEFT JOIN ${sql(relatedTable)} ON ${sql(`${relatedTable}.${relatedPk}`)} = ${sql(`${pivotTable}.${morphId}`)} AND ${sql(`${pivotTable}.${morphType}`)} = ${sql(meta.tableToModel[relatedTable] || relatedTable)}`;
13433
+ const morphVal = formatSubqueryValue(meta.tableToModel[relatedTable] || relatedTable);
13434
+ insertJoin(`LEFT JOIN ${pivotTable} ON ${pivotTable}.${relatedFk} = ${fromTable}.${fromPk} LEFT JOIN ${relatedTable} ON ${relatedTable}.${relatedPk} = ${pivotTable}.${morphId} AND ${pivotTable}.${morphType} = ${morphVal}`);
13383
13435
  joinedTables.add(pivotTable);
13384
13436
  joinedTables.add(relatedTable);
13385
13437
  return relatedTable;
@@ -13388,7 +13440,7 @@ function createQueryBuilder(state) {
13388
13440
  if (isBt) {
13389
13441
  const fkInParent = `${singularize(childTable)}_id`;
13390
13442
  const childPk = meta.primaryKeys[childTable] ?? "id";
13391
- built = sql`${ensureBuilt()} LEFT JOIN ${sql(childTable)} ON ${sql(`${fromTable}.${fkInParent}`)} = ${sql(`${childTable}.${childPk}`)}`;
13443
+ insertJoin(`LEFT JOIN ${childTable} ON ${fromTable}.${fkInParent} = ${childTable}.${childPk}${buildJoinConstraint(childTable)}`);
13392
13444
  joinedTables.add(childTable);
13393
13445
  return childTable;
13394
13446
  }
@@ -13398,20 +13450,15 @@ function createQueryBuilder(state) {
13398
13450
  const morphType = `${relationKey}_type`;
13399
13451
  const morphId = `${relationKey}_id`;
13400
13452
  const fromPk = meta.primaryKeys[fromTable] ?? "id";
13401
- built = sql`${ensureBuilt()} LEFT JOIN ${sql(childTable)} ON ${sql(`${childTable}.${morphId}`)} = ${sql(`${fromTable}.${fromPk}`)} AND ${sql(`${childTable}.${morphType}`)} = ${sql(meta.tableToModel[fromTable] || fromTable)}`;
13453
+ const morphVal = formatSubqueryValue(meta.tableToModel[fromTable] || fromTable);
13454
+ insertJoin(`LEFT JOIN ${childTable} ON ${childTable}.${morphId} = ${fromTable}.${fromPk} AND ${childTable}.${morphType} = ${morphVal}`);
13402
13455
  joinedTables.add(childTable);
13403
13456
  return childTable;
13404
13457
  }
13405
13458
  const fkInChild = `${singularize(fromTable)}_id`;
13406
13459
  const pk = meta.primaryKeys[fromTable] ?? "id";
13407
- const softDeleteCheck = addSoftDeleteCheck(childTable);
13408
- if (softDeleteCheck) {
13409
- const currentSql = String(ensureBuilt());
13410
- const joinCondition = `${childTable}.${fkInChild} = ${fromTable}.${pk}${softDeleteCheck}`;
13411
- built = sql`${sql(currentSql)} LEFT JOIN ${sql(childTable)} ON ${sql(joinCondition)}`;
13412
- } else {
13413
- built = sql`${ensureBuilt()} LEFT JOIN ${sql(childTable)} ON ${sql(`${childTable}.${fkInChild}`)} = ${sql(`${fromTable}.${pk}`)}`;
13414
- }
13460
+ const extraOn = `${addSoftDeleteCheck(childTable)}${buildJoinConstraint(childTable)}`;
13461
+ insertJoin(`LEFT JOIN ${childTable} ON ${childTable}.${fkInChild} = ${fromTable}.${pk}${extraOn}`);
13415
13462
  joinedTables.add(childTable);
13416
13463
  return childTable;
13417
13464
  };
@@ -13448,7 +13495,7 @@ function createQueryBuilder(state) {
13448
13495
  addToSelectClause(pivotColumnsStr);
13449
13496
  }
13450
13497
  }
13451
- text = computeSqlText(ensureBuilt());
13498
+ built = null;
13452
13499
  return this;
13453
13500
  },
13454
13501
  whereHas(relation, callback) {
@@ -29984,7 +30031,7 @@ function getPrefix() {
29984
30031
  }
29985
30032
  var prefix = getPrefix();
29986
30033
  // package.json
29987
- var version2 = "0.1.30";
30034
+ var version2 = "0.1.31";
29988
30035
 
29989
30036
  // bin/cli.ts
29990
30037
  init_actions();
package/dist/src/index.js CHANGED
@@ -12435,6 +12435,8 @@ function formatSubqueryValue(val) {
12435
12435
  return val ? "1" : "0";
12436
12436
  if (typeof val === "string")
12437
12437
  return `'${val.replace(/'/g, "''")}'`;
12438
+ if (val instanceof Date)
12439
+ return `'${val.toISOString()}'`;
12438
12440
  throw new TypeError(`[query-builder] subquery condition: refusing to interpolate value of type ${typeof val}`);
12439
12441
  }
12440
12442
  function buildOverClause(partitionBy, orderBy) {
@@ -13292,6 +13294,54 @@ function createQueryBuilder(state) {
13292
13294
  }
13293
13295
  return "";
13294
13296
  };
13297
+ const buildJoinConstraint = (targetTbl) => {
13298
+ if (!condition)
13299
+ return "";
13300
+ const frags = [];
13301
+ const addCmp = (col, op, val) => {
13302
+ validateIdentifier(String(col), "with() constraint column");
13303
+ const operator = assertSafeWhereOperator(op, "with() constraint operator");
13304
+ frags.push(`${targetTbl}.${String(col)} ${operator} ${formatSubqueryValue(val)}`);
13305
+ };
13306
+ const unsupported = (m) => () => {
13307
+ throw new Error(`[query-builder] with('${relationKey}', ...): ${m} is not supported inside a constraint callback on the JOIN-based builder \u2014 apply it to the outer query, or use the model layer's eager loading. (Silently ignoring it would return wrong data.)`);
13308
+ };
13309
+ const constraintQb = {
13310
+ where: (expr, op, val) => {
13311
+ if (Array.isArray(expr))
13312
+ addCmp(expr[0], expr[1], expr[2]);
13313
+ else if (expr && typeof expr === "object")
13314
+ for (const k of Object.keys(expr))
13315
+ addCmp(k, "=", expr[k]);
13316
+ else if (op !== undefined && val !== undefined)
13317
+ addCmp(expr, op, val);
13318
+ else if (op !== undefined)
13319
+ addCmp(expr, "=", op);
13320
+ return constraintQb;
13321
+ },
13322
+ whereIn: (col, vals) => {
13323
+ validateIdentifier(String(col), "with() constraint column");
13324
+ frags.push(`${targetTbl}.${String(col)} IN (${vals.map(formatSubqueryValue).join(", ")})`);
13325
+ return constraintQb;
13326
+ },
13327
+ whereNull: (col) => {
13328
+ validateIdentifier(String(col), "with() constraint column");
13329
+ frags.push(`${targetTbl}.${String(col)} IS NULL`);
13330
+ return constraintQb;
13331
+ },
13332
+ whereNotNull: (col) => {
13333
+ validateIdentifier(String(col), "with() constraint column");
13334
+ frags.push(`${targetTbl}.${String(col)} IS NOT NULL`);
13335
+ return constraintQb;
13336
+ },
13337
+ orderBy: unsupported("orderBy()"),
13338
+ limit: unsupported("limit()"),
13339
+ offset: unsupported("offset()"),
13340
+ take: unsupported("take()")
13341
+ };
13342
+ condition(constraintQb);
13343
+ return frags.length ? ` AND ${frags.join(" AND ")}` : "";
13344
+ };
13295
13345
  const resolveTarget = () => {
13296
13346
  const pick = (m) => {
13297
13347
  const modelName = m?.[relationKey];
@@ -13336,7 +13386,7 @@ function createQueryBuilder(state) {
13336
13386
  const throughPk = meta.primaryKeys[throughTable] ?? "id";
13337
13387
  const fkInThrough = `${singularize(fromTable)}_id`;
13338
13388
  const fkInFinal = `${singularize(throughTable)}_id`;
13339
- built = sql`${ensureBuilt()} LEFT JOIN ${sql(throughTable)} ON ${sql(`${throughTable}.${fkInThrough}`)} = ${sql(`${fromTable}.${fromPk}`)} LEFT JOIN ${sql(finalTable)} ON ${sql(`${finalTable}.${fkInFinal}`)} = ${sql(`${throughTable}.${throughPk}`)}`;
13389
+ insertJoin(`LEFT JOIN ${throughTable} ON ${throughTable}.${fkInThrough} = ${fromTable}.${fromPk} LEFT JOIN ${finalTable} ON ${finalTable}.${fkInFinal} = ${throughTable}.${throughPk}`);
13340
13390
  joinedTables.add(throughTable);
13341
13391
  joinedTables.add(finalTable);
13342
13392
  return finalTable;
@@ -13349,7 +13399,7 @@ function createQueryBuilder(state) {
13349
13399
  const childPk = meta.primaryKeys[childTable] ?? "id";
13350
13400
  const fkA = resolved?.fkParent ?? `${singularize(fromTable)}_id`;
13351
13401
  const fkB = resolved?.fkRelated ?? `${singularize(childTable)}_id`;
13352
- built = sql`${ensureBuilt()} LEFT JOIN ${sql(pivot)} ON ${sql(`${pivot}.${fkA}`)} = ${sql(`${fromTable}.${fromPk}`)} LEFT JOIN ${sql(childTable)} ON ${sql(`${childTable}.${childPk}`)} = ${sql(`${pivot}.${fkB}`)}`;
13402
+ insertJoin(`LEFT JOIN ${pivot} ON ${pivot}.${fkA} = ${fromTable}.${fromPk} LEFT JOIN ${childTable} ON ${childTable}.${childPk} = ${pivot}.${fkB}${buildJoinConstraint(childTable)}`);
13353
13403
  joinedTables.add(pivot);
13354
13404
  joinedTables.add(childTable);
13355
13405
  return childTable;
@@ -13363,7 +13413,8 @@ function createQueryBuilder(state) {
13363
13413
  const morphType = `${morphName}_type`;
13364
13414
  const morphId = `${morphName}_id`;
13365
13415
  const targetFk = `${singularize(childTable)}_id`;
13366
- built = sql`${ensureBuilt()} LEFT JOIN ${sql(pivotTable)} ON ${sql(`${pivotTable}.${morphId}`)} = ${sql(`${fromTable}.${fromPk}`)} AND ${sql(`${pivotTable}.${morphType}`)} = ${sql(meta.tableToModel[fromTable] || fromTable)} LEFT JOIN ${sql(childTable)} ON ${sql(`${childTable}.${childPk}`)} = ${sql(`${pivotTable}.${targetFk}`)}`;
13416
+ const morphVal = formatSubqueryValue(meta.tableToModel[fromTable] || fromTable);
13417
+ insertJoin(`LEFT JOIN ${pivotTable} ON ${pivotTable}.${morphId} = ${fromTable}.${fromPk} AND ${pivotTable}.${morphType} = ${morphVal} LEFT JOIN ${childTable} ON ${childTable}.${childPk} = ${pivotTable}.${targetFk}`);
13367
13418
  joinedTables.add(pivotTable);
13368
13419
  joinedTables.add(childTable);
13369
13420
  return childTable;
@@ -13379,7 +13430,8 @@ function createQueryBuilder(state) {
13379
13430
  const morphType = `${morphName}_type`;
13380
13431
  const morphId = `${morphName}_id`;
13381
13432
  const relatedFk = `${singularize(relatedTable)}_id`;
13382
- built = sql`${ensureBuilt()} LEFT JOIN ${sql(pivotTable)} ON ${sql(`${pivotTable}.${relatedFk}`)} = ${sql(`${fromTable}.${fromPk}`)} LEFT JOIN ${sql(relatedTable)} ON ${sql(`${relatedTable}.${relatedPk}`)} = ${sql(`${pivotTable}.${morphId}`)} AND ${sql(`${pivotTable}.${morphType}`)} = ${sql(meta.tableToModel[relatedTable] || relatedTable)}`;
13433
+ const morphVal = formatSubqueryValue(meta.tableToModel[relatedTable] || relatedTable);
13434
+ insertJoin(`LEFT JOIN ${pivotTable} ON ${pivotTable}.${relatedFk} = ${fromTable}.${fromPk} LEFT JOIN ${relatedTable} ON ${relatedTable}.${relatedPk} = ${pivotTable}.${morphId} AND ${pivotTable}.${morphType} = ${morphVal}`);
13383
13435
  joinedTables.add(pivotTable);
13384
13436
  joinedTables.add(relatedTable);
13385
13437
  return relatedTable;
@@ -13388,7 +13440,7 @@ function createQueryBuilder(state) {
13388
13440
  if (isBt) {
13389
13441
  const fkInParent = `${singularize(childTable)}_id`;
13390
13442
  const childPk = meta.primaryKeys[childTable] ?? "id";
13391
- built = sql`${ensureBuilt()} LEFT JOIN ${sql(childTable)} ON ${sql(`${fromTable}.${fkInParent}`)} = ${sql(`${childTable}.${childPk}`)}`;
13443
+ insertJoin(`LEFT JOIN ${childTable} ON ${fromTable}.${fkInParent} = ${childTable}.${childPk}${buildJoinConstraint(childTable)}`);
13392
13444
  joinedTables.add(childTable);
13393
13445
  return childTable;
13394
13446
  }
@@ -13398,20 +13450,15 @@ function createQueryBuilder(state) {
13398
13450
  const morphType = `${relationKey}_type`;
13399
13451
  const morphId = `${relationKey}_id`;
13400
13452
  const fromPk = meta.primaryKeys[fromTable] ?? "id";
13401
- built = sql`${ensureBuilt()} LEFT JOIN ${sql(childTable)} ON ${sql(`${childTable}.${morphId}`)} = ${sql(`${fromTable}.${fromPk}`)} AND ${sql(`${childTable}.${morphType}`)} = ${sql(meta.tableToModel[fromTable] || fromTable)}`;
13453
+ const morphVal = formatSubqueryValue(meta.tableToModel[fromTable] || fromTable);
13454
+ insertJoin(`LEFT JOIN ${childTable} ON ${childTable}.${morphId} = ${fromTable}.${fromPk} AND ${childTable}.${morphType} = ${morphVal}`);
13402
13455
  joinedTables.add(childTable);
13403
13456
  return childTable;
13404
13457
  }
13405
13458
  const fkInChild = `${singularize(fromTable)}_id`;
13406
13459
  const pk = meta.primaryKeys[fromTable] ?? "id";
13407
- const softDeleteCheck = addSoftDeleteCheck(childTable);
13408
- if (softDeleteCheck) {
13409
- const currentSql = String(ensureBuilt());
13410
- const joinCondition = `${childTable}.${fkInChild} = ${fromTable}.${pk}${softDeleteCheck}`;
13411
- built = sql`${sql(currentSql)} LEFT JOIN ${sql(childTable)} ON ${sql(joinCondition)}`;
13412
- } else {
13413
- built = sql`${ensureBuilt()} LEFT JOIN ${sql(childTable)} ON ${sql(`${childTable}.${fkInChild}`)} = ${sql(`${fromTable}.${pk}`)}`;
13414
- }
13460
+ const extraOn = `${addSoftDeleteCheck(childTable)}${buildJoinConstraint(childTable)}`;
13461
+ insertJoin(`LEFT JOIN ${childTable} ON ${childTable}.${fkInChild} = ${fromTable}.${pk}${extraOn}`);
13415
13462
  joinedTables.add(childTable);
13416
13463
  return childTable;
13417
13464
  };
@@ -13448,7 +13495,7 @@ function createQueryBuilder(state) {
13448
13495
  addToSelectClause(pivotColumnsStr);
13449
13496
  }
13450
13497
  }
13451
- text = computeSqlText(ensureBuilt());
13498
+ built = null;
13452
13499
  return this;
13453
13500
  },
13454
13501
  whereHas(relation, callback) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bun-query-builder",
3
3
  "type": "module",
4
- "version": "0.1.30",
4
+ "version": "0.1.31",
5
5
  "description": "A simple yet performant query builder for TypeScript. Built with Bun.",
6
6
  "author": "Chris Breuer <chris@stacksjs.org>",
7
7
  "license": "MIT",