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