@type32/tauri-sqlite-orm 0.1.17 → 0.1.18-1

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,1283 +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.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 && !this._rows.includes(data)) {
691
- finalData[key] = coerceValue2(col, col.onUpdateFn());
692
- }
693
- }
694
- }
695
- const entries = Object.entries(finalData).filter(
696
- ([_, value]) => value !== void 0
697
- );
698
- const keys = entries.map(([k]) => {
699
- const col = schema[k];
700
- return col?.name ?? k;
701
- });
702
- const values = entries.map(([k, v]) => {
703
- const col = schema[k];
704
- return coerceValue2(col, v);
705
- });
706
- if (keys.length === 0) {
707
- let query2 = `INSERT INTO ${tableName} DEFAULT VALUES`;
708
- const bindings2 = [];
709
- query2 += this._buildConflictClause();
710
- const ret2 = await this._executeWithReturning(db, query2, bindings2);
711
- if (ret2 !== void 0) return ret2;
712
- continue;
713
- }
714
- const placeholders = values.map(() => "?").join(", ");
715
- let query = `INSERT INTO ${tableName} (${keys.join(
716
- ", "
717
- )}) VALUES (${placeholders})`;
718
- const bindings = [...values];
719
- query += this._buildConflictClause();
720
- const ret = await this._executeWithReturning(db, query, bindings);
721
- if (ret !== void 0) return ret;
722
- }
723
- }
724
- _buildConflictClause() {
725
- if (!this._conflict) return "";
726
- if (this._conflict.kind === "doNothing") {
727
- const tgt2 = this._conflict.target ? Array.isArray(this._conflict.target) ? `(${this._conflict.target.join(", ")})` : `(${this._conflict.target})` : "";
728
- const where = this._conflict.where ? ` WHERE ${this._conflict.where.toSQL().clause}` : "";
729
- return ` ON CONFLICT ${tgt2} DO NOTHING${where}`;
730
- }
731
- const c = this._conflict;
732
- const tgt = Array.isArray(c.target) ? `(${c.target.join(", ")})` : `(${c.target})`;
733
- const setKeys = Object.keys(c.set ?? {});
734
- const setClause = setKeys.map((k) => {
735
- const v = c.set[k];
736
- return `${k} = ${typeof v === "object" && v && typeof v.toSQL === "function" ? v.toSQL().clause : "?"}`;
737
- }).join(", ");
738
- const targetWhere = c.targetWhere ? ` WHERE ${c.targetWhere.toSQL().clause}` : "";
739
- const setWhere = c.setWhere ? ` WHERE ${c.setWhere.toSQL().clause}` : "";
740
- return ` ON CONFLICT ${tgt}${targetWhere} DO UPDATE SET ${setClause}${setWhere}`;
741
- }
742
- async _executeWithReturning(db, query, bindings) {
743
- if (this._returning === null) {
744
- await db.execute(query, bindings);
745
- return void 0;
746
- }
747
- if (this._returning === "__RETURNING_ID__") {
748
- const rows = await db.select(`SELECT last_insert_rowid() as id`);
749
- return rows.map((r) => ({ id: r.id }));
750
- }
751
- if (typeof this._returning === "object") {
752
- const cols = Object.entries(
753
- this._returning
754
- ).map(
755
- ([alias, col]) => `${col.tableName}.${col.name} AS ${alias}`
756
- ).join(", ");
757
- const retSql = `${query} RETURNING ${cols}`;
758
- const res = await db.select(retSql, bindings);
759
- return res;
760
- }
761
- return void 0;
762
- }
763
- }();
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}`;
764
256
  }
765
- update(table) {
766
- const self = this;
767
- return new class UpdateBuilder {
768
- _table = table;
769
- _data = null;
770
- _where = null;
771
- _orderBy = [];
772
- _limit = null;
773
- _from = null;
774
- _returning = null;
775
- set(data) {
776
- this._data = data;
777
- return this;
778
- }
779
- where(cond) {
780
- this._where = cond;
781
- return this;
782
- }
783
- orderBy(...clauses) {
784
- for (const c of clauses) {
785
- if (!c) continue;
786
- if (typeof c === "string") this._orderBy.push(c);
787
- else if (typeof c.toSQL === "function")
788
- this._orderBy.push(c);
789
- else this._orderBy.push(getQualifiedName(c));
790
- }
791
- return this;
792
- }
793
- limit(n) {
794
- this._limit = n;
795
- return this;
796
- }
797
- from(tbl) {
798
- this._from = tbl;
799
- return this;
800
- }
801
- returning(fields) {
802
- this._returning = fields ?? {};
803
- return this;
804
- }
805
- async execute() {
806
- if (!this._data)
807
- throw new Error("Update requires set() before execute()");
808
- const db = await self.getDb();
809
- const tableName = getTableName(this._table);
810
- if (!tableName)
811
- throw new Error(
812
- "Invalid table passed to update(): missing table name"
813
- );
814
- const schema = this._table._schema;
815
- const dataToSet = { ...this._data };
816
- for (const [key, col] of Object.entries(schema)) {
817
- if (!(key in dataToSet) && col.onUpdateFn) {
818
- const v = col.onUpdateFn();
819
- if (col.mode === "boolean") dataToSet[key] = v ? 1 : 0;
820
- else if (v instanceof Date) {
821
- if (col.mode === "timestamp_ms")
822
- dataToSet[key] = v.getTime();
823
- else if (col.mode === "timestamp")
824
- dataToSet[key] = Math.floor(v.getTime() / 1e3);
825
- else dataToSet[key] = v;
826
- } else dataToSet[key] = v;
827
- }
828
- }
829
- const setParts = [];
830
- const bindings = [];
831
- for (const [k, v] of Object.entries(dataToSet)) {
832
- if (v === void 0) continue;
833
- if (v && typeof v === "object" && typeof v.toSQL === "function") {
834
- const s = v.toSQL();
835
- const colName = schema[k]?.name ?? k;
836
- setParts.push(`${colName} = ${s.clause}`);
837
- bindings.push(...s.bindings);
838
- } else {
839
- const colName = schema[k]?.name ?? k;
840
- let val = v;
841
- const col = schema[k];
842
- if (col && col.mode === "boolean") val = v ? 1 : 0;
843
- else if (v instanceof Date) {
844
- if (col && col.mode === "timestamp_ms")
845
- val = v.getTime();
846
- else if (col && col.mode === "timestamp")
847
- val = Math.floor(v.getTime() / 1e3);
848
- }
849
- setParts.push(`${colName} = ?`);
850
- bindings.push(val);
851
- }
852
- }
853
- let query = `UPDATE ${tableName} SET ${setParts.join(", ")}`;
854
- if (this._from) query += ` FROM ${this._from.tableName}`;
855
- if (this._where) {
856
- if (typeof this._where.toSQL === "function") {
857
- const sql2 = this._where.toSQL();
858
- query += ` WHERE ${sql2.clause}`;
859
- bindings.push(...sql2.bindings);
860
- } else {
861
- const entries = Object.entries(this._where);
862
- if (entries.length > 0) {
863
- query += ` WHERE ${entries.map(([k]) => `${schema[k]?.name ?? k} = ?`).join(" AND ")}`;
864
- bindings.push(...entries.map(([, v]) => v));
865
- }
866
- }
867
- }
868
- if (this._orderBy.length > 0) {
869
- const ordParts = [];
870
- for (const ob of this._orderBy) {
871
- if (typeof ob === "string") ordParts.push(ob);
872
- else {
873
- const s = ob.toSQL();
874
- ordParts.push(s.clause);
875
- bindings.push(...s.bindings);
876
- }
877
- }
878
- query += ` ORDER BY ${ordParts.join(", ")}`;
879
- }
880
- if (this._limit !== null) {
881
- query += ` LIMIT ?`;
882
- bindings.push(this._limit);
883
- }
884
- if (this._returning) {
885
- const cols = Object.entries(
886
- this._returning
887
- ).map(
888
- ([alias, col]) => `${col.tableName}.${col.name} AS ${alias}`
889
- ).join(", ");
890
- const retSql = `${query} RETURNING ${cols}`;
891
- return await db.select(retSql, bindings);
892
- }
893
- await db.execute(query, bindings);
894
- }
895
- }();
257
+ async execute() {
258
+ const { sql, params } = this.build();
259
+ const result = await this.db.execute(sql, params);
260
+ return result.rowsAffected;
896
261
  }
897
- delete(table) {
898
- const self = this;
899
- return new class DeleteBuilder {
900
- _table = table;
901
- _where = null;
902
- _orderBy = [];
903
- _limit = null;
904
- _returning = null;
905
- where(cond) {
906
- this._where = cond;
907
- return this;
908
- }
909
- orderBy(...clauses) {
910
- for (const c of clauses) {
911
- if (!c) continue;
912
- if (typeof c === "string") this._orderBy.push(c);
913
- else if (typeof c.toSQL === "function")
914
- this._orderBy.push(c);
915
- else this._orderBy.push(getQualifiedName(c));
916
- }
917
- return this;
918
- }
919
- limit(n) {
920
- this._limit = n;
921
- return this;
922
- }
923
- returning(fields) {
924
- this._returning = fields ?? {};
925
- return this;
926
- }
927
- async execute() {
928
- const db = await self.getDb();
929
- const tableName = getTableName(this._table);
930
- if (!tableName)
931
- throw new Error(
932
- "Invalid table passed to delete(): missing table name"
933
- );
934
- let query = `DELETE FROM ${tableName}`;
935
- const bindings = [];
936
- if (this._where) {
937
- if (typeof this._where.toSQL === "function") {
938
- const sql2 = this._where.toSQL();
939
- query += ` WHERE ${sql2.clause}`;
940
- bindings.push(...sql2.bindings);
941
- } else {
942
- const entries = Object.entries(this._where);
943
- if (entries.length > 0) {
944
- const schema = this._table._schema;
945
- query += ` WHERE ${entries.map(([k]) => `${schema[k]?.name ?? k} = ?`).join(" AND ")}`;
946
- bindings.push(...entries.map(([, v]) => v));
947
- }
948
- }
949
- }
950
- if (this._orderBy.length > 0) {
951
- const ordParts = [];
952
- for (const ob of this._orderBy) {
953
- if (typeof ob === "string") ordParts.push(ob);
954
- else {
955
- const s = ob.toSQL();
956
- ordParts.push(s.clause);
957
- bindings.push(...s.bindings);
958
- }
959
- }
960
- query += ` ORDER BY ${ordParts.join(", ")}`;
961
- }
962
- if (this._limit !== null) {
963
- query += ` LIMIT ?`;
964
- bindings.push(this._limit);
965
- }
966
- if (this._returning) {
967
- const cols = Object.entries(
968
- this._returning
969
- ).map(
970
- ([alias, col]) => `${col.tableName}.${col.name} AS ${alias}`
971
- ).join(", ");
972
- const retSql = `${query} RETURNING ${cols}`;
973
- return await db.select(retSql, bindings);
974
- }
975
- 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);
976
269
  }
977
- }();
978
- }
979
- // legacy direct methods removed in favor of builder APIs
980
- // legacy direct methods removed in favor of builder APIs
981
- // legacy direct methods removed in favor of builder APIs
982
- async run(query, bindings = []) {
983
- const db = await this.getDb();
984
- await db.execute(query, bindings);
985
- }
986
- // --- Migrations API ---
987
- formatDefaultValue(col) {
988
- const dv = col.defaultValue;
989
- if (dv === void 0) return null;
990
- if (dv && typeof dv === "object" && "raw" in dv) {
991
- return dv.raw;
992
- }
993
- if (dv instanceof Date) {
994
- const isMs = col.mode === "timestamp_ms";
995
- const num = isMs ? dv.getTime() : Math.floor(dv.getTime() / 1e3);
996
- return String(num);
997
- }
998
- if (col.mode === "boolean") {
999
- return String(dv ? 1 : 0);
1000
- }
1001
- if (typeof dv === "string") {
1002
- return `'${dv.replace(/'/g, "''")}'`;
1003
270
  }
