@type32/tauri-sqlite-orm 0.1.18-8 → 0.1.19

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
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ BaseQueryBuilder: () => BaseQueryBuilder,
23
24
  DeleteQueryBuilder: () => DeleteQueryBuilder,
24
25
  InsertQueryBuilder: () => InsertQueryBuilder,
25
26
  ManyRelation: () => ManyRelation,
@@ -40,6 +41,7 @@ __export(index_exports, {
40
41
  count: () => count,
41
42
  countDistinct: () => countDistinct,
42
43
  desc: () => desc,
44
+ enumType: () => enumType,
43
45
  eq: () => eq,
44
46
  getTableColumns: () => getTableColumns,
45
47
  gt: () => gt,
@@ -54,6 +56,7 @@ __export(index_exports, {
54
56
  max: () => max,
55
57
  min: () => min,
56
58
  not: () => not,
59
+ numeric: () => numeric,
57
60
  or: () => or,
58
61
  real: () => real,
59
62
  relations: () => relations,
@@ -64,116 +67,51 @@ __export(index_exports, {
64
67
  });
65
68
  module.exports = __toCommonJS(index_exports);
66
69
 
67
- // src/orm.ts
68
- var SQLiteColumn = class _SQLiteColumn {
69
- constructor(name, type, options = {}, mode) {
70
- this.type = type;
71
- this.options = options;
72
- this._ = {
73
- name,
74
- dataType: type,
75
- mode: mode || "default",
76
- notNull: options.notNull ?? false,
77
- hasDefault: options.default !== void 0 || options.$defaultFn !== void 0,
78
- autoincrement: options.autoincrement ?? false
79
- };
80
- }
81
- _;
82
- notNull() {
83
- return new _SQLiteColumn(
84
- this._.name,
85
- this.type,
86
- { ...this.options, notNull: true },
87
- this._.mode
88
- );
89
- }
90
- default(value) {
91
- return new _SQLiteColumn(
92
- this._.name,
93
- this.type,
94
- { ...this.options, default: value },
95
- this._.mode
96
- );
97
- }
98
- $defaultFn(fn) {
99
- return new _SQLiteColumn(
100
- this._.name,
101
- this.type,
102
- { ...this.options, $defaultFn: fn },
103
- this._.mode
104
- );
105
- }
106
- primaryKey() {
107
- return new _SQLiteColumn(
108
- this._.name,
109
- this.type,
110
- { ...this.options, primaryKey: true, notNull: true },
111
- this._.mode
112
- );
113
- }
114
- autoincrement() {
115
- return new _SQLiteColumn(
116
- this._.name,
117
- this.type,
118
- { ...this.options, autoincrement: true },
119
- this._.mode
120
- );
70
+ // src/builders/query-base.ts
71
+ var BaseQueryBuilder = class {
72
+ constructor(db) {
73
+ this.db = db;
121
74
  }
122
- unique() {
123
- return new _SQLiteColumn(
124
- this._.name,
125
- this.type,
126
- { ...this.options, unique: true },
127
- this._.mode
128
- );
75
+ query = "";
76
+ params = [];
77
+ where(condition) {
78
+ this.query += ` WHERE ${condition.sql}`;
79
+ this.params.push(...condition.params);
80
+ return this;
129
81
  }
130
- references(ref, column) {
131
- return new _SQLiteColumn(
132
- this._.name,
133
- this.type,
134
- {
135
- ...this.options,
136
- references: {
137
- table: ref,
138
- column: ref._.columns[column]
139
- }
140
- },
141
- this._.mode
142
- );
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;
143
90
  }
144
- $onUpdateFn(fn) {
145
- return new _SQLiteColumn(
146
- this._.name,
147
- this.type,
148
- { ...this.options, $onUpdateFn: fn },
149
- this._.mode
150
- );
91
+ limit(count2) {
92
+ this.query += ` LIMIT ${count2}`;
93
+ return this;
151
94
  }
152
- as(alias2) {
95
+ offset(count2) {
96
+ this.query += ` OFFSET ${count2}`;
153
97
  return this;
154
98
  }
155
- };
156
- var text = (name) => new SQLiteColumn(name, "TEXT");
157
- var integer = (name, config) => new SQLiteColumn(name, "INTEGER", {}, config?.mode || "default");
158
- var real = (name) => new SQLiteColumn(name, "REAL");
159
- var blob = (name) => new SQLiteColumn(name, "BLOB");
160
- var boolean = (name) => new SQLiteColumn(name, "BOOLEAN");
161
- var Table = class {
162
- _;
163
- constructor(name, columns) {
164
- this._ = {
165
- name,
166
- columns
99
+ build() {
100
+ return {
101
+ sql: this.query,
102
+ params: this.params
167
103
  };
168
104
  }
169
105
  };
170
- var sqliteTable = (tableName, columns) => {
171
- return new Table(tableName, columns);
106
+
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
+ };
172
114
  };
173
- var eq = (column, value) => ({
174
- sql: `${column._.name} = ?`,
175
- params: [value]
176
- });
177
115
  var and = (...conditions) => ({
178
116
  sql: conditions.map((c) => `(${c.sql})`).join(" AND "),
179
117
  params: conditions.flatMap((c) => c.params)
@@ -218,14 +156,6 @@ var inArray = (column, values) => ({
218
156
  sql: `${column._.name} IN (${values.map(() => "?").join(",")})`,
219
157
  params: values
220
158
  });
221
- var asc = (column) => ({
222
- sql: `${column._.name} ASC`,
223
- params: []
224
- });
225
- var desc = (column) => ({
226
- sql: `${column._.name} DESC`,
227
- params: []
228
- });
229
159
  var count = (column) => ({
230
160
  sql: `COUNT(${column ? column._.name : "*"})`,
231
161
  params: []
@@ -250,80 +180,34 @@ var min = (column) => ({
250
180
  sql: `MIN(${column._.name})`,
251
181
  params: []
252
182
  });
253
- var sql = (strings, ...values) => {
254
- const queryParts = [];
255
- const params = [];
256
- strings.forEach((str, i) => {
257
- queryParts.push(str);
258
- if (values[i] !== void 0) {
259
- if (typeof values[i] === "object" && values[i].sql) {
260
- queryParts.push(values[i].sql);
261
- params.push(...values[i].params);
262
- } else {
263
- queryParts.push("?");
264
- params.push(values[i]);
265
- }
266
- }
267
- });
268
- return {
269
- sql: queryParts.join(""),
270
- params
271
- };
272
- };
273
- var BaseQueryBuilder = class {
274
- constructor(db) {
275
- this.db = db;
276
- }
277
- query = "";
278
- params = [];
279
- where(condition) {
280
- this.query += ` WHERE ${condition.sql}`;
281
- this.params.push(...condition.params);
282
- return this;
283
- }
284
- orderBy(column, direction = "ASC") {
285
- if ("sql" in column) {
286
- this.query += ` ORDER BY ${column.sql} ${direction}`;
287
- this.params.push(...column.params);
288
- } else {
289
- this.query += ` ORDER BY ${column._.name} ${direction}`;
290
- }
291
- return this;
292
- }
293
- limit(count2) {
294
- this.query += ` LIMIT ${count2}`;
295
- return this;
296
- }
297
- offset(count2) {
298
- this.query += ` OFFSET ${count2}`;
299
- return this;
300
- }
301
- build() {
302
- return {
303
- sql: this.query,
304
- params: this.params
305
- };
306
- }
307
- };
183
+
184
+ // src/builders/select.ts
308
185
  var SelectQueryBuilder = class extends BaseQueryBuilder {
309
186
  constructor(db, table, columns) {
310
187
  super(db);
311
188
  this.table = table;
312
189
  this.columns = columns;
313
- const columnNames = columns ? columns.map((c) => table._.columns[c]._.name) : ["*"];
314
- this.query = `SELECT ${columnNames.join(", ")} FROM ${table._.name}`;
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}`;
315
196
  }
316
197
  isDistinct = false;
317
198
  groupByColumns = [];
318
199
  havingCondition = null;
200
+ joins = [];
201
+ includeRelations = {};
202
+ selectedTableAlias;
203
+ selectedColumns = [];
319
204
  distinct() {
320
205
  this.isDistinct = true;
321
- this.query = this.query.replace("SELECT", "SELECT DISTINCT");
322
206
  return this;
323
207
  }
324
208
  groupBy(...columns) {
325
209
  this.groupByColumns.push(...columns);
326
- const columnNames = columns.map((col) => col._.name).join(", ");
210
+ const columnNames = columns.map((col) => `${this.selectedTableAlias}.${col._.name}`).join(", ");
327
211
  this.query += ` GROUP BY ${columnNames}`;
328
212
  return this;
329
213
  }
@@ -333,10 +217,169 @@ var SelectQueryBuilder = class extends BaseQueryBuilder {
333
217
  this.params.push(...condition.params);
334
218
  return this;
335
219
  }
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);
226
+ return this;
227
+ }
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);
234
+ return this;
235
+ }
236
+ include(relations2) {
237
+ this.includeRelations = { ...this.includeRelations, ...relations2 };
238
+ return this;
239
+ }
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);
246
+ }
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
+ }
293
+ }
294
+ return { sql: sql2, params };
295
+ }
296
+ // Enhanced execute method that handles relation data mapping
336
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);
337
303
  const { sql: sql2, params } = this.build();
338
- return this.db.select(sql2, params);
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);
309
+ }
310
+ const hasJoins = this.joins.length > 0;
311
+ if (hasJoins) {
312
+ return rawResults;
313
+ }
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;
332
+ }
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
+ }
379
+ }
380
+ return Array.from(groupedResults.values());
339
381
  }
382
+ // Update the return type signatures
340
383
  async all() {
341
384
  return this.execute();
342
385
  }
@@ -346,6 +389,79 @@ var SelectQueryBuilder = class extends BaseQueryBuilder {
346
389
  return result[0];
347
390
  }
348
391
  };
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;
409
+ }
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
459
+ );
460
+ return this.returning(...allColumns).execute();
461
+ }
462
+ };
463
+
464
+ // src/builders/insert.ts
349
465
  var InsertQueryBuilder = class extends BaseQueryBuilder {
350
466
  constructor(db, table) {
351
467
  super(db);
@@ -363,7 +479,7 @@ var InsertQueryBuilder = class extends BaseQueryBuilder {
363
479
  return this;
364
480
  }
365
481
  returning(...columns) {
366
- this.returningColumns = columns;
482
+ this.returningColumns.push(...columns);
367
483
  return this;
368
484
  }
369
485
  onConflictDoNothing(target) {
@@ -470,75 +586,8 @@ var InsertQueryBuilder = class extends BaseQueryBuilder {
470
586
  return this.returning(...allColumns).execute();
471
587
  }
472
588
  };
473
- var UpdateQueryBuilder = class extends BaseQueryBuilder {
474
- constructor(db, table) {
475
- super(db);
476
- this.table = table;
477
- this.query = `UPDATE ${table._.name}`;
478
- }
479
- updateData = {};
480
- returningColumns = [];
481
- set(data) {
482
- this.updateData = { ...this.updateData, ...data };
483
- return this;
484
- }
485
- returning(...columns) {
486
- this.returningColumns = columns;
487
- return this;
488
- }
489
- buildUpdateClause() {
490
- const finalUpdateData = { ...this.updateData };
491
- for (const [key, column] of Object.entries(this.table._.columns)) {
492
- const typedKey = key;
493
- if (finalUpdateData[typedKey] === void 0 && column.options.$onUpdateFn) {
494
- finalUpdateData[typedKey] = column.options.$onUpdateFn();
495
- }
496
- }
497
- const baseQuery = this.query;
498
- const whereParams = this.params;
499
- let tablePart = baseQuery;
500
- let whereClause = "";
501
- const whereIndex = baseQuery.indexOf(" WHERE ");
502
- if (whereIndex !== -1) {
503
- tablePart = baseQuery.substring(0, whereIndex);
504
- whereClause = baseQuery.substring(whereIndex);
505
- }
506
- const entries = Object.entries(finalUpdateData);
507
- if (entries.length === 0) {
508
- throw new Error("Cannot execute an update query without a .set() call.");
509
- }
510
- const setClause = entries.map(([key]) => {
511
- const column = this.table._.columns[key];
512
- if (!column) {
513
- throw new Error(
514
- `Column ${key} does not exist on table ${this.table._.name}`
515
- );
516
- }
517
- return `${column._.name} = ?`;
518
- }).join(", ");
519
- const setParams = entries.map(([, value]) => value);
520
- const sql2 = `${tablePart} SET ${setClause}${whereClause}`;
521
- const params = [...setParams, ...whereParams];
522
- return { sql: sql2, params };
523
- }
524
- async execute() {
525
- const { sql: updateSql, params } = this.buildUpdateClause();
526
- if (this.returningColumns.length > 0) {
527
- const returningNames = this.returningColumns.map((col) => this.table._.columns[col]._.name).join(", ");
528
- const sqlWithReturning = `${updateSql} RETURNING ${returningNames}`;
529
- return this.db.select(sqlWithReturning, params);
530
- } else {
531
- const result = await this.db.execute(updateSql, params);
532
- return [{ rowsAffected: result.rowsAffected }];
533
- }
534
- }
535
- async returningAll() {
536
- const allColumns = Object.keys(
537
- this.table._.columns
538
- );
539
- return this.returning(...allColumns).execute();
540
- }
541
- };
589
+
590
+ // src/builders/delete.ts
542
591
  var DeleteQueryBuilder = class extends BaseQueryBuilder {
543
592
  constructor(db, table) {
544
593
  super(db);
@@ -547,7 +596,7 @@ var DeleteQueryBuilder = class extends BaseQueryBuilder {
547
596
  }
548
597
  returningColumns = [];
549
598
  returning(...columns) {
550
- this.returningColumns = columns;
599
+ this.returningColumns.push(...columns);
551
600
  return this;
552
601
  }
553
602
  async execute() {
@@ -562,12 +611,12 @@ var DeleteQueryBuilder = class extends BaseQueryBuilder {
562
611
  }
563
612
  }
564
613
  async returningAll() {
565
- const allColumns = Object.keys(
566
- this.table._.columns
567
- );
614
+ const allColumns = Object.keys(this.table._.columns);
568
615
  return this.returning(...allColumns).execute();
569
616
  }
570
617
  };
618
+
619
+ // src/builders/with.ts
571
620
  var WithQueryBuilder = class {
572
621
  constructor(db) {
573
622
  this.db = db;
@@ -608,13 +657,119 @@ var WithQueryBuilder = class {
608
657
  }
609
658
  }
610
659
  };
660
+
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
+ };
611
766
  var TauriORM = class {
612
767
  constructor(db, schema = void 0) {
613
768
  this.db = db;
614
769
  if (schema) {
615
- for (const table of Object.values(schema)) {
616
- if (table instanceof Table) {
617
- 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);
618
773
  }
619
774
  }
620
775
  }
@@ -639,31 +794,60 @@ var TauriORM = class {
639
794
  }
640
795
  return sql2;
641
796
  }
642
- 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()));
643
803
  for (const table of this.tables.values()) {
644
- const existingTableInfo = await this.db.select(
645
- `PRAGMA table_info('${table._.name}')`
646
- );
647
- if (existingTableInfo.length === 0) {
804
+ const tableName = table._.name;
805
+ const tableExists = dbTableNames.has(tableName);
806
+ if (!tableExists) {
648
807
  const columnsSql = Object.values(table._.columns).map((col) => this.buildColumnDefinition(col)).join(", ");
649
- const createSql = `CREATE TABLE ${table._.name} (${columnsSql})`;
808
+ const createSql = `CREATE TABLE ${tableName}
809
+ (
810
+ ${columnsSql}
811
+ )`;
650
812
  await this.db.execute(createSql);
651
813
  } else {
652
- const existingColumnNames = new Set(
653
- existingTableInfo.map((c) => c.name)
654
- );
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));
655
817
  for (const column of Object.values(table._.columns)) {
656
818
  if (!existingColumnNames.has(column._.name)) {
657
819
  const columnSql = this.buildColumnDefinition(column, true);
658
- const alterSql = `ALTER TABLE ${table._.name} ADD COLUMN ${columnSql}`;
820
+ const alterSql = `ALTER TABLE ${tableName}
821
+ ADD COLUMN ${columnSql}`;
659
822
  await this.db.execute(alterSql);
660
823
  }
661
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
+ }
662
839
  }
663
840
  }
664
841
  }
665
842
  select(table, columns) {
666
- return new SelectQueryBuilder(this.db, 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);
667
851
  }
668
852
  insert(table) {
669
853
  return new InsertQueryBuilder(this.db, table);
@@ -700,13 +884,25 @@ var TauriORM = class {
700
884
  // --- Schema detection / signature ---
701
885
  async ensureSchemaMeta() {
702
886
  await this.db.execute(
703
- `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
+ )`
704
898
  );
705
899
  }
706
900
  async getSchemaMeta(key) {
707
901
  await this.ensureSchemaMeta();
708
902
  const rows = await this.db.select(
709
- `SELECT value FROM _schema_meta WHERE key = ?`,
903
+ `SELECT value
904
+ FROM _schema_meta
905
+ WHERE key = ?`,
710
906
  [key]
711
907
  );
712
908
  return rows?.[0]?.value ?? null;
@@ -714,7 +910,10 @@ var TauriORM = class {
714
910
  async setSchemaMeta(key, value) {
715
911
  await this.ensureSchemaMeta();
716
912
  await this.db.execute(
717
- `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`,
718
917
  [key, value]
719
918
  );
720
919
  }
@@ -751,14 +950,34 @@ var TauriORM = class {
751
950
  const status = await this.isSchemaDirty();
752
951
  if (status.dirty) {
753
952
  await this.migrate();
754
- await this.setSchemaMeta(
755
- "schema_signature",
756
- this.computeModelSignature()
757
- );
953
+ await this.setSchemaMeta("schema_signature", this.computeModelSignature());
758
954
  return true;
759
955
  }
760
956
  return false;
761
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
+ }
762
981
  };
763
982
  var Relation = class {
764
983
  constructor(foreignTable) {
@@ -776,15 +995,31 @@ var ManyRelation = class extends Relation {
776
995
  super(foreignTable);
777
996
  }
778
997
  };
779
- var relations = (_table, relationsCallback) => {
780
- return relationsCallback({
781
- one: (table, config) => {
782
- return new OneRelation(table, config);
998
+ var relations = (table, relationsCallback) => {
999
+ const builtRelations = relationsCallback({
1000
+ one: (foreignTable, config) => {
1001
+ return new OneRelation(foreignTable, config);
783
1002
  },
784
- many: (table) => {
785
- return new ManyRelation(table);
1003
+ many: (foreignTable) => {
1004
+ return new ManyRelation(foreignTable);
786
1005
  }
787
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;
788
1023
  };
789
1024
  var getTableColumns = (table) => {
790
1025
  return table._.columns;
@@ -792,8 +1027,18 @@ var getTableColumns = (table) => {
792
1027
  var alias = (table, alias2) => {
793
1028
  return table;
794
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 });
795
1039
  // Annotate the CommonJS export names for ESM import in node:
796
1040
  0 && (module.exports = {
1041
+ BaseQueryBuilder,
797
1042
  DeleteQueryBuilder,
798
1043
  InsertQueryBuilder,
799
1044
  ManyRelation,
@@ -814,6 +1059,7 @@ var alias = (table, alias2) => {
814
1059
  count,
815
1060
  countDistinct,
816
1061
  desc,
1062
+ enumType,
817
1063
  eq,
818
1064
  getTableColumns,
819
1065
  gt,
@@ -828,6 +1074,7 @@ var alias = (table, alias2) => {
828
1074
  max,
829
1075
  min,
830
1076
  not,
1077
+ numeric,
831
1078
  or,
832
1079
  real,
833
1080
  relations,