@type32/tauri-sqlite-orm 0.2.13 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,174 +1,84 @@
1
- // src/builders/query-base.ts
2
- var BaseQueryBuilder = class {
1
+ // src/orm.ts
2
+ import { Kysely as Kysely4, sql as kyselySql } from "kysely";
3
+
4
+ // src/dialect.ts
5
+ import {
6
+ CompiledQuery,
7
+ SqliteAdapter,
8
+ SqliteIntrospector,
9
+ SqliteQueryCompiler
10
+ } from "kysely";
11
+ var TauriConnection = class {
3
12
  constructor(db) {
4
13
  this.db = db;
5
14
  }
6
- query = "";
7
- params = [];
8
- where(condition) {
9
- this.query += ` WHERE ${condition.sql}`;
10
- this.params.push(...condition.params);
11
- return this;
15
+ async executeQuery(compiledQuery) {
16
+ const { sql: sql6, parameters } = compiledQuery;
17
+ const params = parameters;
18
+ const trimmed = sql6.trimStart();
19
+ const isSelect = /^\s*(SELECT|WITH|PRAGMA)/i.test(trimmed);
20
+ const hasReturning = /\bRETURNING\b/i.test(sql6);
21
+ if (isSelect || hasReturning) {
22
+ const rows = await this.db.select(sql6, params);
23
+ return { rows };
24
+ }
25
+ const result = await this.db.execute(sql6, params);
26
+ return {
27
+ rows: [],
28
+ insertId: BigInt(Math.round(result.lastInsertId ?? 0)),
29
+ numAffectedRows: BigInt(result.rowsAffected ?? 0)
30
+ };
12
31
  }
13
- orderBy(column, direction = "ASC") {
14
- if ("sql" in column) {
15
- this.query += ` ORDER BY ${column.sql} ${direction}`;
16
- this.params.push(...column.params);
17
- } else {
18
- this.query += ` ORDER BY ${column._.name} ${direction}`;
19
- }
20
- return this;
32
+ async *streamQuery(_compiledQuery) {
33
+ throw new Error("Streaming queries are not supported by @tauri-apps/plugin-sql");
21
34
  }
22
- limit(count2) {
23
- this.query += ` LIMIT ${count2}`;
24
- return this;
35
+ };
36
+ var TauriDriver = class {
37
+ constructor(db) {
38
+ this.db = db;
25
39
  }
26
- offset(count2) {
27
- this.query += ` OFFSET ${count2}`;
28
- return this;
40
+ async init() {
29
41
  }
30
- build() {
31
- return {
32
- sql: this.query,
33
- params: this.params
34
- };
42
+ async acquireConnection() {
43
+ return new TauriConnection(this.db);
35
44
  }
36
- toSQL() {
37
- return this.build();
45
+ async beginTransaction(conn, _settings) {
46
+ await conn.executeQuery(CompiledQuery.raw("BEGIN"));
38
47
  }
39
- };
40
-
41
- // src/operators.ts
42
- var eq = (column, value, tableAlias) => {
43
- const columnName = tableAlias ? `${tableAlias}.${column._.name}` : column._.name;
44
- return {
45
- sql: `${columnName} = ?`,
46
- params: [value]
47
- };
48
- };
49
- var ne = (column, value, tableAlias) => {
50
- const columnName = tableAlias ? `${tableAlias}.${column._.name}` : column._.name;
51
- return {
52
- sql: `${columnName} != ?`,
53
- params: [value]
54
- };
55
- };
56
- var and = (...conditions) => ({
57
- sql: conditions.map((c) => `(${c.sql})`).join(" AND "),
58
- params: conditions.flatMap((c) => c.params)
59
- });
60
- var or = (...conditions) => ({
61
- sql: conditions.map((c) => `(${c.sql})`).join(" OR "),
62
- params: conditions.flatMap((c) => c.params)
63
- });
64
- var not = (condition) => ({
65
- sql: `NOT (${condition.sql})`,
66
- params: condition.params
67
- });
68
- var gt = (column, value) => ({
69
- sql: `${column._.name} > ?`,
70
- params: [value]
71
- });
72
- var gte = (column, value) => ({
73
- sql: `${column._.name} >= ?`,
74
- params: [value]
75
- });
76
- var lt = (column, value) => ({
77
- sql: `${column._.name} < ?`,
78
- params: [value]
79
- });
80
- var lte = (column, value) => ({
81
- sql: `${column._.name} <= ?`,
82
- params: [value]
83
- });
84
- var like = (column, pattern) => ({
85
- sql: `${column._.name} LIKE ?`,
86
- params: [pattern]
87
- });
88
- var ilike = (column, pattern) => ({
89
- sql: `${column._.name} LIKE ? COLLATE NOCASE`,
90
- params: [pattern]
91
- });
92
- var startsWith = (column, value) => ({
93
- sql: `${column._.name} LIKE ?`,
94
- params: [`${value}%`]
95
- });
96
- var endsWith = (column, value) => ({
97
- sql: `${column._.name} LIKE ?`,
98
- params: [`%${value}`]
99
- });
100
- var contains = (column, value) => ({
101
- sql: `${column._.name} LIKE ?`,
102
- params: [`%${value}%`]
103
- });
104
- var isNull = (column) => ({
105
- sql: `${column._.name} IS NULL`,
106
- params: []
107
- });
108
- var isNotNull = (column) => ({
109
- sql: `${column._.name} IS NOT NULL`,
110
- params: []
111
- });
112
- var exists = (subquery2) => ({
113
- sql: `EXISTS (${subquery2.sql})`,
114
- params: subquery2.params
115
- });
116
- var notExists = (subquery2) => ({
117
- sql: `NOT EXISTS (${subquery2.sql})`,
118
- params: subquery2.params
119
- });
120
- var eqSubquery = (column, subquery2) => ({
121
- sql: `${column._.name} = ${subquery2.sql}`,
122
- params: subquery2.params
123
- });
124
- var neSubquery = (column, subquery2) => ({
125
- sql: `${column._.name} != ${subquery2.sql}`,
126
- params: subquery2.params
127
- });
128
- var gtSubquery = (column, subquery2) => ({
129
- sql: `${column._.name} > ${subquery2.sql}`,
130
- params: subquery2.params
131
- });
132
- var gteSubquery = (column, subquery2) => ({
133
- sql: `${column._.name} >= ${subquery2.sql}`,
134
- params: subquery2.params
135
- });
136
- var ltSubquery = (column, subquery2) => ({
137
- sql: `${column._.name} < ${subquery2.sql}`,
138
- params: subquery2.params
139
- });
140
- var lteSubquery = (column, subquery2) => ({
141
- sql: `${column._.name} <= ${subquery2.sql}`,
142
- params: subquery2.params
143
- });
144
- var inArray = (column, values) => {
145
- if ("_isSubquery" in values && values._isSubquery) {
146
- return {
147
- sql: `${column._.name} IN ${values.sql}`,
148
- params: values.params
149
- };
48
+ async commitTransaction(conn) {
49
+ await conn.executeQuery(CompiledQuery.raw("COMMIT"));
50
+ }
51
+ async rollbackTransaction(conn) {
52
+ await conn.executeQuery(CompiledQuery.raw("ROLLBACK"));
53
+ }
54
+ async releaseConnection(_conn) {
55
+ }
56
+ async destroy() {
150
57
  }
151
- return {
152
- sql: `${column._.name} IN (${values.map(() => "?").join(",")})`,
153
- params: values
154
- };
155
58
  };
156
- var notIn = (column, values) => {
157
- if ("_isSubquery" in values && values._isSubquery) {
158
- return {
159
- sql: `${column._.name} NOT IN ${values.sql}`,
160
- params: values.params
161
- };
59
+ var TauriDialect = class {
60
+ constructor(db) {
61
+ this.db = db;
62
+ }
63
+ createAdapter() {
64
+ return new SqliteAdapter();
65
+ }
66
+ createDriver() {
67
+ return new TauriDriver(this.db);
68
+ }
69
+ createIntrospector(db) {
70
+ return new SqliteIntrospector(db);
71
+ }
72
+ createQueryCompiler() {
73
+ return new SqliteQueryCompiler();
162
74
  }
163
- return {
164
- sql: `${column._.name} NOT IN (${values.map(() => "?").join(",")})`,
165
- params: values
166
- };
167
75
  };
168
- var between = (column, min2, max2) => ({
169
- sql: `${column._.name} BETWEEN ? AND ?`,
170
- params: [min2, max2]
171
- });
76
+
77
+ // src/builders/select.ts
78
+ import { sql as sql2 } from "kysely";
79
+
80
+ // src/operators.ts
81
+ import { isExpression, sql } from "kysely";
172
82
 
173
83
  // src/serialization.ts
174
84
  function serializeValue(value, column) {
@@ -271,72 +181,194 @@ function deserializeValue(value, column) {
271
181
  return value;
272
182
  }
273
183
 
184
+ // src/operators.ts
185
+ var eq = (column, value, tableAlias) => {
186
+ const colRef = tableAlias ? `${tableAlias}.${column._.name}` : column._.name;
187
+ const serialized = serializeValue(value, column);
188
+ return sql`${sql.ref(colRef)} = ${sql.val(serialized)}`;
189
+ };
190
+ var ne = (column, value, tableAlias) => {
191
+ const colRef = tableAlias ? `${tableAlias}.${column._.name}` : column._.name;
192
+ const serialized = serializeValue(value, column);
193
+ return sql`${sql.ref(colRef)} != ${sql.val(serialized)}`;
194
+ };
195
+ var and = (...conditions) => {
196
+ if (conditions.length === 0) return sql`1 = 1`;
197
+ if (conditions.length === 1) return conditions[0];
198
+ return sql`(${sql.join(conditions.map((c) => sql`(${c})`), sql` AND `)})`;
199
+ };
200
+ var or = (...conditions) => {
201
+ if (conditions.length === 0) return sql`1 = 1`;
202
+ if (conditions.length === 1) return conditions[0];
203
+ return sql`(${sql.join(conditions.map((c) => sql`(${c})`), sql` OR `)})`;
204
+ };
205
+ var not = (condition) => sql`NOT (${condition})`;
206
+ var gt = (column, value) => {
207
+ const serialized = serializeValue(value, column);
208
+ return sql`${sql.ref(column._.name)} > ${sql.val(serialized)}`;
209
+ };
210
+ var gte = (column, value) => {
211
+ const serialized = serializeValue(value, column);
212
+ return sql`${sql.ref(column._.name)} >= ${sql.val(serialized)}`;
213
+ };
214
+ var lt = (column, value) => {
215
+ const serialized = serializeValue(value, column);
216
+ return sql`${sql.ref(column._.name)} < ${sql.val(serialized)}`;
217
+ };
218
+ var lte = (column, value) => {
219
+ const serialized = serializeValue(value, column);
220
+ return sql`${sql.ref(column._.name)} <= ${sql.val(serialized)}`;
221
+ };
222
+ var like = (column, pattern) => sql`${sql.ref(column._.name)} LIKE ${sql.val(pattern)}`;
223
+ var ilike = (column, pattern) => sql`${sql.ref(column._.name)} LIKE ${sql.val(pattern)} COLLATE NOCASE`;
224
+ var startsWith = (column, value) => sql`${sql.ref(column._.name)} LIKE ${sql.val(`${value}%`)}`;
225
+ var endsWith = (column, value) => sql`${sql.ref(column._.name)} LIKE ${sql.val(`%${value}`)}`;
226
+ var contains = (column, value) => sql`${sql.ref(column._.name)} LIKE ${sql.val(`%${value}%`)}`;
227
+ var isNull = (column) => sql`${sql.ref(column._.name)} IS NULL`;
228
+ var isNotNull = (column) => sql`${sql.ref(column._.name)} IS NOT NULL`;
229
+ var exists = (subquery2) => sql`EXISTS ${subquery2}`;
230
+ var notExists = (subquery2) => sql`NOT EXISTS ${subquery2}`;
231
+ var eqSubquery = (column, subquery2) => sql`${sql.ref(column._.name)} = (${subquery2})`;
232
+ var neSubquery = (column, subquery2) => sql`${sql.ref(column._.name)} != (${subquery2})`;
233
+ var gtSubquery = (column, subquery2) => sql`${sql.ref(column._.name)} > (${subquery2})`;
234
+ var gteSubquery = (column, subquery2) => sql`${sql.ref(column._.name)} >= (${subquery2})`;
235
+ var ltSubquery = (column, subquery2) => sql`${sql.ref(column._.name)} < (${subquery2})`;
236
+ var lteSubquery = (column, subquery2) => sql`${sql.ref(column._.name)} <= (${subquery2})`;
237
+ var inArray = (column, values) => {
238
+ if (isExpression(values)) {
239
+ return sql`${sql.ref(column._.name)} IN (${values})`;
240
+ }
241
+ const arr = values;
242
+ if (arr.length === 0) return sql`1 = 0`;
243
+ const serialized = arr.map((v) => sql.val(serializeValue(v, column)));
244
+ return sql`${sql.ref(column._.name)} IN (${sql.join(serialized)})`;
245
+ };
246
+ var notIn = (column, values) => {
247
+ if (isExpression(values)) {
248
+ return sql`${sql.ref(column._.name)} NOT IN (${values})`;
249
+ }
250
+ const arr = values;
251
+ if (arr.length === 0) return sql`1 = 1`;
252
+ const serialized = arr.map((v) => sql.val(serializeValue(v, column)));
253
+ return sql`${sql.ref(column._.name)} NOT IN (${sql.join(serialized)})`;
254
+ };
255
+ var between = (column, min2, max2) => {
256
+ const serializedMin = serializeValue(min2, column);
257
+ const serializedMax = serializeValue(max2, column);
258
+ return sql`${sql.ref(column._.name)} BETWEEN ${sql.val(serializedMin)} AND ${sql.val(serializedMax)}`;
259
+ };
260
+
274
261
  // src/builders/select.ts
275
- var SelectQueryBuilder = class extends BaseQueryBuilder {
276
- constructor(db, table, columns) {
277
- super(db);
278
- this.table = table;
279
- this.columns = columns;
280
- this.selectedTableAlias = table._.name;
281
- const selected = columns ? columns.map((c) => this.table._.columns[c]) : Object.values(this.table._.columns);
282
- this.selectedColumns = selected.map(
283
- (col) => `${this.selectedTableAlias}.${col._.name} AS "${this.selectedTableAlias}.${col._.name}"`
262
+ function getDbNameToTsName(table) {
263
+ const map = {};
264
+ for (const [tsName, col] of Object.entries(table._.columns)) {
265
+ map[col._.name] = tsName;
266
+ }
267
+ return map;
268
+ }
269
+ function normalizeRowKey(key) {
270
+ if (key.startsWith('"') && key.endsWith('"')) {
271
+ return key.slice(1, -1);
272
+ }
273
+ return key;
274
+ }
275
+ function resolveRelationColumns(table, include) {
276
+ const allEntries = Object.entries(table._.columns);
277
+ if (include === true || typeof include !== "object") {
278
+ return allEntries.map(([, col]) => col);
279
+ }
280
+ const cols = include.columns;
281
+ if (!cols) {
282
+ return allEntries.map(([, col]) => col);
283
+ }
284
+ const names = Array.isArray(cols) ? cols : Object.entries(cols).filter(([, v]) => v).map(([k]) => k);
285
+ const pkNames = allEntries.filter(([, c]) => c.options.primaryKey).map(([k]) => k);
286
+ const combined = /* @__PURE__ */ new Set([...names, ...pkNames]);
287
+ return allEntries.filter(([tsName]) => combined.has(tsName)).map(([, col]) => col);
288
+ }
289
+ var SelectQueryBuilder = class {
290
+ constructor(kysely, table, columns) {
291
+ this.kysely = kysely;
292
+ this._table = table;
293
+ this._columns = columns;
294
+ const selected = columns ? columns.map((c) => table._.columns[c]) : Object.values(table._.columns);
295
+ const colSelections = selected.map(
296
+ (col) => `${table._.name}.${col._.name} as "${table._.name}.${col._.name}"`
284
297
  );
285
- this.query = `FROM ${table._.name} ${this.selectedTableAlias}`;
286
- }
287
- isDistinct = false;
288
- groupByColumns = [];
289
- havingCondition = null;
290
- joins = [];
291
- includeRelations = {};
292
- selectedTableAlias;
293
- selectedColumns = [];
298
+ this._includedColumnAliases = colSelections;
299
+ this._builder = kysely.selectFrom(table._.name).select(colSelections);
300
+ }
301
+ _builder;
302
+ _table;
303
+ _columns;
304
+ _includeRelations = {};
305
+ _manualJoins = [];
306
+ _isDistinct = false;
307
+ _includedColumnAliases = [];
294
308
  distinct() {
295
- this.isDistinct = true;
309
+ this._isDistinct = true;
310
+ this._builder = this._builder.distinct();
311
+ return this;
312
+ }
313
+ where(condition) {
314
+ this._builder = this._builder.where(condition);
315
+ return this;
316
+ }
317
+ orderBy(column, direction = "asc") {
318
+ if ("toOperationNode" in column) {
319
+ this._builder = this._builder.orderBy(column, direction);
320
+ } else {
321
+ this._builder = this._builder.orderBy(
322
+ sql2.ref(column._.name),
323
+ direction
324
+ );
325
+ }
326
+ return this;
327
+ }
328
+ limit(count2) {
329
+ this._builder = this._builder.limit(count2);
330
+ return this;
331
+ }
332
+ offset(count2) {
333
+ this._builder = this._builder.offset(count2);
296
334
  return this;
297
335
  }
298
336
  groupBy(...columns) {
299
- this.groupByColumns.push(...columns);
300
- const columnNames = columns.map((col) => `${this.selectedTableAlias}.${col._.name}`).join(", ");
301
- this.query += ` GROUP BY ${columnNames}`;
337
+ for (const col of columns) {
338
+ this._builder = this._builder.groupBy(
339
+ sql2`${sql2.ref(this._table._.name)}.${sql2.ref(col._.name)}`
340
+ );
341
+ }
302
342
  return this;
303
343
  }
304
344
  having(condition) {
305
- this.havingCondition = condition;
306
- this.query += ` HAVING ${condition.sql}`;
307
- this.params.push(...condition.params);
345
+ this._builder = this._builder.having(condition);
308
346
  return this;
309
347
  }
310
348
  leftJoin(table, condition, alias2) {
311
- this.joins.push({ type: "LEFT", table, condition, alias: alias2 });
312
- const aliasedColumns = Object.values(table._.columns).map(
313
- (col) => `${alias2}.${col._.name} AS "${alias2}.${col._.name}"`
349
+ this._manualJoins.push({ type: "LEFT", table, condition, alias: alias2 });
350
+ const aliasedCols = Object.values(table._.columns).map(
351
+ (col) => `${alias2}.${col._.name} as "${alias2}.${col._.name}"`
314
352
  );
315
- this.selectedColumns.push(...aliasedColumns);
353
+ this._builder = this._builder.leftJoin(`${table._.name} as ${alias2}`, (join) => join.on(condition)).select(aliasedCols);
316
354
  return this;
317
355
  }
318
356
  innerJoin(table, condition, alias2) {
319
- this.joins.push({ type: "INNER", table, condition, alias: alias2 });
320
- const aliasedColumns = Object.values(table._.columns).map(
321
- (col) => `${alias2}.${col._.name} AS "${alias2}.${col._.name}"`
357
+ this._manualJoins.push({ type: "INNER", table, condition, alias: alias2 });
358
+ const aliasedCols = Object.values(table._.columns).map(
359
+ (col) => `${alias2}.${col._.name} as "${alias2}.${col._.name}"`
322
360
  );
323
- this.selectedColumns.push(...aliasedColumns);
361
+ this._builder = this._builder.innerJoin(`${table._.name} as ${alias2}`, (join) => join.on(condition)).select(aliasedCols);
324
362
  return this;
325
363
  }
326
364
  include(relations2) {
327
- this.includeRelations = { ...this.includeRelations, ...relations2 };
365
+ this._includeRelations = { ...this._includeRelations, ...relations2 };
328
366
  return this;
329
367
  }
330
- buildJoins() {
331
- let sql2 = "";
332
- const params = [];
333
- for (const join of this.joins) {
334
- sql2 += ` ${join.type} JOIN ${join.table._.name} ${join.alias} ON ${join.condition.sql}`;
335
- params.push(...join.condition.params);
336
- }
368
+ applyIncludes() {
337
369
  const processRelations = (parentTable, parentAlias, relations2, depth = 0) => {
338
370
  if (depth > 10) {
339
- console.warn("[Tauri-ORM] Maximum relation depth (10) exceeded. Skipping deeper relations.");
371
+ console.warn("[Tauri-ORM] Maximum relation depth (10) exceeded.");
340
372
  return;
341
373
  }
342
374
  for (const [relationName, include] of Object.entries(relations2)) {
@@ -344,77 +376,72 @@ var SelectQueryBuilder = class extends BaseQueryBuilder {
344
376
  const relation = parentTable.relations[relationName];
345
377
  if (!relation) {
346
378
  console.warn(
347
- `[Tauri-ORM] Relation "${relationName}" not found on table "${parentTable._.name}". Skipping include.`
379
+ `[Tauri-ORM] Relation "${relationName}" not found on table "${parentTable._.name}". Skipping.`
348
380
  );
349
381
  continue;
350
382
  }
351
383
  const foreignTable = relation.foreignTable;
352
384
  const foreignAlias = `${parentAlias}_${relationName}`;
353
- const aliasedColumns = Object.values(foreignTable._.columns).map(
354
- (col) => `${foreignAlias}.${col._.name} AS "${foreignAlias}.${col._.name}"`
385
+ const selectedCols = resolveRelationColumns(foreignTable, include);
386
+ const aliasedCols = selectedCols.map(
387
+ (col) => `${foreignAlias}.${col._.name} as "${foreignAlias}.${col._.name}"`
355
388
  );
356
- this.selectedColumns.push(...aliasedColumns);
357
389
  if (relation.type === "one" && relation.fields && relation.references) {
358
- const conditions = relation.fields.map((field, i) => {
359
- const localColumn = `${parentAlias}.${field._.name}`;
360
- const foreignColumn = `${foreignAlias}.${relation.references[i]._.name}`;
361
- return {
362
- sql: `${localColumn} = ${foreignColumn}`,
363
- params: []
364
- };
365
- });
366
- const condition = conditions.length > 1 ? and(...conditions) : conditions[0];
367
- sql2 += ` LEFT JOIN ${foreignTable._.name} ${foreignAlias} ON ${condition.sql}`;
368
- params.push(...condition.params);
390
+ const onCondition = sql2`${sql2.join(
391
+ relation.fields.map(
392
+ (field, i) => sql2`${sql2.ref(`${parentAlias}.${field._.name}`)} = ${sql2.ref(`${foreignAlias}.${relation.references[i]._.name}`)}`
393
+ ),
394
+ sql2` AND `
395
+ )}`;
396
+ this._builder = this._builder.leftJoin(
397
+ `${foreignTable._.name} as ${foreignAlias}`,
398
+ (join) => join.on(onCondition)
399
+ ).select(aliasedCols);
369
400
  } else if (relation.type === "many") {
370
- const refRelation = Object.entries(foreignTable.relations).find(
371
- ([_, r]) => r.foreignTable === parentTable
372
- );
373
- if (refRelation && refRelation[1].fields && refRelation[1].references) {
374
- const [_, relationConfig] = refRelation;
375
- const conditions = relationConfig.fields.map((field, i) => {
376
- const localColumn = `${foreignAlias}.${field._.name}`;
377
- const foreignColumn = `${parentAlias}.${relationConfig.references[i]._.name}`;
378
- return {
379
- sql: `${localColumn} = ${foreignColumn}`,
380
- params: []
381
- };
382
- });
383
- const condition = conditions.length > 1 ? and(...conditions) : conditions[0];
384
- sql2 += ` LEFT JOIN ${foreignTable._.name} ${foreignAlias} ON ${condition.sql}`;
385
- params.push(...condition.params);
386
- }
387
- } else if (relation.type === "manyToMany" && relation.junctionTable && relation.junctionFields && relation.junctionReferences) {
388
- const junctionTable = relation.junctionTable;
389
- const junctionAlias = `${foreignAlias}_junction`;
390
- const parentTablePks = Object.values(parentTable._.columns).filter((c) => c.options.primaryKey).map((c) => c._.name);
391
- if (parentTablePks.length > 0 && relation.junctionFields.length > 0) {
392
- const junctionConditions = relation.junctionFields.map((field, i) => {
393
- const parentPk = parentTablePks[i] || parentTablePks[0];
394
- const localColumn = `${parentAlias}.${parentPk}`;
395
- const junctionColumn = `${junctionAlias}.${field._.name}`;
396
- return {
397
- sql: `${localColumn} = ${junctionColumn}`,
398
- params: []
399
- };
400
- });
401
- const junctionCondition = junctionConditions.length > 1 ? and(...junctionConditions) : junctionConditions[0];
402
- sql2 += ` LEFT JOIN ${junctionTable._.name} ${junctionAlias} ON ${junctionCondition.sql}`;
403
- params.push(...junctionCondition.params);
404
- const foreignTablePks = Object.values(foreignTable._.columns).filter((c) => c.options.primaryKey).map((c) => c._.name);
405
- if (foreignTablePks.length > 0 && relation.junctionReferences.length > 0) {
406
- const foreignConditions = relation.junctionReferences.map((field, i) => {
407
- const foreignPk = foreignTablePks[i] || foreignTablePks[0];
408
- const junctionColumn = `${junctionAlias}.${field._.name}`;
409
- const foreignColumn = `${foreignAlias}.${foreignPk}`;
410
- return {
411
- sql: `${junctionColumn} = ${foreignColumn}`,
412
- params: []
413
- };
414
- });
415
- const foreignCondition = foreignConditions.length > 1 ? and(...foreignConditions) : foreignConditions[0];
416
- sql2 += ` LEFT JOIN ${foreignTable._.name} ${foreignAlias} ON ${foreignCondition.sql}`;
417
- params.push(...foreignCondition.params);
401
+ if (relation.junctionTable && relation.fromJunction && relation.toJunction) {
402
+ const junctionTable = relation.junctionTable;
403
+ const junctionAlias = `${foreignAlias}_jn`;
404
+ const fromJ = relation.fromJunction;
405
+ const toJ = relation.toJunction;
406
+ const join1 = sql2`${sql2.ref(`${parentAlias}.${fromJ.column._.name}`)} = ${sql2.ref(`${junctionAlias}.${fromJ.junctionColumn._.name}`)}`;
407
+ let join2 = sql2`${sql2.ref(`${junctionAlias}.${toJ.junctionColumn._.name}`)} = ${sql2.ref(`${foreignAlias}.${toJ.column._.name}`)}`;
408
+ if (relation.where) {
409
+ join2 = and(join2, relation.where(foreignAlias));
410
+ }
411
+ this._builder = this._builder.leftJoin(
412
+ `${junctionTable._.name} as ${junctionAlias}`,
413
+ (join) => join.on(join1)
414
+ ).leftJoin(
415
+ `${foreignTable._.name} as ${foreignAlias}`,
416
+ (join) => join.on(join2)
417
+ ).select(aliasedCols);
418
+ } else {
419
+ let fields = relation.fields;
420
+ let references = relation.references;
421
+ if (!fields || !references) {
422
+ const refRelation = Object.entries(foreignTable.relations).find(
423
+ ([, r]) => r.foreignTable === parentTable
424
+ );
425
+ if (refRelation && refRelation[1].fields && refRelation[1].references) {
426
+ const [, relationConfig] = refRelation;
427
+ fields = relationConfig.fields;
428
+ references = relationConfig.references;
429
+ }
430
+ }
431
+ if (fields && references) {
432
+ let onCondition = sql2`${sql2.join(
433
+ fields.map(
434
+ (field, i) => sql2`${sql2.ref(`${foreignAlias}.${field._.name}`)} = ${sql2.ref(`${parentAlias}.${references[i]._.name}`)}`
435
+ ),
436
+ sql2` AND `
437
+ )}`;
438
+ if (relation.where) {
439
+ onCondition = and(onCondition, relation.where(foreignAlias));
440
+ }
441
+ this._builder = this._builder.leftJoin(
442
+ `${foreignTable._.name} as ${foreignAlias}`,
443
+ (join) => join.on(onCondition)
444
+ ).select(aliasedCols);
418
445
  }
419
446
  }
420
447
  }
@@ -423,184 +450,160 @@ var SelectQueryBuilder = class extends BaseQueryBuilder {
423
450
  }
424
451
  }
425
452
  };
426
- processRelations(this.table, this.selectedTableAlias, this.includeRelations, 0);
427
- return { sql: sql2, params };
453
+ processRelations(this._table, this._table._.name, this._includeRelations, 0);
428
454
  }
429
- // Enhanced execute method that handles relation data mapping
430
455
  async execute() {
431
- const { sql: joinSql, params: joinParams } = this.buildJoins();
432
- const distinct = this.isDistinct ? "DISTINCT " : "";
433
- const whereIndex = this.query.indexOf(" WHERE ");
434
- let fromPart = this.query;
435
- let wherePart = "";
436
- if (whereIndex !== -1) {
437
- fromPart = this.query.substring(0, whereIndex);
438
- wherePart = this.query.substring(whereIndex);
439
- }
440
- this.query = `SELECT ${distinct}${this.selectedColumns.join(", ")} ${fromPart}${joinSql}${wherePart}`;
441
- this.params = [...joinParams, ...this.params];
442
- const { sql: sql2, params } = this.build();
443
- const rawResults = await this.db.select(sql2, params);
444
- const hasIncludes = Object.values(this.includeRelations).some((i) => i);
456
+ this.applyIncludes();
457
+ const rawResults = await this._builder.execute();
458
+ const hasIncludes = Object.values(this._includeRelations).some((i) => i);
445
459
  if (hasIncludes) {
446
460
  return this.processRelationResults(rawResults);
447
461
  }
448
- const hasJoins = this.joins.length > 0;
449
- if (hasJoins) {
462
+ const hasManualJoins = this._manualJoins.length > 0;
463
+ if (hasManualJoins) {
450
464
  return rawResults;
451
465
  }
452
- const prefix = `${this.selectedTableAlias}.`;
466
+ const prefix = `${this._table._.name}.`;
467
+ const dbNameToTs = getDbNameToTsName(this._table);
453
468
  return rawResults.map((row) => {
454
- const newRow = {};
469
+ const out = {};
455
470
  for (const key in row) {
456
- const columnName = key.startsWith(prefix) ? key.substring(prefix.length) : key;
457
- const column = this.table._.columns[columnName];
458
- if (column) {
459
- newRow[columnName] = deserializeValue(row[key], column);
460
- } else {
461
- newRow[columnName] = row[key];
462
- }
471
+ const normKey = normalizeRowKey(key);
472
+ const dbColName = normKey.startsWith(prefix) ? normKey.slice(prefix.length) : normKey;
473
+ const tsName = dbNameToTs[dbColName] ?? dbColName;
474
+ const column = this._table._.columns[tsName];
475
+ out[tsName] = column ? deserializeValue(row[key], column) : row[key];
463
476
  }
464
- return newRow;
477
+ return out;
465
478
  });
466
479
  }
467
480
  processRelationResults(rawResults) {
468
481
  if (!rawResults.length) return [];
469
- const mainTablePks = Object.values(this.table._.columns).filter((c) => c.options.primaryKey).map((c) => c._.name);
470
- if (mainTablePks.length === 0) {
471
- return rawResults;
472
- }
482
+ const mainTablePks = Object.values(this._table._.columns).filter((c) => c.options.primaryKey).map((c) => c._.name);
483
+ if (mainTablePks.length === 0) return rawResults;
473
484
  const groupedResults = /* @__PURE__ */ new Map();
474
485
  const parseRelationPath = (tableAlias, baseAlias) => {
475
- if (!tableAlias.startsWith(baseAlias + "_")) {
476
- return [];
477
- }
478
- const path = tableAlias.substring(baseAlias.length + 1);
479
- return path.split("_");
486
+ if (!tableAlias.startsWith(baseAlias + "_")) return [];
487
+ return tableAlias.slice(baseAlias.length + 1).split("_");
480
488
  };
481
- const setNestedValue = (obj, path, value, columnName) => {
482
- let current = obj;
489
+ const setNestedValue = (obj, path, columnName, value) => {
490
+ let cur = obj;
483
491
  for (let i = 0; i < path.length; i++) {
484
492
  const key = path[i];
485
493
  if (i === path.length - 1) {
486
- if (!current[key]) current[key] = {};
487
- current[key][columnName] = value;
494
+ if (!cur[key]) cur[key] = {};
495
+ cur[key][columnName] = value;
488
496
  } else {
489
- if (!current[key]) current[key] = {};
490
- current = current[key];
497
+ if (!cur[key]) cur[key] = {};
498
+ cur = cur[key];
491
499
  }
492
500
  }
493
501
  };
494
502
  const getNestedRelation = (table, path) => {
495
- let currentTable = table;
496
- let currentRelation = null;
497
- for (const relationName of path) {
498
- currentRelation = currentTable.relations[relationName];
499
- if (!currentRelation) return null;
500
- currentTable = currentRelation.foreignTable;
503
+ let current = table;
504
+ let relation = null;
505
+ for (const name of path) {
506
+ relation = current.relations[name];
507
+ if (!relation) return null;
508
+ current = relation.foreignTable;
501
509
  }
502
- return currentRelation;
510
+ return relation;
503
511
  };
504
512
  for (const row of rawResults) {
505
- const mainTableKey = mainTablePks.map((pk) => row[`${this.selectedTableAlias}.${pk}`] ?? row[pk]).join("_");
513
+ const getVal = (logicalKey) => {
514
+ const quoted = `"${logicalKey}"`;
515
+ return row[quoted] ?? row[logicalKey];
516
+ };
517
+ const mainTableKey = mainTablePks.map((pk) => getVal(`${this._table._.name}.${pk}`) ?? getVal(pk)).join("_");
506
518
  if (!groupedResults.has(mainTableKey)) {
507
519
  groupedResults.set(mainTableKey, {});
508
520
  }
509
521
  const result = groupedResults.get(mainTableKey);
510
522
  const relations2 = {};
511
523
  for (const [key, value] of Object.entries(row)) {
512
- if (key.includes(".")) {
513
- const [tableAlias, columnName] = key.split(".");
514
- if (tableAlias === this.selectedTableAlias) {
515
- const column = this.table._.columns[columnName];
516
- result[columnName] = column ? deserializeValue(value, column) : value;
524
+ const normKey = normalizeRowKey(key);
525
+ if (!normKey.includes(".")) {
526
+ const mainDbToTs = getDbNameToTsName(this._table);
527
+ const tsName = mainDbToTs[normKey] ?? normKey;
528
+ const column = this._table._.columns[tsName];
529
+ result[tsName] = column ? deserializeValue(value, column) : value;
530
+ continue;
531
+ }
532
+ const dotIndex = normKey.indexOf(".");
533
+ const tableAlias = normKey.slice(0, dotIndex);
534
+ const columnName = normKey.slice(dotIndex + 1);
535
+ if (tableAlias === this._table._.name) {
536
+ const mainDbToTs = getDbNameToTsName(this._table);
537
+ const tsName = mainDbToTs[columnName] ?? columnName;
538
+ const column = this._table._.columns[tsName];
539
+ result[tsName] = column ? deserializeValue(value, column) : value;
540
+ } else {
541
+ if (tableAlias.endsWith("_jn")) continue;
542
+ const path = parseRelationPath(tableAlias, this._table._.name);
543
+ if (path.length > 0) {
544
+ const relationConfig = getNestedRelation(this._table, path);
545
+ const foreignTable = relationConfig?.foreignTable;
546
+ const foreignDbToTs = foreignTable ? getDbNameToTsName(foreignTable) : {};
547
+ const tsName = foreignDbToTs[columnName] ?? columnName;
548
+ const col = foreignTable?._.columns?.[tsName];
549
+ setNestedValue(relations2, path, tsName, col ? deserializeValue(value, col) : value);
517
550
  } else {
518
- const relationPath = parseRelationPath(tableAlias, this.selectedTableAlias);
519
- if (relationPath.length > 0) {
520
- const relationConfig = getNestedRelation(this.table, relationPath);
521
- const column = relationConfig?.foreignTable?._.columns?.[columnName];
522
- const deserializedValue = column ? deserializeValue(value, column) : value;
523
- setNestedValue(relations2, relationPath, deserializedValue, columnName);
524
- } else {
525
- if (!result[tableAlias]) result[tableAlias] = {};
526
- result[tableAlias][columnName] = value;
527
- }
551
+ if (!result[tableAlias]) result[tableAlias] = {};
552
+ result[tableAlias][columnName] = value;
528
553
  }
529
- } else {
530
- const column = this.table._.columns[key];
531
- result[key] = column ? deserializeValue(value, column) : value;
532
554
  }
533
555
  }
534
- const attachRelations = (target, relationsData, table, pathPrefix = []) => {
535
- for (const [relName, relData] of Object.entries(relationsData)) {
536
- const currentPath = [...pathPrefix, relName];
537
- const relationConfig = getNestedRelation(table, currentPath);
556
+ const attachRelations = (target, relData, table) => {
557
+ for (const [relName, data] of Object.entries(relData)) {
558
+ const relationConfig = table.relations[relName];
538
559
  if (!relationConfig) continue;
539
- const hasDirectData = typeof relData === "object" && relData !== null && Object.entries(relData).some(([k, v]) => {
540
- return typeof v !== "object" && v !== null && v !== void 0 && v !== "";
541
- });
542
- if (!hasDirectData && typeof relData === "object" && relData !== null) {
543
- const hasNestedData = Object.values(relData).some(
544
- (v) => typeof v === "object" && v !== null && Object.keys(v).length > 0
545
- );
546
- if (!hasNestedData) continue;
547
- }
548
- if (relationConfig.type === "many" || relationConfig.type === "manyToMany") {
549
- if (!target[relName]) target[relName] = [];
550
- const directData = {};
551
- const nestedData = {};
552
- if (typeof relData === "object" && relData !== null) {
553
- for (const [k, v] of Object.entries(relData)) {
554
- if (typeof v === "object" && v !== null) {
555
- nestedData[k] = v;
556
- } else {
557
- directData[k] = v;
558
- }
560
+ const directData = {};
561
+ const nestedData = {};
562
+ if (typeof data === "object" && data !== null) {
563
+ for (const [k, v] of Object.entries(data)) {
564
+ if (typeof v === "object" && v !== null) {
565
+ nestedData[k] = v;
566
+ } else {
567
+ directData[k] = v;
559
568
  }
560
569
  }
561
- const hasData = Object.values(directData).some(
562
- (v) => v !== null && v !== void 0 && v !== ""
563
- );
570
+ }
571
+ const hasData = Object.values(directData).some(
572
+ (v) => v !== null && v !== void 0 && v !== ""
573
+ );
574
+ if (relationConfig.type === "many") {
575
+ if (!target[relName]) target[relName] = [];
564
576
  if (hasData) {
565
- const relatedPks = Object.values(relationConfig.foreignTable._.columns).filter((c) => c.options.primaryKey).map((c) => c._.name);
566
- const relDataKey = relatedPks.map((pk) => directData[pk]).join("_");
567
- if (relatedPks.length === 0 || !target[relName].some((r) => relatedPks.map((pk) => r[pk]).join("_") === relDataKey)) {
577
+ const relPks = Object.values(relationConfig.foreignTable._.columns).filter((c) => c.options.primaryKey).map((c) => c._.name);
578
+ const key = relPks.map((pk) => directData[pk]).join("_");
579
+ if (relPks.length === 0 || !target[relName].some(
580
+ (r) => relPks.map((pk) => r[pk]).join("_") === key
581
+ )) {
568
582
  const newItem = { ...directData };
569
583
  if (Object.keys(nestedData).length > 0) {
570
- attachRelations(newItem, nestedData, relationConfig.foreignTable, []);
584
+ attachRelations(newItem, nestedData, relationConfig.foreignTable);
571
585
  }
572
586
  target[relName].push(newItem);
573
587
  }
574
588
  }
575
589
  } else {
576
- const directData = {};
577
- const nestedData = {};
578
- if (typeof relData === "object" && relData !== null) {
579
- for (const [k, v] of Object.entries(relData)) {
580
- if (typeof v === "object" && v !== null) {
581
- nestedData[k] = v;
582
- } else {
583
- directData[k] = v;
584
- }
585
- }
586
- }
587
- const hasData = Object.values(directData).some(
588
- (v) => v !== null && v !== void 0 && v !== ""
589
- );
590
590
  if (hasData || Object.keys(nestedData).length > 0) {
591
591
  target[relName] = { ...directData };
592
592
  if (Object.keys(nestedData).length > 0) {
593
- attachRelations(target[relName], nestedData, relationConfig.foreignTable, []);
593
+ attachRelations(
594
+ target[relName],
595
+ nestedData,
596
+ relationConfig.foreignTable
597
+ );
594
598
  }
595
599
  }
596
600
  }
597
601
  }
598
602
  };
599
- attachRelations(result, relations2, this.table);
603
+ attachRelations(result, relations2, this._table);
600
604
  }
601
605
  return Array.from(groupedResults.values());
602
606
  }
603
- // Update the return type signatures
604
607
  async all() {
605
608
  return this.execute();
606
609
  }
@@ -609,61 +612,32 @@ var SelectQueryBuilder = class extends BaseQueryBuilder {
609
612
  const result = await this.execute();
610
613
  return result[0];
611
614
  }
615
+ async first() {
616
+ return this.get();
617
+ }
612
618
  async exists() {
613
- const originalColumns = this.selectedColumns;
614
- this.selectedColumns = ["1"];
615
- const { sql: joinSql, params: joinParams } = this.buildJoins();
616
- const whereIndex = this.query.indexOf(" WHERE ");
617
- let fromPart = this.query;
618
- let wherePart = "";
619
- if (whereIndex !== -1) {
620
- fromPart = this.query.substring(0, whereIndex);
621
- wherePart = this.query.substring(whereIndex);
622
- }
623
- const query = `SELECT 1 ${fromPart}${joinSql}${wherePart} LIMIT 1`;
624
- const params = [...joinParams, ...this.params];
625
- this.selectedColumns = originalColumns;
626
- const result = await this.db.select(query, params);
627
- return result.length > 0;
619
+ this.applyIncludes();
620
+ const compiledResult = await this._builder.clearSelect().select(sql2.raw("1").as("__exists__")).limit(1).execute();
621
+ return compiledResult.length > 0;
628
622
  }
629
623
  async count() {
630
- const originalColumns = this.selectedColumns;
631
- this.selectedColumns = ["COUNT(*) as count"];
632
- const { sql: joinSql, params: joinParams } = this.buildJoins();
633
- const whereIndex = this.query.indexOf(" WHERE ");
634
- let fromPart = this.query;
635
- let wherePart = "";
636
- if (whereIndex !== -1) {
637
- fromPart = this.query.substring(0, whereIndex);
638
- wherePart = this.query.substring(whereIndex);
639
- }
640
- const query = `SELECT COUNT(*) as count ${fromPart}${joinSql}${wherePart}`;
641
- const params = [...joinParams, ...this.params];
642
- this.selectedColumns = originalColumns;
643
- const result = await this.db.select(query, params);
644
- return result[0]?.count || 0;
645
- }
646
- async first() {
647
- return this.get();
624
+ this.applyIncludes();
625
+ const result = await this._builder.clearSelect().select(sql2`COUNT(*)`.as("count")).execute();
626
+ const row = result[0];
627
+ const val = row ? row['"count"'] ?? row.count : void 0;
628
+ return Number(val ?? 0);
648
629
  }
649
630
  async pluck(column) {
650
- const columnName = this.table._.columns[column]._.name;
651
- const originalColumns = this.selectedColumns;
652
- this.selectedColumns = [`${this.selectedTableAlias}.${columnName} AS "${columnName}"`];
653
- const { sql: joinSql, params: joinParams } = this.buildJoins();
654
- const whereIndex = this.query.indexOf(" WHERE ");
655
- let fromPart = this.query;
656
- let wherePart = "";
657
- if (whereIndex !== -1) {
658
- fromPart = this.query.substring(0, whereIndex);
659
- wherePart = this.query.substring(whereIndex);
660
- }
661
- const query = `SELECT ${this.selectedColumns.join(", ")} ${fromPart}${joinSql}${wherePart}`;
662
- const params = [...joinParams, ...this.params];
663
- this.selectedColumns = originalColumns;
664
- const results = await this.db.select(query, params);
665
- const col = this.table._.columns[column];
666
- return results.map((row) => col ? deserializeValue(row[columnName], col) : row[columnName]);
631
+ this.applyIncludes();
632
+ const col = this._table._.columns[column];
633
+ const alias2 = col._.name;
634
+ const results = await this._builder.clearSelect().select(
635
+ sql2.raw(`${this._table._.name}.${alias2}`).as(alias2)
636
+ ).execute();
637
+ return results.map((row) => {
638
+ const val = row['"' + alias2 + '"'] ?? row[alias2];
639
+ return col ? deserializeValue(val, col) : val;
640
+ });
667
641
  }
668
642
  async paginate(page = 1, pageSize = 10) {
669
643
  if (page < 1) page = 1;
@@ -683,16 +657,19 @@ var SelectQueryBuilder = class extends BaseQueryBuilder {
683
657
  };
684
658
  }
685
659
  toSQL() {
686
- const { sql: joinSql, params: joinParams } = this.buildJoins();
687
- const distinct = this.isDistinct ? "DISTINCT " : "";
688
- const finalQuery = `SELECT ${distinct}${this.selectedColumns.join(", ")} ${this.query}${joinSql}`;
689
- return {
690
- sql: finalQuery,
691
- params: [...this.params, ...joinParams]
692
- };
660
+ this.applyIncludes();
661
+ const compiled = this._builder.compile();
662
+ return { sql: compiled.sql, params: [...compiled.parameters] };
663
+ }
664
+ toKyselyExpression() {
665
+ this.applyIncludes();
666
+ return this._builder;
693
667
  }
694
668
  };
695
669
 
670
+ // src/builders/update.ts
671
+ import { sql as sql3 } from "kysely";
672
+
696
673
  // src/errors.ts
697
674
  var TauriORMError = class extends Error {
698
675
  constructor(message) {
@@ -761,414 +738,384 @@ var TableNotFoundError = class extends TauriORMError {
761
738
  };
762
739
 
763
740
  // src/builders/update.ts
764
- var UpdateQueryBuilder = class extends BaseQueryBuilder {
765
- constructor(db, table) {
766
- super(db);
767
- this.table = table;
768
- this.query = `UPDATE ${table._.name}`;
769
- }
770
- updateData = {};
771
- returningColumns = [];
772
- hasWhereClause = false;
773
- allowGlobal = false;
774
- incrementDecrementOps = [];
741
+ var UpdateQueryBuilder = class {
742
+ constructor(kysely, table) {
743
+ this.kysely = kysely;
744
+ this._table = table;
745
+ this._builder = kysely.updateTable(table._.name);
746
+ }
747
+ _builder;
748
+ _table;
749
+ _updateData = {};
750
+ _returningColumns = [];
751
+ _hasWhereClause = false;
752
+ _allowGlobal = false;
753
+ _incrementDecrementOps = [];
775
754
  set(data) {
776
- this.updateData = { ...this.updateData, ...data };
755
+ this._updateData = { ...this._updateData, ...data };
777
756
  return this;
778
757
  }
779
758
  where(condition) {
780
- this.hasWhereClause = true;
781
- return super.where(condition);
759
+ this._hasWhereClause = true;
760
+ this._builder = this._builder.where(condition);
761
+ return this;
782
762
  }
783
763
  increment(column, value = 1) {
784
- const col = this.table._.columns[column];
785
- if (!col) {
786
- throw new ColumnNotFoundError(String(column), this.table._.name);
787
- }
788
- this.incrementDecrementOps.push({ column: col._.name, op: "increment", value });
764
+ const col = this._table._.columns[column];
765
+ if (!col) throw new ColumnNotFoundError(String(column), this._table._.name);
766
+ this._incrementDecrementOps.push({ column: col._.name, op: "increment", value });
789
767
  return this;
790
768
  }
791
769
  decrement(column, value = 1) {
792
- const col = this.table._.columns[column];
793
- if (!col) {
794
- throw new ColumnNotFoundError(String(column), this.table._.name);
795
- }
796
- this.incrementDecrementOps.push({ column: col._.name, op: "decrement", value });
770
+ const col = this._table._.columns[column];
771
+ if (!col) throw new ColumnNotFoundError(String(column), this._table._.name);
772
+ this._incrementDecrementOps.push({ column: col._.name, op: "decrement", value });
797
773
  return this;
798
774
  }
799
775
  allowGlobalOperation() {
800
- this.allowGlobal = true;
776
+ this._allowGlobal = true;
801
777
  return this;
802
778
  }
803
779
  returning(...columns) {
804
- this.returningColumns.push(...columns);
780
+ this._returningColumns.push(...columns);
805
781
  return this;
806
782
  }
807
- buildUpdateClause() {
808
- const finalUpdateData = { ...this.updateData };
809
- for (const [key, column] of Object.entries(this.table._.columns)) {
810
- const typedKey = key;
811
- if (finalUpdateData[typedKey] === void 0 && column.options.$onUpdateFn) {
812
- finalUpdateData[typedKey] = column.options.$onUpdateFn();
783
+ mapReturningRows(rows) {
784
+ const dbNameToTs = {};
785
+ for (const [tsName, col] of Object.entries(this._table._.columns)) {
786
+ dbNameToTs[col._.name] = tsName;
787
+ }
788
+ const norm = (k) => k.startsWith('"') && k.endsWith('"') ? k.slice(1, -1) : k;
789
+ return rows.map((row) => {
790
+ const out = {};
791
+ for (const [dbKey, value] of Object.entries(row)) {
792
+ const logicalKey = norm(dbKey);
793
+ const tsName = dbNameToTs[logicalKey] ?? logicalKey;
794
+ const column = this._table._.columns[tsName];
795
+ out[tsName] = column ? deserializeValue(value, column) : value;
796
+ }
797
+ return out;
798
+ });
799
+ }
800
+ buildSetClause() {
801
+ const finalData = { ...this._updateData };
802
+ for (const [key, column] of Object.entries(this._table._.columns)) {
803
+ if (finalData[key] === void 0 && column.options.$onUpdateFn) {
804
+ ;
805
+ finalData[key] = column.options.$onUpdateFn();
813
806
  }
814
807
  }
815
- const baseQuery = this.query;
816
- const whereParams = this.params;
817
- let tablePart = baseQuery;
818
- let whereClause = "";
819
- const whereIndex = baseQuery.indexOf(" WHERE ");
820
- if (whereIndex !== -1) {
821
- tablePart = baseQuery.substring(0, whereIndex);
822
- whereClause = baseQuery.substring(whereIndex);
823
- }
824
- const entries = Object.entries(finalUpdateData);
808
+ const entries = Object.entries(finalData);
825
809
  const hasSetData = entries.length > 0;
826
- const hasIncrementDecrement = this.incrementDecrementOps.length > 0;
827
- if (!hasSetData && !hasIncrementDecrement) {
828
- throw new UpdateValidationError("Cannot execute an update query without a .set(), .increment(), or .decrement() call.");
810
+ const hasOps = this._incrementDecrementOps.length > 0;
811
+ if (!hasSetData && !hasOps) {
812
+ throw new UpdateValidationError(
813
+ "Cannot execute an update query without a .set(), .increment(), or .decrement() call."
814
+ );
829
815
  }
830
- const setClauses = [];
831
- const setParams = [];
832
- if (hasSetData) {
833
- for (const [key, value] of entries) {
834
- const column = this.table._.columns[key];
835
- if (!column) {
836
- throw new ColumnNotFoundError(key, this.table._.name);
837
- }
838
- setClauses.push(`${column._.name} = ?`);
839
- setParams.push(serializeValue(value, column));
840
- }
816
+ const setMap = {};
817
+ for (const [key, value] of entries) {
818
+ const column = this._table._.columns[key];
819
+ if (!column) throw new ColumnNotFoundError(key, this._table._.name);
820
+ setMap[column._.name] = serializeValue(value, column);
841
821
  }
842
- for (const op of this.incrementDecrementOps) {
822
+ for (const op of this._incrementDecrementOps) {
843
823
  const sign = op.op === "increment" ? "+" : "-";
844
- setClauses.push(`${op.column} = ${op.column} ${sign} ?`);
845
- setParams.push(op.value);
824
+ setMap[op.column] = sql3.raw(`${op.column} ${sign} ${op.value}`);
846
825
  }
847
- const setClause = setClauses.join(", ");
848
- const sql2 = `${tablePart} SET ${setClause}${whereClause}`;
849
- const params = [...setParams, ...whereParams];
850
- return { sql: sql2, params };
826
+ return setMap;
851
827
  }
852
828
  async execute() {
853
- if (!this.hasWhereClause && !this.allowGlobal) {
854
- throw new MissingWhereClauseError("UPDATE", this.table._.name);
855
- }
856
- const { sql: updateSql, params } = this.buildUpdateClause();
857
- if (this.returningColumns.length > 0) {
858
- const returningNames = this.returningColumns.map((col) => this.table._.columns[col]._.name).join(", ");
859
- const sqlWithReturning = `${updateSql} RETURNING ${returningNames}`;
860
- return this.db.select(sqlWithReturning, params);
861
- } else {
862
- const result = await this.db.execute(updateSql, params);
863
- return [{ rowsAffected: result.rowsAffected }];
829
+ if (!this._hasWhereClause && !this._allowGlobal) {
830
+ throw new MissingWhereClauseError("UPDATE", this._table._.name);
831
+ }
832
+ const setMap = this.buildSetClause();
833
+ let builder = this._builder.set(setMap);
834
+ if (this._returningColumns.length > 0) {
835
+ const cols = this._returningColumns.map(
836
+ (k) => this._table._.columns[k]._.name
837
+ );
838
+ const rows = await builder.returning(cols).execute();
839
+ return this.mapReturningRows(rows);
864
840
  }
841
+ const result = await builder.executeTakeFirst();
842
+ return [{ rowsAffected: Number(result?.numUpdatedRows ?? 0) }];
865
843
  }
866
844
  async returningAll() {
867
- const allColumns = Object.keys(
868
- this.table._.columns
869
- );
870
- return this.returning(...allColumns).execute();
845
+ const allCols = Object.keys(this._table._.columns);
846
+ return this.returning(...allCols).execute();
871
847
  }
872
848
  async returningFirst() {
873
- const allColumns = Object.keys(
874
- this.table._.columns
875
- );
876
- const results = await this.returning(...allColumns).execute();
849
+ const results = await this.returningAll();
877
850
  return results[0];
878
851
  }
879
852
  toSQL() {
880
- const { sql: updateSql, params } = this.buildUpdateClause();
881
- if (this.returningColumns.length > 0) {
882
- const returningNames = this.returningColumns.map((col) => this.table._.columns[col]._.name).join(", ");
883
- return {
884
- sql: `${updateSql} RETURNING ${returningNames}`,
885
- params
886
- };
853
+ const setMap = this.buildSetClause();
854
+ let builder = this._builder.set(setMap);
855
+ if (this._returningColumns.length > 0) {
856
+ builder = builder.returning(
857
+ this._returningColumns.map((k) => this._table._.columns[k]._.name)
858
+ );
887
859
  }
888
- return { sql: updateSql, params };
860
+ const compiled = builder.compile();
861
+ return { sql: compiled.sql, params: [...compiled.parameters] };
889
862
  }
890
863
  };
891
864
 
892
865
  // src/builders/insert.ts
893
- var InsertQueryBuilder = class extends BaseQueryBuilder {
894
- constructor(db, table) {
895
- super(db);
896
- this.table = table;
897
- this.query = `INSERT INTO ${table._.name}`;
898
- }
899
- dataSets = [];
900
- returningColumns = [];
901
- onConflictAction = null;
902
- conflictTarget = [];
903
- updateSet = {};
866
+ var InsertQueryBuilder = class {
867
+ constructor(kysely, table) {
868
+ this.kysely = kysely;
869
+ this._table = table;
870
+ this._builder = kysely.insertInto(table._.name);
871
+ }
872
+ _builder;
873
+ _table;
874
+ _dataSets = [];
875
+ _returningColumns = [];
876
+ _onConflictAction = null;
877
+ _conflictTarget = [];
878
+ _updateSet = {};
904
879
  values(data) {
905
- const dataArray = Array.isArray(data) ? data : [data];
906
- this.dataSets.push(...dataArray);
880
+ const arr = Array.isArray(data) ? data : [data];
881
+ this._dataSets.push(...arr);
907
882
  return this;
908
883
  }
909
884
  returning(...columns) {
910
- this.returningColumns.push(...columns);
885
+ this._returningColumns.push(...columns);
911
886
  return this;
912
887
  }
913
888
  onConflictDoNothing(target) {
914
- this.onConflictAction = "nothing";
889
+ this._onConflictAction = "nothing";
915
890
  if (target) {
916
- this.conflictTarget = Array.isArray(target) ? target : [target];
891
+ this._conflictTarget = Array.isArray(target) ? target : [target];
917
892
  }
918
893
  return this;
919
894
  }
920
895
  onConflictDoUpdate(config) {
921
- this.onConflictAction = "update";
922
- this.conflictTarget = Array.isArray(config.target) ? config.target : [config.target];
923
- this.updateSet = config.set;
896
+ this._onConflictAction = "update";
897
+ this._conflictTarget = Array.isArray(config.target) ? config.target : [config.target];
898
+ this._updateSet = config.set;
924
899
  return this;
925
900
  }
926
- processDefaultValues(data) {
927
- const finalData = { ...data };
928
- for (const [key, column] of Object.entries(this.table._.columns)) {
929
- const typedKey = key;
930
- if (finalData[typedKey] === void 0) {
931
- if (column.options.$defaultFn) {
932
- finalData[typedKey] = column.options.$defaultFn();
933
- }
901
+ processDefaults(data) {
902
+ const out = { ...data };
903
+ for (const [key, column] of Object.entries(this._table._.columns)) {
904
+ if (out[key] === void 0 && column.options.$defaultFn) {
905
+ ;
906
+ out[key] = column.options.$defaultFn();
934
907
  }
935
908
  }
936
- return finalData;
937
- }
938
- buildConflictClause() {
939
- if (!this.onConflictAction) return "";
940
- let clause = " ON CONFLICT";
941
- if (this.conflictTarget.length > 0) {
942
- const targetNames = this.conflictTarget.map((col) => col._.name).join(", ");
943
- clause += ` (${targetNames})`;
944
- }
945
- if (this.onConflictAction === "nothing") {
946
- clause += " DO NOTHING";
947
- } else if (this.onConflictAction === "update") {
948
- const setEntries = Object.entries(this.updateSet);
949
- if (setEntries.length > 0) {
950
- const setClause = setEntries.map(([key]) => `${key} = ?`).join(", ");
951
- clause += ` DO UPDATE SET ${setClause}`;
909
+ return out;
910
+ }
911
+ mapReturningRows(rows) {
912
+ const dbNameToTs = {};
913
+ for (const [tsName, col] of Object.entries(this._table._.columns)) {
914
+ dbNameToTs[col._.name] = tsName;
915
+ }
916
+ const norm = (k) => k.startsWith('"') && k.endsWith('"') ? k.slice(1, -1) : k;
917
+ return rows.map((row) => {
918
+ const out = {};
919
+ for (const [dbKey, value] of Object.entries(row)) {
920
+ const logicalKey = norm(dbKey);
921
+ const tsName = dbNameToTs[logicalKey] ?? logicalKey;
922
+ const column = this._table._.columns[tsName];
923
+ out[tsName] = column ? deserializeValue(value, column) : value;
952
924
  }
925
+ return out;
926
+ });
927
+ }
928
+ serializeDataSet(data) {
929
+ const out = {};
930
+ for (const [key, value] of Object.entries(data)) {
931
+ const column = this._table._.columns[key];
932
+ out[column ? column._.name : key] = column ? serializeValue(value, column) : value;
953
933
  }
954
- return clause;
934
+ return out;
955
935
  }
956
936
  async execute() {
957
- if (this.dataSets.length === 0) {
958
- throw new InsertValidationError("No data provided for insert. Use .values() to provide data.");
959
- }
960
- const processedDataSets = this.dataSets.map(
961
- (data) => this.processDefaultValues(data)
962
- );
963
- const groups = /* @__PURE__ */ new Map();
964
- for (const dataSet of processedDataSets) {
965
- const keys = Object.keys(dataSet).sort().join(",");
966
- if (!groups.has(keys)) {
967
- groups.set(keys, []);
968
- }
969
- groups.get(keys).push(dataSet);
970
- }
971
- let results = [];
972
- let lastInsertId;
973
- let rowsAffected = 0;
974
- for (const [_, dataSets] of groups) {
975
- const columns = Object.keys(dataSets[0]);
976
- const columnNames = columns.map(
977
- (key) => this.table._.columns[key]._.name
978
- );
979
- const placeholders = `(${columns.map(() => "?").join(", ")})`;
980
- const valuesSql = dataSets.map(() => placeholders).join(", ");
981
- const conflictClause = this.buildConflictClause();
982
- const finalQuery = `${this.query} (${columnNames.join(
983
- ", "
984
- )}) VALUES ${valuesSql}${conflictClause}`;
985
- const params = dataSets.flatMap(
986
- (data) => columns.map((col) => {
987
- const value = data[col] ?? null;
988
- const column = this.table._.columns[col];
989
- return column ? serializeValue(value, column) : value;
990
- })
937
+ if (this._dataSets.length === 0) {
938
+ throw new InsertValidationError(
939
+ "No data provided for insert. Use .values() to provide data."
991
940
  );
992
- if (this.onConflictAction === "update") {
993
- const setValues = Object.entries(this.updateSet).map(
994
- ([key, value]) => {
995
- const column = this.table._.columns[key];
996
- return column ? serializeValue(value, column) : value;
997
- }
941
+ }
942
+ const processed = this._dataSets.map((d) => this.serializeDataSet(this.processDefaults(d)));
943
+ let builder = this._builder.values(processed.length === 1 ? processed[0] : processed);
944
+ if (this._onConflictAction === "nothing") {
945
+ if (this._conflictTarget.length > 0) {
946
+ const targetCols = this._conflictTarget.map((c) => c._.name);
947
+ builder = builder.onConflict(
948
+ (oc) => oc.columns(targetCols).doNothing()
998
949
  );
999
- params.push(...setValues);
1000
- }
1001
- if (this.returningColumns.length > 0) {
1002
- const returningNames = this.returningColumns.map((col) => this.table._.columns[col]._.name).join(", ");
1003
- const queryWithReturning = `${finalQuery} RETURNING ${returningNames}`;
1004
- const rows = await this.db.select(queryWithReturning, params);
1005
- results = results.concat(rows);
1006
950
  } else {
1007
- const result = await this.db.execute(finalQuery, params);
1008
- lastInsertId = result.lastInsertId;
1009
- rowsAffected += result.rowsAffected;
951
+ builder = builder.onConflict((oc) => oc.doNothing());
1010
952
  }
953
+ } else if (this._onConflictAction === "update") {
954
+ const targetCols = this._conflictTarget.map((c) => c._.name);
955
+ const updateData = this.serializeDataSet(this._updateSet);
956
+ builder = builder.onConflict(
957
+ (oc) => oc.columns(targetCols).doUpdateSet(updateData)
958
+ );
1011
959
  }
1012
- if (this.returningColumns.length > 0) {
1013
- return results;
960
+ if (this._returningColumns.length > 0) {
961
+ const cols = this._returningColumns.map(
962
+ (k) => this._table._.columns[k]._.name
963
+ );
964
+ const rows = await builder.returning(cols).execute();
965
+ return this.mapReturningRows(rows);
1014
966
  }
1015
- return [{ lastInsertId, rowsAffected }];
967
+ const result = await builder.executeTakeFirst();
968
+ return [
969
+ {
970
+ lastInsertId: Number(result?.insertId ?? 0),
971
+ rowsAffected: Number(result?.numInsertedOrUpdatedRows ?? 0)
972
+ }
973
+ ];
1016
974
  }
1017
975
  async returningAll() {
1018
- const allColumns = Object.keys(
1019
- this.table._.columns
1020
- );
1021
- return this.returning(...allColumns).execute();
976
+ const allCols = Object.keys(this._table._.columns);
977
+ return this.returning(...allCols).execute();
1022
978
  }
1023
979
  async returningFirst() {
1024
- const allColumns = Object.keys(
1025
- this.table._.columns
1026
- );
1027
- const results = await this.returning(...allColumns).execute();
980
+ const results = await this.returningAll();
1028
981
  return results[0];
1029
982
  }
1030
983
  toSQL() {
1031
- if (this.dataSets.length === 0) {
1032
- throw new InsertValidationError("No data provided for insert. Use .values() to provide data.");
984
+ if (this._dataSets.length === 0) {
985
+ throw new InsertValidationError(
986
+ "No data provided for insert. Use .values() to provide data."
987
+ );
1033
988
  }
1034
- const processedDataSets = this.dataSets.map(
1035
- (data) => this.processDefaultValues(data)
1036
- );
1037
- const dataSet = processedDataSets[0];
1038
- const columns = Object.keys(dataSet);
1039
- const columnNames = columns.map(
1040
- (key) => this.table._.columns[key]._.name
1041
- );
1042
- const placeholders = `(${columns.map(() => "?").join(", ")})`;
1043
- const valuesSql = processedDataSets.map(() => placeholders).join(", ");
1044
- const conflictClause = this.buildConflictClause();
1045
- const finalQuery = `${this.query} (${columnNames.join(
1046
- ", "
1047
- )}) VALUES ${valuesSql}${conflictClause}`;
1048
- const params = processedDataSets.flatMap(
1049
- (data) => columns.map((col) => {
1050
- const value = data[col] ?? null;
1051
- const column = this.table._.columns[col];
1052
- return column ? serializeValue(value, column) : value;
1053
- })
1054
- );
1055
- if (this.onConflictAction === "update") {
1056
- const setValues = Object.entries(this.updateSet).map(
1057
- ([key, value]) => {
1058
- const column = this.table._.columns[key];
1059
- return column ? serializeValue(value, column) : value;
1060
- }
989
+ const processed = this._dataSets.map((d) => this.serializeDataSet(this.processDefaults(d)));
990
+ let builder = this._builder.values(processed.length === 1 ? processed[0] : processed);
991
+ if (this._onConflictAction === "nothing") {
992
+ if (this._conflictTarget.length > 0) {
993
+ builder = builder.onConflict(
994
+ (oc) => oc.columns(this._conflictTarget.map((c) => c._.name)).doNothing()
995
+ );
996
+ } else {
997
+ builder = builder.onConflict((oc) => oc.doNothing());
998
+ }
999
+ } else if (this._onConflictAction === "update") {
1000
+ const updateData = this.serializeDataSet(this._updateSet);
1001
+ builder = builder.onConflict(
1002
+ (oc) => oc.columns(this._conflictTarget.map((c) => c._.name)).doUpdateSet(updateData)
1061
1003
  );
1062
- params.push(...setValues);
1063
1004
  }
1064
- if (this.returningColumns.length > 0) {
1065
- const returningNames = this.returningColumns.map((col) => this.table._.columns[col]._.name).join(", ");
1066
- return {
1067
- sql: `${finalQuery} RETURNING ${returningNames}`,
1068
- params
1069
- };
1005
+ if (this._returningColumns.length > 0) {
1006
+ builder = builder.returning(
1007
+ this._returningColumns.map((k) => this._table._.columns[k]._.name)
1008
+ );
1070
1009
  }
1071
- return { sql: finalQuery, params };
1010
+ const compiled = builder.compile();
1011
+ return { sql: compiled.sql, params: [...compiled.parameters] };
1072
1012
  }
1073
1013
  };
1074
1014
 
1075
1015
  // src/builders/delete.ts
1076
- var DeleteQueryBuilder = class extends BaseQueryBuilder {
1077
- constructor(db, table) {
1078
- super(db);
1079
- this.table = table;
1080
- this.query = `DELETE FROM ${table._.name}`;
1081
- }
1082
- returningColumns = [];
1083
- hasWhereClause = false;
1084
- allowGlobal = false;
1016
+ var DeleteQueryBuilder = class {
1017
+ constructor(kysely, table) {
1018
+ this.kysely = kysely;
1019
+ this._table = table;
1020
+ this._builder = kysely.deleteFrom(table._.name);
1021
+ }
1022
+ _builder;
1023
+ _table;
1024
+ _returningColumns = [];
1025
+ _hasWhereClause = false;
1026
+ _allowGlobal = false;
1027
+ mapReturningRows(rows) {
1028
+ const dbNameToTs = {};
1029
+ for (const [tsName, col] of Object.entries(this._table._.columns)) {
1030
+ dbNameToTs[col._.name] = tsName;
1031
+ }
1032
+ const norm = (k) => k.startsWith('"') && k.endsWith('"') ? k.slice(1, -1) : k;
1033
+ return rows.map((row) => {
1034
+ const out = {};
1035
+ for (const [dbKey, value] of Object.entries(row)) {
1036
+ const logicalKey = norm(dbKey);
1037
+ const tsName = dbNameToTs[logicalKey] ?? logicalKey;
1038
+ const column = this._table._.columns[tsName];
1039
+ out[tsName] = column ? deserializeValue(value, column) : value;
1040
+ }
1041
+ return out;
1042
+ });
1043
+ }
1085
1044
  where(condition) {
1086
- this.hasWhereClause = true;
1087
- return super.where(condition);
1045
+ this._hasWhereClause = true;
1046
+ this._builder = this._builder.where(condition);
1047
+ return this;
1088
1048
  }
1089
1049
  allowGlobalOperation() {
1090
- this.allowGlobal = true;
1050
+ this._allowGlobal = true;
1091
1051
  return this;
1092
1052
  }
1093
1053
  returning(...columns) {
1094
- this.returningColumns.push(...columns);
1054
+ this._returningColumns.push(...columns);
1095
1055
  return this;
1096
1056
  }
1097
1057
  async execute() {
1098
- if (!this.hasWhereClause && !this.allowGlobal) {
1099
- throw new MissingWhereClauseError("DELETE", this.table._.name);
1058
+ if (!this._hasWhereClause && !this._allowGlobal) {
1059
+ throw new MissingWhereClauseError("DELETE", this._table._.name);
1100
1060
  }
1101
- const { sql: sql2, params } = this.build();
1102
- if (this.returningColumns.length > 0) {
1103
- const returningNames = this.returningColumns.map((col) => this.table._.columns[col]._.name).join(", ");
1104
- const sqlWithReturning = `${sql2} RETURNING ${returningNames}`;
1105
- return this.db.select(sqlWithReturning, params);
1106
- } else {
1107
- const result = await this.db.execute(sql2, params);
1108
- return [{ rowsAffected: result.rowsAffected }];
1061
+ if (this._returningColumns.length > 0) {
1062
+ const cols = this._returningColumns.map(
1063
+ (k) => this._table._.columns[k]._.name
1064
+ );
1065
+ const rows = await this._builder.returning(cols).execute();
1066
+ return this.mapReturningRows(rows);
1109
1067
  }
1068
+ const result = await this._builder.executeTakeFirst();
1069
+ return [{ rowsAffected: Number(result?.numDeletedRows ?? 0) }];
1110
1070
  }
1111
1071
  async returningAll() {
1112
- const allColumns = Object.keys(this.table._.columns);
1113
- return this.returning(...allColumns).execute();
1072
+ const allCols = Object.keys(this._table._.columns);
1073
+ return this.returning(...allCols).execute();
1114
1074
  }
1115
1075
  async returningFirst() {
1116
- const allColumns = Object.keys(this.table._.columns);
1117
- const results = await this.returning(...allColumns).execute();
1076
+ const results = await this.returningAll();
1118
1077
  return results[0];
1119
1078
  }
1120
1079
  toSQL() {
1121
- const { sql: sql2, params } = this.build();
1122
- if (this.returningColumns.length > 0) {
1123
- const returningNames = this.returningColumns.map((col) => this.table._.columns[col]._.name).join(", ");
1124
- return {
1125
- sql: `${sql2} RETURNING ${returningNames}`,
1126
- params
1127
- };
1080
+ let builder = this._builder;
1081
+ if (this._returningColumns.length > 0) {
1082
+ builder = builder.returning(
1083
+ this._returningColumns.map((k) => this._table._.columns[k]._.name)
1084
+ );
1128
1085
  }
1129
- return { sql: sql2, params };
1086
+ const compiled = builder.compile();
1087
+ return { sql: compiled.sql, params: [...compiled.parameters] };
1130
1088
  }
1131
1089
  };
1132
1090
 
1133
1091
  // src/builders/with.ts
1134
1092
  var WithQueryBuilder = class {
1135
- constructor(db) {
1136
- this.db = db;
1093
+ constructor(kysely) {
1094
+ this.kysely = kysely;
1137
1095
  }
1138
- ctes = [];
1096
+ _ctes = [];
1139
1097
  with(alias2, query) {
1140
- this.ctes.push({ alias: alias2, query: query.sql, params: query.params });
1098
+ this._ctes.push({ alias: alias2, query: query.toKyselyExpression() });
1141
1099
  return this;
1142
1100
  }
1101
+ applyWith(builder) {
1102
+ let b = builder;
1103
+ for (const { alias: alias2, query } of this._ctes) {
1104
+ b = b.with(alias2, () => query);
1105
+ }
1106
+ return b;
1107
+ }
1143
1108
  select(table, columns) {
1144
- const builder = new SelectQueryBuilder(this.db, table, columns);
1145
- this.applyWithClause(builder);
1146
- return builder;
1109
+ return new SelectQueryBuilder(this.kysely, table, columns);
1147
1110
  }
1148
1111
  insert(table) {
1149
- const builder = new InsertQueryBuilder(this.db, table);
1150
- this.applyWithClause(builder);
1151
- return builder;
1112
+ return new InsertQueryBuilder(this.kysely, table);
1152
1113
  }
1153
1114
  update(table) {
1154
- const builder = new UpdateQueryBuilder(this.db, table);
1155
- this.applyWithClause(builder);
1156
- return builder;
1115
+ return new UpdateQueryBuilder(this.kysely, table);
1157
1116
  }
1158
1117
  delete(table) {
1159
- const builder = new DeleteQueryBuilder(this.db, table);
1160
- this.applyWithClause(builder);
1161
- return builder;
1162
- }
1163
- applyWithClause(builder) {
1164
- if (this.ctes.length > 0) {
1165
- const cteSql = this.ctes.map((cte) => `${cte.alias} AS (${cte.query})`).join(", ");
1166
- builder["query"] = `WITH ${cteSql} ${builder["query"]}`;
1167
- builder["params"] = [
1168
- ...this.ctes.flatMap((cte) => cte.params),
1169
- ...builder["params"]
1170
- ];
1171
- }
1118
+ return new DeleteQueryBuilder(this.kysely, table);
1172
1119
  }
1173
1120
  };
1174
1121
 
@@ -1211,7 +1158,7 @@ var SQLiteColumn = class _SQLiteColumn {
1211
1158
  unique() {
1212
1159
  return new _SQLiteColumn(this._.name, this.type, { ...this.options, unique: true, mode: this._.mode });
1213
1160
  }
1214
- references(ref, column) {
1161
+ references(ref, column, options) {
1215
1162
  const columnKey = typeof column === "string" ? column : column._.name;
1216
1163
  const columnObj = typeof column === "string" ? ref._.columns[column] : column;
1217
1164
  return new _SQLiteColumn(
@@ -1221,7 +1168,9 @@ var SQLiteColumn = class _SQLiteColumn {
1221
1168
  ...this.options,
1222
1169
  references: {
1223
1170
  table: ref,
1224
- column: columnObj
1171
+ column: columnObj,
1172
+ onDelete: options?.onDelete,
1173
+ onUpdate: options?.onUpdate
1225
1174
  },
1226
1175
  mode: this._.mode
1227
1176
  }
@@ -1250,39 +1199,14 @@ var Table = class {
1250
1199
  var sqliteTable = (tableName, columns) => {
1251
1200
  return new Table(tableName, columns);
1252
1201
  };
1253
- var asc = (column) => ({
1254
- sql: `${column._.name} ASC`,
1255
- params: []
1256
- });
1257
- var desc = (column) => ({
1258
- sql: `${column._.name} DESC`,
1259
- params: []
1260
- });
1261
- var sql = (strings, ...values) => {
1262
- const queryParts = [];
1263
- const params = [];
1264
- strings.forEach((str, i) => {
1265
- queryParts.push(str);
1266
- if (values[i] !== void 0) {
1267
- if (typeof values[i] === "object" && values[i].sql) {
1268
- queryParts.push(values[i].sql);
1269
- params.push(...values[i].params);
1270
- } else {
1271
- queryParts.push("?");
1272
- params.push(values[i]);
1273
- }
1274
- }
1275
- });
1276
- return {
1277
- sql: queryParts.join(""),
1278
- params
1279
- };
1280
- };
1202
+ var asc = (column) => kyselySql`${kyselySql.ref(column._.name)} ASC`;
1203
+ var desc = (column) => kyselySql`${kyselySql.ref(column._.name)} DESC`;
1281
1204
  var TauriORM = class {
1282
1205
  constructor(db, schema = void 0) {
1283
1206
  this.db = db;
1207
+ this.kysely = new Kysely4({ dialect: new TauriDialect(db) });
1284
1208
  if (schema) {
1285
- for (const [key, value] of Object.entries(schema)) {
1209
+ for (const [, value] of Object.entries(schema)) {
1286
1210
  if (value instanceof Table) {
1287
1211
  this.tables.set(value._.name, value);
1288
1212
  }
@@ -1290,24 +1214,31 @@ var TauriORM = class {
1290
1214
  }
1291
1215
  }
1292
1216
  tables = /* @__PURE__ */ new Map();
1217
+ kysely;
1293
1218
  buildColumnDefinition(col, forAlterTable = false) {
1294
- let sql2 = `${col._.name} ${col.type}`;
1219
+ let sql6 = `${col._.name} ${col.type}`;
1295
1220
  if (col.options.primaryKey && !forAlterTable) {
1296
- sql2 += " PRIMARY KEY";
1221
+ sql6 += " PRIMARY KEY";
1297
1222
  if (col._.autoincrement) {
1298
- sql2 += " AUTOINCREMENT";
1223
+ sql6 += " AUTOINCREMENT";
1299
1224
  }
1300
1225
  }
1301
- if (col._.notNull) sql2 += " NOT NULL";
1302
- if (col.options.unique) sql2 += " UNIQUE";
1226
+ if (col._.notNull) sql6 += " NOT NULL";
1227
+ if (col.options.unique) sql6 += " UNIQUE";
1303
1228
  if (col.options.default !== void 0) {
1304
1229
  const value = col.options.default;
1305
- sql2 += ` DEFAULT ${typeof value === "string" ? `'${value.replace(/'/g, "''")}'` : value}`;
1230
+ sql6 += ` DEFAULT ${typeof value === "string" ? `'${value.replace(/'/g, "''")}'` : value}`;
1306
1231
  }
1307
1232
  if (col.options.references) {
1308
- sql2 += ` REFERENCES ${col.options.references.table._.name}(${col.options.references.column._.name})`;
1233
+ sql6 += ` REFERENCES ${col.options.references.table._.name}(${col.options.references.column._.name})`;
1234
+ if (col.options.references.onDelete) {
1235
+ sql6 += ` ON DELETE ${col.options.references.onDelete.toUpperCase()}`;
1236
+ }
1237
+ if (col.options.references.onUpdate) {
1238
+ sql6 += ` ON UPDATE ${col.options.references.onUpdate.toUpperCase()}`;
1239
+ }
1309
1240
  }
1310
- return sql2;
1241
+ return sql6;
1311
1242
  }
1312
1243
  async checkMigration() {
1313
1244
  const dbTables = await this.db.select(
@@ -1349,15 +1280,16 @@ var TauriORM = class {
1349
1280
  const schemaColumns = table._.columns;
1350
1281
  let needsRecreate = false;
1351
1282
  for (const [colName, column] of Object.entries(schemaColumns)) {
1352
- const existing = existingColumns.get(colName);
1283
+ const dbColName = column._.name;
1284
+ const existing = existingColumns.get(dbColName);
1353
1285
  if (!existing) {
1354
1286
  if (!this.canAddColumnWithAlter(column)) {
1355
1287
  needsRecreate = true;
1356
1288
  break;
1357
1289
  }
1358
- changes.columnsToAdd.push({ table: tableName, column: colName });
1290
+ changes.columnsToAdd.push({ table: tableName, column: dbColName });
1359
1291
  } else {
1360
- const hasUniqueInDB = uniqueColumns.has(colName);
1292
+ const hasUniqueInDB = uniqueColumns.has(dbColName);
1361
1293
  const wantsUnique = !!column.options.unique;
1362
1294
  if (hasUniqueInDB !== wantsUnique || this.hasColumnDefinitionChanged(column, existing)) {
1363
1295
  needsRecreate = true;
@@ -1366,7 +1298,8 @@ var TauriORM = class {
1366
1298
  }
1367
1299
  }
1368
1300
  for (const existingCol of existingColumns.keys()) {
1369
- if (!schemaColumns[existingCol]) {
1301
+ const schemaHasCol = Object.values(schemaColumns).some((c) => c._.name === existingCol);
1302
+ if (!schemaHasCol) {
1370
1303
  needsRecreate = true;
1371
1304
  break;
1372
1305
  }
@@ -1418,7 +1351,8 @@ var TauriORM = class {
1418
1351
  let needsRecreate = false;
1419
1352
  const columnsToAdd = [];
1420
1353
  for (const [colName, column] of Object.entries(schemaColumns)) {
1421
- const existing = existingColumns.get(colName);
1354
+ const dbColName = column._.name;
1355
+ const existing = existingColumns.get(dbColName);
1422
1356
  if (!existing) {
1423
1357
  if (this.canAddColumnWithAlter(column)) {
1424
1358
  columnsToAdd.push(column);
@@ -1427,7 +1361,7 @@ var TauriORM = class {
1427
1361
  break;
1428
1362
  }
1429
1363
  } else {
1430
- const hasUniqueInDB = uniqueColumns.has(colName);
1364
+ const hasUniqueInDB = uniqueColumns.has(dbColName);
1431
1365
  const wantsUnique = !!column.options.unique;
1432
1366
  if (hasUniqueInDB !== wantsUnique) {
1433
1367
  needsRecreate = true;
@@ -1441,7 +1375,8 @@ var TauriORM = class {
1441
1375
  }
1442
1376
  if (options?.performDestructiveActions) {
1443
1377
  for (const existingCol of existingColumns.keys()) {
1444
- if (!schemaColumns[existingCol]) {
1378
+ const schemaHasCol = Object.values(schemaColumns).some((c) => c._.name === existingCol);
1379
+ if (!schemaHasCol) {
1445
1380
  needsRecreate = true;
1446
1381
  break;
1447
1382
  }
@@ -1486,7 +1421,7 @@ var TauriORM = class {
1486
1421
  await this.db.execute(`CREATE TABLE ${tempTableName} (${columnsSql})`);
1487
1422
  const oldColumns = await this.db.select(`PRAGMA table_info('${tableName}')`);
1488
1423
  const oldColumnNames = oldColumns.map((c) => c.name);
1489
- const newColumnNames = Object.keys(table._.columns);
1424
+ const newColumnNames = Object.values(table._.columns).map((c) => c._.name);
1490
1425
  const commonColumns = oldColumnNames.filter((name) => newColumnNames.includes(name));
1491
1426
  if (commonColumns.length > 0) {
1492
1427
  const columnsList = commonColumns.join(", ");
@@ -1503,18 +1438,18 @@ var TauriORM = class {
1503
1438
  console.warn(
1504
1439
  `[Tauri-ORM] Table "${table._.name}" was not passed in the schema to the ORM constructor. Relations will not be available.`
1505
1440
  );
1506
- return new SelectQueryBuilder(this.db, table, columns);
1441
+ return new SelectQueryBuilder(this.kysely, table, columns);
1507
1442
  }
1508
- return new SelectQueryBuilder(this.db, internalTable, columns);
1443
+ return new SelectQueryBuilder(this.kysely, internalTable, columns);
1509
1444
  }
1510
1445
  insert(table) {
1511
- return new InsertQueryBuilder(this.db, table);
1446
+ return new InsertQueryBuilder(this.kysely, table);
1512
1447
  }
1513
1448
  update(table) {
1514
- return new UpdateQueryBuilder(this.db, table);
1449
+ return new UpdateQueryBuilder(this.kysely, table);
1515
1450
  }
1516
1451
  delete(table) {
1517
- return new DeleteQueryBuilder(this.db, table);
1452
+ return new DeleteQueryBuilder(this.kysely, table);
1518
1453
  }
1519
1454
  async upsert(table, data, conflictTarget) {
1520
1455
  const columns = conflictTarget.map((col) => table._.columns[col]);
@@ -1524,7 +1459,7 @@ var TauriORM = class {
1524
1459
  }).execute();
1525
1460
  }
1526
1461
  $with(alias2) {
1527
- const withBuilder = new WithQueryBuilder(this.db);
1462
+ const withBuilder = new WithQueryBuilder(this.kysely);
1528
1463
  return {
1529
1464
  as: (query) => {
1530
1465
  withBuilder.with(alias2, query);
@@ -1533,14 +1468,14 @@ var TauriORM = class {
1533
1468
  };
1534
1469
  }
1535
1470
  async transaction(callback) {
1536
- await this.db.execute("BEGIN TRANSACTION");
1471
+ await this.db.execute("BEGIN");
1537
1472
  try {
1538
1473
  const result = await callback(this);
1539
1474
  await this.db.execute("COMMIT");
1540
1475
  return result;
1541
- } catch (error) {
1476
+ } catch (e) {
1542
1477
  await this.db.execute("ROLLBACK");
1543
- throw error;
1478
+ throw e;
1544
1479
  }
1545
1480
  }
1546
1481
  rollback() {
@@ -1592,7 +1527,9 @@ var TauriORM = class {
1592
1527
  unique: !!col.options.unique,
1593
1528
  dv: col.options.default && typeof col.options.default === "object" && col.options.default.raw ? { raw: col.options.default.raw } : col.options.default ?? null,
1594
1529
  hasDefaultFn: col.options.$defaultFn !== void 0,
1595
- hasOnUpdateFn: col.options.$onUpdateFn !== void 0
1530
+ hasOnUpdateFn: col.options.$onUpdateFn !== void 0,
1531
+ onDelete: col.options.references?.onDelete ?? null,
1532
+ onUpdate: col.options.references?.onUpdate ?? null
1596
1533
  };
1597
1534
  }
1598
1535
  computeModelSignature() {
@@ -1656,11 +1593,6 @@ var OneRelation = class extends Relation {
1656
1593
  }
1657
1594
  };
1658
1595
  var ManyRelation = class extends Relation {
1659
- constructor(foreignTable) {
1660
- super(foreignTable);
1661
- }
1662
- };
1663
- var ManyToManyRelation = class extends Relation {
1664
1596
  constructor(foreignTable, config) {
1665
1597
  super(foreignTable);
1666
1598
  this.config = config;
@@ -1673,9 +1605,6 @@ var relations = (table, relationsCallback) => {
1673
1605
  },
1674
1606
  many: (foreignTable) => {
1675
1607
  return new ManyRelation(foreignTable);
1676
- },
1677
- manyToMany: (foreignTable, config) => {
1678
- return new ManyToManyRelation(foreignTable, config);
1679
1608
  }
1680
1609
  });
1681
1610
  for (const [name, relation] of Object.entries(builtRelations)) {
@@ -1684,21 +1613,15 @@ var relations = (table, relationsCallback) => {
1684
1613
  type: "one",
1685
1614
  foreignTable: relation.foreignTable,
1686
1615
  fields: relation.config?.fields,
1687
- references: relation.config?.references
1616
+ references: relation.config?.references,
1617
+ optional: relation.config?.optional,
1618
+ alias: relation.config?.alias
1688
1619
  };
1689
1620
  } else if (relation instanceof ManyRelation) {
1690
1621
  table.relations[name] = {
1691
1622
  type: "many",
1692
1623
  foreignTable: relation.foreignTable
1693
1624
  };
1694
- } else if (relation instanceof ManyToManyRelation) {
1695
- table.relations[name] = {
1696
- type: "manyToMany",
1697
- foreignTable: relation.foreignTable,
1698
- junctionTable: relation.config.junctionTable,
1699
- junctionFields: relation.config.junctionFields,
1700
- junctionReferences: relation.config.junctionReferences
1701
- };
1702
1625
  }
1703
1626
  }
1704
1627
  return builtRelations;
@@ -1711,50 +1634,22 @@ var alias = (table, alias2) => {
1711
1634
  };
1712
1635
 
1713
1636
  // src/aggregates.ts
1714
- var count = (column) => ({
1715
- sql: `COUNT(${column ? column._.name : "*"})`,
1716
- params: []
1717
- });
1718
- var countDistinct = (column) => ({
1719
- sql: `COUNT(DISTINCT ${column._.name})`,
1720
- params: []
1721
- });
1722
- var sum = (column) => ({
1723
- sql: `SUM(${column._.name})`,
1724
- params: []
1725
- });
1726
- var avg = (column) => ({
1727
- sql: `AVG(${column._.name})`,
1728
- params: []
1729
- });
1730
- var max = (column) => ({
1731
- sql: `MAX(${column._.name})`,
1732
- params: []
1733
- });
1734
- var min = (column) => ({
1735
- sql: `MIN(${column._.name})`,
1736
- params: []
1737
- });
1738
- var groupConcat = (column, separator = ",") => ({
1739
- sql: `GROUP_CONCAT(${column._.name}, ?)`,
1740
- params: [separator]
1741
- });
1742
- var as = (aggregate, alias2) => ({
1743
- ...aggregate,
1744
- alias: alias2
1745
- });
1637
+ import { sql as sql4 } from "kysely";
1638
+ var count = (column) => sql4`COUNT(${column ? sql4.ref(column._.name) : sql4.raw("*")})`;
1639
+ var countDistinct = (column) => sql4`COUNT(DISTINCT ${sql4.ref(column._.name)})`;
1640
+ var sum = (column) => sql4`SUM(${sql4.ref(column._.name)})`;
1641
+ var avg = (column) => sql4`AVG(${sql4.ref(column._.name)})`;
1642
+ var max = (column) => sql4`MAX(${sql4.ref(column._.name)})`;
1643
+ var min = (column) => sql4`MIN(${sql4.ref(column._.name)})`;
1644
+ var groupConcat = (column, separator = ",") => sql4`GROUP_CONCAT(${sql4.ref(column._.name)}, ${sql4.val(separator)})`;
1645
+ var as = (aggregate, alias2) => Object.assign(aggregate, { alias: alias2 });
1746
1646
 
1747
1647
  // src/subquery.ts
1748
1648
  var subquery = (query) => {
1749
- const { sql: sql2, params } = query.toSQL();
1750
- return {
1751
- sql: `(${sql2})`,
1752
- params,
1753
- _isSubquery: true
1754
- };
1649
+ return query.toKyselyExpression();
1755
1650
  };
1756
1651
  var scalarSubquery = (query) => {
1757
- return subquery(query);
1652
+ return query.toKyselyExpression();
1758
1653
  };
1759
1654
 
1760
1655
  // src/column-helpers.ts
@@ -1773,14 +1668,135 @@ function numeric(name, config) {
1773
1668
  return new SQLiteColumn(name, "NUMERIC", config);
1774
1669
  }
1775
1670
  var enumType = (name, values) => text(name, { enum: values });
1671
+
1672
+ // src/relations-v2.ts
1673
+ function extractTables(schema) {
1674
+ const tables = {};
1675
+ for (const [key, value] of Object.entries(schema)) {
1676
+ const v = value;
1677
+ if (v && typeof v === "object" && v._?.name && v._?.columns && typeof v.relations === "object") {
1678
+ tables[key] = v;
1679
+ }
1680
+ }
1681
+ return tables;
1682
+ }
1683
+ function through(column, junctionColumn, junctionTable) {
1684
+ return { column, junctionColumn, junctionTable };
1685
+ }
1686
+ function toArray(col) {
1687
+ return Array.isArray(col) ? col : [col];
1688
+ }
1689
+ function isThroughRef(v) {
1690
+ return v && typeof v === "object" && "column" in v && "junctionColumn" in v && "junctionTable" in v;
1691
+ }
1692
+ function buildTableRef(table) {
1693
+ return { ...table._.columns };
1694
+ }
1695
+ function buildR(tables) {
1696
+ const tableRefs = {};
1697
+ const oneFns = {};
1698
+ const manyFns = {};
1699
+ for (const [tableKey, table] of Object.entries(tables)) {
1700
+ tableRefs[tableKey] = buildTableRef(table);
1701
+ const foreignTable = table;
1702
+ oneFns[tableKey] = (opts) => {
1703
+ return new OneRelation(foreignTable, {
1704
+ fields: toArray(opts.from),
1705
+ references: toArray(opts.to),
1706
+ optional: opts.optional,
1707
+ alias: opts.alias
1708
+ });
1709
+ };
1710
+ manyFns[tableKey] = (opts) => {
1711
+ if (!opts?.from || !opts?.to) return new ManyRelation(foreignTable);
1712
+ if (isThroughRef(opts.from) && isThroughRef(opts.to)) {
1713
+ return new ManyRelation(foreignTable, {
1714
+ through: {
1715
+ junctionTable: opts.from.junctionTable,
1716
+ fromRef: { column: opts.from.column, junctionColumn: opts.from.junctionColumn },
1717
+ toRef: { column: opts.to.column, junctionColumn: opts.to.junctionColumn }
1718
+ },
1719
+ optional: opts.optional,
1720
+ alias: opts.alias,
1721
+ where: opts.where
1722
+ });
1723
+ }
1724
+ return new ManyRelation(foreignTable, {
1725
+ from: toArray(opts.from),
1726
+ to: toArray(opts.to),
1727
+ optional: opts.optional,
1728
+ alias: opts.alias,
1729
+ where: opts.where
1730
+ });
1731
+ };
1732
+ }
1733
+ return {
1734
+ ...tableRefs,
1735
+ one: oneFns,
1736
+ many: manyFns
1737
+ };
1738
+ }
1739
+ function applyRelationsToTables(tables, relationsResult) {
1740
+ for (const [tableKey, rels] of Object.entries(relationsResult)) {
1741
+ const table = tables[tableKey];
1742
+ if (!table) continue;
1743
+ for (const [relName, relation] of Object.entries(rels)) {
1744
+ if (relation instanceof OneRelation) {
1745
+ table.relations[relName] = {
1746
+ type: "one",
1747
+ foreignTable: relation.foreignTable,
1748
+ fields: relation.config?.fields,
1749
+ references: relation.config?.references,
1750
+ optional: relation.config?.optional,
1751
+ alias: relation.config?.alias
1752
+ };
1753
+ } else if (relation instanceof ManyRelation) {
1754
+ const config = relation.config;
1755
+ if (config?.through) {
1756
+ table.relations[relName] = {
1757
+ type: "many",
1758
+ foreignTable: relation.foreignTable,
1759
+ junctionTable: config.through.junctionTable,
1760
+ fromJunction: config.through.fromRef,
1761
+ toJunction: config.through.toRef,
1762
+ optional: config.optional,
1763
+ alias: config.alias,
1764
+ where: config.where
1765
+ };
1766
+ } else {
1767
+ table.relations[relName] = {
1768
+ type: "many",
1769
+ foreignTable: relation.foreignTable,
1770
+ fields: config ? config.to : void 0,
1771
+ references: config ? config.from : void 0,
1772
+ optional: config?.optional,
1773
+ alias: config?.alias,
1774
+ where: config?.where
1775
+ };
1776
+ }
1777
+ }
1778
+ }
1779
+ }
1780
+ }
1781
+ function defineRelations(schema, callback) {
1782
+ const tables = extractTables(schema);
1783
+ const r = buildR(tables);
1784
+ const result = callback(r);
1785
+ applyRelationsToTables(tables, result);
1786
+ return result;
1787
+ }
1788
+ function defineRelationsPart(schema, callback) {
1789
+ return defineRelations(schema, callback);
1790
+ }
1791
+
1792
+ // src/index.ts
1793
+ import { sql as sql5 } from "kysely";
1776
1794
  export {
1777
- BaseQueryBuilder,
1778
1795
  ColumnNotFoundError,
1779
1796
  DeleteQueryBuilder,
1780
1797
  InsertQueryBuilder,
1781
1798
  InsertValidationError,
1782
1799
  ManyRelation,
1783
- ManyToManyRelation,
1784
1800
  MigrationError,
1785
1801
  MissingWhereClauseError,
1786
1802
  OneRelation,
@@ -1791,6 +1807,7 @@ export {
1791
1807
  SelectQueryBuilder,
1792
1808
  Table,
1793
1809
  TableNotFoundError,
1810
+ TauriDialect,
1794
1811
  TauriORM,
1795
1812
  TauriORMError,
1796
1813
  UpdateQueryBuilder,
@@ -1808,6 +1825,8 @@ export {
1808
1825
  contains,
1809
1826
  count,
1810
1827
  countDistinct,
1828
+ defineRelations,
1829
+ defineRelationsPart,
1811
1830
  desc,
1812
1831
  endsWith,
1813
1832
  enumType,
@@ -1842,10 +1861,11 @@ export {
1842
1861
  real,
1843
1862
  relations,
1844
1863
  scalarSubquery,
1845
- sql,
1864
+ sql5 as sql,
1846
1865
  sqliteTable,
1847
1866
  startsWith,
1848
1867
  subquery,
1849
1868
  sum,
1850
- text
1869
+ text,
1870
+ through
1851
1871
  };