1004
- return String(dv);
1005
271
  }
1006
- generateCreateTableSql(table) {
1007
- const tableName = getTableName(table);
1008
- if (!tableName)
1009
- throw new Error("Invalid table passed to DDL: missing table name");
1010
- const columns = Object.values(table._schema);
1011
- const columnDefs = columns.map((col) => {
1012
- let def = `${col.name} ${col.type}`;
1013
- if (col.isPrimaryKey) {
1014
- def += col.autoIncrement ? " PRIMARY KEY AUTOINCREMENT" : " PRIMARY KEY";
1015
- }
1016
- if (col.isNotNull) def += " NOT NULL";
1017
- if (col.defaultValue !== void 0) {
1018
- const formatted = this.formatDefaultValue(col);
1019
- if (formatted !== null) def += ` DEFAULT ${formatted}`;
1020
- }
1021
- if (col.references && !col.isPrimaryKey) {
1022
- def += ` REFERENCES ${col.references.table} (${col.references.column})`;
1023
- if (col.references.onDelete)
1024
- def += ` ON DELETE ${col.references.onDelete.toUpperCase()}`;
1025
- if (col.references.onUpdate)
1026
- def += ` ON UPDATE ${col.references.onUpdate.toUpperCase()}`;
1027
- }
1028
- return def;
1029
- });
1030
- const tableConstraints = [];
1031
- const constraints = table._constraints;
1032
- if (constraints && constraints.length) {
1033
- for (const spec of constraints) {
1034
- if (spec.expr) {
1035
- const name = spec.name;
1036
- const expr = spec.expr.raw ?? spec.expr?.raw ?? String(spec.expr);
1037
- tableConstraints.push(
1038
- name ? `CONSTRAINT ${name} CHECK (${expr})` : `CHECK (${expr})`
1039
- );
1040
- 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}`;
1041
284
  }
1042
- if (spec.foreignColumns) {
1043
- const name = spec.name;
1044
- const cols = spec.columns.join(", ");
1045
- const fTable = spec.foreignTable;
1046
- const fCols = spec.foreignColumns.join(", ");
1047
- let clause = `${name ? `CONSTRAINT ${name} ` : ""}FOREIGN KEY (${cols}) REFERENCES ${fTable} (${fCols})`;
1048
- if (spec.onDelete)
1049
- clause += ` ON DELETE ${String(
1050
- spec.onDelete
1051
- ).toUpperCase()}`;
1052
- if (spec.onUpdate)
1053
- clause += ` ON UPDATE ${String(
1054
- spec.onUpdate
1055
- ).toUpperCase()}`;
1056
- tableConstraints.push(clause);
1057
- continue;
285
+ if (col.options.references) {
286
+ sql += ` REFERENCES ${col.options.references.table._.name}(${col.options.references.column._.name})`;
1058
287
  }
1059
- if (spec.columns) {
1060
- const cols = spec.columns.join(", ");
1061
- const name = spec.name;
1062
- const isPk = spec.kind === "primaryKey" || name && name.toLowerCase().includes("pk");
1063
- if (isPk) {
1064
- tableConstraints.push(
1065
- name ? `CONSTRAINT ${name} PRIMARY KEY (${cols})` : `PRIMARY KEY (${cols})`
1066
- );
1067
- } else {
1068
- tableConstraints.push(
1069
- name ? `CONSTRAINT ${name} UNIQUE (${cols})` : `UNIQUE (${cols})`
1070
- );
1071
- }
1072
- continue;
1073
- }
1074
- }
288
+ return sql;
289
+ }).join(", ");
290
+ const createSql = `CREATE TABLE IF NOT EXISTS ${table._.name} (${columnsSql})`;
291
+ await this.db.execute(createSql);
1075
292
  }
1076
- const parts = [...columnDefs, ...tableConstraints];
1077
- return `CREATE TABLE IF NOT EXISTS ${tableName} (${parts.join(", ")});`;
1078
- }
1079
- async createTableIfNotExists(table) {
1080
- const sql2 = this.generateCreateTableSql(table);
1081
- await this.run(sql2);
1082
- await this.createIndexesForTable(table);
1083
- }
1084
- async createTablesIfNotExist(tables) {
1085
- for (const t of tables) {
1086
- await this.createTableIfNotExists(t);
1087
- }
1088
- }
1089
- generateCreateIndexSqls(table) {
1090
- const tableName = table.tableName;
1091
- const indexes = table._indexes || [];
1092
- const stmts = [];
1093
- for (const idx of indexes) {
1094
- const unique2 = idx.unique ? "UNIQUE " : "";
1095
- if (!idx.name) continue;
1096
- const colList = Array.isArray(idx.columns) ? idx.columns : [];
1097
- if (colList.length === 0) continue;
1098
- const cols = `(${colList.join(", ")})`;
1099
- const where = idx.where?.raw ? ` WHERE ${idx.where.raw}` : "";
1100
- stmts.push(
1101
- `CREATE ${unique2}INDEX IF NOT EXISTS ${idx.name} ON ${tableName} ${cols}${where};`
1102
- );
1103
- }
1104
- return stmts;
1105
- }
1106
- async createIndexesForTable(table) {
1107
- const stmts = this.generateCreateIndexSqls(table);
1108
- for (const s of stmts) await this.run(s);
1109
- }
1110
- async ensureMigrationsTable() {
1111
- await this.run(
1112
- `CREATE TABLE IF NOT EXISTS _migrations (name TEXT PRIMARY KEY, applied_at INTEGER NOT NULL)`
1113
- );
1114
293
  }
1115
- async hasMigration(name) {
1116
- const db = await this.getDb();
1117
- const rows = await db.select(
1118
- `SELECT name FROM _migrations WHERE name = ?`,
1119
- [name]
1120
- );
1121
- return Array.isArray(rows) && rows.length > 0;
1122
- }
1123
- async recordMigration(name) {
1124
- const db = await this.getDb();
1125
- await db.execute(
1126
- `INSERT INTO _migrations (name, applied_at) VALUES (?, ?)`,
1127
- [name, Date.now()]
1128
- );
294
+ select(table, columns) {
295
+ return new SelectQueryBuilder(this.db, table, columns);
1129
296
  }
1130
- async migrate(tables, options) {
1131
- const track = options?.track ?? true;
1132
- if (track) {
1133
- await this.ensureMigrationsTable();
1134
- }
1135
- await this.forcePushForTables(tables, { preserveData: true });
1136
- if (track) {
1137
- const name = options?.name ?? `init:${tables.map((t) => t.tableName).join(",")}`;
1138
- const already = await this.hasMigration(name);
1139
- if (!already) await this.recordMigration(name);
1140
- }
297
+ insert(table) {
298
+ return new InsertQueryBuilder(this.db, table);
1141
299
  }
1142
- // Configure schema and relations, and generate db.query automatically
1143
- configure(tables, relDefs) {
1144
- this._tables = tables;
1145
- this._relations = relDefs ?? {};
1146
- this.query = makeQueryAPI(
1147
- tables,
1148
- this._relations ?? {},
1149
- this.getDb.bind(this)
1150
- );
1151
- return this;
300
+ update(table) {
301
+ return new UpdateQueryBuilder(this.db, table);
1152
302
  }
1153
- // Convenience: migrate from configured tables
1154
- async migrateConfigured(options) {
1155
- if (!this._tables)
1156
- throw new Error("No tables configured. Call db.configure({...}) first.");
1157
- await this.migrate(Object.values(this._tables), options);
1158
- await this.setSchemaMeta("schema_signature", this.computeModelSignature());
303
+ delete(table) {
304
+ return new DeleteQueryBuilder(this.db, table);
1159
305
  }
1160
- // --- Schema diff and CLI-like helpers ---
1161
- async diffSchema() {
1162
- if (!this._tables) throw new Error("No tables configured.");
1163
- const dbi = await this.getDb();
1164
- const configuredNames = Object.values(this._tables).map(
1165
- (t) => getTableName(t)
1166
- );
1167
- const existing = await dbi.select(
1168
- `SELECT name FROM sqlite_master WHERE type='table'`
1169
- );
1170
- const existingNames = existing.map((r) => r.name);
1171
- const extraTables = existingNames.filter(
1172
- (n) => !configuredNames.includes(n)
1173
- );
1174
- const missingTables = configuredNames.filter(
1175
- (n) => !existingNames.includes(n)
1176
- );
1177
- const tables = {};
1178
- for (const tbl of Object.values(this._tables)) {
1179
- const tableName = getTableName(tbl);
1180
- if (!existingNames.includes(tableName)) {
1181
- tables[tableName] = {
1182
- missingColumns: Object.keys(tbl._schema),
1183
- extraColumns: [],
1184
- changedColumns: []
1185
- };
1186
- continue;
1187
- }
1188
- const cols = await dbi.select(`PRAGMA table_info('${tableName}')`);
1189
- const colMap = new Map(cols.map((c) => [c.name, c]));
1190
- const modelCols = Object.values(
1191
- tbl._schema
1192
- );
1193
- const missingColumns = [];
1194
- const extraColumns = [];
1195
- const changedColumns = [];
1196
- const modelNamesSet = new Set(modelCols.map((c) => c.name));
1197
- for (const m of modelCols) {
1198
- const info = colMap.get(m.name);
1199
- if (!info) {
1200
- missingColumns.push(m.name);
1201
- continue;
1202
- }
1203
- const diffs = {};
1204
- if ((info.type || "").toUpperCase() !== m.type.toUpperCase())
1205
- diffs.type = true;
1206
- if (!!info.pk !== !!m.isPrimaryKey) diffs.pk = true;
1207
- if (!!info.notnull !== !!m.isNotNull) diffs.notNull = true;
1208
- const modelDv = m.defaultValue && typeof m.defaultValue === "object" && m.defaultValue.raw ? m.defaultValue.raw : m.defaultValue ?? null;
1209
- if ((info.dflt_value ?? null) !== modelDv)
1210
- diffs.default = true;
1211
- if (Object.keys(diffs).length)
1212
- changedColumns.push({ name: m.name, diffs });
1213
- }
1214
- for (const c of cols)
1215
- if (!modelNamesSet.has(c.name)) extraColumns.push(c.name);
1216
- 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;
1217
315
  }
1218
- return { extraTables, missingTables, tables };
1219
- }
1220
- async generate() {
1221
- if (!this._tables) throw new Error("No tables configured.");
1222
- return {
1223
- statements: Object.values(this._tables).map(
1224
- (t) => this.buildCreateTableSQL(t)
1225
- )
1226
- };
1227
- }
1228
- async migrateCli(opts) {
1229
- return this.migrateConfigured(opts);
1230
- }
1231
- async push(opts) {
1232
- return this.forcePush(opts);
1233
- }
1234
- async pull() {
1235
- return this.pullSchema();
1236
- }
1237
- async studio() {
1238
- const dbi = await this.getDb();
1239
- return { driver: "sqlite", path: dbi.path };
1240
316
  }
1241
317
  // --- Schema detection / signature ---
1242
318
  async ensureSchemaMeta() {
1243
- await this.run(
319
+ await this.db.execute(
1244
320
  `CREATE TABLE IF NOT EXISTS _schema_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)`
1245
321
  );
1246
322
  }
1247
323
  async getSchemaMeta(key) {
1248
- const dbi = await this.getDb();
1249
324
  await this.ensureSchemaMeta();
1250
- const rows = await dbi.select(
325
+ const rows = await this.db.select(
1251
326
  `SELECT value FROM _schema_meta WHERE key = ?`,
1252
327
  [key]
1253
328
  );
1254
329
  return rows?.[0]?.value ?? null;
1255
330
  }
1256
331
  async setSchemaMeta(key, value) {
1257
- const dbi = await this.getDb();
1258
332
  await this.ensureSchemaMeta();
1259
- await dbi.execute(
333
+ await this.db.execute(
1260
334
  `INSERT INTO _schema_meta(key, value) VALUES(?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value`,
1261
335
  [key, value]
1262
336
  );
1263
337
  }
1264
338
  normalizeColumn(col) {
1265
339
  return {
1266
- name: col.name,
340
+ name: col._.name,
1267
341
  type: col.type,
1268
- pk: !!col.isPrimaryKey,
1269
- ai: !!col.autoIncrement,
1270
- nn: !!col.isNotNull,
1271
- 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
1272
346
  };
1273
347
  }
1274
348
  computeModelSignature() {
1275
- if (!this._tables) return "";
1276
- const entries = Object.entries(this._tables).map(([k, tbl]) => {
1277
- const cols = Object.values(
1278
- tbl._schema
1279
- ).map((c) => this.normalizeColumn(c)).sort((a, b) => a.name.localeCompare(b.name));
1280
- 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 };
1281
352
  });
1282
353
  entries.sort((a, b) => a.table.localeCompare(b.table));
1283
354
  return JSON.stringify(entries);
@@ -1285,22 +356,15 @@ var TauriORM = class {
1285
356
  getSchemaSignature() {
1286
357
  return this.computeModelSignature();
1287
358
  }
1288
- async printSchemaDiff() {
1289
- const diff = await this.diffSchema();
1290
- console.log("Schema diff:", JSON.stringify(diff, null, 2));
1291
- }
1292
359
  async isSchemaDirty() {
1293
360
  const sig = this.computeModelSignature();
1294
361
  const stored = await this.getSchemaMeta("schema_signature");
1295
362
  return { dirty: sig !== stored, current: sig, stored };
1296
363
  }
1297
- async migrateIfDirty(options) {
364
+ async migrateIfDirty() {
1298
365
  const status = await this.isSchemaDirty();
1299
- if (!this._tables) throw new Error("No tables configured.");
1300
366
  if (status.dirty) {
1301
- await this.forcePushForTables(Object.values(this._tables), {
1302
- preserveData: true
1303
- });
367
+ await this.migrate();
1304
368
  await this.setSchemaMeta(
1305
369
  "schema_signature",
1306
370
  this.computeModelSignature()
@@ -1309,454 +373,45 @@ var TauriORM = class {
1309
373
  }
1310
374
  return false;
1311
375
  }
1312
- // Pull current DB schema (minimal) for configured tables
1313
- async pullSchema() {
1314
- if (!this._tables) throw new Error("No tables configured.");
1315
- const dbi = await this.getDb();
1316
- const result = {};
1317
- for (const tbl of Object.values(this._tables)) {
1318
- const name = tbl.tableName;
1319
- const cols = await dbi.select(`PRAGMA table_info('${name}')`);
1320
- result[name] = cols.map((c) => ({
1321
- name: c.name,
1322
- type: c.type,
1323
- notnull: !!c.notnull,
1324
- pk: !!c.pk,
1325
- dflt_value: c.dflt_value ?? null
1326
- }));
1327
- }
1328
- return result;
1329
- }
1330
- buildCreateTableSQL(table) {
1331
- return this.generateCreateTableSql(table);
1332
- }
1333
- async tableExists(name) {
1334
- const dbi = await this.getDb();
1335
- const rows = await dbi.select(
1336
- `SELECT name FROM sqlite_master WHERE type='table' AND name = ?`,
1337
- [name]
1338
- );
1339
- return rows.length > 0;
1340
- }
1341
- // Force push model to DB: add missing tables/columns, rebuild tables if incompatible
1342
- async forcePush(options) {
1343
- if (!this._tables) throw new Error("No tables configured.");
1344
- await this.forcePushForTables(Object.values(this._tables), options);
1345
- }
1346
- async forcePushForTables(tables, options) {
1347
- const dbi = await this.getDb();
1348
- const preserve = options?.preserveData !== false;
1349
- for (const tbl of tables) {
1350
- const tableName = getTableName(tbl);
1351
- const exists2 = await this.tableExists(tableName);
1352
- if (!exists2) {
1353
- await this.run(this.buildCreateTableSQL(tbl));
1354
- await this.createIndexesForTable(tbl);
1355
- continue;
1356
- }
1357
- const existingCols = await dbi.select(
1358
- `PRAGMA table_info('${tableName}')`
1359
- );
1360
- const existingMap = new Map(existingCols.map((c) => [c.name, c]));
1361
- const modelCols = Object.values(
1362
- tbl._schema
1363
- );
1364
- const missing = [];
1365
- let requiresRebuild = false;
1366
- for (const m of modelCols) {
1367
- const info = existingMap.get(m.name);
1368
- if (!info) {
1369
- missing.push(m);
1370
- continue;
1371
- }
1372
- const typeDiff = (info.type || "").toUpperCase() !== m.type.toUpperCase();
1373
- const pkDiff = !!info.pk !== !!m.isPrimaryKey;
1374
- const nnDiff = !!info.notnull !== !!m.isNotNull;
1375
- const modelDv = m.defaultValue && typeof m.defaultValue === "object" && m.defaultValue.raw ? m.defaultValue.raw : m.defaultValue ?? null;
1376
- const defDiff = (info.dflt_value ?? null) !== modelDv;
1377
- if (typeDiff || pkDiff || nnDiff && !modelDv || defDiff) {
1378
- requiresRebuild = true;
1379
- }
1380
- }
1381
- if (requiresRebuild) {
1382
- const tmp = `_new_${tableName}`;
1383
- await this.run(this.buildCreateTableSQL(tbl));
1384
- await this.run(
1385
- this.buildCreateTableSQL({ ...tbl, tableName: tmp })
1386
- );
1387
- const existingNames = existingCols.map((c) => c.name);
1388
- const modelNames = modelCols.map((c) => c.name);
1389
- const shared = existingNames.filter((n) => modelNames.includes(n));
1390
- if (preserve && shared.length > 0) {
1391
- await this.run(
1392
- `INSERT INTO ${tmp} (${shared.join(", ")}) SELECT ${shared.join(
1393
- ", "
1394
- )} FROM ${tableName}`
1395
- );
1396
- }
1397
- await this.run(`DROP TABLE ${tableName}`);
1398
- await this.run(`ALTER TABLE ${tmp} RENAME TO ${tableName}`);
1399
- await this.createIndexesForTable(tbl);
1400
- } else {
1401
- for (const m of missing) {
1402
- let clause = `${m.name} ${m.type}`;
1403
- if (m.isNotNull) clause += " NOT NULL";
1404
- if (m.defaultValue !== void 0) {
1405
- const formatted = this.formatDefaultValue(m);
1406
- if (formatted !== null) clause += ` DEFAULT ${formatted}`;
1407
- }
1408
- await this.run(`ALTER TABLE ${tableName} ADD COLUMN ${clause}`);
1409
- }
1410
- await this.createIndexesForTable(tbl);
1411
- }
1412
- }
1413
- await this.setSchemaMeta("schema_signature", this.computeModelSignature());
1414
- }
1415
376
  };
1416
- function relations(baseTable, builder) {
1417
- const ctx = {
1418
- one: (table, cfg) => ({ kind: "one", table, cfg }),
1419
- many: (table, cfg) => ({ kind: "many", table, cfg })
1420
- };
1421
- const rels = builder(ctx);
1422
- return rels;
1423
- }
1424
- function getPrimaryKey(table) {
1425
- const cols = Object.values(table._schema);
1426
- return cols.find((c) => c.isPrimaryKey) || cols.find((c) => c.name === "id") || cols[0];
1427
- }
1428
- function guessChildFk(child, base, rel) {
1429
- const childCols = Object.values(child._schema);
1430
- if (rel && rel.kind === "one" && rel.cfg?.fields?.[0])
1431
- return rel.cfg.fields[0];
1432
- const basePk = getPrimaryKey(base);
1433
- const guessNames = [
1434
- `${base.tableName}_id`,
1435
- `${base.tableName}Id`,
1436
- `${basePk.name}`,
1437
- `${base.tableName.slice(0, -1)}Id`
1438
- ];
1439
- return childCols.find((c) => guessNames.includes(c.name)) || childCols.find((c) => /.*_id$/i.test(c.name)) || null;
1440
- }
1441
- function guessOneRelationJoin(base, rel) {
1442
- const child = rel.table;
1443
- const basePk = getPrimaryKey(base);
1444
- const childCols = Object.values(child._schema);
1445
- if (rel.cfg?.fields && rel.cfg?.references && rel.cfg.fields[0] && rel.cfg.references[0]) {
1446
- const fk = rel.cfg.fields[0];
1447
- const ref = rel.cfg.references[0];
1448
- if (childCols.some((c) => c.name === fk.name)) {
1449
- return { lhsTable: child, lhsCol: fk, rhsTable: base, rhsCol: ref };
1450
- }
1451
- const baseCols = Object.values(base._schema);
1452
- if (baseCols.some((c) => c.name === fk.name)) {
1453
- return { lhsTable: base, lhsCol: fk, rhsTable: child, rhsCol: ref };
1454
- }
1455
- }
1456
- const childFk = guessChildFk(child, base, rel);
1457
- if (!childFk) return null;
1458
- return { lhsTable: child, lhsCol: childFk, rhsTable: base, rhsCol: basePk };
1459
- }
1460
- function isFlatWith(spec) {
1461
- return Object.values(spec).every((v) => typeof v === "boolean");
1462
- }
1463
- function makeQueryAPI(tables, relDefs, dbProvider) {
1464
- const api = {};
1465
- const tableKeyByName = {};
1466
- for (const [k, t] of Object.entries(tables)) tableKeyByName[t.tableName] = k;
1467
- for (const [tblKey, tbl] of Object.entries(tables)) {
1468
- api[tblKey] = {
1469
- async findMany(opts) {
1470
- const base = tbl;
1471
- const withSpec = opts?.with ?? {};
1472
- const dbi = await dbProvider();
1473
- const rels = relDefs[tblKey] ?? {};
1474
- if (opts?.join && isFlatWith(withSpec)) {
1475
- const baseCols = Object.values(base._schema);
1476
- const basePk = baseCols.find((c) => c.isPrimaryKey) || baseCols.find((c) => c.name === "id") || baseCols[0];
1477
- const selectParts = [];
1478
- let baseSelected2;
1479
- if (opts?.columns && !Array.isArray(opts.columns)) {
1480
- baseSelected2 = Object.entries(opts.columns).filter(([, v]) => !!v).map(([k]) => k);
1481
- } else if (Array.isArray(opts?.columns) && opts.columns.length > 0) {
1482
- baseSelected2 = opts.columns;
1483
- } else {
1484
- baseSelected2 = baseCols.map((c) => c.name);
1485
- }
1486
- for (const name of baseSelected2)
1487
- selectParts.push(`${base.tableName}.${name} AS __base_${name}`);
1488
- const joins = [];
1489
- const relColsMap = {};
1490
- const fkMap = {};
1491
- for (const [relName, enabled] of Object.entries(withSpec)) {
1492
- if (!enabled) continue;
1493
- const rel = rels[relName];
1494
- if (!rel) continue;
1495
- const child = rel.table;
1496
- const childCols = Object.values(child._schema);
1497
- const childPk = childCols.find((c) => c.isPrimaryKey) || childCols.find((c) => c.name === "id") || null;
1498
- if (rel.kind === "one") {
1499
- const mapping = guessOneRelationJoin(base, rel);
1500
- if (!mapping) continue;
1501
- if (mapping.lhsTable.tableName === child.tableName) {
1502
- fkMap[relName] = { childFk: mapping.lhsCol, childPk };
1503
- joins.push(
1504
- `LEFT JOIN ${child.tableName} ON ${mapping.lhsTable.tableName}.${mapping.lhsCol.name} = ${mapping.rhsTable.tableName}.${mapping.rhsCol.name}`
1505
- );
1506
- } else {
1507
- fkMap[relName] = { childFk: mapping.rhsCol, childPk };
1508
- joins.push(
1509
- `LEFT JOIN ${child.tableName} ON ${mapping.lhsTable.tableName}.${mapping.lhsCol.name} = ${mapping.rhsTable.tableName}.${mapping.rhsCol.name}`
1510
- );
1511
- }
1512
- } else {
1513
- const childFk = guessChildFk(child, base, rel);
1514
- if (!childFk) continue;
1515
- fkMap[relName] = { childFk, childPk };
1516
- joins.push(
1517
- `LEFT JOIN ${child.tableName} ON ${child.tableName}.${childFk.name} = ${base.tableName}.${basePk.name}`
1518
- );
1519
- }
1520
- const selected = typeof enabled === "object" && enabled.columns?.length ? enabled.columns : childCols.map((c) => c.name);
1521
- relColsMap[relName] = selected;
1522
- for (const name of selected)
1523
- selectParts.push(
1524
- `${child.tableName}.${name} AS __rel_${relName}_${name}`
1525
- );
1526
- }
1527
- let sqlText = `SELECT ${selectParts.join(", ")} FROM ${base.tableName}${joins.length ? " " + joins.join(" ") : ""}`;
1528
- const bindings = [];
1529
- if (opts?.where) {
1530
- if (typeof opts.where === "function") {
1531
- const w = opts.where(base, { eq, ne, gt, gte, lt, lte, like }).toSQL();
1532
- sqlText += ` WHERE ${w.clause}`;
1533
- bindings.push(...w.bindings);
1534
- } else if (typeof opts.where.toSQL === "function") {
1535
- const w = opts.where.toSQL();
1536
- sqlText += ` WHERE ${w.clause}`;
1537
- bindings.push(...w.bindings);
1538
- } else {
1539
- const entries = Object.entries(opts.where);
1540
- if (entries.length > 0) {
1541
- sqlText += ` WHERE ${entries.map(([k]) => `${base.tableName}.${k} = ?`).join(" AND ")}`;
1542
- bindings.push(...entries.map(([, v]) => v));
1543
- }
1544
- }
1545
- }
1546
- const orderByClauses = typeof opts?.orderBy === "function" ? opts.orderBy(base, { asc, desc }) : opts?.orderBy;
1547
- if (orderByClauses?.length)
1548
- sqlText += ` ORDER BY ${orderByClauses.join(", ")}`;
1549
- if (typeof opts?.limit === "number")
1550
- sqlText += ` LIMIT ${opts.limit}`;
1551
- if (typeof opts?.offset === "number")
1552
- sqlText += ` OFFSET ${opts.offset}`;
1553
- const rows = await dbi.select(sqlText, bindings);
1554
- const groups = /* @__PURE__ */ new Map();
1555
- for (const row of rows) {
1556
- const baseObj = {};
1557
- for (const name of baseSelected2)
1558
- baseObj[name] = row[`__base_${name}`];
1559
- const baseKey = baseObj[basePk.name];
1560
- if (!groups.has(baseKey)) {
1561
- const seed = { ...baseObj };
1562
- for (const [relName, enabled] of Object.entries(withSpec)) {
1563
- if (!enabled) continue;
1564
- const rel = rels[relName];
1565
- if (!rel) continue;
1566
- seed[relName] = rel.kind === "many" ? [] : null;
1567
- }
1568
- groups.set(baseKey, seed);
1569
- }
1570
- const acc = groups.get(baseKey);
1571
- for (const [relName, enabled] of Object.entries(withSpec)) {
1572
- if (!enabled) continue;
1573
- const rel = rels[relName];
1574
- if (!rel) continue;
1575
- const childCols = relColsMap[relName];
1576
- const childObj = {};
1577
- let allNull = true;
1578
- for (const name of childCols) {
1579
- const v = row[`__rel_${relName}_${name}`];
1580
- childObj[name] = v;
1581
- if (v !== null && v !== void 0) allNull = false;
1582
- }
1583
- if (allNull) continue;
1584
- if (rel.kind === "many") {
1585
- const childPk = fkMap[relName].childPk;
1586
- if (childPk) {
1587
- if (!acc[relName]) acc[relName] = [];
1588
- const exists2 = acc[relName].some(
1589
- (r) => r[childPk.name] === childObj[childPk.name]
1590
- );
1591
- if (!exists2) acc[relName].push(childObj);
1592
- } else {
1593
- acc[relName].push(childObj);
1594
- }
1595
- } else {
1596
- acc[relName] = childObj;
1597
- }
1598
- }
1599
- }
1600
- return Array.from(groups.values());
1601
- }
1602
- let baseSelected;
1603
- if (opts?.columns && !Array.isArray(opts.columns)) {
1604
- baseSelected = Object.entries(opts.columns).filter(([, v]) => !!v).map(([k]) => k);
1605
- } else if (Array.isArray(opts?.columns) && opts.columns.length > 0) {
1606
- baseSelected = opts.columns;
1607
- } else {
1608
- baseSelected = Object.values(base._schema).map(
1609
- (c) => c.name
1610
- );
1611
- }
1612
- let baseSql = `SELECT ${baseSelected.join(", ")} FROM ${base.tableName}`;
1613
- const baseBindings = [];
1614
- if (opts?.where) {
1615
- if (typeof opts.where === "function") {
1616
- const w = opts.where(base, { eq, ne, gt, gte, lt, lte, like }).toSQL();
1617
- baseSql += ` WHERE ${w.clause}`;
1618
- baseBindings.push(...w.bindings);
1619
- } else if (typeof opts.where.toSQL === "function") {
1620
- const w = opts.where.toSQL();
1621
- baseSql += ` WHERE ${w.clause}`;
1622
- baseBindings.push(...w.bindings);
1623
- } else {
1624
- const entries = Object.entries(opts.where);
1625
- if (entries.length > 0) {
1626
- baseSql += ` WHERE ${entries.map(([k]) => `${k} = ?`).join(" AND ")}`;
1627
- baseBindings.push(...entries.map(([, v]) => v));
1628
- }
1629
- }
1630
- }
1631
- const orderByClauses2 = typeof opts?.orderBy === "function" ? opts.orderBy(base, { asc, desc }) : opts?.orderBy;
1632
- if (orderByClauses2?.length)
1633
- baseSql += ` ORDER BY ${orderByClauses2.join(", ")}`;
1634
- if (typeof opts?.limit === "number") baseSql += ` LIMIT ${opts.limit}`;
1635
- if (typeof opts?.offset === "number")
1636
- baseSql += ` OFFSET ${opts.offset}`;
1637
- const baseRows = await dbi.select(baseSql, baseBindings);
1638
- const result = baseRows.map((r) => ({ ...r }));
1639
- async function loadRelationsFor(parents, parentTable, spec) {
1640
- const parentPk = getPrimaryKey(parentTable);
1641
- const parentIds = parents.map((p) => p[parentPk.name]);
1642
- const relsMap = relDefs[Object.keys(tables).find(
1643
- (k) => tables[k].tableName === parentTable.tableName
1644
- )] || {};
1645
- for (const [relName, v] of Object.entries(spec)) {
1646
- const enabled = v;
1647
- const rel = relsMap[relName];
1648
- if (!rel) continue;
1649
- const child = rel.table;
1650
- const childCols = Object.values(child._schema);
1651
- const selectCols = enabled?.columns && enabled.columns.length > 0 ? enabled.columns : childCols.map((c) => c.name);
1652
- if (rel.kind === "many") {
1653
- const fkCol = guessChildFk(child, parentTable, rel);
1654
- if (!fkCol) continue;
1655
- const sql2 = `SELECT ${selectCols.join(", ")} FROM ${child.tableName} WHERE ${fkCol.name} IN (${parentIds.map(() => "?").join(", ")})`;
1656
- const rows = await dbi.select(sql2, parentIds);
1657
- const buckets = /* @__PURE__ */ new Map();
1658
- for (const r of rows) {
1659
- const key = r[fkCol.name];
1660
- if (!buckets.has(key)) buckets.set(key, []);
1661
- buckets.get(key).push(r);
1662
- }
1663
- for (const p of parents)
1664
- p[relName] = buckets.get(p[parentPk.name]) ?? [];
1665
- if (enabled?.with) {
1666
- const children = parents.flatMap(
1667
- (p) => p[relName]
1668
- );
1669
- if (children.length > 0)
1670
- await loadRelationsFor(children, child, enabled.with);
1671
- }
1672
- } else {
1673
- const mapping = guessOneRelationJoin(parentTable, rel);
1674
- if (!mapping) continue;
1675
- if (mapping.lhsTable.tableName === child.tableName) {
1676
- const sql2 = `SELECT ${selectCols.join(", ")} FROM ${child.tableName} WHERE ${mapping.lhsCol.name} IN (${parentIds.map(() => "?").join(", ")})`;
1677
- const rows = await dbi.select(sql2, parentIds);
1678
- const mapOne = /* @__PURE__ */ new Map();
1679
- for (const r of rows) mapOne.set(r[mapping.lhsCol.name], r);
1680
- for (const p of parents)
1681
- p[relName] = mapOne.get(p[parentPk.name]) ?? null;
1682
- } else {
1683
- const parentFkName = mapping.lhsCol.name;
1684
- const childPkName = mapping.rhsCol.name;
1685
- const childIds = parents.map((p) => p[parentFkName]).filter((v2) => v2 !== void 0 && v2 !== null);
1686
- if (childIds.length === 0) {
1687
- for (const p of parents) p[relName] = null;
1688
- } else {
1689
- const sql2 = `SELECT ${selectCols.join(", ")} FROM ${child.tableName} WHERE ${childPkName} IN (${childIds.map(() => "?").join(", ")})`;
1690
- const rows = await dbi.select(sql2, childIds);
1691
- const mapOne = /* @__PURE__ */ new Map();
1692
- for (const r of rows) mapOne.set(r[childPkName], r);
1693
- for (const p of parents)
1694
- p[relName] = mapOne.get(p[parentFkName]) ?? null;
1695
- }
1696
- }
1697
- if (enabled?.with) {
1698
- const children = parents.map((p) => p[relName]).filter((x) => Boolean(x));
1699
- if (children.length > 0)
1700
- await loadRelationsFor(children, child, enabled.with);
1701
- }
1702
- }
1703
- }
1704
- }
1705
- if (Object.keys(withSpec).length > 0) {
1706
- await loadRelationsFor(result, base, withSpec);
1707
- }
1708
- return result;
1709
- },
1710
- async findFirst(opts) {
1711
- const rows = await api[tblKey].findMany({ ...opts, limit: 1 });
1712
- return rows?.[0] ?? null;
1713
- }
1714
- };
1715
- }
1716
- return api;
1717
- }
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
+ };
1718
391
  export {
392
+ DeleteQueryBuilder,
393
+ InsertQueryBuilder,
394
+ SQLiteColumn,
395
+ SelectQueryBuilder,
396
+ Table,
1719
397
  TauriORM,
398
+ UpdateQueryBuilder,
1720
399
  and,
1721
- asc,
1722
- between,
1723
400
  blob,
1724
401
  boolean,
1725
- check,
1726
- defineTable,
1727
- desc,
1728
402
  eq,
1729
- exists,
1730
- foreignKey,
1731
- getQualifiedName,
1732
403
  gt,
1733
404
  gte,
1734
- ilike,
1735
405
  inArray,
1736
- increments,
1737
- index,
1738
406
  integer,
1739
407
  isNotNull,
1740
408
  isNull,
1741
409
  like,
1742
410
  lt,
1743
411
  lte,
1744
- makeQueryAPI,
1745
- ne,
1746
- not,
1747
- notBetween,
1748
- notExists,
1749
- notIlike,
1750
- notInArray,
1751
- numeric,
1752
412
  or,
1753
- primaryKey,
1754
- raw,
1755
413
  real,
1756
414
  relations,
1757
- sql,
1758
- text,
1759
- timestamp,
1760
- unique,
1761
- uniqueIndex
415
+ sqliteTable,
416
+ text
1762
417
  };