@type32/tauri-sqlite-orm 0.1.16 → 0.1.18-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,1267 +1,354 @@
1
- // src/schema-builder.ts
2
- function sql(strings, ...values) {
3
- const raw2 = strings.reduce(
4
- (acc, part, idx) => acc + part + (idx < values.length ? String(values[idx]) : ""),
5
- ""
6
- );
7
- return { raw: raw2 };
8
- }
9
- function createColumn(params) {
10
- const col = { ...params };
11
- col.primaryKey = (opts) => {
12
- col.isPrimaryKey = true;
13
- if (opts?.autoIncrement) col.autoIncrement = true;
14
- return col;
15
- };
16
- col.notNull = () => {
17
- col.isNotNull = true;
18
- return col;
19
- };
20
- col.default = (value) => {
21
- col.defaultValue = value;
22
- return col;
23
- };
24
- col.$type = () => col;
25
- col.$defaultFn = (fn) => {
26
- col.defaultFn = fn;
27
- return col;
28
- };
29
- col.$default = (fn) => {
30
- col.defaultFn = fn;
31
- return col;
32
- };
33
- col.$onUpdate = (fn) => {
34
- col.onUpdateFn = fn;
35
- return col;
36
- };
37
- col.$onUpdateFn = (fn) => {
38
- col.onUpdateFn = fn;
39
- return col;
40
- };
41
- col.references = (target, actions) => {
42
- const t = target();
43
- col.references = {
44
- table: t.tableName,
45
- column: t.name,
46
- onDelete: actions?.onDelete,
47
- onUpdate: actions?.onUpdate
48
- };
49
- return col;
50
- };
51
- return col;
52
- }
53
- function text(nameOrConfig, maybeConfig) {
54
- const name = typeof nameOrConfig === "string" ? nameOrConfig : "";
55
- const config = typeof nameOrConfig === "string" ? maybeConfig : nameOrConfig;
56
- const col = createColumn({
57
- name,
58
- type: "TEXT",
59
- _dataType: ""
60
- });
61
- if (config?.enum) col.enumValues = config.enum;
62
- if (config?.mode) col.mode = config.mode;
63
- return col;
64
- }
65
- function integer(nameOrConfig, maybeConfig) {
66
- const name = typeof nameOrConfig === "string" ? nameOrConfig : "";
67
- const config = typeof nameOrConfig === "string" ? maybeConfig : nameOrConfig;
68
- let dt = 0;
69
- if (config?.mode === "boolean") dt = false;
70
- if (config?.mode === "timestamp" || config?.mode === "timestamp_ms")
71
- dt = /* @__PURE__ */ new Date();
72
- const col = createColumn({
73
- name,
74
- type: "INTEGER",
75
- mode: config?.mode ?? "number",
76
- _dataType: dt
77
- });
78
- return col;
79
- }
80
- function real(name) {
81
- return createColumn({
82
- name: name ?? "",
83
- type: "REAL",
84
- _dataType: 0
85
- });
86
- }
87
- function blob(nameOrConfig, maybeConfig) {
88
- const name = typeof nameOrConfig === "string" ? nameOrConfig : "";
89
- const config = typeof nameOrConfig === "string" ? maybeConfig : nameOrConfig;
90
- let dt = new Uint8Array();
91
- if (config?.mode === "bigint") dt = 0n;
92
- if (config?.mode === "json") dt = void 0;
93
- return createColumn({
94
- name,
95
- type: "BLOB",
96
- mode: config?.mode,
97
- _dataType: dt
98
- });
99
- }
100
- function numeric(nameOrConfig, maybeConfig) {
101
- const name = typeof nameOrConfig === "string" ? nameOrConfig : "";
102
- const config = typeof nameOrConfig === "string" ? maybeConfig : nameOrConfig;
103
- let dt = "";
104
- if (config?.mode === "number") dt = 0;
105
- if (config?.mode === "bigint") dt = 0n;
106
- return createColumn({
107
- name,
108
- type: "NUMERIC",
109
- mode: config?.mode,
110
- _dataType: dt
111
- });
112
- }
113
- function boolean(name) {
114
- return createColumn({
115
- name: name ?? "",
116
- type: "INTEGER",
117
- _dataType: false,
118
- mode: "boolean"
119
- });
120
- }
121
- function timestamp(name) {
122
- return createColumn({
123
- name: name ?? "",
124
- type: "INTEGER",
125
- _dataType: /* @__PURE__ */ new Date(),
126
- mode: "timestamp"
127
- });
128
- }
129
- function increments(name) {
130
- return integer(name ?? "").primaryKey({
131
- autoIncrement: true
132
- });
133
- }
134
- function unique(name) {
135
- return {
136
- on: (...cols) => ({
137
- name,
138
- columns: cols.map((c) => c.name),
139
- // runtime marker for DDL rendering
140
- kind: "unique"
141
- })
142
- };
143
- }
144
- function primaryKey(opts) {
145
- return {
146
- name: opts.name,
147
- columns: opts.columns.map((c) => c.name),
148
- // runtime marker for DDL rendering
149
- kind: "primaryKey"
150
- };
151
- }
152
- function check(name, expr) {
153
- return { name, expr };
154
- }
155
- function foreignKey(opts) {
156
- const first = opts.columns[0];
157
- return {
158
- name: opts.name,
159
- columns: opts.columns.map((c) => c.name),
160
- foreignTable: first?.tableName || opts.foreignColumns[0]?.tableName || "",
161
- foreignColumns: opts.foreignColumns.map((c) => c.name),
162
- onDelete: opts.onDelete,
163
- onUpdate: opts.onUpdate
164
- };
165
- }
166
- function index(name) {
167
- return {
168
- on: (...cols) => ({
169
- name,
170
- columns: cols.map((c) => c.name)
171
- }),
172
- where: (expr) => ({ name, columns: [], where: expr })
173
- };
174
- }
175
- function uniqueIndex(name) {
176
- return {
177
- on: (...cols) => ({
178
- name,
179
- columns: cols.map((c) => c.name),
180
- unique: true
181
- }),
182
- where: (expr) => ({
1
+ // src/orm.ts
2
+ var SQLiteColumn = class _SQLiteColumn {
3
+ constructor(name, type, options = {}, mode) {
4
+ this.type = type;
5
+ this.options = options;
6
+ this._ = {
183
7
  name,
184
- columns: [],
185
- unique: true,
186
- where: expr
187
- })
188
- };
189
- }
190
- function defineTable(tableName, schema, extras) {
191
- const finalizedSchema = { ...schema };
192
- for (const key of Object.keys(finalizedSchema)) {
193
- const col = finalizedSchema[key];
194
- if (!col.name || col.name === "") col.name = key;
195
- col.tableName = tableName;
8
+ dataType: type,
9
+ mode: mode || "default",
10
+ notNull: options.notNull ?? false,
11
+ hasDefault: options.default !== void 0 || options.$defaultFn !== void 0,
12
+ autoincrement: options.autoincrement ?? false
13
+ };
196
14
  }
197
- const table = {
198
- tableName,
199
- _schema: finalizedSchema,
200
- _constraints: [],
201
- _indexes: [],
202
- // The Drizzle-like type inference properties
203
- $inferSelect: {},
204
- $inferInsert: {}
205
- // omit PK columns
206
- };
207
- for (const [key, col] of Object.entries(finalizedSchema)) {
208
- table[key] = col;
15
+ _;
16
+ notNull() {
17
+ return new _SQLiteColumn(
18
+ this._.name,
19
+ this.type,
20
+ { ...this.options, notNull: true },
21
+ this._.mode
22
+ );
209
23
  }
210
- if (extras) {
211
- const specs = extras(table) || [];
212
- for (const s of specs) {
213
- if (s.columns && s.unique !== void 0) {
214
- table._indexes.push(s);
215
- } else if (s.columns && s.foreignColumns) {
216
- table._constraints.push(s);
217
- } else if (s.columns && (s.name || s.name === void 0)) {
218
- if (s.columns && s.name !== void 0 && s.columns.length > 0) {
219
- const pk = s;
220
- if (pk.columns.length > 1 || pk.name && pk.name.length > 0) {
221
- table._constraints.push(s);
222
- } else {
223
- table._constraints.push(s);
224
- }
225
- } else {
226
- table._constraints.push(s);
227
- }
228
- } else if (s.expr) {
229
- table._constraints.push(s);
230
- }
231
- }
24
+ default(value) {
25
+ return new _SQLiteColumn(
26
+ this._.name,
27
+ this.type,
28
+ { ...this.options, default: value },
29
+ this._.mode
30
+ );
232
31
  }
233
- return table;
234
- }
235
-
236
- // src/orm.ts
237
- import Database from "@tauri-apps/plugin-sql";
238
-
239
- // src/sql-helpers.ts
240
- function raw(strings, ...values) {
241
- return {
242
- toSQL: () => {
243
- let clause = "";
244
- const bindings = [];
245
- for (let i = 0; i < strings.length; i++) {
246
- clause += strings[i];
247
- if (i < values.length) {
248
- const v = values[i];
249
- if (v && typeof v === "object" && typeof v.toSQL === "function") {
250
- const s = v.toSQL();
251
- clause += s.clause;
252
- bindings.push(...s.bindings);
253
- } else if (v && typeof v === "object" && "_dataType" in v) {
254
- clause += getQualifiedName(v);
255
- } else {
256
- clause += "?";
257
- bindings.push(v);
258
- }
32
+ $defaultFn(fn) {
33
+ return new _SQLiteColumn(
34
+ this._.name,
35
+ this.type,
36
+ { ...this.options, $defaultFn: fn },
37
+ this._.mode
38
+ );
39
+ }
40
+ primaryKey() {
41
+ return new _SQLiteColumn(
42
+ this._.name,
43
+ this.type,
44
+ { ...this.options, primaryKey: true },
45
+ this._.mode
46
+ );
47
+ }
48
+ autoincrement() {
49
+ return new _SQLiteColumn(
50
+ this._.name,
51
+ this.type,
52
+ { ...this.options, autoincrement: true },
53
+ this._.mode
54
+ );
55
+ }
56
+ unique() {
57
+ return new _SQLiteColumn(
58
+ this._.name,
59
+ this.type,
60
+ { ...this.options, unique: true },
61
+ this._.mode
62
+ );
63
+ }
64
+ references(ref, column) {
65
+ return new _SQLiteColumn(
66
+ this._.name,
67
+ this.type,
68
+ {
69
+ ...this.options,
70
+ references: {
71
+ table: ref,
72
+ column: ref._.columns[column]
259
73
  }
260
- }
261
- return { clause, bindings };
262
- }
263
- };
264
- }
265
- function isColumn(value) {
266
- return typeof value === "object" && value !== null && "_dataType" in value;
267
- }
268
- function getQualifiedName(column) {
269
- if (column.tableName) return `${column.tableName}.${column.name}`;
270
- return column.name;
271
- }
272
- function comparison(operator, column, value) {
273
- return {
274
- toSQL: () => {
275
- if (isColumn(value)) {
276
- return {
277
- clause: `${getQualifiedName(column)} ${operator} ${getQualifiedName(
278
- value
279
- )}`,
280
- bindings: []
281
- };
282
- }
283
- return {
284
- clause: `${getQualifiedName(column)} ${operator} ?`,
285
- bindings: [value]
286
- };
287
- }
288
- };
289
- }
290
- var and = (...conditions) => ({
291
- toSQL: () => {
292
- const parts = [];
293
- const bindings = [];
294
- for (const c of conditions) {
295
- const s = c.toSQL();
296
- parts.push(`(${s.clause})`);
297
- bindings.push(...s.bindings);
298
- }
299
- return { clause: parts.join(" AND "), bindings };
74
+ },
75
+ this._.mode
76
+ );
300
77
  }
301
- });
302
- var or = (...conditions) => ({
303
- toSQL: () => {
304
- const parts = [];
305
- const bindings = [];
306
- for (const c of conditions) {
307
- const s = c.toSQL();
308
- parts.push(`(${s.clause})`);
309
- bindings.push(...s.bindings);
310
- }
311
- return { clause: parts.join(" OR "), bindings };
78
+ $onUpdateFn(fn) {
79
+ return new _SQLiteColumn(
80
+ this._.name,
81
+ this.type,
82
+ { ...this.options, $onUpdateFn: fn },
83
+ this._.mode
84
+ );
312
85
  }
313
- });
314
- var not = (condition) => ({
315
- toSQL: () => {
316
- const s = condition.toSQL();
317
- return { clause: `NOT (${s.clause})`, bindings: s.bindings };
86
+ };
87
+ var text = (name) => new SQLiteColumn(name, "TEXT");
88
+ var integer = (name, config) => new SQLiteColumn(name, "INTEGER", {}, config?.mode || "default");
89
+ var real = (name) => new SQLiteColumn(name, "REAL");
90
+ var blob = (name) => new SQLiteColumn(name, "BLOB");
91
+ var boolean = (name) => new SQLiteColumn(name, "BOOLEAN");
92
+ var Table = class {
93
+ _;
94
+ constructor(name, columns) {
95
+ this._ = {
96
+ name,
97
+ columns
98
+ };
318
99
  }
100
+ };
101
+ var sqliteTable = (tableName, columns) => {
102
+ return new Table(tableName, columns);
103
+ };
104
+ var eq = (column, value) => ({
105
+ sql: `${column._.name} = ?`,
106
+ params: [value]
319
107
  });
320
- var eq = (column, value) => comparison("=", column, value);
321
- var ne = (column, value) => comparison("!=", column, value);
322
- var gt = (column, value) => comparison(">", column, value);
323
- var gte = (column, value) => comparison(">=", column, value);
324
- var lt = (column, value) => comparison("<", column, value);
325
- var lte = (column, value) => comparison("<=", column, value);
326
- var like = (column, value) => comparison("LIKE", column, value);
327
- var ilike = (column, value) => ({
328
- toSQL: () => {
329
- const colExpr = `LOWER(${getQualifiedName(column)})`;
330
- if (isColumn(value)) {
331
- return {
332
- clause: `${colExpr} LIKE LOWER(${getQualifiedName(value)})`,
333
- bindings: []
334
- };
335
- }
336
- return { clause: `${colExpr} LIKE LOWER(?)`, bindings: [value] };
337
- }
108
+ var and = (...conditions) => ({
109
+ sql: conditions.map((c) => `(${c.sql})`).join(" AND "),
110
+ params: conditions.flatMap((c) => c.params)
338
111
  });
339
- var notIlike = (column, value) => ({
340
- toSQL: () => {
341
- const colExpr = `LOWER(${getQualifiedName(column)})`;
342
- if (isColumn(value)) {
343
- return {
344
- clause: `${colExpr} NOT LIKE LOWER(${getQualifiedName(value)})`,
345
- bindings: []
346
- };
347
- }
348
- return { clause: `${colExpr} NOT LIKE LOWER(?)`, bindings: [value] };
349
- }
112
+ var or = (...conditions) => ({
113
+ sql: conditions.map((c) => `(${c.sql})`).join(" OR "),
114
+ params: conditions.flatMap((c) => c.params)
350
115
  });
351
- var isNull = (column) => ({
352
- toSQL: () => ({
353
- clause: `${getQualifiedName(column)} IS NULL`,
354
- bindings: []
355
- })
116
+ var gt = (column, value) => ({
117
+ sql: `${column._.name} > ?`,
118
+ params: [value]
356
119
  });
357
- var isNotNull = (column) => ({
358
- toSQL: () => ({
359
- clause: `${getQualifiedName(column)} IS NOT NULL`,
360
- bindings: []
361
- })
120
+ var gte = (column, value) => ({
121
+ sql: `${column._.name} >= ?`,
122
+ params: [value]
362
123
  });
363
- var between = (column, from, to) => ({
364
- toSQL: () => {
365
- const left = getQualifiedName(column);
366
- const [fromClause, fromBindings] = isColumn(from) ? [getQualifiedName(from), []] : ["?", [from]];
367
- const [toClause, toBindings] = isColumn(to) ? [getQualifiedName(to), []] : ["?", [to]];
368
- return {
369
- clause: `${left} BETWEEN ${fromClause} AND ${toClause}`,
370
- bindings: [...fromBindings, ...toBindings]
371
- };
372
- }
124
+ var lt = (column, value) => ({
125
+ sql: `${column._.name} < ?`,
126
+ params: [value]
373
127
  });
374
- var notBetween = (column, from, to) => ({
375
- toSQL: () => {
376
- const left = getQualifiedName(column);
377
- const [fromClause, fromBindings] = isColumn(from) ? [getQualifiedName(from), []] : ["?", [from]];
378
- const [toClause, toBindings] = isColumn(to) ? [getQualifiedName(to), []] : ["?", [to]];
379
- return {
380
- clause: `${left} NOT BETWEEN ${fromClause} AND ${toClause}`,
381
- bindings: [...fromBindings, ...toBindings]
382
- };
383
- }
128
+ var lte = (column, value) => ({
129
+ sql: `${column._.name} <= ?`,
130
+ params: [value]
384
131
  });
385
- var inArray = (column, valuesOrQuery) => ({
386
- toSQL: () => {
387
- const left = getQualifiedName(column);
388
- if (Array.isArray(valuesOrQuery)) {
389
- const placeholders = valuesOrQuery.map(() => "?").join(", ");
390
- return {
391
- clause: `${left} IN (${placeholders})`,
392
- bindings: valuesOrQuery
393
- };
394
- }
395
- const sq = valuesOrQuery.toSQL ? valuesOrQuery.toSQL() : valuesOrQuery.toSQL();
396
- return { clause: `${left} IN (${sq.clause})`, bindings: sq.bindings };
397
- }
132
+ var like = (column, pattern) => ({
133
+ sql: `${column._.name} LIKE ?`,
134
+ params: [pattern]
398
135
  });
399
- var notInArray = (column, valuesOrQuery) => ({
400
- toSQL: () => {
401
- const left = getQualifiedName(column);
402
- if (Array.isArray(valuesOrQuery)) {
403
- const placeholders = valuesOrQuery.map(() => "?").join(", ");
404
- return {
405
- clause: `${left} NOT IN (${placeholders})`,
406
- bindings: valuesOrQuery
407
- };
408
- }
409
- const sq = valuesOrQuery.toSQL ? valuesOrQuery.toSQL() : valuesOrQuery.toSQL();
410
- return { clause: `${left} NOT IN (${sq.clause})`, bindings: sq.bindings };
411
- }
136
+ var isNull = (column) => ({
137
+ sql: `${column._.name} IS NULL`,
138
+ params: []
412
139
  });
413
- var exists = (subquery) => ({
414
- toSQL: () => {
415
- const sq = subquery.toSQL ? subquery.toSQL() : subquery.toSQL();
416
- return { clause: `EXISTS (${sq.clause})`, bindings: sq.bindings };
417
- }
140
+ var isNotNull = (column) => ({
141
+ sql: `${column._.name} IS NOT NULL`,
142
+ params: []
418
143
  });
419
- var notExists = (subquery) => ({
420
- toSQL: () => {
421
- const sq = subquery.toSQL ? subquery.toSQL() : subquery.toSQL();
422
- return { clause: `NOT EXISTS (${sq.clause})`, bindings: sq.bindings };
423
- }
144
+ var inArray = (column, values) => ({
145
+ sql: `${column._.name} IN (${values.map(() => "?").join(",")})`,
146
+ params: values
424
147
  });
425
- var asc = (column) => `${getQualifiedName(column)} ASC`;
426
- var desc = (column) => `${getQualifiedName(column)} DESC`;
427
-
428
- // src/orm.ts
429
- function getTableName(table) {
430
- const anyTable = table;
431
- return anyTable._tableName || anyTable.tableName || anyTable.name || "";
432
- }
433
- var SelectQueryBuilder = class {
434
- _table = null;
435
- _selectedColumns = [];
436
- _joins = [];
437
- _where = [];
438
- _orderBy = [];
439
- _limit = null;
440
- _offset = null;
441
- _groupBy = [];
442
- _having = [];
443
- _distinct = false;
444
- _dbProvider;
445
- constructor(dbProvider, fields) {
446
- this._dbProvider = dbProvider;
447
- if (fields) {
448
- for (const [alias, col] of Object.entries(fields)) {
449
- const sql2 = getQualifiedName(col);
450
- this._selectedColumns.push({ sql: sql2, alias });
451
- }
452
- }
453
- }
454
- distinct() {
455
- this._distinct = true;
456
- return this;
457
- }
458
- select(fields) {
459
- this._selectedColumns = [];
460
- for (const [alias, expr] of Object.entries(fields)) {
461
- if (typeof expr.toSQL === "function") {
462
- const s = expr.toSQL();
463
- this._selectedColumns.push({ sql: s.clause, alias });
464
- } else {
465
- this._selectedColumns.push({
466
- sql: getQualifiedName(expr),
467
- alias
468
- });
469
- }
470
- }
471
- return this;
472
- }
473
- from(table) {
474
- this._table = table;
148
+ var BaseQueryBuilder = class {
149
+ constructor(db) {
150
+ this.db = db;
151
+ }
152
+ query = "";
153
+ params = [];
154
+ where(condition) {
155
+ this.query += ` WHERE ${condition.sql}`;
156
+ this.params.push(...condition.params);
475
157
  return this;
476
158
  }
477
- where(...conditions) {
478
- this._where.push(...conditions.filter(Boolean));
159
+ orderBy(column, direction = "ASC") {
160
+ this.query += ` ORDER BY ${column._.name} ${direction}`;
479
161
  return this;
480
162
  }
481
- leftJoin(otherTable, on) {
482
- const onSql = on.toSQL();
483
- const joinClause = `LEFT JOIN ${otherTable._tableName} ON ${onSql.clause}`;
484
- this._joins.push(joinClause);
163
+ limit(count) {
164
+ this.query += ` LIMIT ${count}`;
485
165
  return this;
486
166
  }
487
- groupBy(...exprs) {
488
- for (const e of exprs) {
489
- if (!e) continue;
490
- if (typeof e === "string") this._groupBy.push(e);
491
- else this._groupBy.push(getQualifiedName(e));
492
- }
167
+ offset(count) {
168
+ this.query += ` OFFSET ${count}`;
493
169
  return this;
494
170
  }
495
- having(...conditions) {
496
- this._having.push(...conditions);
497
- return this;
171
+ build() {
172
+ return {
173
+ sql: this.query,
174
+ params: this.params
175
+ };
498
176
  }
499
- orderBy(...clauses) {
500
- for (const c of clauses) {
501
- if (!c) continue;
502
- if (typeof c === "string") this._orderBy.push(c);
503
- else if (typeof c.toSQL === "function")
504
- this._orderBy.push(c);
505
- else this._orderBy.push(getQualifiedName(c));
506
- }
507
- return this;
177
+ };
178
+ var SelectQueryBuilder = class extends BaseQueryBuilder {
179
+ constructor(db, table, columns) {
180
+ super(db);
181
+ this.table = table;
182
+ this.columns = columns;
183
+ const columnNames = columns ? columns.map((c) => table._.columns[c]._.name) : ["*"];
184
+ this.query = `SELECT ${columnNames.join(", ")} FROM ${table._.name}`;
508
185
  }
509
- limit(value) {
510
- this._limit = value;
511
- return this;
186
+ async execute() {
187
+ const { sql, params } = this.build();
188
+ return this.db.select(sql, ...params);
512
189
  }
513
- offset(value) {
514
- this._offset = value;
190
+ };
191
+ var InsertQueryBuilder = class extends BaseQueryBuilder {
192
+ constructor(db, table) {
193
+ super(db);
194
+ this.table = table;
195
+ this.query = `INSERT INTO ${table._.name}`;
196
+ }
197
+ dataSets = [];
198
+ values(data) {
199
+ const dataArray = Array.isArray(data) ? data : [data];
200
+ this.dataSets.push(...dataArray);
515
201
  return this;
516
202
  }
517
203
  async execute() {
518
- if (!this._table) {
519
- throw new Error("Cannot execute select query without a 'from' table.");
520
- }
521
- const db = await this._dbProvider();
522
- const baseTableName = getTableName(this._table);
523
- if (!baseTableName) {
524
- throw new Error(
525
- "Invalid table passed to select.from(): missing table name"
526
- );
204
+ if (this.dataSets.length === 0) {
205
+ throw new Error("No data provided for insert");
527
206
  }
528
- const bindings = [];
529
- const selectList = this._selectedColumns.length > 0 ? this._selectedColumns.map((c) => c.alias ? `${c.sql} AS ${c.alias}` : c.sql).join(", ") : Object.values(this._table._schema).map((c) => `${baseTableName}.${c.name}`).join(", ");
530
- let query = `SELECT ${this._distinct ? "DISTINCT " : ""}${selectList} FROM ${baseTableName}`;
531
- if (this._joins.length > 0) query += ` ${this._joins.join(" ")}`;
532
- if (this._where.length > 0) {
533
- const whereClauses = this._where.map((condition) => {
534
- const sql2 = condition.toSQL();
535
- bindings.push(...sql2.bindings);
536
- return `(${sql2.clause})`;
537
- });
538
- query += ` WHERE ${whereClauses.join(" AND ")}`;
539
- }
540
- if (this._groupBy.length > 0) {
541
- query += ` GROUP BY ${this._groupBy.join(", ")}`;
542
- }
543
- if (this._having.length > 0) {
544
- const havingClauses = this._having.map((h) => {
545
- const sql2 = h.toSQL();
546
- bindings.push(...sql2.bindings);
547
- return `(${sql2.clause})`;
548
- });
549
- query += ` HAVING ${havingClauses.join(" AND ")}`;
550
- }
551
- if (this._orderBy.length > 0) {
552
- const ordParts = [];
553
- for (const ob of this._orderBy) {
554
- if (typeof ob === "string") ordParts.push(ob);
555
- else {
556
- const s = ob.toSQL();
557
- ordParts.push(s.clause);
558
- bindings.push(...s.bindings);
559
- }
560
- }
561
- query += ` ORDER BY ${ordParts.join(", ")}`;
562
- }
563
- if (this._limit !== null) {
564
- query += ` LIMIT ?`;
565
- bindings.push(this._limit);
566
- }
567
- if (this._offset !== null) {
568
- if (this._limit === null) query += ` LIMIT -1`;
569
- query += ` OFFSET ?`;
570
- bindings.push(this._offset);
571
- }
572
- return db.select(query, bindings);
573
- }
574
- async iterator() {
575
- const rows = await this.execute();
576
- async function* gen() {
577
- for (const r of rows) yield r;
578
- }
579
- return gen();
207
+ const columns = Object.keys(
208
+ this.dataSets[0]
209
+ );
210
+ const columnNames = columns.map(
211
+ (c) => this.table._.columns[c]._.name
212
+ );
213
+ const placeholders = `(${columnNames.map(() => "?").join(", ")})`;
214
+ const valuesSql = this.dataSets.map(() => placeholders).join(", ");
215
+ this.query += ` (${columnNames.join(", ")}) VALUES ${valuesSql}`;
216
+ const params = this.dataSets.flatMap(
217
+ (data) => columns.map((col) => data[col])
218
+ );
219
+ const result = await this.db.execute(this.query, ...params);
220
+ return result.lastInsertId ?? 0;
580
221
  }
581
222
  };
582
- var TauriORM = class {
583
- // Soft relational query API: db.query.users.findMany({ with: { posts: true } })
584
- query = {};
585
- _tables = null;
586
- _relations = null;
587
- _dbPromise;
588
- constructor(dbUri) {
589
- this._dbPromise = Database.load(dbUri).then(async (db) => {
590
- await db.execute("PRAGMA foreign_keys = ON");
591
- return db;
592
- });
593
- }
594
- async getDb() {
595
- return this._dbPromise;
596
- }
597
- // Deprecated: use configure()
598
- configureQuery(tables, relations2) {
599
- this.configure(tables, relations2);
600
- }
601
- select(fields) {
602
- return new SelectQueryBuilder(this.getDb.bind(this), fields);
223
+ var UpdateQueryBuilder = class extends BaseQueryBuilder {
224
+ constructor(db, table) {
225
+ super(db);
226
+ this.table = table;
227
+ this.query = `UPDATE ${table._.name}`;
228
+ }
229
+ updateData = {};
230
+ set(data) {
231
+ this.updateData = { ...this.updateData, ...data };
232
+ return this;
603
233
  }
604
- selectDistinct(fields) {
605
- const qb = new SelectQueryBuilder(this.getDb.bind(this), fields);
606
- qb.distinct();
607
- return qb;
234
+ async execute() {
235
+ const entries = Object.entries(this.updateData);
236
+ const setClause = entries.map(([key]) => {
237
+ const column = this.table._.columns[key];
238
+ if (!column)
239
+ throw new Error(
240
+ `Column ${key} does not exist on table ${this.table._.name}`
241
+ );
242
+ return `${column._.name} = ?`;
243
+ }).join(", ");
244
+ this.query += ` SET ${setClause}`;
245
+ this.params.push(...entries.map(([, value]) => value));
246
+ const { sql, params } = this.build();
247
+ const result = await this.db.execute(sql, ...params);
248
+ return result.rowsAffected;
608
249
  }
609
- // --- Drizzle-style CRUD builders ---
610
- insert(table) {
611
- const self = this;
612
- return new class InsertBuilder {
613
- _table = table;
614
- _rows = [];
615
- _selectSql = null;
616
- _conflict = null;
617
- _returning = null;
618
- values(rowOrRows) {
619
- this._rows = Array.isArray(rowOrRows) ? rowOrRows : [rowOrRows];
620
- return this;
621
- }
622
- select(qb) {
623
- if (qb.toSQL) this._selectSql = qb.toSQL();
624
- else this._selectSql = qb.toSQL();
625
- return this;
626
- }
627
- returning(fields) {
628
- this._returning = fields ?? {};
629
- return this;
630
- }
631
- $returningId() {
632
- this._returning = "__RETURNING_ID__";
633
- return this;
634
- }
635
- onConflictDoNothing(opts) {
636
- const target = opts?.target ? Array.isArray(opts.target) ? opts.target.map((c) => c.name) : opts.target.name : void 0;
637
- this._conflict = {
638
- kind: "doNothing",
639
- target,
640
- where: opts?.where
641
- };
642
- return this;
643
- }
644
- onConflictDoUpdate(opts) {
645
- const target = Array.isArray(opts.target) ? opts.target.map((c) => c.name) : opts.target.name;
646
- this._conflict = {
647
- kind: "doUpdate",
648
- target,
649
- targetWhere: opts.targetWhere,
650
- set: opts.set,
651
- setWhere: opts.setWhere
652
- };
653
- return this;
654
- }
655
- async execute() {
656
- const db = await self.getDb();
657
- const tableName = getTableName(this._table);
658
- if (!tableName)
659
- throw new Error(
660
- "Invalid table passed to insert(): missing table name"
661
- );
662
- if (this._selectSql) {
663
- const cols = Object.keys(this._table._schema);
664
- let query = `INSERT INTO ${tableName} (${cols.join(", ")}) ${this._selectSql.clause}`;
665
- const bindings = [...this._selectSql.bindings];
666
- query += this._buildConflictClause();
667
- const ret = await this._executeWithReturning(db, query, bindings);
668
- return ret;
669
- }
670
- for (const data of this._rows) {
671
- let coerceValue2 = function(col, value) {
672
- if (col && col.mode === "boolean") {
673
- return value ? 1 : 0;
674
- }
675
- if (value instanceof Date) {
676
- if (col && col.mode === "timestamp_ms")
677
- return value.getTime();
678
- if (col && col.mode === "timestamp")
679
- return Math.floor(value.getTime() / 1e3);
680
- }
681
- return value;
682
- };
683
- var coerceValue = coerceValue2;
684
- const finalData = Object.assign({}, data);
685
- const schema = this._table._schema;
686
- for (const [key, col] of Object.entries(schema)) {
687
- if (finalData[key] === void 0) {
688
- if (col.defaultFn) {
689
- finalData[key] = coerceValue2(col, col.defaultFn());
690
- } else if (col.onUpdateFn) {
691
- finalData[key] = coerceValue2(col, col.onUpdateFn());
692
- }
693
- }
694
- }
695
- const entries = Object.entries(finalData);
696
- const keys = entries.map(([k]) => schema[k]?.name ?? k);
697
- const values = entries.map(([k, v]) => coerceValue2(schema[k], v));
698
- const placeholders = values.map(() => "?").join(", ");
699
- let query = `INSERT INTO ${tableName} (${keys.join(
700
- ", "
701
- )}) VALUES (${placeholders})`;
702
- const bindings = [...values];
703
- query += this._buildConflictClause();
704
- const ret = await this._executeWithReturning(db, query, bindings);
705
- if (ret !== void 0) return ret;
706
- }
707
- }
708
- _buildConflictClause() {
709
- if (!this._conflict) return "";
710
- if (this._conflict.kind === "doNothing") {
711
- const tgt2 = this._conflict.target ? Array.isArray(this._conflict.target) ? `(${this._conflict.target.join(", ")})` : `(${this._conflict.target})` : "";
712
- const where = this._conflict.where ? ` WHERE ${this._conflict.where.toSQL().clause}` : "";
713
- return ` ON CONFLICT ${tgt2} DO NOTHING${where}`;
714
- }
715
- const c = this._conflict;
716
- const tgt = Array.isArray(c.target) ? `(${c.target.join(", ")})` : `(${c.target})`;
717
- const setKeys = Object.keys(c.set ?? {});
718
- const setClause = setKeys.map((k) => {
719
- const v = c.set[k];
720
- return `${k} = ${typeof v === "object" && v && typeof v.toSQL === "function" ? v.toSQL().clause : "?"}`;
721
- }).join(", ");
722
- const targetWhere = c.targetWhere ? ` WHERE ${c.targetWhere.toSQL().clause}` : "";
723
- const setWhere = c.setWhere ? ` WHERE ${c.setWhere.toSQL().clause}` : "";
724
- return ` ON CONFLICT ${tgt}${targetWhere} DO UPDATE SET ${setClause}${setWhere}`;
725
- }
726
- async _executeWithReturning(db, query, bindings) {
727
- if (this._returning === null) {
728
- await db.execute(query, bindings);
729
- return void 0;
730
- }
731
- if (this._returning === "__RETURNING_ID__") {
732
- const rows = await db.select(`SELECT last_insert_rowid() as id`);
733
- return rows.map((r) => ({ id: r.id }));
734
- }
735
- if (typeof this._returning === "object") {
736
- const cols = Object.entries(
737
- this._returning
738
- ).map(
739
- ([alias, col]) => `${col.tableName}.${col.name} AS ${alias}`
740
- ).join(", ");
741
- const retSql = `${query} RETURNING ${cols}`;
742
- const res = await db.select(retSql, bindings);
743
- return res;
744
- }
745
- return void 0;
746
- }
747
- }();
250
+ };
251
+ var DeleteQueryBuilder = class extends BaseQueryBuilder {
252
+ constructor(db, table) {
253
+ super(db);
254
+ this.table = table;
255
+ this.query = `DELETE FROM ${table._.name}`;
748
256
  }
749
- update(table) {
750
- const self = this;
751
- return new class UpdateBuilder {
752
- _table = table;
753
- _data = null;
754
- _where = null;
755
- _orderBy = [];
756
- _limit = null;
757
- _from = null;
758
- _returning = null;
759
- set(data) {
760
- this._data = data;
761
- return this;
762
- }
763
- where(cond) {
764
- this._where = cond;
765
- return this;
766
- }
767
- orderBy(...clauses) {
768
- for (const c of clauses) {
769
- if (!c) continue;
770
- if (typeof c === "string") this._orderBy.push(c);
771
- else if (typeof c.toSQL === "function")
772
- this._orderBy.push(c);
773
- else this._orderBy.push(getQualifiedName(c));
774
- }
775
- return this;
776
- }
777
- limit(n) {
778
- this._limit = n;
779
- return this;
780
- }
781
- from(tbl) {
782
- this._from = tbl;
783
- return this;
784
- }
785
- returning(fields) {
786
- this._returning = fields ?? {};
787
- return this;
788
- }
789
- async execute() {
790
- if (!this._data)
791
- throw new Error("Update requires set() before execute()");
792
- const db = await self.getDb();
793
- const tableName = getTableName(this._table);
794
- if (!tableName)
795
- throw new Error(
796
- "Invalid table passed to update(): missing table name"
797
- );
798
- const schema = this._table._schema;
799
- const dataToSet = { ...this._data };
800
- for (const [key, col] of Object.entries(schema)) {
801
- if (!(key in dataToSet) && col.onUpdateFn) {
802
- const v = col.onUpdateFn();
803
- if (col.mode === "boolean") dataToSet[key] = v ? 1 : 0;
804
- else if (v instanceof Date) {
805
- if (col.mode === "timestamp_ms")
806
- dataToSet[key] = v.getTime();
807
- else if (col.mode === "timestamp")
808
- dataToSet[key] = Math.floor(v.getTime() / 1e3);
809
- else dataToSet[key] = v;
810
- } else dataToSet[key] = v;
811
- }
812
- }
813
- const setParts = [];
814
- const bindings = [];
815
- for (const [k, v] of Object.entries(dataToSet)) {
816
- if (v === void 0) continue;
817
- if (v && typeof v === "object" && typeof v.toSQL === "function") {
818
- const s = v.toSQL();
819
- const colName = schema[k]?.name ?? k;
820
- setParts.push(`${colName} = ${s.clause}`);
821
- bindings.push(...s.bindings);
822
- } else {
823
- const colName = schema[k]?.name ?? k;
824
- let val = v;
825
- const col = schema[k];
826
- if (col && col.mode === "boolean") val = v ? 1 : 0;
827
- else if (v instanceof Date) {
828
- if (col && col.mode === "timestamp_ms")
829
- val = v.getTime();
830
- else if (col && col.mode === "timestamp")
831
- val = Math.floor(v.getTime() / 1e3);
832
- }
833
- setParts.push(`${colName} = ?`);
834
- bindings.push(val);
835
- }
836
- }
837
- let query = `UPDATE ${tableName} SET ${setParts.join(", ")}`;
838
- if (this._from) query += ` FROM ${this._from._tableName}`;
839
- if (this._where) {
840
- if (typeof this._where.toSQL === "function") {
841
- const sql2 = this._where.toSQL();
842
- query += ` WHERE ${sql2.clause}`;
843
- bindings.push(...sql2.bindings);
844
- } else {
845
- const entries = Object.entries(this._where);
846
- if (entries.length > 0) {
847
- query += ` WHERE ${entries.map(([k]) => `${schema[k]?.name ?? k} = ?`).join(" AND ")}`;
848
- bindings.push(...entries.map(([, v]) => v));
849
- }
850
- }
851
- }
852
- if (this._orderBy.length > 0) {
853
- const ordParts = [];
854
- for (const ob of this._orderBy) {
855
- if (typeof ob === "string") ordParts.push(ob);
856
- else {
857
- const s = ob.toSQL();
858
- ordParts.push(s.clause);
859
- bindings.push(...s.bindings);
860
- }
861
- }
862
- query += ` ORDER BY ${ordParts.join(", ")}`;
863
- }
864
- if (this._limit !== null) {
865
- query += ` LIMIT ?`;
866
- bindings.push(this._limit);
867
- }
868
- if (this._returning) {
869
- const cols = Object.entries(
870
- this._returning
871
- ).map(
872
- ([alias, col]) => `${col.tableName}.${col.name} AS ${alias}`
873
- ).join(", ");
874
- const retSql = `${query} RETURNING ${cols}`;
875
- return await db.select(retSql, bindings);
876
- }
877
- await db.execute(query, bindings);
878
- }
879
- }();
257
+ async execute() {
258
+ const { sql, params } = this.build();
259
+ const result = await this.db.execute(sql, ...params);
260
+ return result.rowsAffected;
880
261
  }
881
- delete(table) {
882
- const self = this;
883
- return new class DeleteBuilder {
884
- _table = table;
885
- _where = null;
886
- _orderBy = [];
887
- _limit = null;
888
- _returning = null;
889
- where(cond) {
890
- this._where = cond;
891
- return this;
892
- }
893
- orderBy(...clauses) {
894
- for (const c of clauses) {
895
- if (!c) continue;
896
- if (typeof c === "string") this._orderBy.push(c);
897
- else if (typeof c.toSQL === "function")
898
- this._orderBy.push(c);
899
- else this._orderBy.push(getQualifiedName(c));
900
- }
901
- return this;
902
- }
903
- limit(n) {
904
- this._limit = n;
905
- return this;
906
- }
907
- returning(fields) {
908
- this._returning = fields ?? {};
909
- return this;
910
- }
911
- async execute() {
912
- const db = await self.getDb();
913
- const tableName = getTableName(this._table);
914
- if (!tableName)
915
- throw new Error(
916
- "Invalid table passed to delete(): missing table name"
917
- );
918
- let query = `DELETE FROM ${tableName}`;
919
- const bindings = [];
920
- if (this._where) {
921
- if (typeof this._where.toSQL === "function") {
922
- const sql2 = this._where.toSQL();
923
- query += ` WHERE ${sql2.clause}`;
924
- bindings.push(...sql2.bindings);
925
- } else {
926
- const entries = Object.entries(this._where);
927
- if (entries.length > 0) {
928
- const schema = this._table._schema;
929
- query += ` WHERE ${entries.map(([k]) => `${schema[k]?.name ?? k} = ?`).join(" AND ")}`;
930
- bindings.push(...entries.map(([, v]) => v));
931
- }
932
- }
933
- }
934
- if (this._orderBy.length > 0) {
935
- const ordParts = [];
936
- for (const ob of this._orderBy) {
937
- if (typeof ob === "string") ordParts.push(ob);
938
- else {
939
- const s = ob.toSQL();
940
- ordParts.push(s.clause);
941
- bindings.push(...s.bindings);
942
- }
943
- }
944
- query += ` ORDER BY ${ordParts.join(", ")}`;
945
- }
946
- if (this._limit !== null) {
947
- query += ` LIMIT ?`;
948
- bindings.push(this._limit);
949
- }
950
- if (this._returning) {
951
- const cols = Object.entries(
952
- this._returning
953
- ).map(
954
- ([alias, col]) => `${col.tableName}.${col.name} AS ${alias}`
955
- ).join(", ");
956
- const retSql = `${query} RETURNING ${cols}`;
957
- return await db.select(retSql, bindings);
958
- }
959
- await db.execute(query, bindings);
262
+ };
263
+ var TauriORM = class {
264
+ constructor(db, schema = void 0) {
265
+ this.db = db;
266
+ if (schema) {
267
+ for (const table of Object.values(schema)) {
268
+ this.tables.set(table._.name, table);
960
269
  }
961
- }();
962
- }
963
- // legacy direct methods removed in favor of builder APIs
964
- // legacy direct methods removed in favor of builder APIs
965
- // legacy direct methods removed in favor of builder APIs
966
- async run(query, bindings = []) {
967
- const db = await this.getDb();
968
- await db.execute(query, bindings);
969
- }
970
- // --- Migrations API ---
971
- formatDefaultValue(col) {
972
- const dv = col.defaultValue;
973
- if (dv === void 0) return null;
974
- if (dv && typeof dv === "object" && "raw" in dv) {
975
- return dv.raw;
976
- }
977
- if (dv instanceof Date) {
978
- const isMs = col.mode === "timestamp_ms";
979
- const num = isMs ? dv.getTime() : Math.floor(dv.getTime() / 1e3);
980
- return String(num);
981
- }
982
- if (col.mode === "boolean") {
983
- return String(dv ? 1 : 0);
984
- }
985
- if (typeof dv === "string") {
986
- return `'${dv.replace(/'/g, "''")}'`;
987
270
  }
988
- return String(dv);
989
271
  }
990
- generateCreateTableSql(table) {
991
- const tableName = getTableName(table);
992
- if (!tableName)
993
- throw new Error("Invalid table passed to DDL: missing table name");
994
- const columns = Object.values(table._schema);
995
- const columnDefs = columns.map((col) => {
996
- let def = `${col.name} ${col.type}`;
997
- if (col.isPrimaryKey) {
998
- def += col.autoIncrement ? " PRIMARY KEY AUTOINCREMENT" : " PRIMARY KEY";
999
- }
1000
- if (col.isNotNull) def += " NOT NULL";
1001
- if (col.defaultValue !== void 0) {
1002
- const formatted = this.formatDefaultValue(col);
1003
- if (formatted !== null) def += ` DEFAULT ${formatted}`;
1004
- }
1005
- if (col.references && !col.isPrimaryKey) {
1006
- def += ` REFERENCES ${col.references.table} (${col.references.column})`;
1007
- if (col.references.onDelete)
1008
- def += ` ON DELETE ${col.references.onDelete.toUpperCase()}`;
1009
- if (col.references.onUpdate)
1010
- def += ` ON UPDATE ${col.references.onUpdate.toUpperCase()}`;
1011
- }
1012
- return def;
1013
- });
1014
- const tableConstraints = [];
1015
- const constraints = table._constraints;
1016
- if (constraints && constraints.length) {
1017
- for (const spec of constraints) {
1018
- if (spec.expr) {
1019
- const name = spec.name;
1020
- const expr = spec.expr.raw ?? spec.expr?.raw ?? String(spec.expr);
1021
- tableConstraints.push(
1022
- name ? `CONSTRAINT ${name} CHECK (${expr})` : `CHECK (${expr})`
1023
- );
1024
- continue;
272
+ tables = /* @__PURE__ */ new Map();
273
+ async migrate() {
274
+ for (const table of this.tables.values()) {
275
+ const columnsSql = Object.entries(table._.columns).map(([name, col]) => {
276
+ let sql = `${col._.name} ${col.type}`;
277
+ if (col.options.primaryKey) sql += " PRIMARY KEY";
278
+ if (col._.autoincrement) sql += " AUTOINCREMENT";
279
+ if (col._.notNull) sql += " NOT NULL";
280
+ if (col.options.unique) sql += " UNIQUE";
281
+ if (col.options.default !== void 0) {
282
+ const value = col.options.default;
283
+ sql += ` DEFAULT ${typeof value === "string" ? `'${value}'` : value}`;
1025
284
  }
1026
- if (spec.foreignColumns) {
1027
- const name = spec.name;
1028
- const cols = spec.columns.join(", ");
1029
- const fTable = spec.foreignTable;
1030
- const fCols = spec.foreignColumns.join(", ");
1031
- let clause = `${name ? `CONSTRAINT ${name} ` : ""}FOREIGN KEY (${cols}) REFERENCES ${fTable} (${fCols})`;
1032
- if (spec.onDelete)
1033
- clause += ` ON DELETE ${String(
1034
- spec.onDelete
1035
- ).toUpperCase()}`;
1036
- if (spec.onUpdate)
1037
- clause += ` ON UPDATE ${String(
1038
- spec.onUpdate
1039
- ).toUpperCase()}`;
1040
- tableConstraints.push(clause);
1041
- continue;
285
+ if (col.options.references) {
286
+ sql += ` REFERENCES ${col.options.references.table._.name}(${col.options.references.column._.name})`;
1042
287
  }
1043
- if (spec.columns) {
1044
- const cols = spec.columns.join(", ");
1045
- const name = spec.name;
1046
- const isPk = spec.kind === "primaryKey" || name && name.toLowerCase().includes("pk");
1047
- if (isPk) {
1048
- tableConstraints.push(
1049
- name ? `CONSTRAINT ${name} PRIMARY KEY (${cols})` : `PRIMARY KEY (${cols})`
1050
- );
1051
- } else {
1052
- tableConstraints.push(
1053
- name ? `CONSTRAINT ${name} UNIQUE (${cols})` : `UNIQUE (${cols})`
1054
- );
1055
- }
1056
- continue;
1057
- }
1058
- }
288
+ return sql;
289
+ }).join(", ");
290
+ const createSql = `CREATE TABLE IF NOT EXISTS ${table._.name} (${columnsSql})`;
291
+ await this.db.execute(createSql);
1059
292
  }
1060
- const parts = [...columnDefs, ...tableConstraints];
1061
- return `CREATE TABLE IF NOT EXISTS ${tableName} (${parts.join(", ")});`;
1062
- }
1063
- async createTableIfNotExists(table) {
1064
- const sql2 = this.generateCreateTableSql(table);
1065
- await this.run(sql2);
1066
- await this.createIndexesForTable(table);
1067
- }
1068
- async createTablesIfNotExist(tables) {
1069
- for (const t of tables) {
1070
- await this.createTableIfNotExists(t);
1071
- }
1072
- }
1073
- generateCreateIndexSqls(table) {
1074
- const tableName = table._tableName;
1075
- const indexes = table._indexes || [];
1076
- const stmts = [];
1077
- for (const idx of indexes) {
1078
- const unique2 = idx.unique ? "UNIQUE " : "";
1079
- if (!idx.name) continue;
1080
- const colList = Array.isArray(idx.columns) ? idx.columns : [];
1081
- if (colList.length === 0) continue;
1082
- const cols = `(${colList.join(", ")})`;
1083
- const where = idx.where?.raw ? ` WHERE ${idx.where.raw}` : "";
1084
- stmts.push(
1085
- `CREATE ${unique2}INDEX IF NOT EXISTS ${idx.name} ON ${tableName} ${cols}${where};`
1086
- );
1087
- }
1088
- return stmts;
1089
- }
1090
- async createIndexesForTable(table) {
1091
- const stmts = this.generateCreateIndexSqls(table);
1092
- for (const s of stmts) await this.run(s);
1093
- }
1094
- async ensureMigrationsTable() {
1095
- await this.run(
1096
- `CREATE TABLE IF NOT EXISTS _migrations (name TEXT PRIMARY KEY, applied_at INTEGER NOT NULL)`
1097
- );
1098
293
  }
1099
- async hasMigration(name) {
1100
- const db = await this.getDb();
1101
- const rows = await db.select(
1102
- `SELECT name FROM _migrations WHERE name = ?`,
1103
- [name]
1104
- );
1105
- return Array.isArray(rows) && rows.length > 0;
1106
- }
1107
- async recordMigration(name) {
1108
- const db = await this.getDb();
1109
- await db.execute(
1110
- `INSERT INTO _migrations (name, applied_at) VALUES (?, ?)`,
1111
- [name, Date.now()]
1112
- );
294
+ select(table, columns) {
295
+ return new SelectQueryBuilder(this.db, table, columns);
1113
296
  }
1114
- async migrate(tables, options) {
1115
- const track = options?.track ?? true;
1116
- if (track) {
1117
- await this.ensureMigrationsTable();
1118
- }
1119
- await this.forcePushForTables(tables, { preserveData: true });
1120
- if (track) {
1121
- const name = options?.name ?? `init:${tables.map((t) => t._tableName).join(",")}`;
1122
- const already = await this.hasMigration(name);
1123
- if (!already) await this.recordMigration(name);
1124
- }
297
+ insert(table) {
298
+ return new InsertQueryBuilder(this.db, table);
1125
299
  }
1126
- // Configure schema and relations, and generate db.query automatically
1127
- configure(tables, relDefs) {
1128
- this._tables = tables;
1129
- this._relations = relDefs ?? {};
1130
- this.query = makeQueryAPI(
1131
- tables,
1132
- this._relations ?? {},
1133
- this.getDb.bind(this)
1134
- );
1135
- return this;
300
+ update(table) {
301
+ return new UpdateQueryBuilder(this.db, table);
1136
302
  }
1137
- // Convenience: migrate from configured tables
1138
- async migrateConfigured(options) {
1139
- if (!this._tables)
1140
- throw new Error("No tables configured. Call db.configure({...}) first.");
1141
- await this.migrate(Object.values(this._tables), options);
1142
- await this.setSchemaMeta("schema_signature", this.computeModelSignature());
303
+ delete(table) {
304
+ return new DeleteQueryBuilder(this.db, table);
1143
305
  }
1144
- // --- Schema diff and CLI-like helpers ---
1145
- async diffSchema() {
1146
- if (!this._tables) throw new Error("No tables configured.");
1147
- const dbi = await this.getDb();
1148
- const configuredNames = Object.values(this._tables).map(
1149
- (t) => getTableName(t)
1150
- );
1151
- const existing = await dbi.select(
1152
- `SELECT name FROM sqlite_master WHERE type='table'`
1153
- );
1154
- const existingNames = existing.map((r) => r.name);
1155
- const extraTables = existingNames.filter(
1156
- (n) => !configuredNames.includes(n)
1157
- );
1158
- const missingTables = configuredNames.filter(
1159
- (n) => !existingNames.includes(n)
1160
- );
1161
- const tables = {};
1162
- for (const tbl of Object.values(this._tables)) {
1163
- const tableName = getTableName(tbl);
1164
- if (!existingNames.includes(tableName)) {
1165
- tables[tableName] = {
1166
- missingColumns: Object.keys(tbl._schema),
1167
- extraColumns: [],
1168
- changedColumns: []
1169
- };
1170
- continue;
1171
- }
1172
- const cols = await dbi.select(`PRAGMA table_info('${tableName}')`);
1173
- const colMap = new Map(cols.map((c) => [c.name, c]));
1174
- const modelCols = Object.values(
1175
- tbl._schema
1176
- );
1177
- const missingColumns = [];
1178
- const extraColumns = [];
1179
- const changedColumns = [];
1180
- const modelNamesSet = new Set(modelCols.map((c) => c.name));
1181
- for (const m of modelCols) {
1182
- const info = colMap.get(m.name);
1183
- if (!info) {
1184
- missingColumns.push(m.name);
1185
- continue;
1186
- }
1187
- const diffs = {};
1188
- if ((info.type || "").toUpperCase() !== m.type.toUpperCase())
1189
- diffs.type = true;
1190
- if (!!info.pk !== !!m.isPrimaryKey) diffs.pk = true;
1191
- if (!!info.notnull !== !!m.isNotNull) diffs.notNull = true;
1192
- const modelDv = m.defaultValue && typeof m.defaultValue === "object" && m.defaultValue.raw ? m.defaultValue.raw : m.defaultValue ?? null;
1193
- if ((info.dflt_value ?? null) !== modelDv)
1194
- diffs.default = true;
1195
- if (Object.keys(diffs).length)
1196
- changedColumns.push({ name: m.name, diffs });
1197
- }
1198
- for (const c of cols)
1199
- if (!modelNamesSet.has(c.name)) extraColumns.push(c.name);
1200
- tables[tableName] = { missingColumns, extraColumns, changedColumns };
306
+ async transaction(callback) {
307
+ await this.db.execute("BEGIN TRANSACTION");
308
+ try {
309
+ const result = await callback(this);
310
+ await this.db.execute("COMMIT");
311
+ return result;
312
+ } catch (error) {
313
+ await this.db.execute("ROLLBACK");
314
+ throw error;
1201
315
  }
1202
- return { extraTables, missingTables, tables };
1203
- }
1204
- async generate() {
1205
- if (!this._tables) throw new Error("No tables configured.");
1206
- return {
1207
- statements: Object.values(this._tables).map(
1208
- (t) => this.buildCreateTableSQL(t)
1209
- )
1210
- };
1211
- }
1212
- async migrateCli(opts) {
1213
- return this.migrateConfigured(opts);
1214
- }
1215
- async push(opts) {
1216
- return this.forcePush(opts);
1217
- }
1218
- async pull() {
1219
- return this.pullSchema();
1220
- }
1221
- async studio() {
1222
- const dbi = await this.getDb();
1223
- return { driver: "sqlite", path: dbi.path };
1224
316
  }
1225
317
  // --- Schema detection / signature ---
1226
318
  async ensureSchemaMeta() {
1227
- await this.run(
319
+ await this.db.execute(
1228
320
  `CREATE TABLE IF NOT EXISTS _schema_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)`
1229
321
  );
1230
322
  }
1231
323
  async getSchemaMeta(key) {
1232
- const dbi = await this.getDb();
1233
324
  await this.ensureSchemaMeta();
1234
- const rows = await dbi.select(
325
+ const rows = await this.db.select(
1235
326
  `SELECT value FROM _schema_meta WHERE key = ?`,
1236
327
  [key]
1237
328
  );
1238
329
  return rows?.[0]?.value ?? null;
1239
330
  }
1240
331
  async setSchemaMeta(key, value) {
1241
- const dbi = await this.getDb();
1242
332
  await this.ensureSchemaMeta();
1243
- await dbi.execute(
333
+ await this.db.execute(
1244
334
  `INSERT INTO _schema_meta(key, value) VALUES(?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value`,
1245
335
  [key, value]
1246
336
  );
1247
337
  }
1248
338
  normalizeColumn(col) {
1249
339
  return {
1250
- name: col.name,
340
+ name: col._.name,
1251
341
  type: col.type,
1252
- pk: !!col.isPrimaryKey,
1253
- ai: !!col.autoIncrement,
1254
- nn: !!col.isNotNull,
1255
- dv: col.defaultValue && typeof col.defaultValue === "object" && col.defaultValue.raw ? { raw: col.defaultValue.raw } : col.defaultValue ?? null
342
+ pk: !!col.options.primaryKey,
343
+ ai: !!col._.autoincrement,
344
+ nn: !!col._.notNull,
345
+ dv: col.options.default && typeof col.options.default === "object" && col.options.default.raw ? { raw: col.options.default.raw } : col.options.default ?? null
1256
346
  };
1257
347
  }
1258
348
  computeModelSignature() {
1259
- if (!this._tables) return "";
1260
- const entries = Object.entries(this._tables).map(([k, tbl]) => {
1261
- const cols = Object.values(
1262
- tbl._schema
1263
- ).map((c) => this.normalizeColumn(c)).sort((a, b) => a.name.localeCompare(b.name));
1264
- return { table: tbl._tableName, columns: cols };
349
+ const entries = Array.from(this.tables.values()).map((tbl) => {
350
+ const cols = Object.values(tbl._.columns).map((c) => this.normalizeColumn(c)).sort((a, b) => a.name.localeCompare(b.name));
351
+ return { table: tbl._.name, columns: cols };
1265
352
  });
1266
353
  entries.sort((a, b) => a.table.localeCompare(b.table));
1267
354
  return JSON.stringify(entries);
@@ -1269,22 +356,15 @@ var TauriORM = class {
1269
356
  getSchemaSignature() {
1270
357
  return this.computeModelSignature();
1271
358
  }
1272
- async printSchemaDiff() {
1273
- const diff = await this.diffSchema();
1274
- console.log("Schema diff:", JSON.stringify(diff, null, 2));
1275
- }
1276
359
  async isSchemaDirty() {
1277
360
  const sig = this.computeModelSignature();
1278
361
  const stored = await this.getSchemaMeta("schema_signature");
1279
362
  return { dirty: sig !== stored, current: sig, stored };
1280
363
  }
1281
- async migrateIfDirty(options) {
364
+ async migrateIfDirty() {
1282
365
  const status = await this.isSchemaDirty();
1283
- if (!this._tables) throw new Error("No tables configured.");
1284
366
  if (status.dirty) {
1285
- await this.forcePushForTables(Object.values(this._tables), {
1286
- preserveData: true
1287
- });
367
+ await this.migrate();
1288
368
  await this.setSchemaMeta(
1289
369
  "schema_signature",
1290
370
  this.computeModelSignature()
@@ -1293,454 +373,45 @@ var TauriORM = class {
1293
373
  }
1294
374
  return false;
1295
375
  }
1296
- // Pull current DB schema (minimal) for configured tables
1297
- async pullSchema() {
1298
- if (!this._tables) throw new Error("No tables configured.");
1299
- const dbi = await this.getDb();
1300
- const result = {};
1301
- for (const tbl of Object.values(this._tables)) {
1302
- const name = tbl._tableName;
1303
- const cols = await dbi.select(`PRAGMA table_info('${name}')`);
1304
- result[name] = cols.map((c) => ({
1305
- name: c.name,
1306
- type: c.type,
1307
- notnull: !!c.notnull,
1308
- pk: !!c.pk,
1309
- dflt_value: c.dflt_value ?? null
1310
- }));
1311
- }
1312
- return result;
1313
- }
1314
- buildCreateTableSQL(table) {
1315
- return this.generateCreateTableSql(table);
1316
- }
1317
- async tableExists(name) {
1318
- const dbi = await this.getDb();
1319
- const rows = await dbi.select(
1320
- `SELECT name FROM sqlite_master WHERE type='table' AND name = ?`,
1321
- [name]
1322
- );
1323
- return rows.length > 0;
1324
- }
1325
- // Force push model to DB: add missing tables/columns, rebuild tables if incompatible
1326
- async forcePush(options) {
1327
- if (!this._tables) throw new Error("No tables configured.");
1328
- await this.forcePushForTables(Object.values(this._tables), options);
1329
- }
1330
- async forcePushForTables(tables, options) {
1331
- const dbi = await this.getDb();
1332
- const preserve = options?.preserveData !== false;
1333
- for (const tbl of tables) {
1334
- const tableName = getTableName(tbl);
1335
- const exists2 = await this.tableExists(tableName);
1336
- if (!exists2) {
1337
- await this.run(this.buildCreateTableSQL(tbl));
1338
- await this.createIndexesForTable(tbl);
1339
- continue;
1340
- }
1341
- const existingCols = await dbi.select(
1342
- `PRAGMA table_info('${tableName}')`
1343
- );
1344
- const existingMap = new Map(existingCols.map((c) => [c.name, c]));
1345
- const modelCols = Object.values(
1346
- tbl._schema
1347
- );
1348
- const missing = [];
1349
- let requiresRebuild = false;
1350
- for (const m of modelCols) {
1351
- const info = existingMap.get(m.name);
1352
- if (!info) {
1353
- missing.push(m);
1354
- continue;
1355
- }
1356
- const typeDiff = (info.type || "").toUpperCase() !== m.type.toUpperCase();
1357
- const pkDiff = !!info.pk !== !!m.isPrimaryKey;
1358
- const nnDiff = !!info.notnull !== !!m.isNotNull;
1359
- const modelDv = m.defaultValue && typeof m.defaultValue === "object" && m.defaultValue.raw ? m.defaultValue.raw : m.defaultValue ?? null;
1360
- const defDiff = (info.dflt_value ?? null) !== modelDv;
1361
- if (typeDiff || pkDiff || nnDiff && !modelDv || defDiff) {
1362
- requiresRebuild = true;
1363
- }
1364
- }
1365
- if (requiresRebuild) {
1366
- const tmp = `_new_${tableName}`;
1367
- await this.run(this.buildCreateTableSQL(tbl));
1368
- await this.run(
1369
- this.buildCreateTableSQL({ ...tbl, _tableName: tmp })
1370
- );
1371
- const existingNames = existingCols.map((c) => c.name);
1372
- const modelNames = modelCols.map((c) => c.name);
1373
- const shared = existingNames.filter((n) => modelNames.includes(n));
1374
- if (preserve && shared.length > 0) {
1375
- await this.run(
1376
- `INSERT INTO ${tmp} (${shared.join(", ")}) SELECT ${shared.join(
1377
- ", "
1378
- )} FROM ${tableName}`
1379
- );
1380
- }
1381
- await this.run(`DROP TABLE ${tableName}`);
1382
- await this.run(`ALTER TABLE ${tmp} RENAME TO ${tableName}`);
1383
- await this.createIndexesForTable(tbl);
1384
- } else {
1385
- for (const m of missing) {
1386
- let clause = `${m.name} ${m.type}`;
1387
- if (m.isNotNull) clause += " NOT NULL";
1388
- if (m.defaultValue !== void 0) {
1389
- const formatted = this.formatDefaultValue(m);
1390
- if (formatted !== null) clause += ` DEFAULT ${formatted}`;
1391
- }
1392
- await this.run(`ALTER TABLE ${tableName} ADD COLUMN ${clause}`);
1393
- }
1394
- await this.createIndexesForTable(tbl);
1395
- }
1396
- }
1397
- await this.setSchemaMeta("schema_signature", this.computeModelSignature());
1398
- }
1399
376
  };
1400
- function relations(baseTable, builder) {
1401
- const ctx = {
1402
- one: (table, cfg) => ({ kind: "one", table, cfg }),
1403
- many: (table, cfg) => ({ kind: "many", table, cfg })
1404
- };
1405
- const rels = builder(ctx);
1406
- return rels;
1407
- }
1408
- function getPrimaryKey(table) {
1409
- const cols = Object.values(table._schema);
1410
- return cols.find((c) => c.isPrimaryKey) || cols.find((c) => c.name === "id") || cols[0];
1411
- }
1412
- function guessChildFk(child, base, rel) {
1413
- const childCols = Object.values(child._schema);
1414
- if (rel && rel.kind === "one" && rel.cfg?.fields?.[0])
1415
- return rel.cfg.fields[0];
1416
- const basePk = getPrimaryKey(base);
1417
- const guessNames = [
1418
- `${base._tableName}_id`,
1419
- `${base._tableName}Id`,
1420
- `${basePk.name}`,
1421
- `${base._tableName.slice(0, -1)}Id`
1422
- ];
1423
- return childCols.find((c) => guessNames.includes(c.name)) || childCols.find((c) => /.*_id$/i.test(c.name)) || null;
1424
- }
1425
- function guessOneRelationJoin(base, rel) {
1426
- const child = rel.table;
1427
- const basePk = getPrimaryKey(base);
1428
- const childCols = Object.values(child._schema);
1429
- if (rel.cfg?.fields && rel.cfg?.references && rel.cfg.fields[0] && rel.cfg.references[0]) {
1430
- const fk = rel.cfg.fields[0];
1431
- const ref = rel.cfg.references[0];
1432
- if (childCols.some((c) => c.name === fk.name)) {
1433
- return { lhsTable: child, lhsCol: fk, rhsTable: base, rhsCol: ref };
1434
- }
1435
- const baseCols = Object.values(base._schema);
1436
- if (baseCols.some((c) => c.name === fk.name)) {
1437
- return { lhsTable: base, lhsCol: fk, rhsTable: child, rhsCol: ref };
1438
- }
1439
- }
1440
- const childFk = guessChildFk(child, base, rel);
1441
- if (!childFk) return null;
1442
- return { lhsTable: child, lhsCol: childFk, rhsTable: base, rhsCol: basePk };
1443
- }
1444
- function isFlatWith(spec) {
1445
- return Object.values(spec).every((v) => typeof v === "boolean");
1446
- }
1447
- function makeQueryAPI(tables, relDefs, dbProvider) {
1448
- const api = {};
1449
- const tableKeyByName = {};
1450
- for (const [k, t] of Object.entries(tables)) tableKeyByName[t._tableName] = k;
1451
- for (const [tblKey, tbl] of Object.entries(tables)) {
1452
- api[tblKey] = {
1453
- async findMany(opts) {
1454
- const base = tbl;
1455
- const withSpec = opts?.with ?? {};
1456
- const dbi = await dbProvider();
1457
- const rels = relDefs[tblKey] ?? {};
1458
- if (opts?.join && isFlatWith(withSpec)) {
1459
- const baseCols = Object.values(base._schema);
1460
- const basePk = baseCols.find((c) => c.isPrimaryKey) || baseCols.find((c) => c.name === "id") || baseCols[0];
1461
- const selectParts = [];
1462
- let baseSelected2;
1463
- if (opts?.columns && !Array.isArray(opts.columns)) {
1464
- baseSelected2 = Object.entries(opts.columns).filter(([, v]) => !!v).map(([k]) => k);
1465
- } else if (Array.isArray(opts?.columns) && opts.columns.length > 0) {
1466
- baseSelected2 = opts.columns;
1467
- } else {
1468
- baseSelected2 = baseCols.map((c) => c.name);
1469
- }
1470
- for (const name of baseSelected2)
1471
- selectParts.push(`${base._tableName}.${name} AS __base_${name}`);
1472
- const joins = [];
1473
- const relColsMap = {};
1474
- const fkMap = {};
1475
- for (const [relName, enabled] of Object.entries(withSpec)) {
1476
- if (!enabled) continue;
1477
- const rel = rels[relName];
1478
- if (!rel) continue;
1479
- const child = rel.table;
1480
- const childCols = Object.values(child._schema);
1481
- const childPk = childCols.find((c) => c.isPrimaryKey) || childCols.find((c) => c.name === "id") || null;
1482
- if (rel.kind === "one") {
1483
- const mapping = guessOneRelationJoin(base, rel);
1484
- if (!mapping) continue;
1485
- if (mapping.lhsTable._tableName === child._tableName) {
1486
- fkMap[relName] = { childFk: mapping.lhsCol, childPk };
1487
- joins.push(
1488
- `LEFT JOIN ${child._tableName} ON ${mapping.lhsTable._tableName}.${mapping.lhsCol.name} = ${mapping.rhsTable._tableName}.${mapping.rhsCol.name}`
1489
- );
1490
- } else {
1491
- fkMap[relName] = { childFk: mapping.rhsCol, childPk };
1492
- joins.push(
1493
- `LEFT JOIN ${child._tableName} ON ${mapping.lhsTable._tableName}.${mapping.lhsCol.name} = ${mapping.rhsTable._tableName}.${mapping.rhsCol.name}`
1494
- );
1495
- }
1496
- } else {
1497
- const childFk = guessChildFk(child, base, rel);
1498
- if (!childFk) continue;
1499
- fkMap[relName] = { childFk, childPk };
1500
- joins.push(
1501
- `LEFT JOIN ${child._tableName} ON ${child._tableName}.${childFk.name} = ${base._tableName}.${basePk.name}`
1502
- );
1503
- }
1504
- const selected = typeof enabled === "object" && enabled.columns?.length ? enabled.columns : childCols.map((c) => c.name);
1505
- relColsMap[relName] = selected;
1506
- for (const name of selected)
1507
- selectParts.push(
1508
- `${child._tableName}.${name} AS __rel_${relName}_${name}`
1509
- );
1510
- }
1511
- let sqlText = `SELECT ${selectParts.join(", ")} FROM ${base._tableName}${joins.length ? " " + joins.join(" ") : ""}`;
1512
- const bindings = [];
1513
- if (opts?.where) {
1514
- if (typeof opts.where === "function") {
1515
- const w = opts.where(base, { eq, ne, gt, gte, lt, lte, like }).toSQL();
1516
- sqlText += ` WHERE ${w.clause}`;
1517
- bindings.push(...w.bindings);
1518
- } else if (typeof opts.where.toSQL === "function") {
1519
- const w = opts.where.toSQL();
1520
- sqlText += ` WHERE ${w.clause}`;
1521
- bindings.push(...w.bindings);
1522
- } else {
1523
- const entries = Object.entries(opts.where);
1524
- if (entries.length > 0) {
1525
- sqlText += ` WHERE ${entries.map(([k]) => `${base._tableName}.${k} = ?`).join(" AND ")}`;
1526
- bindings.push(...entries.map(([, v]) => v));
1527
- }
1528
- }
1529
- }
1530
- const orderByClauses = typeof opts?.orderBy === "function" ? opts.orderBy(base, { asc, desc }) : opts?.orderBy;
1531
- if (orderByClauses?.length)
1532
- sqlText += ` ORDER BY ${orderByClauses.join(", ")}`;
1533
- if (typeof opts?.limit === "number")
1534
- sqlText += ` LIMIT ${opts.limit}`;
1535
- if (typeof opts?.offset === "number")
1536
- sqlText += ` OFFSET ${opts.offset}`;
1537
- const rows = await dbi.select(sqlText, bindings);
1538
- const groups = /* @__PURE__ */ new Map();
1539
- for (const row of rows) {
1540
- const baseObj = {};
1541
- for (const name of baseSelected2)
1542
- baseObj[name] = row[`__base_${name}`];
1543
- const baseKey = baseObj[basePk.name];
1544
- if (!groups.has(baseKey)) {
1545
- const seed = { ...baseObj };
1546
- for (const [relName, enabled] of Object.entries(withSpec)) {
1547
- if (!enabled) continue;
1548
- const rel = rels[relName];
1549
- if (!rel) continue;
1550
- seed[relName] = rel.kind === "many" ? [] : null;
1551
- }
1552
- groups.set(baseKey, seed);
1553
- }
1554
- const acc = groups.get(baseKey);
1555
- for (const [relName, enabled] of Object.entries(withSpec)) {
1556
- if (!enabled) continue;
1557
- const rel = rels[relName];
1558
- if (!rel) continue;
1559
- const childCols = relColsMap[relName];
1560
- const childObj = {};
1561
- let allNull = true;
1562
- for (const name of childCols) {
1563
- const v = row[`__rel_${relName}_${name}`];
1564
- childObj[name] = v;
1565
- if (v !== null && v !== void 0) allNull = false;
1566
- }
1567
- if (allNull) continue;
1568
- if (rel.kind === "many") {
1569
- const childPk = fkMap[relName].childPk;
1570
- if (childPk) {
1571
- if (!acc[relName]) acc[relName] = [];
1572
- const exists2 = acc[relName].some(
1573
- (r) => r[childPk.name] === childObj[childPk.name]
1574
- );
1575
- if (!exists2) acc[relName].push(childObj);
1576
- } else {
1577
- acc[relName].push(childObj);
1578
- }
1579
- } else {
1580
- acc[relName] = childObj;
1581
- }
1582
- }
1583
- }
1584
- return Array.from(groups.values());
1585
- }
1586
- let baseSelected;
1587
- if (opts?.columns && !Array.isArray(opts.columns)) {
1588
- baseSelected = Object.entries(opts.columns).filter(([, v]) => !!v).map(([k]) => k);
1589
- } else if (Array.isArray(opts?.columns) && opts.columns.length > 0) {
1590
- baseSelected = opts.columns;
1591
- } else {
1592
- baseSelected = Object.values(base._schema).map(
1593
- (c) => c.name
1594
- );
1595
- }
1596
- let baseSql = `SELECT ${baseSelected.join(", ")} FROM ${base._tableName}`;
1597
- const baseBindings = [];
1598
- if (opts?.where) {
1599
- if (typeof opts.where === "function") {
1600
- const w = opts.where(base, { eq, ne, gt, gte, lt, lte, like }).toSQL();
1601
- baseSql += ` WHERE ${w.clause}`;
1602
- baseBindings.push(...w.bindings);
1603
- } else if (typeof opts.where.toSQL === "function") {
1604
- const w = opts.where.toSQL();
1605
- baseSql += ` WHERE ${w.clause}`;
1606
- baseBindings.push(...w.bindings);
1607
- } else {
1608
- const entries = Object.entries(opts.where);
1609
- if (entries.length > 0) {
1610
- baseSql += ` WHERE ${entries.map(([k]) => `${k} = ?`).join(" AND ")}`;
1611
- baseBindings.push(...entries.map(([, v]) => v));
1612
- }
1613
- }
1614
- }
1615
- const orderByClauses2 = typeof opts?.orderBy === "function" ? opts.orderBy(base, { asc, desc }) : opts?.orderBy;
1616
- if (orderByClauses2?.length)
1617
- baseSql += ` ORDER BY ${orderByClauses2.join(", ")}`;
1618
- if (typeof opts?.limit === "number") baseSql += ` LIMIT ${opts.limit}`;
1619
- if (typeof opts?.offset === "number")
1620
- baseSql += ` OFFSET ${opts.offset}`;
1621
- const baseRows = await dbi.select(baseSql, baseBindings);
1622
- const result = baseRows.map((r) => ({ ...r }));
1623
- async function loadRelationsFor(parents, parentTable, spec) {
1624
- const parentPk = getPrimaryKey(parentTable);
1625
- const parentIds = parents.map((p) => p[parentPk.name]);
1626
- const relsMap = relDefs[Object.keys(tables).find(
1627
- (k) => tables[k]._tableName === parentTable._tableName
1628
- )] || {};
1629
- for (const [relName, v] of Object.entries(spec)) {
1630
- const enabled = v;
1631
- const rel = relsMap[relName];
1632
- if (!rel) continue;
1633
- const child = rel.table;
1634
- const childCols = Object.values(child._schema);
1635
- const selectCols = enabled?.columns && enabled.columns.length > 0 ? enabled.columns : childCols.map((c) => c.name);
1636
- if (rel.kind === "many") {
1637
- const fkCol = guessChildFk(child, parentTable, rel);
1638
- if (!fkCol) continue;
1639
- const sql2 = `SELECT ${selectCols.join(", ")} FROM ${child._tableName} WHERE ${fkCol.name} IN (${parentIds.map(() => "?").join(", ")})`;
1640
- const rows = await dbi.select(sql2, parentIds);
1641
- const buckets = /* @__PURE__ */ new Map();
1642
- for (const r of rows) {
1643
- const key = r[fkCol.name];
1644
- if (!buckets.has(key)) buckets.set(key, []);
1645
- buckets.get(key).push(r);
1646
- }
1647
- for (const p of parents)
1648
- p[relName] = buckets.get(p[parentPk.name]) ?? [];
1649
- if (enabled?.with) {
1650
- const children = parents.flatMap(
1651
- (p) => p[relName]
1652
- );
1653
- if (children.length > 0)
1654
- await loadRelationsFor(children, child, enabled.with);
1655
- }
1656
- } else {
1657
- const mapping = guessOneRelationJoin(parentTable, rel);
1658
- if (!mapping) continue;
1659
- if (mapping.lhsTable._tableName === child._tableName) {
1660
- const sql2 = `SELECT ${selectCols.join(", ")} FROM ${child._tableName} WHERE ${mapping.lhsCol.name} IN (${parentIds.map(() => "?").join(", ")})`;
1661
- const rows = await dbi.select(sql2, parentIds);
1662
- const mapOne = /* @__PURE__ */ new Map();
1663
- for (const r of rows) mapOne.set(r[mapping.lhsCol.name], r);
1664
- for (const p of parents)
1665
- p[relName] = mapOne.get(p[parentPk.name]) ?? null;
1666
- } else {
1667
- const parentFkName = mapping.lhsCol.name;
1668
- const childPkName = mapping.rhsCol.name;
1669
- const childIds = parents.map((p) => p[parentFkName]).filter((v2) => v2 !== void 0 && v2 !== null);
1670
- if (childIds.length === 0) {
1671
- for (const p of parents) p[relName] = null;
1672
- } else {
1673
- const sql2 = `SELECT ${selectCols.join(", ")} FROM ${child._tableName} WHERE ${childPkName} IN (${childIds.map(() => "?").join(", ")})`;
1674
- const rows = await dbi.select(sql2, childIds);
1675
- const mapOne = /* @__PURE__ */ new Map();
1676
- for (const r of rows) mapOne.set(r[childPkName], r);
1677
- for (const p of parents)
1678
- p[relName] = mapOne.get(p[parentFkName]) ?? null;
1679
- }
1680
- }
1681
- if (enabled?.with) {
1682
- const children = parents.map((p) => p[relName]).filter((x) => Boolean(x));
1683
- if (children.length > 0)
1684
- await loadRelationsFor(children, child, enabled.with);
1685
- }
1686
- }
1687
- }
1688
- }
1689
- if (Object.keys(withSpec).length > 0) {
1690
- await loadRelationsFor(result, base, withSpec);
1691
- }
1692
- return result;
1693
- },
1694
- async findFirst(opts) {
1695
- const rows = await api[tblKey].findMany({ ...opts, limit: 1 });
1696
- return rows?.[0] ?? null;
1697
- }
1698
- };
1699
- }
1700
- return api;
1701
- }
377
+ var relations = (table, relationsCallback) => {
378
+ return relationsCallback({
379
+ one: (table2, config) => ({
380
+ table: table2,
381
+ type: "one",
382
+ foreignKey: config.fields[0],
383
+ localKey: config.references[0]
384
+ }),
385
+ many: (table2) => ({
386
+ table: table2,
387
+ type: "many"
388
+ })
389
+ });
390
+ };
1702
391
  export {
392
+ DeleteQueryBuilder,
393
+ InsertQueryBuilder,
394
+ SQLiteColumn,
395
+ SelectQueryBuilder,
396
+ Table,
1703
397
  TauriORM,
398
+ UpdateQueryBuilder,
1704
399
  and,
1705
- asc,
1706
- between,
1707
400
  blob,
1708
401
  boolean,
1709
- check,
1710
- defineTable,
1711
- desc,
1712
402
  eq,
1713
- exists,
1714
- foreignKey,
1715
- getQualifiedName,
1716
403
  gt,
1717
404
  gte,
1718
- ilike,
1719
405
  inArray,
1720
- increments,
1721
- index,
1722
406
  integer,
1723
407
  isNotNull,
1724
408
  isNull,
1725
409
  like,
1726
410
  lt,
1727
411
  lte,
1728
- makeQueryAPI,
1729
- ne,
1730
- not,
1731
- notBetween,
1732
- notExists,
1733
- notIlike,
1734
- notInArray,
1735
- numeric,
1736
412
  or,
1737
- primaryKey,
1738
- raw,
1739
413
  real,
1740
414
  relations,
1741
- sql,
1742
- text,
1743
- timestamp,
1744
- unique,
1745
- uniqueIndex
415
+ sqliteTable,
416
+ text
1746
417
  };