@type32/tauri-sqlite-orm 0.1.18-9 → 0.1.20

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.js CHANGED
@@ -27,7 +27,6 @@ __export(index_exports, {
27
27
  OneRelation: () => OneRelation,
28
28
  Relation: () => Relation,
29
29
  SQLiteColumn: () => SQLiteColumn,
30
- SelectBuilder: () => SelectBuilder,
31
30
  SelectQueryBuilder: () => SelectQueryBuilder,
32
31
  Table: () => Table,
33
32
  TauriORM: () => TauriORM,
@@ -42,6 +41,7 @@ __export(index_exports, {
42
41
  count: () => count,
43
42
  countDistinct: () => countDistinct,
44
43
  desc: () => desc,
44
+ enumType: () => enumType,
45
45
  eq: () => eq,
46
46
  getTableColumns: () => getTableColumns,
47
47
  gt: () => gt,
@@ -56,6 +56,7 @@ __export(index_exports, {
56
56
  max: () => max,
57
57
  min: () => min,
58
58
  not: () => not,
59
+ numeric: () => numeric,
59
60
  or: () => or,
60
61
  real: () => real,
61
62
  relations: () => relations,
@@ -66,129 +67,51 @@ __export(index_exports, {
66
67
  });
67
68
  module.exports = __toCommonJS(index_exports);
68
69
 
69
- // src/schema.ts
70
- var SQLiteColumn = class _SQLiteColumn {
71
- constructor(name, type, options = {}, mode) {
72
- this.type = type;
73
- this.options = options;
74
- this._ = {
75
- name,
76
- dataType: type,
77
- mode: mode || "default",
78
- notNull: options.notNull ?? false,
79
- hasDefault: options.default !== void 0 || options.$defaultFn !== void 0,
80
- autoincrement: options.autoincrement ?? false,
81
- table: void 0
82
- };
83
- }
84
- _;
85
- notNull() {
86
- return new _SQLiteColumn(
87
- this._.name,
88
- this.type,
89
- { ...this.options, notNull: true },
90
- this._.mode
91
- );
92
- }
93
- default(value) {
94
- return new _SQLiteColumn(
95
- this._.name,
96
- this.type,
97
- { ...this.options, default: value },
98
- this._.mode
99
- );
100
- }
101
- $defaultFn(fn) {
102
- return new _SQLiteColumn(
103
- this._.name,
104
- this.type,
105
- { ...this.options, $defaultFn: fn },
106
- this._.mode
107
- );
108
- }
109
- primaryKey() {
110
- return new _SQLiteColumn(
111
- this._.name,
112
- this.type,
113
- { ...this.options, primaryKey: true, notNull: true },
114
- this._.mode
115
- );
116
- }
117
- autoincrement() {
118
- return new _SQLiteColumn(
119
- this._.name,
120
- this.type,
121
- { ...this.options, autoincrement: true },
122
- this._.mode
123
- );
70
+ // src/builders/query-base.ts
71
+ var BaseQueryBuilder = class {
72
+ constructor(db) {
73
+ this.db = db;
124
74
  }
125
- unique() {
126
- return new _SQLiteColumn(
127
- this._.name,
128
- this.type,
129
- { ...this.options, unique: true },
130
- this._.mode
131
- );
75
+ query = "";
76
+ params = [];
77
+ where(condition) {
78
+ this.query += ` WHERE ${condition.sql}`;
79
+ this.params.push(...condition.params);
80
+ return this;
132
81
  }
133
- references(ref, column) {
134
- return new _SQLiteColumn(
135
- this._.name,
136
- this.type,
137
- {
138
- ...this.options,
139
- references: {
140
- table: ref,
141
- column: ref._.columns[column]
142
- }
143
- },
144
- this._.mode
145
- );
82
+ orderBy(column, direction = "ASC") {
83
+ if ("sql" in column) {
84
+ this.query += ` ORDER BY ${column.sql} ${direction}`;
85
+ this.params.push(...column.params);
86
+ } else {
87
+ this.query += ` ORDER BY ${column._.name} ${direction}`;
88
+ }
89
+ return this;
146
90
  }
147
- $onUpdateFn(fn) {
148
- return new _SQLiteColumn(
149
- this._.name,
150
- this.type,
151
- { ...this.options, $onUpdateFn: fn },
152
- this._.mode
153
- );
91
+ limit(count2) {
92
+ this.query += ` LIMIT ${count2}`;
93
+ return this;
154
94
  }
155
- as(alias2) {
95
+ offset(count2) {
96
+ this.query += ` OFFSET ${count2}`;
156
97
  return this;
157
98
  }
158
- };
159
- var text = (name) => new SQLiteColumn(name, "TEXT");
160
- var integer = (name, config) => new SQLiteColumn(name, "INTEGER", {}, config?.mode || "default");
161
- var real = (name) => new SQLiteColumn(name, "REAL");
162
- var blob = (name) => new SQLiteColumn(name, "BLOB");
163
- var boolean = (name) => new SQLiteColumn(name, "BOOLEAN");
164
- var Table = class {
165
- _;
166
- constructor(name, columns) {
167
- this._ = {
168
- name,
169
- columns
99
+ build() {
100
+ return {
101
+ sql: this.query,
102
+ params: this.params
170
103
  };
171
104
  }
172
105
  };
173
- var sqliteTable = (tableName, columns) => {
174
- const table = new Table(tableName, columns);
175
- for (const col of Object.values(columns)) {
176
- col._.table = table;
177
- }
178
- return table;
179
- };
180
- var getTableColumns = (table) => {
181
- return table._.columns;
182
- };
183
- var alias = (table, alias2) => {
184
- return table;
185
- };
186
106
 
187
- // src/query-builder.ts
188
- var eq = (column, value) => ({
189
- sql: `${column._.name} = ?`,
190
- params: [value]
191
- });
107
+ // src/operators.ts
108
+ var eq = (column, value, tableAlias) => {
109
+ const columnName = tableAlias ? `${tableAlias}.${column._.name}` : column._.name;
110
+ return {
111
+ sql: `${columnName} = ?`,
112
+ params: [value]
113
+ };
114
+ };
192
115
  var and = (...conditions) => ({
193
116
  sql: conditions.map((c) => `(${c.sql})`).join(" AND "),
194
117
  params: conditions.flatMap((c) => c.params)
@@ -233,14 +156,6 @@ var inArray = (column, values) => ({
233
156
  sql: `${column._.name} IN (${values.map(() => "?").join(",")})`,
234
157
  params: values
235
158
  });
236
- var asc = (column) => ({
237
- sql: `${column._.name} ASC`,
238
- params: []
239
- });
240
- var desc = (column) => ({
241
- sql: `${column._.name} DESC`,
242
- params: []
243
- });
244
159
  var count = (column) => ({
245
160
  sql: `COUNT(${column ? column._.name : "*"})`,
246
161
  params: []
@@ -265,170 +180,206 @@ var min = (column) => ({
265
180
  sql: `MIN(${column._.name})`,
266
181
  params: []
267
182
  });
268
- var sql = (strings, ...values) => {
269
- const queryParts = [];
270
- const params = [];
271
- strings.forEach((str, i) => {
272
- queryParts.push(str);
273
- if (values[i] !== void 0) {
274
- if (typeof values[i] === "object" && values[i].sql) {
275
- queryParts.push(values[i].sql);
276
- params.push(...values[i].params);
277
- } else {
278
- queryParts.push("?");
279
- params.push(values[i]);
280
- }
281
- }
282
- });
283
- return {
284
- sql: queryParts.join(""),
285
- params
286
- };
287
- };
288
- var BaseQueryBuilder = class {
289
- constructor(db) {
290
- this.db = db;
291
- }
292
- query = "";
293
- params = [];
294
- build() {
295
- return {
296
- sql: this.query,
297
- params: this.params
298
- };
299
- }
300
- };
183
+
184
+ // src/builders/select.ts
301
185
  var SelectQueryBuilder = class extends BaseQueryBuilder {
302
- constructor(db, table, selection) {
186
+ constructor(db, table, columns) {
303
187
  super(db);
304
- this.selection = selection;
305
- this.fromTable = table;
306
- this.query = "";
307
- this.params = [];
188
+ this.table = table;
189
+ this.columns = columns;
190
+ this.selectedTableAlias = table._.name;
191
+ const selected = columns ? columns.map((c) => this.table._.columns[c]) : Object.values(this.table._.columns);
192
+ this.selectedColumns = selected.map(
193
+ (col) => `${this.selectedTableAlias}.${col._.name} AS "${this.selectedTableAlias}.${col._.name}"`
194
+ );
195
+ this.query = `FROM ${table._.name} ${this.selectedTableAlias}`;
308
196
  }
309
197
  isDistinct = false;
310
198
  groupByColumns = [];
311
- havingCondition;
312
- joinClauses = [];
313
- fromTable;
314
- orderByClauses = [];
315
- limitCount;
316
- offsetCount;
317
- whereCondition;
318
- where(condition) {
319
- this.whereCondition = condition;
320
- return this;
321
- }
322
- leftJoin(table, on) {
323
- this.joinClauses.push({ type: "LEFT JOIN", table, on });
324
- return this;
325
- }
326
- innerJoin(table, on) {
327
- this.joinClauses.push({ type: "INNER JOIN", table, on });
328
- return this;
329
- }
330
- rightJoin(table, on) {
331
- this.joinClauses.push({ type: "RIGHT JOIN", table, on });
332
- return this;
333
- }
334
- fullJoin(table, on) {
335
- this.joinClauses.push({ type: "FULL JOIN", table, on });
336
- return this;
337
- }
199
+ havingCondition = null;
200
+ joins = [];
201
+ includeRelations = {};
202
+ selectedTableAlias;
203
+ selectedColumns = [];
338
204
  distinct() {
339
205
  this.isDistinct = true;
340
206
  return this;
341
207
  }
342
208
  groupBy(...columns) {
343
209
  this.groupByColumns.push(...columns);
210
+ const columnNames = columns.map((col) => `${this.selectedTableAlias}.${col._.name}`).join(", ");
211
+ this.query += ` GROUP BY ${columnNames}`;
344
212
  return this;
345
213
  }
346
214
  having(condition) {
347
215
  this.havingCondition = condition;
216
+ this.query += ` HAVING ${condition.sql}`;
217
+ this.params.push(...condition.params);
348
218
  return this;
349
219
  }
350
- orderBy(column, direction = "ASC") {
351
- if ("sql" in column) {
352
- this.orderByClauses.push({
353
- sql: `${column.sql} ${direction}`,
354
- params: column.params
355
- });
356
- } else {
357
- this.orderByClauses.push({
358
- sql: `${column._.name} ${direction}`,
359
- params: []
360
- });
361
- }
220
+ leftJoin(table, condition, alias2) {
221
+ this.joins.push({ type: "LEFT", table, condition, alias: alias2 });
222
+ const aliasedColumns = Object.values(table._.columns).map(
223
+ (col) => `${alias2}.${col._.name} AS "${alias2}.${col._.name}"`
224
+ );
225
+ this.selectedColumns.push(...aliasedColumns);
362
226
  return this;
363
227
  }
364
- limit(count2) {
365
- this.limitCount = count2;
228
+ innerJoin(table, condition, alias2) {
229
+ this.joins.push({ type: "INNER", table, condition, alias: alias2 });
230
+ const aliasedColumns = Object.values(table._.columns).map(
231
+ (col) => `${alias2}.${col._.name} AS "${alias2}.${col._.name}"`
232
+ );
233
+ this.selectedColumns.push(...aliasedColumns);
366
234
  return this;
367
235
  }
368
- offset(count2) {
369
- this.offsetCount = count2;
236
+ include(relations2) {
237
+ this.includeRelations = { ...this.includeRelations, ...relations2 };
370
238
  return this;
371
239
  }
372
- buildSelectQuery() {
373
- const selectionEntries = this.selection ? Object.entries(this.selection) : [];
374
- let columnsClause;
375
- const selectParams = [];
376
- if (selectionEntries.length === 0) {
377
- columnsClause = "*";
378
- } else {
379
- columnsClause = selectionEntries.map(([alias2, col]) => {
380
- if (col instanceof SQLiteColumn) {
381
- return `${col._.table._.name}.${col._.name} AS "${alias2}"`;
382
- } else {
383
- selectParams.push(...col.params);
384
- return `(${col.sql}) AS "${alias2}"`;
385
- }
386
- }).join(", ");
387
- }
388
- let query = `SELECT ${this.isDistinct ? "DISTINCT " : ""}${columnsClause} FROM ${this.fromTable._.name}`;
389
- const queryParams = [...selectParams];
390
- if (this.joinClauses.length > 0) {
391
- const joins = this.joinClauses.map((j) => {
392
- queryParams.push(...j.on.params);
393
- return `${j.type} ${j.table._.name} ON ${j.on.sql}`;
394
- });
395
- query += ` ${joins.join(" ")}`;
240
+ buildJoins() {
241
+ let sql2 = "";
242
+ const params = [];
243
+ for (const join of this.joins) {
244
+ sql2 += ` ${join.type} JOIN ${join.table._.name} ${join.alias} ON ${join.condition.sql}`;
245
+ params.push(...join.condition.params);
396
246
  }
397
- if (this.whereCondition) {
398
- query += ` WHERE ${this.whereCondition.sql}`;
399
- queryParams.push(...this.whereCondition.params);
400
- }
401
- if (this.groupByColumns.length > 0) {
402
- const columnNames = this.groupByColumns.map((c) => c._.name).join(", ");
403
- query += ` GROUP BY ${columnNames}`;
247
+ for (const [relationName, include] of Object.entries(this.includeRelations)) {
248
+ if (!include) continue;
249
+ const relation = this.table.relations[relationName];
250
+ if (!relation) {
251
+ console.warn(
252
+ `[Tauri-ORM] Relation "${relationName}" not found on table "${this.table._.name}". Skipping include.`
253
+ );
254
+ continue;
255
+ }
256
+ const foreignTable = relation.foreignTable;
257
+ const foreignAlias = `${this.selectedTableAlias}_${relationName}`;
258
+ const aliasedColumns = Object.values(foreignTable._.columns).map(
259
+ (col) => `${foreignAlias}.${col._.name} AS "${foreignAlias}.${col._.name}"`
260
+ );
261
+ this.selectedColumns.push(...aliasedColumns);
262
+ if (relation.type === "one" && relation.fields && relation.references) {
263
+ const conditions = relation.fields.map((field, i) => {
264
+ const localColumn = `${this.selectedTableAlias}.${field._.name}`;
265
+ const foreignColumn = `${foreignAlias}.${relation.references[i]._.name}`;
266
+ return {
267
+ sql: `${localColumn} = ${foreignColumn}`,
268
+ params: []
269
+ };
270
+ });
271
+ const condition = conditions.length > 1 ? and(...conditions) : conditions[0];
272
+ sql2 += ` LEFT JOIN ${foreignTable._.name} ${foreignAlias} ON ${condition.sql}`;
273
+ params.push(...condition.params);
274
+ } else if (relation.type === "many") {
275
+ const refRelation = Object.entries(foreignTable.relations).find(
276
+ ([_, r]) => r.foreignTable === this.table
277
+ );
278
+ if (refRelation && refRelation[1].fields && refRelation[1].references) {
279
+ const [_, relationConfig] = refRelation;
280
+ const conditions = relationConfig.fields.map((field, i) => {
281
+ const localColumn = `${foreignAlias}.${field._.name}`;
282
+ const foreignColumn = `${this.selectedTableAlias}.${relationConfig.references[i]._.name}`;
283
+ return {
284
+ sql: `${localColumn} = ${foreignColumn}`,
285
+ params: []
286
+ };
287
+ });
288
+ const condition = conditions.length > 1 ? and(...conditions) : conditions[0];
289
+ sql2 += ` LEFT JOIN ${foreignTable._.name} ${foreignAlias} ON ${condition.sql}`;
290
+ params.push(...condition.params);
291
+ }
292
+ }
404
293
  }
405
- if (this.havingCondition) {
406
- query += ` HAVING ${this.havingCondition.sql}`;
407
- queryParams.push(...this.havingCondition.params);
294
+ return { sql: sql2, params };
295
+ }
296
+ // Enhanced execute method that handles relation data mapping
297
+ async execute() {
298
+ const { sql: joinSql, params: joinParams } = this.buildJoins();
299
+ const distinct = this.isDistinct ? "DISTINCT " : "";
300
+ this.query = `SELECT ${distinct}${this.selectedColumns.join(", ")} ${this.query}`;
301
+ this.query += joinSql;
302
+ this.params.push(...joinParams);
303
+ const { sql: sql2, params } = this.build();
304
+ console.log("Executing SQL:", sql2, "with params:", params);
305
+ const rawResults = await this.db.select(sql2, params);
306
+ const hasIncludes = Object.values(this.includeRelations).some((i) => i);
307
+ if (hasIncludes) {
308
+ return this.processRelationResults(rawResults);
408
309
  }
409
- if (this.orderByClauses.length > 0) {
410
- const orderBySql = this.orderByClauses.map((c) => c.sql).join(", ");
411
- query += ` ORDER BY ${orderBySql}`;
412
- queryParams.push(...this.orderByClauses.flatMap((c) => c.params));
310
+ const hasJoins = this.joins.length > 0;
311
+ if (hasJoins) {
312
+ return rawResults;
413
313
  }
414
- if (this.limitCount !== void 0) {
415
- query += ` LIMIT ${this.limitCount}`;
314
+ const prefix = `${this.selectedTableAlias}.`;
315
+ return rawResults.map((row) => {
316
+ const newRow = {};
317
+ for (const key in row) {
318
+ if (key.startsWith(prefix)) {
319
+ newRow[key.substring(prefix.length)] = row[key];
320
+ } else {
321
+ newRow[key] = row[key];
322
+ }
323
+ }
324
+ return newRow;
325
+ });
326
+ }
327
+ processRelationResults(rawResults) {
328
+ if (!rawResults.length) return [];
329
+ const mainTablePks = Object.values(this.table._.columns).filter((c) => c.options.primaryKey).map((c) => c._.name);
330
+ if (mainTablePks.length === 0) {
331
+ return rawResults;
416
332
  }
417
- if (this.offsetCount !== void 0) {
418
- query += ` OFFSET ${this.offsetCount}`;
333
+ const groupedResults = /* @__PURE__ */ new Map();
334
+ for (const row of rawResults) {
335
+ const mainTableKey = mainTablePks.map((pk) => row[`${this.selectedTableAlias}.${pk}`] ?? row[pk]).join("_");
336
+ if (!groupedResults.has(mainTableKey)) {
337
+ groupedResults.set(mainTableKey, {});
338
+ }
339
+ const result = groupedResults.get(mainTableKey);
340
+ const relations2 = {};
341
+ for (const [key, value] of Object.entries(row)) {
342
+ if (key.includes(".")) {
343
+ const [tableAlias, columnName] = key.split(".");
344
+ if (tableAlias === this.selectedTableAlias) {
345
+ result[columnName] = value;
346
+ } else {
347
+ const parts = tableAlias.split("_");
348
+ if (parts.length >= 2 && parts[0] === this.selectedTableAlias) {
349
+ const relationName = parts.slice(1).join("_");
350
+ if (!relations2[relationName]) relations2[relationName] = {};
351
+ relations2[relationName][columnName] = value;
352
+ } else {
353
+ if (!result[tableAlias]) result[tableAlias] = {};
354
+ result[tableAlias][columnName] = value;
355
+ }
356
+ }
357
+ } else {
358
+ result[key] = value;
359
+ }
360
+ }
361
+ for (const [relName, relData] of Object.entries(relations2)) {
362
+ const relationConfig = this.table.relations[relName];
363
+ if (!relationConfig) continue;
364
+ const hasData = Object.values(relData).some(
365
+ (v) => v !== null && v !== void 0 && v !== ""
366
+ );
367
+ if (!hasData) continue;
368
+ if (relationConfig.type === "many") {
369
+ if (!result[relName]) result[relName] = [];
370
+ const relatedPks = Object.values(relationConfig.foreignTable._.columns).filter((c) => c.options.primaryKey).map((c) => c._.name);
371
+ const relDataKey = relatedPks.map((pk) => relData[pk]).join("_");
372
+ if (relatedPks.length === 0 || !result[relName].some((r) => relatedPks.map((pk) => r[pk]).join("_") === relDataKey)) {
373
+ result[relName].push(relData);
374
+ }
375
+ } else {
376
+ result[relName] = relData;
377
+ }
378
+ }
419
379
  }
420
- return {
421
- sql: query,
422
- params: queryParams
423
- };
424
- }
425
- build() {
426
- return this.buildSelectQuery();
427
- }
428
- async execute() {
429
- const { sql: sql2, params } = this.buildSelectQuery();
430
- return this.db.select(sql2, params);
380
+ return Array.from(groupedResults.values());
431
381
  }
382
+ // Update the return type signatures
432
383
  async all() {
433
384
  return this.execute();
434
385
  }
@@ -438,19 +389,79 @@ var SelectQueryBuilder = class extends BaseQueryBuilder {
438
389
  return result[0];
439
390
  }
440
391
  };
441
- var SelectBuilder = class {
442
- constructor(db, selection) {
443
- this.db = db;
444
- this.selection = selection;
392
+
393
+ // src/builders/update.ts
394
+ var UpdateQueryBuilder = class extends BaseQueryBuilder {
395
+ constructor(db, table) {
396
+ super(db);
397
+ this.table = table;
398
+ this.query = `UPDATE ${table._.name}`;
399
+ }
400
+ updateData = {};
401
+ returningColumns = [];
402
+ set(data) {
403
+ this.updateData = { ...this.updateData, ...data };
404
+ return this;
405
+ }
406
+ returning(...columns) {
407
+ this.returningColumns.push(...columns);
408
+ return this;
445
409
  }
446
- from(table) {
447
- return new SelectQueryBuilder(
448
- this.db,
449
- table,
450
- this.selection
410
+ buildUpdateClause() {
411
+ const finalUpdateData = { ...this.updateData };
412
+ for (const [key, column] of Object.entries(this.table._.columns)) {
413
+ const typedKey = key;
414
+ if (finalUpdateData[typedKey] === void 0 && column.options.$onUpdateFn) {
415
+ finalUpdateData[typedKey] = column.options.$onUpdateFn();
416
+ }
417
+ }
418
+ const baseQuery = this.query;
419
+ const whereParams = this.params;
420
+ let tablePart = baseQuery;
421
+ let whereClause = "";
422
+ const whereIndex = baseQuery.indexOf(" WHERE ");
423
+ if (whereIndex !== -1) {
424
+ tablePart = baseQuery.substring(0, whereIndex);
425
+ whereClause = baseQuery.substring(whereIndex);
426
+ }
427
+ const entries = Object.entries(finalUpdateData);
428
+ if (entries.length === 0) {
429
+ throw new Error("Cannot execute an update query without a .set() call.");
430
+ }
431
+ const setClause = entries.map(([key]) => {
432
+ const column = this.table._.columns[key];
433
+ if (!column) {
434
+ throw new Error(
435
+ `Column ${key} does not exist on table ${this.table._.name}`
436
+ );
437
+ }
438
+ return `${column._.name} = ?`;
439
+ }).join(", ");
440
+ const setParams = entries.map(([, value]) => value);
441
+ const sql2 = `${tablePart} SET ${setClause}${whereClause}`;
442
+ const params = [...setParams, ...whereParams];
443
+ return { sql: sql2, params };
444
+ }
445
+ async execute() {
446
+ const { sql: updateSql, params } = this.buildUpdateClause();
447
+ if (this.returningColumns.length > 0) {
448
+ const returningNames = this.returningColumns.map((col) => this.table._.columns[col]._.name).join(", ");
449
+ const sqlWithReturning = `${updateSql} RETURNING ${returningNames}`;
450
+ return this.db.select(sqlWithReturning, params);
451
+ } else {
452
+ const result = await this.db.execute(updateSql, params);
453
+ return [{ rowsAffected: result.rowsAffected }];
454
+ }
455
+ }
456
+ async returningAll() {
457
+ const allColumns = Object.keys(
458
+ this.table._.columns
451
459
  );
460
+ return this.returning(...allColumns).execute();
452
461
  }
453
462
  };
463
+
464
+ // src/builders/insert.ts
454
465
  var InsertQueryBuilder = class extends BaseQueryBuilder {
455
466
  constructor(db, table) {
456
467
  super(db);
@@ -468,13 +479,7 @@ var InsertQueryBuilder = class extends BaseQueryBuilder {
468
479
  return this;
469
480
  }
470
481
  returning(...columns) {
471
- for (const col of columns) {
472
- if (typeof col === "string") {
473
- this.returningColumns.push(this.table._.columns[col]);
474
- } else {
475
- this.returningColumns.push(col);
476
- }
477
- }
482
+ this.returningColumns.push(...columns);
478
483
  return this;
479
484
  }
480
485
  onConflictDoNothing(target) {
@@ -559,7 +564,7 @@ var InsertQueryBuilder = class extends BaseQueryBuilder {
559
564
  params.push(...setValues);
560
565
  }
561
566
  if (this.returningColumns.length > 0) {
562
- const returningNames = this.returningColumns.map((col) => col._.name).join(", ");
567
+ const returningNames = this.returningColumns.map((col) => this.table._.columns[col]._.name).join(", ");
563
568
  const queryWithReturning = `${finalQuery} RETURNING ${returningNames}`;
564
569
  const rows = await this.db.select(queryWithReturning, params);
565
570
  results = results.concat(rows);
@@ -581,81 +586,8 @@ var InsertQueryBuilder = class extends BaseQueryBuilder {
581
586
  return this.returning(...allColumns).execute();
582
587
  }
583
588
  };
584
- var UpdateQueryBuilder = class extends BaseQueryBuilder {
585
- constructor(db, table) {
586
- super(db);
587
- this.table = table;
588
- this.query = `UPDATE ${table._.name}`;
589
- }
590
- updateData = {};
591
- returningColumns = [];
592
- set(data) {
593
- this.updateData = { ...this.updateData, ...data };
594
- return this;
595
- }
596
- returning(...columns) {
597
- for (const col of columns) {
598
- if (typeof col === "string") {
599
- this.returningColumns.push(this.table._.columns[col]);
600
- } else {
601
- this.returningColumns.push(col);
602
- }
603
- }
604
- return this;
605
- }
606
- buildUpdateClause() {
607
- const finalUpdateData = { ...this.updateData };
608
- for (const [key, column] of Object.entries(this.table._.columns)) {
609
- const typedKey = key;
610
- if (finalUpdateData[typedKey] === void 0 && column.options.$onUpdateFn) {
611
- finalUpdateData[typedKey] = column.options.$onUpdateFn();
612
- }
613
- }
614
- const baseQuery = this.query;
615
- const whereParams = this.params;
616
- let tablePart = baseQuery;
617
- let whereClause = "";
618
- const whereIndex = baseQuery.indexOf(" WHERE ");
619
- if (whereIndex !== -1) {
620
- tablePart = baseQuery.substring(0, whereIndex);
621
- whereClause = baseQuery.substring(whereIndex);
622
- }
623
- const entries = Object.entries(finalUpdateData);
624
- if (entries.length === 0) {
625
- throw new Error("Cannot execute an update query without a .set() call.");
626
- }
627
- const setClause = entries.map(([key]) => {
628
- const column = this.table._.columns[key];
629
- if (!column) {
630
- throw new Error(
631
- `Column ${key} does not exist on table ${this.table._.name}`
632
- );
633
- }
634
- return `${column._.name} = ?`;
635
- }).join(", ");
636
- const setParams = entries.map(([, value]) => value);
637
- const sql2 = `${tablePart} SET ${setClause}${whereClause}`;
638
- const params = [...setParams, ...whereParams];
639
- return { sql: sql2, params };
640
- }
641
- async execute() {
642
- const { sql: updateSql, params } = this.buildUpdateClause();
643
- if (this.returningColumns.length > 0) {
644
- const returningNames = this.returningColumns.map((col) => col._.name).join(", ");
645
- const sqlWithReturning = `${updateSql} RETURNING ${returningNames}`;
646
- return this.db.select(sqlWithReturning, params);
647
- } else {
648
- const result = await this.db.execute(updateSql, params);
649
- return [{ rowsAffected: result.rowsAffected }];
650
- }
651
- }
652
- async returningAll() {
653
- const allColumns = Object.keys(
654
- this.table._.columns
655
- );
656
- return this.returning(...allColumns).execute();
657
- }
658
- };
589
+
590
+ // src/builders/delete.ts
659
591
  var DeleteQueryBuilder = class extends BaseQueryBuilder {
660
592
  constructor(db, table) {
661
593
  super(db);
@@ -664,19 +596,13 @@ var DeleteQueryBuilder = class extends BaseQueryBuilder {
664
596
  }
665
597
  returningColumns = [];
666
598
  returning(...columns) {
667
- for (const col of columns) {
668
- if (typeof col === "string") {
669
- this.returningColumns.push(this.table._.columns[col]);
670
- } else {
671
- this.returningColumns.push(col);
672
- }
673
- }
599
+ this.returningColumns.push(...columns);
674
600
  return this;
675
601
  }
676
602
  async execute() {
677
603
  const { sql: sql2, params } = this.build();
678
604
  if (this.returningColumns.length > 0) {
679
- const returningNames = this.returningColumns.map((col) => col._.name).join(", ");
605
+ const returningNames = this.returningColumns.map((col) => this.table._.columns[col]._.name).join(", ");
680
606
  const sqlWithReturning = `${sql2} RETURNING ${returningNames}`;
681
607
  return this.db.select(sqlWithReturning, params);
682
608
  } else {
@@ -685,12 +611,12 @@ var DeleteQueryBuilder = class extends BaseQueryBuilder {
685
611
  }
686
612
  }
687
613
  async returningAll() {
688
- const allColumns = Object.keys(
689
- this.table._.columns
690
- );
614
+ const allColumns = Object.keys(this.table._.columns);
691
615
  return this.returning(...allColumns).execute();
692
616
  }
693
617
  };
618
+
619
+ // src/builders/with.ts
694
620
  var WithQueryBuilder = class {
695
621
  constructor(db) {
696
622
  this.db = db;
@@ -700,12 +626,8 @@ var WithQueryBuilder = class {
700
626
  this.ctes.push({ alias: alias2, query: query.sql, params: query.params });
701
627
  return this;
702
628
  }
703
- select(table, selection) {
704
- const builder = new SelectQueryBuilder(
705
- this.db,
706
- table,
707
- selection
708
- );
629
+ select(table, columns) {
630
+ const builder = new SelectQueryBuilder(this.db, table, columns);
709
631
  this.applyWithClause(builder);
710
632
  return builder;
711
633
  }
@@ -737,13 +659,117 @@ var WithQueryBuilder = class {
737
659
  };
738
660
 
739
661
  // src/orm.ts
662
+ var SQLiteColumn = class _SQLiteColumn {
663
+ constructor(name, type, options = {}, mode) {
664
+ this.type = type;
665
+ this.options = options;
666
+ this._ = {
667
+ name,
668
+ dataType: type,
669
+ mode: mode || "default",
670
+ notNull: options.notNull ?? false,
671
+ hasDefault: options.default !== void 0 || options.$defaultFn !== void 0,
672
+ autoincrement: options.autoincrement ?? false,
673
+ enum: options.enum,
674
+ customType: void 0
675
+ };
676
+ }
677
+ _;
678
+ notNull() {
679
+ return new _SQLiteColumn(this._.name, this.type, { ...this.options, notNull: true }, this._.mode);
680
+ }
681
+ default(value) {
682
+ return new _SQLiteColumn(this._.name, this.type, { ...this.options, default: value }, this._.mode);
683
+ }
684
+ $defaultFn(fn) {
685
+ return new _SQLiteColumn(this._.name, this.type, { ...this.options, $defaultFn: fn }, this._.mode);
686
+ }
687
+ primaryKey() {
688
+ return new _SQLiteColumn(
689
+ this._.name,
690
+ this.type,
691
+ { ...this.options, primaryKey: true, notNull: true },
692
+ this._.mode
693
+ );
694
+ }
695
+ autoincrement() {
696
+ return new _SQLiteColumn(this._.name, this.type, { ...this.options, autoincrement: true }, this._.mode);
697
+ }
698
+ unique() {
699
+ return new _SQLiteColumn(this._.name, this.type, { ...this.options, unique: true }, this._.mode);
700
+ }
701
+ references(ref, column) {
702
+ return new _SQLiteColumn(
703
+ this._.name,
704
+ this.type,
705
+ {
706
+ ...this.options,
707
+ references: {
708
+ table: ref,
709
+ column: ref._.columns[column]
710
+ }
711
+ },
712
+ this._.mode
713
+ );
714
+ }
715
+ $onUpdateFn(fn) {
716
+ return new _SQLiteColumn(this._.name, this.type, { ...this.options, $onUpdateFn: fn }, this._.mode);
717
+ }
718
+ $type() {
719
+ return this;
720
+ }
721
+ as(alias2) {
722
+ return this;
723
+ }
724
+ };
725
+ var Table = class {
726
+ _;
727
+ relations = {};
728
+ constructor(name, columns) {
729
+ this._ = {
730
+ name,
731
+ columns
732
+ };
733
+ }
734
+ };
735
+ var sqliteTable = (tableName, columns) => {
736
+ return new Table(tableName, columns);
737
+ };
738
+ var asc = (column) => ({
739
+ sql: `${column._.name} ASC`,
740
+ params: []
741
+ });
742
+ var desc = (column) => ({
743
+ sql: `${column._.name} DESC`,
744
+ params: []
745
+ });
746
+ var sql = (strings, ...values) => {
747
+ const queryParts = [];
748
+ const params = [];
749
+ strings.forEach((str, i) => {
750
+ queryParts.push(str);
751
+ if (values[i] !== void 0) {
752
+ if (typeof values[i] === "object" && values[i].sql) {
753
+ queryParts.push(values[i].sql);
754
+ params.push(...values[i].params);
755
+ } else {
756
+ queryParts.push("?");
757
+ params.push(values[i]);
758
+ }
759
+ }
760
+ });
761
+ return {
762
+ sql: queryParts.join(""),
763
+ params
764
+ };
765
+ };
740
766
  var TauriORM = class {
741
767
  constructor(db, schema = void 0) {
742
768
  this.db = db;
743
769
  if (schema) {
744
- for (const table of Object.values(schema)) {
745
- if (table instanceof Table) {
746
- this.tables.set(table._.name, table);
770
+ for (const [key, value] of Object.entries(schema)) {
771
+ if (value instanceof Table) {
772
+ this.tables.set(value._.name, value);
747
773
  }
748
774
  }
749
775
  }
@@ -768,31 +794,60 @@ var TauriORM = class {
768
794
  }
769
795
  return sql2;
770
796
  }
771
- async migrate() {
797
+ async migrate(options) {
798
+ const dbTables = await this.db.select(
799
+ `SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'`
800
+ );
801
+ const dbTableNames = new Set(dbTables.map((t) => t.name));
802
+ const schemaTableNames = new Set(Array.from(this.tables.keys()));
772
803
  for (const table of this.tables.values()) {
773
- const existingTableInfo = await this.db.select(
774
- `PRAGMA table_info('${table._.name}')`
775
- );
776
- if (existingTableInfo.length === 0) {
804
+ const tableName = table._.name;
805
+ const tableExists = dbTableNames.has(tableName);
806
+ if (!tableExists) {
777
807
  const columnsSql = Object.values(table._.columns).map((col) => this.buildColumnDefinition(col)).join(", ");
778
- const createSql = `CREATE TABLE ${table._.name} (${columnsSql})`;
808
+ const createSql = `CREATE TABLE ${tableName}
809
+ (
810
+ ${columnsSql}
811
+ )`;
779
812
  await this.db.execute(createSql);
780
813
  } else {
781
- const existingColumnNames = new Set(
782
- existingTableInfo.map((c) => c.name)
783
- );
814
+ const existingTableInfo = await this.db.select(`PRAGMA table_info('${tableName}')`);
815
+ const existingColumnNames = new Set(existingTableInfo.map((c) => c.name));
816
+ const schemaColumnNames = new Set(Object.keys(table._.columns));
784
817
  for (const column of Object.values(table._.columns)) {
785
818
  if (!existingColumnNames.has(column._.name)) {
786
819
  const columnSql = this.buildColumnDefinition(column, true);
787
- const alterSql = `ALTER TABLE ${table._.name} ADD COLUMN ${columnSql}`;
820
+ const alterSql = `ALTER TABLE ${tableName}
821
+ ADD COLUMN ${columnSql}`;
788
822
  await this.db.execute(alterSql);
789
823
  }
790
824
  }
825
+ if (options?.performDestructiveActions) {
826
+ for (const colName of existingColumnNames) {
827
+ if (!schemaColumnNames.has(colName)) {
828
+ await this.dropColumn(tableName, colName);
829
+ }
830
+ }
831
+ }
832
+ }
833
+ }
834
+ if (options?.performDestructiveActions) {
835
+ for (const tableName of dbTableNames) {
836
+ if (!schemaTableNames.has(tableName)) {
837
+ await this.dropTable(tableName);
838
+ }
791
839
  }
792
840
  }
793
841
  }
794
- select(selection) {
795
- return new SelectBuilder(this.db, selection);
842
+ select(table, columns) {
843
+ const internalTable = this.tables.get(table._.name);
844
+ if (!internalTable) {
845
+ console.warn(
846
+ `[Tauri-ORM] Table "${table._.name}" was not passed in the schema to the ORM constructor. Relations will not be available.`
847
+ );
848
+ return new SelectQueryBuilder(this.db, table, columns);
849
+ }
850
+ return new SelectQueryBuilder(this.db, internalTable, columns);
796
851
  }
797
852
  insert(table) {
798
853
  return new InsertQueryBuilder(this.db, table);
@@ -829,13 +884,25 @@ var TauriORM = class {
829
884
  // --- Schema detection / signature ---
830
885
  async ensureSchemaMeta() {
831
886
  await this.db.execute(
832
- `CREATE TABLE IF NOT EXISTS _schema_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)`
887
+ `CREATE TABLE IF NOT EXISTS _schema_meta
888
+ (
889
+ key
890
+ TEXT
891
+ PRIMARY
892
+ KEY,
893
+ value
894
+ TEXT
895
+ NOT
896
+ NULL
897
+ )`
833
898
  );
834
899
  }
835
900
  async getSchemaMeta(key) {
836
901
  await this.ensureSchemaMeta();
837
902
  const rows = await this.db.select(
838
- `SELECT value FROM _schema_meta WHERE key = ?`,
903
+ `SELECT value
904
+ FROM _schema_meta
905
+ WHERE key = ?`,
839
906
  [key]
840
907
  );
841
908
  return rows?.[0]?.value ?? null;
@@ -843,7 +910,10 @@ var TauriORM = class {
843
910
  async setSchemaMeta(key, value) {
844
911
  await this.ensureSchemaMeta();
845
912
  await this.db.execute(
846
- `INSERT INTO _schema_meta(key, value) VALUES(?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value`,
913
+ `INSERT INTO _schema_meta(key, value)
914
+ VALUES (?, ?) ON CONFLICT(key) DO
915
+ UPDATE
916
+ SET value = excluded.value`,
847
917
  [key, value]
848
918
  );
849
919
  }
@@ -880,14 +950,34 @@ var TauriORM = class {
880
950
  const status = await this.isSchemaDirty();
881
951
  if (status.dirty) {
882
952
  await this.migrate();
883
- await this.setSchemaMeta(
884
- "schema_signature",
885
- this.computeModelSignature()
886
- );
953
+ await this.setSchemaMeta("schema_signature", this.computeModelSignature());
887
954
  return true;
888
955
  }
889
956
  return false;
890
957
  }
958
+ async doesTableExist(tableName) {
959
+ const result = await this.db.select(
960
+ `SELECT name FROM sqlite_master WHERE type='table' AND name=?`,
961
+ [tableName]
962
+ );
963
+ return result.length > 0;
964
+ }
965
+ async dropTable(tableName) {
966
+ await this.db.execute(`DROP TABLE IF EXISTS ${tableName}`);
967
+ }
968
+ async doesColumnExist(tableName, columnName) {
969
+ const result = await this.db.select(`PRAGMA table_info('${tableName}')`);
970
+ return result.some((col) => col.name === columnName);
971
+ }
972
+ async renameTable(from, to) {
973
+ await this.db.execute(`ALTER TABLE ${from} RENAME TO ${to}`);
974
+ }
975
+ async dropColumn(tableName, columnName) {
976
+ await this.db.execute(`ALTER TABLE ${tableName} DROP COLUMN ${columnName}`);
977
+ }
978
+ async renameColumn(tableName, from, to) {
979
+ await this.db.execute(`ALTER TABLE ${tableName} RENAME COLUMN ${from} TO ${to}`);
980
+ }
891
981
  };
892
982
  var Relation = class {
893
983
  constructor(foreignTable) {
@@ -905,16 +995,47 @@ var ManyRelation = class extends Relation {
905
995
  super(foreignTable);
906
996
  }
907
997
  };
908
- var relations = (_table, relationsCallback) => {
909
- return relationsCallback({
910
- one: (table, config) => {
911
- return new OneRelation(table, config);
998
+ var relations = (table, relationsCallback) => {
999
+ const builtRelations = relationsCallback({
1000
+ one: (foreignTable, config) => {
1001
+ return new OneRelation(foreignTable, config);
912
1002
  },
913
- many: (table) => {
914
- return new ManyRelation(table);
1003
+ many: (foreignTable) => {
1004
+ return new ManyRelation(foreignTable);
915
1005
  }
916
1006
  });
1007
+ for (const [name, relation] of Object.entries(builtRelations)) {
1008
+ if (relation instanceof OneRelation) {
1009
+ table.relations[name] = {
1010
+ type: "one",
1011
+ foreignTable: relation.foreignTable,
1012
+ fields: relation.config?.fields,
1013
+ references: relation.config?.references
1014
+ };
1015
+ } else if (relation instanceof ManyRelation) {
1016
+ table.relations[name] = {
1017
+ type: "many",
1018
+ foreignTable: relation.foreignTable
1019
+ };
1020
+ }
1021
+ }
1022
+ return builtRelations;
1023
+ };
1024
+ var getTableColumns = (table) => {
1025
+ return table._.columns;
917
1026
  };
1027
+ var alias = (table, alias2) => {
1028
+ return table;
1029
+ };
1030
+
1031
+ // src/column-helpers.ts
1032
+ var text = (name, config) => new SQLiteColumn(name, "TEXT", config, config?.mode);
1033
+ var integer = (name, config) => new SQLiteColumn(name, "INTEGER", {}, config?.mode || "default");
1034
+ var real = (name) => new SQLiteColumn(name, "REAL");
1035
+ var blob = (name, config) => new SQLiteColumn(name, "BLOB", {}, config?.mode);
1036
+ var boolean = (name) => new SQLiteColumn(name, "BOOLEAN");
1037
+ var numeric = (name, config) => new SQLiteColumn(name, "NUMERIC", {}, config?.mode);
1038
+ var enumType = (name, values) => text(name, { enum: values });
918
1039
  // Annotate the CommonJS export names for ESM import in node:
919
1040
  0 && (module.exports = {
920
1041
  BaseQueryBuilder,
@@ -924,7 +1045,6 @@ var relations = (_table, relationsCallback) => {
924
1045
  OneRelation,
925
1046
  Relation,
926
1047
  SQLiteColumn,
927
- SelectBuilder,
928
1048
  SelectQueryBuilder,
929
1049
  Table,
930
1050
  TauriORM,
@@ -939,6 +1059,7 @@ var relations = (_table, relationsCallback) => {
939
1059
  count,
940
1060
  countDistinct,
941
1061
  desc,
1062
+ enumType,
942
1063
  eq,
943
1064
  getTableColumns,
944
1065
  gt,
@@ -953,6 +1074,7 @@ var relations = (_table, relationsCallback) => {
953
1074
  max,
954
1075
  min,
955
1076
  not,
1077
+ numeric,
956
1078
  or,
957
1079
  real,
958
1080
  relations,