bun-query-builder 0.2.41 → 0.2.44
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 +257 -96
- package/dist/client.d.ts +19 -1
- package/dist/column-types.d.ts +26 -0
- package/dist/drivers/sqlite.d.ts +11 -6
- package/dist/model.d.ts +4 -0
- package/dist/orm.d.ts +2 -0
- package/dist/src/browser.js +1 -1
- package/dist/src/index.js +258 -95
- package/package.json +1 -1
package/dist/src/index.js
CHANGED
|
@@ -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 (
|
|
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");
|
|
@@ -12855,7 +12855,10 @@ function warnOnceBareSqlFragment(context) {
|
|
|
12855
12855
|
if (warnedSqlFragmentContexts.has(context))
|
|
12856
12856
|
return;
|
|
12857
12857
|
warnedSqlFragmentContexts.add(context);
|
|
12858
|
-
console.warn(`[query-builder] ${context}: bare string passed to a *Raw method. ` + `Prefer \`
|
|
12858
|
+
console.warn(`[query-builder] ${context}: bare string passed to a *Raw method. ` + `Prefer the \`raw\`...\`\` tagged template, which escapes interpolated ` + `values for the configured dialect \u2014 concatenating request input into SQL ` + `is an injection vector. This will become a hard error in a future release.`);
|
|
12859
|
+
}
|
|
12860
|
+
function escapeStringLiteral(value, dialect = config5.dialect) {
|
|
12861
|
+
return isMysqlLike(dialect) ? value.replace(/\\/g, "\\\\").replace(/'/g, "''") : value.replace(/'/g, "''");
|
|
12859
12862
|
}
|
|
12860
12863
|
function formatSubqueryValue(val) {
|
|
12861
12864
|
if (val === null)
|
|
@@ -12865,7 +12868,7 @@ function formatSubqueryValue(val) {
|
|
|
12865
12868
|
if (typeof val === "boolean")
|
|
12866
12869
|
return val ? "1" : "0";
|
|
12867
12870
|
if (typeof val === "string")
|
|
12868
|
-
return `'${val
|
|
12871
|
+
return `'${escapeStringLiteral(val)}'`;
|
|
12869
12872
|
if (val instanceof Date)
|
|
12870
12873
|
return `'${val.toISOString()}'`;
|
|
12871
12874
|
throw new TypeError(`[query-builder] subquery condition: refusing to interpolate value of type ${typeof val}`);
|
|
@@ -14486,11 +14489,13 @@ function createQueryBuilder(state) {
|
|
|
14486
14489
|
const dialect = config5.dialect;
|
|
14487
14490
|
const idx = whereParams.length + 1;
|
|
14488
14491
|
if (dialect === "postgres") {
|
|
14492
|
+
const needsJsonbLift = typeof json === "number" || typeof json === "boolean";
|
|
14493
|
+
const operand = needsJsonbLift ? `to_jsonb(${getPlaceholder(idx)})` : getPlaceholder(idx);
|
|
14489
14494
|
if (config5.sql?.jsonContainsMode === "function")
|
|
14490
|
-
pushWhere("AND", `jsonb_contains(${column}, ${
|
|
14495
|
+
pushWhere("AND", `jsonb_contains(${column}, ${operand})`);
|
|
14491
14496
|
else
|
|
14492
|
-
pushWhere("AND", `${column} @> ${
|
|
14493
|
-
whereParams.push(
|
|
14497
|
+
pushWhere("AND", `${column} @> ${operand}`);
|
|
14498
|
+
whereParams.push(json);
|
|
14494
14499
|
} else if (isMysqlLike(dialect)) {
|
|
14495
14500
|
pushWhere("AND", `JSON_CONTAINS(${column}, ${getPlaceholder(idx)})`);
|
|
14496
14501
|
whereParams.push(JSON.stringify(json));
|
|
@@ -15787,6 +15792,31 @@ function createQueryBuilder(state) {
|
|
|
15787
15792
|
let built;
|
|
15788
15793
|
let sqlText = "";
|
|
15789
15794
|
const params = [];
|
|
15795
|
+
let noRows = false;
|
|
15796
|
+
const emptyInsertResult = () => isPostgres ? [] : { changes: 0, lastInsertRowid: 0 };
|
|
15797
|
+
const emptyReturningBuilder = () => {
|
|
15798
|
+
const noRow = async () => {
|
|
15799
|
+
return;
|
|
15800
|
+
};
|
|
15801
|
+
const noRowOrFail = async () => {
|
|
15802
|
+
throw new Error("Insert with RETURNING returned no rows");
|
|
15803
|
+
};
|
|
15804
|
+
return {
|
|
15805
|
+
where: () => emptyReturningBuilder(),
|
|
15806
|
+
andWhere: () => emptyReturningBuilder(),
|
|
15807
|
+
orWhere: () => emptyReturningBuilder(),
|
|
15808
|
+
orderBy: () => emptyReturningBuilder(),
|
|
15809
|
+
limit: () => emptyReturningBuilder(),
|
|
15810
|
+
offset: () => emptyReturningBuilder(),
|
|
15811
|
+
toSQL: () => makeExecutableQuery(null, ""),
|
|
15812
|
+
execute: async () => [],
|
|
15813
|
+
get: async () => [],
|
|
15814
|
+
first: noRow,
|
|
15815
|
+
executeTakeFirst: noRow,
|
|
15816
|
+
firstOrFail: noRowOrFail,
|
|
15817
|
+
executeTakeFirstOrThrow: noRowOrFail
|
|
15818
|
+
};
|
|
15819
|
+
};
|
|
15790
15820
|
const isPostgres = config5.dialect === "postgres";
|
|
15791
15821
|
const quoteId = isPostgres ? (id) => `"${String(id).replace(/"/g, '""')}"` : isMysqlLike(config5.dialect) ? (id) => `\`${String(id).replace(/`/g, "``")}\`` : (id) => `"${String(id).replace(/"/g, '""')}"`;
|
|
15792
15822
|
const getPlaceholder2 = isPostgres ? (index) => `$${index + 1}` : (_index) => "?";
|
|
@@ -15795,9 +15825,13 @@ function createQueryBuilder(state) {
|
|
|
15795
15825
|
const rows = Array.isArray(data) ? data : [data];
|
|
15796
15826
|
const rowCount = rows.length;
|
|
15797
15827
|
if (rowCount === 0) {
|
|
15798
|
-
|
|
15828
|
+
noRows = true;
|
|
15829
|
+
built = null;
|
|
15830
|
+
sqlText = "";
|
|
15831
|
+
params.length = 0;
|
|
15799
15832
|
return this;
|
|
15800
15833
|
}
|
|
15834
|
+
noRows = false;
|
|
15801
15835
|
const firstRow = rows[0];
|
|
15802
15836
|
const keys = Object.keys(firstRow);
|
|
15803
15837
|
const colCount = keys.length;
|
|
@@ -15851,6 +15885,8 @@ function createQueryBuilder(state) {
|
|
|
15851
15885
|
return this;
|
|
15852
15886
|
},
|
|
15853
15887
|
returning(...cols) {
|
|
15888
|
+
if (noRows)
|
|
15889
|
+
return emptyReturningBuilder();
|
|
15854
15890
|
const returningSql = `${sqlText} RETURNING ${cols.join(", ")}`;
|
|
15855
15891
|
const q = _sql.unsafe(returningSql, params);
|
|
15856
15892
|
const runFirst = async () => {
|
|
@@ -15884,11 +15920,15 @@ function createQueryBuilder(state) {
|
|
|
15884
15920
|
};
|
|
15885
15921
|
},
|
|
15886
15922
|
toSQL() {
|
|
15923
|
+
if (noRows)
|
|
15924
|
+
return makeExecutableQuery(null, "");
|
|
15887
15925
|
if (!built)
|
|
15888
15926
|
built = _sql.unsafe(sqlText, params);
|
|
15889
15927
|
return makeExecutableQuery(built, sqlText);
|
|
15890
15928
|
},
|
|
15891
15929
|
execute() {
|
|
15930
|
+
if (noRows)
|
|
15931
|
+
return Promise.resolve(emptyInsertResult());
|
|
15892
15932
|
const hooks = activeHooks();
|
|
15893
15933
|
const hasHooks = hooks && (hooks.onQueryStart || hooks.onQueryEnd || hooks.onQueryError || hooks.startSpan || hooks.beforeCreate || hooks.afterCreate || hasSlowQueryHook(hooks));
|
|
15894
15934
|
if (!hasHooks) {
|
|
@@ -15903,12 +15943,16 @@ function createQueryBuilder(state) {
|
|
|
15903
15943
|
return runWithHooks(built, "insert");
|
|
15904
15944
|
},
|
|
15905
15945
|
async executeTakeFirst() {
|
|
15946
|
+
if (noRows)
|
|
15947
|
+
return emptyInsertResult();
|
|
15906
15948
|
if (!built)
|
|
15907
15949
|
built = _sql.unsafe(sqlText, params);
|
|
15908
15950
|
const result = await runWithHooks(built, "insert");
|
|
15909
15951
|
return result;
|
|
15910
15952
|
},
|
|
15911
15953
|
async executeTakeFirstOrThrow() {
|
|
15954
|
+
if (noRows)
|
|
15955
|
+
throw new Error("Insert failed");
|
|
15912
15956
|
if (!built)
|
|
15913
15957
|
built = _sql.unsafe(sqlText, params);
|
|
15914
15958
|
const result = await runWithHooks(built, "insert");
|
|
@@ -15917,6 +15961,8 @@ function createQueryBuilder(state) {
|
|
|
15917
15961
|
return result;
|
|
15918
15962
|
},
|
|
15919
15963
|
returningAll() {
|
|
15964
|
+
if (noRows)
|
|
15965
|
+
return emptyReturningBuilder();
|
|
15920
15966
|
const returningSql = `${sqlText} RETURNING *`;
|
|
15921
15967
|
const q = _sql.unsafe(returningSql, params);
|
|
15922
15968
|
const runFirst = async () => {
|
|
@@ -16023,8 +16069,22 @@ function createQueryBuilder(state) {
|
|
|
16023
16069
|
built = _sql.unsafe(sqlText, params);
|
|
16024
16070
|
return this;
|
|
16025
16071
|
}
|
|
16026
|
-
if (
|
|
16072
|
+
if (isRawExpression(expr)) {
|
|
16073
|
+
sqlText = `${sqlText} ${getWhereKeyword()} ${expr.raw}`;
|
|
16074
|
+
built = _sql.unsafe(sqlText, params);
|
|
16075
|
+
return this;
|
|
16076
|
+
}
|
|
16077
|
+
if (isBoundSqlExpression(expr)) {
|
|
16078
|
+
const rendered = renderBoundSqlExpression(expr, params.length + 1);
|
|
16079
|
+
sqlText = `${sqlText} ${getWhereKeyword()} ${rendered.text}`;
|
|
16080
|
+
params.push(...rendered.parameters);
|
|
16081
|
+
built = _sql.unsafe(sqlText, params);
|
|
16082
|
+
return this;
|
|
16083
|
+
}
|
|
16084
|
+
if (expr && typeof expr === "object") {
|
|
16027
16085
|
const keys = Object.keys(expr);
|
|
16086
|
+
if (keys.length === 0)
|
|
16087
|
+
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.");
|
|
16028
16088
|
const len = keys.length;
|
|
16029
16089
|
const baseIdx = params.length;
|
|
16030
16090
|
const conditions = Array.from({ length: len });
|
|
@@ -16034,8 +16094,9 @@ function createQueryBuilder(state) {
|
|
|
16034
16094
|
}
|
|
16035
16095
|
sqlText = `${sqlText} ${getWhereKeyword()} ${conditions.join(" AND ")}`;
|
|
16036
16096
|
built = _sql.unsafe(sqlText, params);
|
|
16097
|
+
return this;
|
|
16037
16098
|
}
|
|
16038
|
-
|
|
16099
|
+
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.`);
|
|
16039
16100
|
},
|
|
16040
16101
|
whereNull(column) {
|
|
16041
16102
|
const keyword = SQL_PATTERNS.WHERE.test(sqlText) ? "AND" : "WHERE";
|
|
@@ -16050,22 +16111,40 @@ function createQueryBuilder(state) {
|
|
|
16050
16111
|
return this;
|
|
16051
16112
|
},
|
|
16052
16113
|
returning(...cols) {
|
|
16053
|
-
const
|
|
16054
|
-
const
|
|
16114
|
+
const parent = this;
|
|
16115
|
+
const retText = () => `${sqlText} RETURNING ${cols.join(", ")}`;
|
|
16116
|
+
const build = () => params.length > 0 ? _sql.unsafe(retText(), params) : _sql.unsafe(retText());
|
|
16055
16117
|
const runFirst = async () => {
|
|
16056
|
-
const rows = await runWithHooks(
|
|
16118
|
+
const rows = await runWithHooks(build(), "update");
|
|
16057
16119
|
return Array.isArray(rows) ? rows[0] : rows;
|
|
16058
16120
|
};
|
|
16121
|
+
const unsupported = (name) => () => {
|
|
16122
|
+
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.`);
|
|
16123
|
+
};
|
|
16059
16124
|
const obj = {
|
|
16060
|
-
where: () =>
|
|
16061
|
-
|
|
16062
|
-
|
|
16063
|
-
|
|
16064
|
-
|
|
16065
|
-
|
|
16066
|
-
|
|
16067
|
-
|
|
16068
|
-
|
|
16125
|
+
where: (...args) => {
|
|
16126
|
+
parent.where(...args);
|
|
16127
|
+
return obj;
|
|
16128
|
+
},
|
|
16129
|
+
andWhere: (...args) => {
|
|
16130
|
+
parent.where(...args);
|
|
16131
|
+
return obj;
|
|
16132
|
+
},
|
|
16133
|
+
whereNull: (...args) => {
|
|
16134
|
+
parent.whereNull(...args);
|
|
16135
|
+
return obj;
|
|
16136
|
+
},
|
|
16137
|
+
whereNotNull: (...args) => {
|
|
16138
|
+
parent.whereNotNull(...args);
|
|
16139
|
+
return obj;
|
|
16140
|
+
},
|
|
16141
|
+
orWhere: unsupported("orWhere"),
|
|
16142
|
+
orderBy: unsupported("orderBy"),
|
|
16143
|
+
limit: unsupported("limit"),
|
|
16144
|
+
offset: unsupported("offset"),
|
|
16145
|
+
toSQL: () => makeExecutableQuery(build(), retText()),
|
|
16146
|
+
execute: () => runWithHooks(build(), "update"),
|
|
16147
|
+
get: () => runWithHooks(build(), "update"),
|
|
16069
16148
|
first: runFirst,
|
|
16070
16149
|
executeTakeFirst: runFirst,
|
|
16071
16150
|
async firstOrFail() {
|
|
@@ -16104,17 +16183,17 @@ function createQueryBuilder(state) {
|
|
|
16104
16183
|
return { numUpdatedRows: result };
|
|
16105
16184
|
},
|
|
16106
16185
|
returningAll() {
|
|
16107
|
-
const retAllText = `${sqlText} RETURNING *`;
|
|
16108
|
-
const
|
|
16186
|
+
const retAllText = () => `${sqlText} RETURNING *`;
|
|
16187
|
+
const build = () => params.length > 0 ? _sql.unsafe(retAllText(), params) : _sql.unsafe(retAllText());
|
|
16109
16188
|
return {
|
|
16110
|
-
toSQL: () => makeExecutableQuery(
|
|
16111
|
-
execute: () => runWithHooks(
|
|
16189
|
+
toSQL: () => makeExecutableQuery(build(), retAllText()),
|
|
16190
|
+
execute: () => runWithHooks(build(), "update"),
|
|
16112
16191
|
async executeTakeFirst() {
|
|
16113
|
-
const result = await runWithHooks(
|
|
16192
|
+
const result = await runWithHooks(build(), "update");
|
|
16114
16193
|
return Array.isArray(result) ? result[0] : result;
|
|
16115
16194
|
},
|
|
16116
16195
|
async executeTakeFirstOrThrow() {
|
|
16117
|
-
const result = await runWithHooks(
|
|
16196
|
+
const result = await runWithHooks(build(), "update");
|
|
16118
16197
|
const first = Array.isArray(result) ? result[0] : result;
|
|
16119
16198
|
if (!first)
|
|
16120
16199
|
throw new Error("Update with RETURNING failed");
|
|
@@ -16179,8 +16258,22 @@ function createQueryBuilder(state) {
|
|
|
16179
16258
|
built = null;
|
|
16180
16259
|
return this;
|
|
16181
16260
|
}
|
|
16182
|
-
if (
|
|
16261
|
+
if (isRawExpression(expr)) {
|
|
16262
|
+
sqlText += ` ${getWhereKeyword()} ${expr.raw}`;
|
|
16263
|
+
built = null;
|
|
16264
|
+
return this;
|
|
16265
|
+
}
|
|
16266
|
+
if (isBoundSqlExpression(expr)) {
|
|
16267
|
+
const rendered = renderBoundSqlExpression(expr, delParams.length + 1);
|
|
16268
|
+
sqlText += ` ${getWhereKeyword()} ${rendered.text}`;
|
|
16269
|
+
delParams.push(...rendered.parameters);
|
|
16270
|
+
built = null;
|
|
16271
|
+
return this;
|
|
16272
|
+
}
|
|
16273
|
+
if (expr && typeof expr === "object") {
|
|
16183
16274
|
const keys = Object.keys(expr);
|
|
16275
|
+
if (keys.length === 0)
|
|
16276
|
+
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.");
|
|
16184
16277
|
const conditions = [];
|
|
16185
16278
|
for (const key of keys) {
|
|
16186
16279
|
const paramIndex = delParams.length + 1;
|
|
@@ -16191,8 +16284,7 @@ function createQueryBuilder(state) {
|
|
|
16191
16284
|
built = null;
|
|
16192
16285
|
return this;
|
|
16193
16286
|
}
|
|
16194
|
-
|
|
16195
|
-
return this;
|
|
16287
|
+
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.`);
|
|
16196
16288
|
},
|
|
16197
16289
|
whereNull(column) {
|
|
16198
16290
|
sqlText += ` ${getWhereKeyword()} ${quoteId(String(column))} IS NULL`;
|
|
@@ -16205,22 +16297,48 @@ function createQueryBuilder(state) {
|
|
|
16205
16297
|
return this;
|
|
16206
16298
|
},
|
|
16207
16299
|
returning(...cols) {
|
|
16208
|
-
const
|
|
16209
|
-
const
|
|
16300
|
+
const parent = this;
|
|
16301
|
+
const retText = () => `${sqlText} RETURNING ${cols.join(", ")}`;
|
|
16302
|
+
const build = () => delParams.length > 0 ? _sql.unsafe(retText(), delParams) : _sql.unsafe(retText());
|
|
16303
|
+
const runDelete = async () => {
|
|
16304
|
+
await activeHooks()?.beforeDelete?.({ table: String(table), where: whereCondition });
|
|
16305
|
+
const rows = await runWithHooks(build(), "delete");
|
|
16306
|
+
try {
|
|
16307
|
+
await activeHooks()?.afterDelete?.({ table: String(table), where: whereCondition, result: rows });
|
|
16308
|
+
} catch {}
|
|
16309
|
+
return rows;
|
|
16310
|
+
};
|
|
16210
16311
|
const runFirst = async () => {
|
|
16211
|
-
const rows = await
|
|
16312
|
+
const rows = await runDelete();
|
|
16212
16313
|
return Array.isArray(rows) ? rows[0] : rows;
|
|
16213
16314
|
};
|
|
16315
|
+
const unsupported = (name) => () => {
|
|
16316
|
+
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.`);
|
|
16317
|
+
};
|
|
16214
16318
|
const obj = {
|
|
16215
|
-
where: () =>
|
|
16216
|
-
|
|
16217
|
-
|
|
16218
|
-
|
|
16219
|
-
|
|
16220
|
-
|
|
16221
|
-
|
|
16222
|
-
|
|
16223
|
-
|
|
16319
|
+
where: (...args) => {
|
|
16320
|
+
parent.where(...args);
|
|
16321
|
+
return obj;
|
|
16322
|
+
},
|
|
16323
|
+
andWhere: (...args) => {
|
|
16324
|
+
parent.where(...args);
|
|
16325
|
+
return obj;
|
|
16326
|
+
},
|
|
16327
|
+
whereNull: (...args) => {
|
|
16328
|
+
parent.whereNull(...args);
|
|
16329
|
+
return obj;
|
|
16330
|
+
},
|
|
16331
|
+
whereNotNull: (...args) => {
|
|
16332
|
+
parent.whereNotNull(...args);
|
|
16333
|
+
return obj;
|
|
16334
|
+
},
|
|
16335
|
+
orWhere: unsupported("orWhere"),
|
|
16336
|
+
orderBy: unsupported("orderBy"),
|
|
16337
|
+
limit: unsupported("limit"),
|
|
16338
|
+
offset: unsupported("offset"),
|
|
16339
|
+
toSQL: () => makeExecutableQuery(build(), retText()),
|
|
16340
|
+
execute: () => runDelete(),
|
|
16341
|
+
get: () => runDelete(),
|
|
16224
16342
|
first: runFirst,
|
|
16225
16343
|
executeTakeFirst: runFirst,
|
|
16226
16344
|
async firstOrFail() {
|
|
@@ -16264,17 +16382,17 @@ function createQueryBuilder(state) {
|
|
|
16264
16382
|
return { numDeletedRows: result };
|
|
16265
16383
|
},
|
|
16266
16384
|
returningAll() {
|
|
16267
|
-
const retAllText = `${sqlText} RETURNING *`;
|
|
16268
|
-
const
|
|
16385
|
+
const retAllText = () => `${sqlText} RETURNING *`;
|
|
16386
|
+
const build = () => delParams.length > 0 ? _sql.unsafe(retAllText(), delParams) : _sql.unsafe(retAllText());
|
|
16269
16387
|
return {
|
|
16270
|
-
toSQL: () => makeExecutableQuery(
|
|
16271
|
-
execute: () => runWithHooks(
|
|
16388
|
+
toSQL: () => makeExecutableQuery(build(), retAllText()),
|
|
16389
|
+
execute: () => runWithHooks(build(), "delete"),
|
|
16272
16390
|
async executeTakeFirst() {
|
|
16273
|
-
const result = await runWithHooks(
|
|
16391
|
+
const result = await runWithHooks(build(), "delete");
|
|
16274
16392
|
return Array.isArray(result) ? result[0] : result;
|
|
16275
16393
|
},
|
|
16276
16394
|
async executeTakeFirstOrThrow() {
|
|
16277
|
-
const result = await runWithHooks(
|
|
16395
|
+
const result = await runWithHooks(build(), "delete");
|
|
16278
16396
|
const first = Array.isArray(result) ? result[0] : result;
|
|
16279
16397
|
if (!first)
|
|
16280
16398
|
throw new Error("Delete with RETURNING failed");
|
|
@@ -18938,11 +19056,66 @@ var init_vitess = __esm(() => {
|
|
|
18938
19056
|
};
|
|
18939
19057
|
});
|
|
18940
19058
|
|
|
18941
|
-
// src/
|
|
19059
|
+
// src/column-types.ts
|
|
18942
19060
|
function isNumericPlanType(type) {
|
|
18943
19061
|
return type === "integer" || type === "bigint" || type === "float" || type === "double" || type === "decimal";
|
|
18944
19062
|
}
|
|
19063
|
+
function normalizeAttributeType(raw2) {
|
|
19064
|
+
if (typeof raw2 !== "string")
|
|
19065
|
+
return;
|
|
19066
|
+
switch (raw2.toLowerCase()) {
|
|
19067
|
+
case "string":
|
|
19068
|
+
return "string";
|
|
19069
|
+
case "text":
|
|
19070
|
+
return "text";
|
|
19071
|
+
case "integer":
|
|
19072
|
+
case "int":
|
|
19073
|
+
return "integer";
|
|
19074
|
+
case "number":
|
|
19075
|
+
return "integer";
|
|
19076
|
+
case "bigint":
|
|
19077
|
+
return "bigint";
|
|
19078
|
+
case "float":
|
|
19079
|
+
return "float";
|
|
19080
|
+
case "double":
|
|
19081
|
+
return "double";
|
|
19082
|
+
case "decimal":
|
|
19083
|
+
return "decimal";
|
|
19084
|
+
case "boolean":
|
|
19085
|
+
case "bool":
|
|
19086
|
+
return "boolean";
|
|
19087
|
+
case "date":
|
|
19088
|
+
return "date";
|
|
19089
|
+
case "datetime":
|
|
19090
|
+
case "timestamp":
|
|
19091
|
+
return "datetime";
|
|
19092
|
+
case "timestamptz":
|
|
19093
|
+
case "timestamp_tz":
|
|
19094
|
+
return "timestamptz";
|
|
19095
|
+
case "json":
|
|
19096
|
+
return "json";
|
|
19097
|
+
case "enum":
|
|
19098
|
+
return "enum";
|
|
19099
|
+
default:
|
|
19100
|
+
return;
|
|
19101
|
+
}
|
|
19102
|
+
}
|
|
19103
|
+
function sqliteAffinityFor(type) {
|
|
19104
|
+
switch (type) {
|
|
19105
|
+
case "boolean":
|
|
19106
|
+
case "integer":
|
|
19107
|
+
case "bigint":
|
|
19108
|
+
return "INTEGER";
|
|
19109
|
+
case "float":
|
|
19110
|
+
case "double":
|
|
19111
|
+
case "decimal":
|
|
19112
|
+
return "REAL";
|
|
19113
|
+
default:
|
|
19114
|
+
return "TEXT";
|
|
19115
|
+
}
|
|
19116
|
+
}
|
|
18945
19117
|
|
|
19118
|
+
// src/drivers/sqlite.ts
|
|
18946
19119
|
class SQLiteDriver {
|
|
18947
19120
|
quoteIdentifier(id) {
|
|
18948
19121
|
return `"${id.replace(/"/g, '""')}"`;
|
|
@@ -18951,40 +19124,14 @@ class SQLiteDriver {
|
|
|
18951
19124
|
if (column.name.endsWith("_id") && isNumericPlanType(column.type)) {
|
|
18952
19125
|
return "INTEGER";
|
|
18953
19126
|
}
|
|
18954
|
-
|
|
18955
|
-
|
|
18956
|
-
|
|
18957
|
-
|
|
18958
|
-
|
|
18959
|
-
|
|
18960
|
-
return "INTEGER";
|
|
18961
|
-
case "integer":
|
|
18962
|
-
return "INTEGER";
|
|
18963
|
-
case "bigint":
|
|
18964
|
-
return "INTEGER";
|
|
18965
|
-
case "float":
|
|
18966
|
-
return "REAL";
|
|
18967
|
-
case "double":
|
|
18968
|
-
return "REAL";
|
|
18969
|
-
case "decimal":
|
|
18970
|
-
return "REAL";
|
|
18971
|
-
case "date":
|
|
18972
|
-
return "TEXT";
|
|
18973
|
-
case "datetime":
|
|
18974
|
-
return "TEXT";
|
|
18975
|
-
case "timestamptz":
|
|
18976
|
-
return "TEXT";
|
|
18977
|
-
case "json":
|
|
18978
|
-
return "TEXT";
|
|
18979
|
-
case "enum":
|
|
18980
|
-
if (column.enumValues && column.enumValues.length > 0) {
|
|
18981
|
-
const enumValues = column.enumValues.map((v) => `'${v.replace(/'/g, "''")}'`).join(", ");
|
|
18982
|
-
return `TEXT CHECK (${this.quoteIdentifier(column.name)} IN (${enumValues}))`;
|
|
18983
|
-
}
|
|
18984
|
-
return "TEXT";
|
|
18985
|
-
default:
|
|
18986
|
-
return "TEXT";
|
|
19127
|
+
if (column.type === "enum") {
|
|
19128
|
+
if (column.enumValues && column.enumValues.length > 0) {
|
|
19129
|
+
const enumValues = column.enumValues.map((v) => `'${v.replace(/'/g, "''")}'`).join(", ");
|
|
19130
|
+
return `TEXT CHECK (${this.quoteIdentifier(column.name)} IN (${enumValues}))`;
|
|
19131
|
+
}
|
|
19132
|
+
return "TEXT";
|
|
18987
19133
|
}
|
|
19134
|
+
return sqliteAffinityFor(column.type);
|
|
18988
19135
|
}
|
|
18989
19136
|
getPrimaryKeyType(column) {
|
|
18990
19137
|
return this.getColumnType(column);
|
|
@@ -25380,6 +25527,14 @@ function assertValidOrderByColumn(name, context) {
|
|
|
25380
25527
|
if (parts.length > 2 || parts.some((p2) => p2.length === 0 || p2.length > 64 || !SAFE_SQL_IDENTIFIER.test(p2)))
|
|
25381
25528
|
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`);
|
|
25382
25529
|
}
|
|
25530
|
+
function registerLocalModel(name, model) {
|
|
25531
|
+
localModels.set(name, model);
|
|
25532
|
+
relationCache.clear();
|
|
25533
|
+
}
|
|
25534
|
+
function clearLocalModels() {
|
|
25535
|
+
localModels.clear();
|
|
25536
|
+
relationCache.clear();
|
|
25537
|
+
}
|
|
25383
25538
|
function getModelFromRegistry(name) {
|
|
25384
25539
|
if (!_getModel) {
|
|
25385
25540
|
try {
|
|
@@ -25390,7 +25545,7 @@ function getModelFromRegistry(name) {
|
|
|
25390
25545
|
};
|
|
25391
25546
|
}
|
|
25392
25547
|
}
|
|
25393
|
-
return _getModel(name);
|
|
25548
|
+
return _getModel(name) ?? localModels.get(name);
|
|
25394
25549
|
}
|
|
25395
25550
|
function toPostgresPlaceholders(sql2) {
|
|
25396
25551
|
const hit = pgPlaceholderCache.get(sql2);
|
|
@@ -25588,6 +25743,7 @@ function findAttributeDef(attrs, key) {
|
|
|
25588
25743
|
class ModelInstance {
|
|
25589
25744
|
_attributes;
|
|
25590
25745
|
_original;
|
|
25746
|
+
_forced = new Set;
|
|
25591
25747
|
_definition;
|
|
25592
25748
|
_hasSaved = false;
|
|
25593
25749
|
_relations = {};
|
|
@@ -25721,7 +25877,10 @@ class ModelInstance {
|
|
|
25721
25877
|
forceFill(data) {
|
|
25722
25878
|
if (this._original === null)
|
|
25723
25879
|
this._original = { ...this._attributes };
|
|
25724
|
-
|
|
25880
|
+
const normalized = normalizeAttributeKeys(data);
|
|
25881
|
+
Object.assign(this._attributes, normalized);
|
|
25882
|
+
for (const col of Object.keys(normalized))
|
|
25883
|
+
this._forced.add(col);
|
|
25725
25884
|
return this;
|
|
25726
25885
|
}
|
|
25727
25886
|
async save() {
|
|
@@ -25753,7 +25912,7 @@ class ModelInstance {
|
|
|
25753
25912
|
const attrs = this._definition.attributes;
|
|
25754
25913
|
const data = {};
|
|
25755
25914
|
for (const [key, attr] of Object.entries(attrs)) {
|
|
25756
|
-
if (attr.guarded)
|
|
25915
|
+
if (attr.guarded && !this._forced.has(toSnakeCase(key)))
|
|
25757
25916
|
continue;
|
|
25758
25917
|
const col = toSnakeCase(key);
|
|
25759
25918
|
if (this._attributes[col] !== undefined) {
|
|
@@ -27151,7 +27310,10 @@ function createModelInternal(definition) {
|
|
|
27151
27310
|
});
|
|
27152
27311
|
}
|
|
27153
27312
|
function createModel(definition) {
|
|
27154
|
-
|
|
27313
|
+
const model = createModelInternal(definition);
|
|
27314
|
+
if (definition?.name)
|
|
27315
|
+
registerLocalModel(definition.name, model);
|
|
27316
|
+
return model;
|
|
27155
27317
|
}
|
|
27156
27318
|
async function createTableFromModel(definition) {
|
|
27157
27319
|
const exec = getExecutor();
|
|
@@ -27168,12 +27330,9 @@ async function createTableFromModel(definition) {
|
|
|
27168
27330
|
if (emitted.has(name))
|
|
27169
27331
|
continue;
|
|
27170
27332
|
emitted.add(name);
|
|
27171
|
-
|
|
27172
|
-
|
|
27173
|
-
|
|
27174
|
-
else if (attr.type === "boolean")
|
|
27175
|
-
colType = "INTEGER";
|
|
27176
|
-
if (name.endsWith("_id"))
|
|
27333
|
+
const declaredType = normalizeAttributeType(attr.type);
|
|
27334
|
+
let colType = sqliteAffinityFor(declaredType);
|
|
27335
|
+
if (name.endsWith("_id") && (declaredType === undefined || isNumericPlanType(declaredType)))
|
|
27177
27336
|
colType = "INTEGER";
|
|
27178
27337
|
let colDef = `${name} ${colType}`;
|
|
27179
27338
|
if (attr.unique)
|
|
@@ -27239,12 +27398,13 @@ async function seedModel(definition, count, faker) {
|
|
|
27239
27398
|
await exec.run(`INSERT INTO ${definition.table} (${columns.join(", ")}) VALUES (${columns.map(() => "?").join(", ")})`, Object.values(data));
|
|
27240
27399
|
}
|
|
27241
27400
|
}
|
|
27242
|
-
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;
|
|
27401
|
+
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;
|
|
27243
27402
|
var init_orm = __esm(() => {
|
|
27244
27403
|
init_config();
|
|
27245
27404
|
init_db();
|
|
27246
27405
|
init_sqlite_pragmas();
|
|
27247
27406
|
SAFE_SQL_IDENTIFIER = /^[A-Z_][A-Z0-9_]*$/i;
|
|
27407
|
+
localModels = new Map;
|
|
27248
27408
|
pgPlaceholderCache = new Map;
|
|
27249
27409
|
btmKeysCache = new WeakMap;
|
|
27250
27410
|
snakeCaseCache = new Map;
|
|
@@ -27289,6 +27449,7 @@ function hasModel(name) {
|
|
|
27289
27449
|
}
|
|
27290
27450
|
function clearModelRegistry() {
|
|
27291
27451
|
modelRegistry.clear();
|
|
27452
|
+
clearLocalModels();
|
|
27292
27453
|
}
|
|
27293
27454
|
function registerModel(name, model) {
|
|
27294
27455
|
modelRegistry.set(name, model);
|
|
@@ -29064,7 +29225,7 @@ function detectTypeFromValidationRule(rule) {
|
|
|
29064
29225
|
}
|
|
29065
29226
|
return;
|
|
29066
29227
|
}
|
|
29067
|
-
function
|
|
29228
|
+
function normalizeAttributeType2(value) {
|
|
29068
29229
|
if (typeof value !== "string")
|
|
29069
29230
|
return;
|
|
29070
29231
|
const type = value.trim().toLowerCase().replace(/[\s-]+/g, "_");
|
|
@@ -29154,7 +29315,7 @@ function buildMigrationPlan2(models, options) {
|
|
|
29154
29315
|
let inferred;
|
|
29155
29316
|
let enumValues;
|
|
29156
29317
|
const isPk = attrName === primaryKey;
|
|
29157
|
-
inferred =
|
|
29318
|
+
inferred = normalizeAttributeType2(attr.type) ?? detectTypeFromValidationRule(attr.validation?.rule);
|
|
29158
29319
|
if (inferred === "string") {
|
|
29159
29320
|
const maxLength = extractMaxFromRules(attr.validation?.rule);
|
|
29160
29321
|
if (maxLength && maxLength > MAX_BOUNDED_VARCHAR_LENGTH)
|
|
@@ -30380,6 +30541,7 @@ export {
|
|
|
30380
30541
|
queryExplainAll as explainAllQueries,
|
|
30381
30542
|
explain,
|
|
30382
30543
|
executeMigration,
|
|
30544
|
+
escapeStringLiteral,
|
|
30383
30545
|
dynamo,
|
|
30384
30546
|
dumpDatabase,
|
|
30385
30547
|
defineSeeder,
|
|
@@ -30414,6 +30576,7 @@ export {
|
|
|
30414
30576
|
config5 as config,
|
|
30415
30577
|
clearQueryCache,
|
|
30416
30578
|
clearModelRegistry,
|
|
30579
|
+
clearLocalModels,
|
|
30417
30580
|
checkSchema,
|
|
30418
30581
|
canonicalizeDefault,
|
|
30419
30582
|
canonicalStorageType,
|
package/package.json
CHANGED