bun-query-builder 0.2.43 → 0.2.45

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
@@ -140,7 +140,7 @@ class BrowserQueryBuilder {
140
140
  return this;
141
141
  }
142
142
  andWhere(column, operatorOrValue, value) {
143
- return this.where(column, operatorOrValue, value);
143
+ return value === undefined ? this.where(column, operatorOrValue) : this.where(column, operatorOrValue, value);
144
144
  }
145
145
  whereNull(column) {
146
146
  return this.where(column, "is", null);
@@ -476,7 +476,7 @@ class BrowserModelQueryBuilder {
476
476
  for (const where of this._wheres) {
477
477
  if (where.operator === "=") {
478
478
  params.append(where.column, String(where.value));
479
- } else if ((where.operator === "in" || where.operator === "not in") && Array.isArray(where.value)) {
479
+ } else if (where.operator === "in" && Array.isArray(where.value)) {
480
480
  params.append(`${where.column}[]`, where.value.join(","));
481
481
  } else if (where.operator === "is" && where.value === null) {
482
482
  params.append(`filter[${where.column}][is]`, "null");
@@ -11862,6 +11862,12 @@ import { Database } from "bun:sqlite";
11862
11862
  import { mkdirSync as mkdirSync5 } from "fs";
11863
11863
  import { dirname as dirname5 } from "path";
11864
11864
  import process21 from "process";
11865
+ function toBindings(params) {
11866
+ return params;
11867
+ }
11868
+ function asEmbeddedValue(value) {
11869
+ return value !== null && typeof value === "object" ? value : null;
11870
+ }
11865
11871
  function bindNumberedPlaceholders(sql, params) {
11866
11872
  if (params.length === 0 || !/\$\d/.test(sql))
11867
11873
  return { sql, params };
@@ -12050,11 +12056,13 @@ function createSQLiteSQL(filename) {
12050
12056
  const params = [];
12051
12057
  for (let i = 0;i < values.length; i++) {
12052
12058
  const value = values[i];
12053
- if (value && typeof value === "object" && typeof value.sql === "string" && Array.isArray(value.values)) {
12054
- sql += value.sql + (strings[i + 1] || "");
12055
- params.push(...value.values);
12056
- } else if (value && typeof value === "object" && (value.__raw || value.raw)) {
12057
- const rawValue = value.__raw ? value.value : typeof value.raw === "string" ? value.raw : value.raw();
12059
+ const embedded = asEmbeddedValue(value);
12060
+ if (embedded && typeof embedded.sql === "string" && Array.isArray(embedded.values)) {
12061
+ sql += embedded.sql + (strings[i + 1] || "");
12062
+ params.push(...embedded.values);
12063
+ } else if (embedded && (embedded.__raw || embedded.raw)) {
12064
+ const raw = embedded.raw;
12065
+ const rawValue = embedded.__raw ? embedded.value : typeof raw === "string" ? raw : raw();
12058
12066
  sql += rawValue + (strings[i + 1] || "");
12059
12067
  } else if (Array.isArray(value)) {
12060
12068
  const placeholders = value.map(() => "?").join(", ");
@@ -12072,10 +12080,10 @@ function createSQLiteSQL(filename) {
12072
12080
  try {
12073
12081
  const trimmed = sql.trim().toUpperCase();
12074
12082
  if (trimmed.startsWith("SELECT") || trimmed.startsWith("PRAGMA") || /\bRETURNING\b/.test(trimmed)) {
12075
- const result = wrapper.query(sql, params);
12083
+ const result = wrapper.query(sql, toBindings(params));
12076
12084
  return Promise.resolve(result);
12077
12085
  } else {
12078
- const result = wrapper.run(sql, params);
12086
+ const result = wrapper.run(sql, toBindings(params));
12079
12087
  return Promise.resolve(result);
12080
12088
  }
12081
12089
  } catch (error) {
@@ -12102,10 +12110,10 @@ function createSQLiteSQL(filename) {
12102
12110
  try {
12103
12111
  const trimmed = sql.trim().toUpperCase();
12104
12112
  if (trimmed.startsWith("SELECT") || trimmed.startsWith("PRAGMA") || /\bRETURNING\b/.test(trimmed)) {
12105
- const result = wrapper.query(sql, params);
12113
+ const result = wrapper.query(sql, toBindings(params));
12106
12114
  return Promise.resolve(result);
12107
12115
  } else {
12108
- const result = wrapper.run(sql, params);
12116
+ const result = wrapper.run(sql, toBindings(params));
12109
12117
  return Promise.resolve(result);
12110
12118
  }
12111
12119
  } catch (error) {
@@ -12128,7 +12136,7 @@ function createSQLiteSQL(filename) {
12128
12136
  };
12129
12137
  sqlFunction.query = (sql, params) => {
12130
12138
  try {
12131
- const result = wrapper.query(sql, params || []);
12139
+ const result = wrapper.query(sql, toBindings(params || []));
12132
12140
  return Promise.resolve(result);
12133
12141
  } catch (error) {
12134
12142
  return Promise.reject(error);
@@ -15793,6 +15801,31 @@ function createQueryBuilder(state) {
15793
15801
  let built;
15794
15802
  let sqlText = "";
15795
15803
  const params = [];
15804
+ let noRows = false;
15805
+ const emptyInsertResult = () => isPostgres ? [] : { changes: 0, lastInsertRowid: 0 };
15806
+ const emptyReturningBuilder = () => {
15807
+ const noRow = async () => {
15808
+ return;
15809
+ };
15810
+ const noRowOrFail = async () => {
15811
+ throw new Error("Insert with RETURNING returned no rows");
15812
+ };
15813
+ return {
15814
+ where: () => emptyReturningBuilder(),
15815
+ andWhere: () => emptyReturningBuilder(),
15816
+ orWhere: () => emptyReturningBuilder(),
15817
+ orderBy: () => emptyReturningBuilder(),
15818
+ limit: () => emptyReturningBuilder(),
15819
+ offset: () => emptyReturningBuilder(),
15820
+ toSQL: () => makeExecutableQuery(null, ""),
15821
+ execute: async () => [],
15822
+ get: async () => [],
15823
+ first: noRow,
15824
+ executeTakeFirst: noRow,
15825
+ firstOrFail: noRowOrFail,
15826
+ executeTakeFirstOrThrow: noRowOrFail
15827
+ };
15828
+ };
15796
15829
  const isPostgres = config5.dialect === "postgres";
15797
15830
  const quoteId = isPostgres ? (id) => `"${String(id).replace(/"/g, '""')}"` : isMysqlLike(config5.dialect) ? (id) => `\`${String(id).replace(/`/g, "``")}\`` : (id) => `"${String(id).replace(/"/g, '""')}"`;
15798
15831
  const getPlaceholder2 = isPostgres ? (index) => `$${index + 1}` : (_index) => "?";
@@ -15801,9 +15834,13 @@ function createQueryBuilder(state) {
15801
15834
  const rows = Array.isArray(data) ? data : [data];
15802
15835
  const rowCount = rows.length;
15803
15836
  if (rowCount === 0) {
15804
- built = _sql.unsafe("SELECT 1");
15837
+ noRows = true;
15838
+ built = null;
15839
+ sqlText = "";
15840
+ params.length = 0;
15805
15841
  return this;
15806
15842
  }
15843
+ noRows = false;
15807
15844
  const firstRow = rows[0];
15808
15845
  const keys = Object.keys(firstRow);
15809
15846
  const colCount = keys.length;
@@ -15857,6 +15894,8 @@ function createQueryBuilder(state) {
15857
15894
  return this;
15858
15895
  },
15859
15896
  returning(...cols) {
15897
+ if (noRows)
15898
+ return emptyReturningBuilder();
15860
15899
  const returningSql = `${sqlText} RETURNING ${cols.join(", ")}`;
15861
15900
  const q = _sql.unsafe(returningSql, params);
15862
15901
  const runFirst = async () => {
@@ -15890,11 +15929,15 @@ function createQueryBuilder(state) {
15890
15929
  };
15891
15930
  },
15892
15931
  toSQL() {
15932
+ if (noRows)
15933
+ return makeExecutableQuery(null, "");
15893
15934
  if (!built)
15894
15935
  built = _sql.unsafe(sqlText, params);
15895
15936
  return makeExecutableQuery(built, sqlText);
15896
15937
  },
15897
15938
  execute() {
15939
+ if (noRows)
15940
+ return Promise.resolve(emptyInsertResult());
15898
15941
  const hooks = activeHooks();
15899
15942
  const hasHooks = hooks && (hooks.onQueryStart || hooks.onQueryEnd || hooks.onQueryError || hooks.startSpan || hooks.beforeCreate || hooks.afterCreate || hasSlowQueryHook(hooks));
15900
15943
  if (!hasHooks) {
@@ -15909,12 +15952,16 @@ function createQueryBuilder(state) {
15909
15952
  return runWithHooks(built, "insert");
15910
15953
  },
15911
15954
  async executeTakeFirst() {
15955
+ if (noRows)
15956
+ return emptyInsertResult();
15912
15957
  if (!built)
15913
15958
  built = _sql.unsafe(sqlText, params);
15914
15959
  const result = await runWithHooks(built, "insert");
15915
15960
  return result;
15916
15961
  },
15917
15962
  async executeTakeFirstOrThrow() {
15963
+ if (noRows)
15964
+ throw new Error("Insert failed");
15918
15965
  if (!built)
15919
15966
  built = _sql.unsafe(sqlText, params);
15920
15967
  const result = await runWithHooks(built, "insert");
@@ -15923,6 +15970,8 @@ function createQueryBuilder(state) {
15923
15970
  return result;
15924
15971
  },
15925
15972
  returningAll() {
15973
+ if (noRows)
15974
+ return emptyReturningBuilder();
15926
15975
  const returningSql = `${sqlText} RETURNING *`;
15927
15976
  const q = _sql.unsafe(returningSql, params);
15928
15977
  const runFirst = async () => {
@@ -16029,8 +16078,22 @@ function createQueryBuilder(state) {
16029
16078
  built = _sql.unsafe(sqlText, params);
16030
16079
  return this;
16031
16080
  }
16032
- if (expr && typeof expr === "object" && !("raw" in expr)) {
16081
+ if (isRawExpression(expr)) {
16082
+ sqlText = `${sqlText} ${getWhereKeyword()} ${expr.raw}`;
16083
+ built = _sql.unsafe(sqlText, params);
16084
+ return this;
16085
+ }
16086
+ if (isBoundSqlExpression(expr)) {
16087
+ const rendered = renderBoundSqlExpression(expr, params.length + 1);
16088
+ sqlText = `${sqlText} ${getWhereKeyword()} ${rendered.text}`;
16089
+ params.push(...rendered.parameters);
16090
+ built = _sql.unsafe(sqlText, params);
16091
+ return this;
16092
+ }
16093
+ if (expr && typeof expr === "object") {
16033
16094
  const keys = Object.keys(expr);
16095
+ if (keys.length === 0)
16096
+ throw new TypeError("[query-builder] updateTable.where({}): an empty object is not a filter. Pass a condition, or drop the where() call if updating every row is intended.");
16034
16097
  const len = keys.length;
16035
16098
  const baseIdx = params.length;
16036
16099
  const conditions = Array.from({ length: len });
@@ -16040,8 +16103,9 @@ function createQueryBuilder(state) {
16040
16103
  }
16041
16104
  sqlText = `${sqlText} ${getWhereKeyword()} ${conditions.join(" AND ")}`;
16042
16105
  built = _sql.unsafe(sqlText, params);
16106
+ return this;
16043
16107
  }
16044
- return this;
16108
+ throw new TypeError(`[query-builder] updateTable.where(): expected a condition, got ${expr === null ? "null" : typeof expr}. Refusing to run an UPDATE with no WHERE \u2014 drop the where() call if updating every row is intended.`);
16045
16109
  },
16046
16110
  whereNull(column) {
16047
16111
  const keyword = SQL_PATTERNS.WHERE.test(sqlText) ? "AND" : "WHERE";
@@ -16056,22 +16120,40 @@ function createQueryBuilder(state) {
16056
16120
  return this;
16057
16121
  },
16058
16122
  returning(...cols) {
16059
- const retText = `${sqlText} RETURNING ${cols.join(", ")}`;
16060
- const q = params.length > 0 ? _sql.unsafe(retText, params) : _sql.unsafe(retText);
16123
+ const parent = this;
16124
+ const retText = () => `${sqlText} RETURNING ${cols.join(", ")}`;
16125
+ const build = () => params.length > 0 ? _sql.unsafe(retText(), params) : _sql.unsafe(retText());
16061
16126
  const runFirst = async () => {
16062
- const rows = await runWithHooks(q, "update");
16127
+ const rows = await runWithHooks(build(), "update");
16063
16128
  return Array.isArray(rows) ? rows[0] : rows;
16064
16129
  };
16130
+ const unsupported = (name) => () => {
16131
+ throw new TypeError(`[query-builder] updateTable.returning(...).${name}() is not supported \u2014 an UPDATE cannot be ordered or limited through this builder. Apply the filter with where() instead.`);
16132
+ };
16065
16133
  const obj = {
16066
- where: () => obj,
16067
- andWhere: () => obj,
16068
- orWhere: () => obj,
16069
- orderBy: () => obj,
16070
- limit: () => obj,
16071
- offset: () => obj,
16072
- toSQL: () => makeExecutableQuery(q, retText),
16073
- execute: () => runWithHooks(q, "update"),
16074
- get: () => runWithHooks(q, "update"),
16134
+ where: (...args) => {
16135
+ parent.where(...args);
16136
+ return obj;
16137
+ },
16138
+ andWhere: (...args) => {
16139
+ parent.where(...args);
16140
+ return obj;
16141
+ },
16142
+ whereNull: (...args) => {
16143
+ parent.whereNull(...args);
16144
+ return obj;
16145
+ },
16146
+ whereNotNull: (...args) => {
16147
+ parent.whereNotNull(...args);
16148
+ return obj;
16149
+ },
16150
+ orWhere: unsupported("orWhere"),
16151
+ orderBy: unsupported("orderBy"),
16152
+ limit: unsupported("limit"),
16153
+ offset: unsupported("offset"),
16154
+ toSQL: () => makeExecutableQuery(build(), retText()),
16155
+ execute: () => runWithHooks(build(), "update"),
16156
+ get: () => runWithHooks(build(), "update"),
16075
16157
  first: runFirst,
16076
16158
  executeTakeFirst: runFirst,
16077
16159
  async firstOrFail() {
@@ -16110,17 +16192,17 @@ function createQueryBuilder(state) {
16110
16192
  return { numUpdatedRows: result };
16111
16193
  },
16112
16194
  returningAll() {
16113
- const retAllText = `${sqlText} RETURNING *`;
16114
- const q = params.length > 0 ? _sql.unsafe(retAllText, params) : _sql.unsafe(retAllText);
16195
+ const retAllText = () => `${sqlText} RETURNING *`;
16196
+ const build = () => params.length > 0 ? _sql.unsafe(retAllText(), params) : _sql.unsafe(retAllText());
16115
16197
  return {
16116
- toSQL: () => makeExecutableQuery(q, retAllText),
16117
- execute: () => runWithHooks(q, "update"),
16198
+ toSQL: () => makeExecutableQuery(build(), retAllText()),
16199
+ execute: () => runWithHooks(build(), "update"),
16118
16200
  async executeTakeFirst() {
16119
- const result = await runWithHooks(q, "update");
16201
+ const result = await runWithHooks(build(), "update");
16120
16202
  return Array.isArray(result) ? result[0] : result;
16121
16203
  },
16122
16204
  async executeTakeFirstOrThrow() {
16123
- const result = await runWithHooks(q, "update");
16205
+ const result = await runWithHooks(build(), "update");
16124
16206
  const first = Array.isArray(result) ? result[0] : result;
16125
16207
  if (!first)
16126
16208
  throw new Error("Update with RETURNING failed");
@@ -16185,8 +16267,22 @@ function createQueryBuilder(state) {
16185
16267
  built = null;
16186
16268
  return this;
16187
16269
  }
16188
- if (expr && typeof expr === "object" && !("raw" in expr)) {
16270
+ if (isRawExpression(expr)) {
16271
+ sqlText += ` ${getWhereKeyword()} ${expr.raw}`;
16272
+ built = null;
16273
+ return this;
16274
+ }
16275
+ if (isBoundSqlExpression(expr)) {
16276
+ const rendered = renderBoundSqlExpression(expr, delParams.length + 1);
16277
+ sqlText += ` ${getWhereKeyword()} ${rendered.text}`;
16278
+ delParams.push(...rendered.parameters);
16279
+ built = null;
16280
+ return this;
16281
+ }
16282
+ if (expr && typeof expr === "object") {
16189
16283
  const keys = Object.keys(expr);
16284
+ if (keys.length === 0)
16285
+ throw new TypeError("[query-builder] deleteFrom.where({}): an empty object is not a filter. Pass a condition, or drop the where() call if deleting every row is intended.");
16190
16286
  const conditions = [];
16191
16287
  for (const key of keys) {
16192
16288
  const paramIndex = delParams.length + 1;
@@ -16197,8 +16293,7 @@ function createQueryBuilder(state) {
16197
16293
  built = null;
16198
16294
  return this;
16199
16295
  }
16200
- built = applyWhere({}, ensureDelBuilt(), expr);
16201
- return this;
16296
+ throw new TypeError(`[query-builder] deleteFrom.where(): expected a condition, got ${expr === null ? "null" : typeof expr}. Refusing to run a DELETE with no WHERE \u2014 drop the where() call if deleting every row is intended.`);
16202
16297
  },
16203
16298
  whereNull(column) {
16204
16299
  sqlText += ` ${getWhereKeyword()} ${quoteId(String(column))} IS NULL`;
@@ -16211,22 +16306,48 @@ function createQueryBuilder(state) {
16211
16306
  return this;
16212
16307
  },
16213
16308
  returning(...cols) {
16214
- const retText = `${sqlText} RETURNING ${cols.join(", ")}`;
16215
- const q = delParams.length > 0 ? _sql.unsafe(retText, delParams) : _sql.unsafe(retText);
16309
+ const parent = this;
16310
+ const retText = () => `${sqlText} RETURNING ${cols.join(", ")}`;
16311
+ const build = () => delParams.length > 0 ? _sql.unsafe(retText(), delParams) : _sql.unsafe(retText());
16312
+ const runDelete = async () => {
16313
+ await activeHooks()?.beforeDelete?.({ table: String(table), where: whereCondition });
16314
+ const rows = await runWithHooks(build(), "delete");
16315
+ try {
16316
+ await activeHooks()?.afterDelete?.({ table: String(table), where: whereCondition, result: rows });
16317
+ } catch {}
16318
+ return rows;
16319
+ };
16216
16320
  const runFirst = async () => {
16217
- const rows = await runWithHooks(q, "delete");
16321
+ const rows = await runDelete();
16218
16322
  return Array.isArray(rows) ? rows[0] : rows;
16219
16323
  };
16324
+ const unsupported = (name) => () => {
16325
+ throw new TypeError(`[query-builder] deleteFrom.returning(...).${name}() is not supported \u2014 a DELETE cannot be ordered or limited through this builder. Narrow it with where() instead.`);
16326
+ };
16220
16327
  const obj = {
16221
- where: () => obj,
16222
- andWhere: () => obj,
16223
- orWhere: () => obj,
16224
- orderBy: () => obj,
16225
- limit: () => obj,
16226
- offset: () => obj,
16227
- toSQL: () => makeExecutableQuery(q, retText),
16228
- execute: () => runWithHooks(q, "delete"),
16229
- get: () => runWithHooks(q, "delete"),
16328
+ where: (...args) => {
16329
+ parent.where(...args);
16330
+ return obj;
16331
+ },
16332
+ andWhere: (...args) => {
16333
+ parent.where(...args);
16334
+ return obj;
16335
+ },
16336
+ whereNull: (...args) => {
16337
+ parent.whereNull(...args);
16338
+ return obj;
16339
+ },
16340
+ whereNotNull: (...args) => {
16341
+ parent.whereNotNull(...args);
16342
+ return obj;
16343
+ },
16344
+ orWhere: unsupported("orWhere"),
16345
+ orderBy: unsupported("orderBy"),
16346
+ limit: unsupported("limit"),
16347
+ offset: unsupported("offset"),
16348
+ toSQL: () => makeExecutableQuery(build(), retText()),
16349
+ execute: () => runDelete(),
16350
+ get: () => runDelete(),
16230
16351
  first: runFirst,
16231
16352
  executeTakeFirst: runFirst,
16232
16353
  async firstOrFail() {
@@ -16270,17 +16391,17 @@ function createQueryBuilder(state) {
16270
16391
  return { numDeletedRows: result };
16271
16392
  },
16272
16393
  returningAll() {
16273
- const retAllText = `${sqlText} RETURNING *`;
16274
- const q = delParams.length > 0 ? _sql.unsafe(retAllText, delParams) : _sql.unsafe(retAllText);
16394
+ const retAllText = () => `${sqlText} RETURNING *`;
16395
+ const build = () => delParams.length > 0 ? _sql.unsafe(retAllText(), delParams) : _sql.unsafe(retAllText());
16275
16396
  return {
16276
- toSQL: () => makeExecutableQuery(q, retAllText),
16277
- execute: () => runWithHooks(q, "delete"),
16397
+ toSQL: () => makeExecutableQuery(build(), retAllText()),
16398
+ execute: () => runWithHooks(build(), "delete"),
16278
16399
  async executeTakeFirst() {
16279
- const result = await runWithHooks(q, "delete");
16400
+ const result = await runWithHooks(build(), "delete");
16280
16401
  return Array.isArray(result) ? result[0] : result;
16281
16402
  },
16282
16403
  async executeTakeFirstOrThrow() {
16283
- const result = await runWithHooks(q, "delete");
16404
+ const result = await runWithHooks(build(), "delete");
16284
16405
  const first = Array.isArray(result) ? result[0] : result;
16285
16406
  if (!first)
16286
16407
  throw new Error("Delete with RETURNING failed");
@@ -18944,11 +19065,66 @@ var init_vitess = __esm(() => {
18944
19065
  };
18945
19066
  });
18946
19067
 
18947
- // src/drivers/sqlite.ts
19068
+ // src/column-types.ts
18948
19069
  function isNumericPlanType(type) {
18949
19070
  return type === "integer" || type === "bigint" || type === "float" || type === "double" || type === "decimal";
18950
19071
  }
19072
+ function normalizeAttributeType(raw2) {
19073
+ if (typeof raw2 !== "string")
19074
+ return;
19075
+ switch (raw2.toLowerCase()) {
19076
+ case "string":
19077
+ return "string";
19078
+ case "text":
19079
+ return "text";
19080
+ case "integer":
19081
+ case "int":
19082
+ return "integer";
19083
+ case "number":
19084
+ return "integer";
19085
+ case "bigint":
19086
+ return "bigint";
19087
+ case "float":
19088
+ return "float";
19089
+ case "double":
19090
+ return "double";
19091
+ case "decimal":
19092
+ return "decimal";
19093
+ case "boolean":
19094
+ case "bool":
19095
+ return "boolean";
19096
+ case "date":
19097
+ return "date";
19098
+ case "datetime":
19099
+ case "timestamp":
19100
+ return "datetime";
19101
+ case "timestamptz":
19102
+ case "timestamp_tz":
19103
+ return "timestamptz";
19104
+ case "json":
19105
+ return "json";
19106
+ case "enum":
19107
+ return "enum";
19108
+ default:
19109
+ return;
19110
+ }
19111
+ }
19112
+ function sqliteAffinityFor(type) {
19113
+ switch (type) {
19114
+ case "boolean":
19115
+ case "integer":
19116
+ case "bigint":
19117
+ return "INTEGER";
19118
+ case "float":
19119
+ case "double":
19120
+ case "decimal":
19121
+ return "REAL";
19122
+ default:
19123
+ return "TEXT";
19124
+ }
19125
+ }
18951
19126
 
19127
+ // src/drivers/sqlite.ts
18952
19128
  class SQLiteDriver {
18953
19129
  quoteIdentifier(id) {
18954
19130
  return `"${id.replace(/"/g, '""')}"`;
@@ -18957,40 +19133,14 @@ class SQLiteDriver {
18957
19133
  if (column.name.endsWith("_id") && isNumericPlanType(column.type)) {
18958
19134
  return "INTEGER";
18959
19135
  }
18960
- switch (column.type) {
18961
- case "string":
18962
- return "TEXT";
18963
- case "text":
18964
- return "TEXT";
18965
- case "boolean":
18966
- return "INTEGER";
18967
- case "integer":
18968
- return "INTEGER";
18969
- case "bigint":
18970
- return "INTEGER";
18971
- case "float":
18972
- return "REAL";
18973
- case "double":
18974
- return "REAL";
18975
- case "decimal":
18976
- return "REAL";
18977
- case "date":
18978
- return "TEXT";
18979
- case "datetime":
18980
- return "TEXT";
18981
- case "timestamptz":
18982
- return "TEXT";
18983
- case "json":
18984
- return "TEXT";
18985
- case "enum":
18986
- if (column.enumValues && column.enumValues.length > 0) {
18987
- const enumValues = column.enumValues.map((v) => `'${v.replace(/'/g, "''")}'`).join(", ");
18988
- return `TEXT CHECK (${this.quoteIdentifier(column.name)} IN (${enumValues}))`;
18989
- }
18990
- return "TEXT";
18991
- default:
18992
- return "TEXT";
19136
+ if (column.type === "enum") {
19137
+ if (column.enumValues && column.enumValues.length > 0) {
19138
+ const enumValues = column.enumValues.map((v) => `'${v.replace(/'/g, "''")}'`).join(", ");
19139
+ return `TEXT CHECK (${this.quoteIdentifier(column.name)} IN (${enumValues}))`;
19140
+ }
19141
+ return "TEXT";
18993
19142
  }
19143
+ return sqliteAffinityFor(column.type);
18994
19144
  }
18995
19145
  getPrimaryKeyType(column) {
18996
19146
  return this.getColumnType(column);
@@ -25386,6 +25536,14 @@ function assertValidOrderByColumn(name, context) {
25386
25536
  if (parts.length > 2 || parts.some((p2) => p2.length === 0 || p2.length > 64 || !SAFE_SQL_IDENTIFIER.test(p2)))
25387
25537
  throw new TypeError(`[bun-query-builder] ${context}: invalid ORDER BY column '${name}' \u2014 expected 'column' or 'table.column' of [A-Za-z0-9_] \u2014 refusing to interpolate into SQL`);
25388
25538
  }
25539
+ function registerLocalModel(name, model) {
25540
+ localModels.set(name, model);
25541
+ relationCache.clear();
25542
+ }
25543
+ function clearLocalModels() {
25544
+ localModels.clear();
25545
+ relationCache.clear();
25546
+ }
25389
25547
  function getModelFromRegistry(name) {
25390
25548
  if (!_getModel) {
25391
25549
  try {
@@ -25396,7 +25554,7 @@ function getModelFromRegistry(name) {
25396
25554
  };
25397
25555
  }
25398
25556
  }
25399
- return _getModel(name);
25557
+ return _getModel(name) ?? localModels.get(name);
25400
25558
  }
25401
25559
  function toPostgresPlaceholders(sql2) {
25402
25560
  const hit = pgPlaceholderCache.get(sql2);
@@ -25594,6 +25752,7 @@ function findAttributeDef(attrs, key) {
25594
25752
  class ModelInstance {
25595
25753
  _attributes;
25596
25754
  _original;
25755
+ _forced = new Set;
25597
25756
  _definition;
25598
25757
  _hasSaved = false;
25599
25758
  _relations = {};
@@ -25727,7 +25886,10 @@ class ModelInstance {
25727
25886
  forceFill(data) {
25728
25887
  if (this._original === null)
25729
25888
  this._original = { ...this._attributes };
25730
- Object.assign(this._attributes, normalizeAttributeKeys(data));
25889
+ const normalized = normalizeAttributeKeys(data);
25890
+ Object.assign(this._attributes, normalized);
25891
+ for (const col of Object.keys(normalized))
25892
+ this._forced.add(col);
25731
25893
  return this;
25732
25894
  }
25733
25895
  async save() {
@@ -25759,7 +25921,7 @@ class ModelInstance {
25759
25921
  const attrs = this._definition.attributes;
25760
25922
  const data = {};
25761
25923
  for (const [key, attr] of Object.entries(attrs)) {
25762
- if (attr.guarded)
25924
+ if (attr.guarded && !this._forced.has(toSnakeCase(key)))
25763
25925
  continue;
25764
25926
  const col = toSnakeCase(key);
25765
25927
  if (this._attributes[col] !== undefined) {
@@ -27157,7 +27319,10 @@ function createModelInternal(definition) {
27157
27319
  });
27158
27320
  }
27159
27321
  function createModel(definition) {
27160
- return createModelInternal(definition);
27322
+ const model = createModelInternal(definition);
27323
+ if (definition?.name)
27324
+ registerLocalModel(definition.name, model);
27325
+ return model;
27161
27326
  }
27162
27327
  async function createTableFromModel(definition) {
27163
27328
  const exec = getExecutor();
@@ -27174,12 +27339,9 @@ async function createTableFromModel(definition) {
27174
27339
  if (emitted.has(name))
27175
27340
  continue;
27176
27341
  emitted.add(name);
27177
- let colType = "TEXT";
27178
- if (attr.type === "number")
27179
- colType = "INTEGER";
27180
- else if (attr.type === "boolean")
27181
- colType = "INTEGER";
27182
- if (name.endsWith("_id"))
27342
+ const declaredType = normalizeAttributeType(attr.type);
27343
+ let colType = sqliteAffinityFor(declaredType);
27344
+ if (name.endsWith("_id") && (declaredType === undefined || isNumericPlanType(declaredType)))
27183
27345
  colType = "INTEGER";
27184
27346
  let colDef = `${name} ${colType}`;
27185
27347
  if (attr.unique)
@@ -27245,12 +27407,13 @@ async function seedModel(definition, count, faker) {
27245
27407
  await exec.run(`INSERT INTO ${definition.table} (${columns.join(", ")}) VALUES (${columns.map(() => "?").join(", ")})`, Object.values(data));
27246
27408
  }
27247
27409
  }
27248
- var SAFE_SQL_IDENTIFIER, _getModel = null, pgPlaceholderCache, PG_PLACEHOLDER_CACHE_MAX = 500, globalDb = null, _executor = null, _executorForDb = null, _executorDialect = null, _executorDatabase = null, SOFT_DELETE_COLUMN = "deleted_at", BTM_RELATED_ALIAS = "__btm_rel__", btmKeysCache, snakeCaseCache, tableNameCache, relationCache, RELATION_CACHE_MAX = 1000, RESOLVABLE_RELATION_KINDS, DECLARABLE_RELATION_KINDS;
27410
+ var SAFE_SQL_IDENTIFIER, _getModel = null, localModels, pgPlaceholderCache, PG_PLACEHOLDER_CACHE_MAX = 500, globalDb = null, _executor = null, _executorForDb = null, _executorDialect = null, _executorDatabase = null, SOFT_DELETE_COLUMN = "deleted_at", BTM_RELATED_ALIAS = "__btm_rel__", btmKeysCache, snakeCaseCache, tableNameCache, relationCache, RELATION_CACHE_MAX = 1000, RESOLVABLE_RELATION_KINDS, DECLARABLE_RELATION_KINDS;
27249
27411
  var init_orm = __esm(() => {
27250
27412
  init_config();
27251
27413
  init_db();
27252
27414
  init_sqlite_pragmas();
27253
27415
  SAFE_SQL_IDENTIFIER = /^[A-Z_][A-Z0-9_]*$/i;
27416
+ localModels = new Map;
27254
27417
  pgPlaceholderCache = new Map;
27255
27418
  btmKeysCache = new WeakMap;
27256
27419
  snakeCaseCache = new Map;
@@ -27295,6 +27458,7 @@ function hasModel(name) {
27295
27458
  }
27296
27459
  function clearModelRegistry() {
27297
27460
  modelRegistry.clear();
27461
+ clearLocalModels();
27298
27462
  }
27299
27463
  function registerModel(name, model) {
27300
27464
  modelRegistry.set(name, model);
@@ -29070,7 +29234,7 @@ function detectTypeFromValidationRule(rule) {
29070
29234
  }
29071
29235
  return;
29072
29236
  }
29073
- function normalizeAttributeType(value) {
29237
+ function normalizeAttributeType2(value) {
29074
29238
  if (typeof value !== "string")
29075
29239
  return;
29076
29240
  const type = value.trim().toLowerCase().replace(/[\s-]+/g, "_");
@@ -29160,7 +29324,7 @@ function buildMigrationPlan2(models, options) {
29160
29324
  let inferred;
29161
29325
  let enumValues;
29162
29326
  const isPk = attrName === primaryKey;
29163
- inferred = normalizeAttributeType(attr.type) ?? detectTypeFromValidationRule(attr.validation?.rule);
29327
+ inferred = normalizeAttributeType2(attr.type) ?? detectTypeFromValidationRule(attr.validation?.rule);
29164
29328
  if (inferred === "string") {
29165
29329
  const maxLength = extractMaxFromRules(attr.validation?.rule);
29166
29330
  if (maxLength && maxLength > MAX_BOUNDED_VARCHAR_LENGTH)
@@ -32359,7 +32523,7 @@ function getPrefix() {
32359
32523
  }
32360
32524
  var prefix = getPrefix();
32361
32525
  // package.json
32362
- var version2 = "0.2.43";
32526
+ var version2 = "0.2.45";
32363
32527
 
32364
32528
  // bin/cli.ts
32365
32529
  init_actions();