@type32/tauri-sqlite-orm 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -34,14 +34,12 @@ __export(index_exports, {
34
34
  asc: () => asc,
35
35
  blob: () => blob,
36
36
  boolean: () => boolean,
37
- db: () => db2,
38
37
  defineTable: () => defineTable,
39
38
  desc: () => desc,
40
39
  eq: () => eq,
41
- getDb: () => getDb,
42
40
  gt: () => gt,
43
41
  gte: () => gte,
44
- initDb: () => initDb,
42
+ increments: () => increments,
45
43
  integer: () => integer,
46
44
  like: () => like,
47
45
  lt: () => lt,
@@ -57,20 +55,6 @@ __export(index_exports, {
57
55
  });
58
56
  module.exports = __toCommonJS(index_exports);
59
57
 
60
- // src/connection.ts
61
- var import_plugin_sql = __toESM(require("@tauri-apps/plugin-sql"));
62
- var db = null;
63
- async function initDb(dbPath) {
64
- db = await import_plugin_sql.default.load(dbPath);
65
- return db;
66
- }
67
- function getDb() {
68
- if (!db) {
69
- throw new Error("Database not initialized. Please call initDb() first.");
70
- }
71
- return db;
72
- }
73
-
74
58
  // src/schema-builder.ts
75
59
  function sql(strings, ...values) {
76
60
  const raw = strings.reduce(
@@ -99,6 +83,18 @@ function createColumn(params) {
99
83
  col.defaultFn = fn;
100
84
  return col;
101
85
  };
86
+ col.$default = (fn) => {
87
+ col.defaultFn = fn;
88
+ return col;
89
+ };
90
+ col.$onUpdate = (fn) => {
91
+ col.onUpdateFn = fn;
92
+ return col;
93
+ };
94
+ col.$onUpdateFn = (fn) => {
95
+ col.onUpdateFn = fn;
96
+ return col;
97
+ };
102
98
  col.references = (target, actions) => {
103
99
  const t = target();
104
100
  col.references = {
@@ -111,34 +107,43 @@ function createColumn(params) {
111
107
  };
112
108
  return col;
113
109
  }
114
- function text(name, config) {
110
+ function text(nameOrConfig, maybeConfig) {
111
+ const name = typeof nameOrConfig === "string" ? nameOrConfig : "";
112
+ const config = typeof nameOrConfig === "string" ? maybeConfig : nameOrConfig;
115
113
  const col = createColumn({
116
114
  name,
117
115
  type: "TEXT",
118
- isPrimaryKey: config?.isPrimaryKey,
119
116
  _dataType: ""
120
117
  });
121
118
  if (config?.enum) col.enumValues = config.enum;
119
+ if (config?.mode) col.mode = config.mode;
122
120
  return col;
123
121
  }
124
- function integer(name, config) {
122
+ function integer(nameOrConfig, maybeConfig) {
123
+ const name = typeof nameOrConfig === "string" ? nameOrConfig : "";
124
+ const config = typeof nameOrConfig === "string" ? maybeConfig : nameOrConfig;
125
125
  let dt = 0;
126
126
  if (config?.mode === "boolean") dt = false;
127
- if (config?.mode === "timestamp") dt = /* @__PURE__ */ new Date();
127
+ if (config?.mode === "timestamp" || config?.mode === "timestamp_ms")
128
+ dt = /* @__PURE__ */ new Date();
128
129
  const col = createColumn({
129
130
  name,
130
131
  type: "INTEGER",
131
- isPrimaryKey: config?.isPrimaryKey,
132
- autoIncrement: config?.autoIncrement,
133
132
  mode: config?.mode ?? "number",
134
133
  _dataType: dt
135
134
  });
136
135
  return col;
137
136
  }
138
137
  function real(name) {
139
- return createColumn({ name, type: "REAL", _dataType: 0 });
138
+ return createColumn({
139
+ name: name ?? "",
140
+ type: "REAL",
141
+ _dataType: 0
142
+ });
140
143
  }
141
- function blob(name, config) {
144
+ function blob(nameOrConfig, maybeConfig) {
145
+ const name = typeof nameOrConfig === "string" ? nameOrConfig : "";
146
+ const config = typeof nameOrConfig === "string" ? maybeConfig : nameOrConfig;
142
147
  let dt = new Uint8Array();
143
148
  if (config?.mode === "bigint") dt = 0n;
144
149
  if (config?.mode === "json") dt = void 0;
@@ -149,7 +154,9 @@ function blob(name, config) {
149
154
  _dataType: dt
150
155
  });
151
156
  }
152
- function numeric(name, config) {
157
+ function numeric(nameOrConfig, maybeConfig) {
158
+ const name = typeof nameOrConfig === "string" ? nameOrConfig : "";
159
+ const config = typeof nameOrConfig === "string" ? maybeConfig : nameOrConfig;
153
160
  let dt = "";
154
161
  if (config?.mode === "number") dt = 0;
155
162
  if (config?.mode === "bigint") dt = 0n;
@@ -160,22 +167,32 @@ function numeric(name, config) {
160
167
  _dataType: dt
161
168
  });
162
169
  }
163
- var boolean = (name) => createColumn({
164
- name,
165
- type: "INTEGER",
166
- _dataType: false,
167
- mode: "boolean"
168
- });
169
- var timestamp = (name) => createColumn({
170
- name,
171
- type: "INTEGER",
172
- _dataType: /* @__PURE__ */ new Date(),
173
- mode: "timestamp"
174
- });
170
+ function boolean(name) {
171
+ return createColumn({
172
+ name: name ?? "",
173
+ type: "INTEGER",
174
+ _dataType: false,
175
+ mode: "boolean"
176
+ });
177
+ }
178
+ function timestamp(name) {
179
+ return createColumn({
180
+ name: name ?? "",
181
+ type: "INTEGER",
182
+ _dataType: /* @__PURE__ */ new Date(),
183
+ mode: "timestamp"
184
+ });
185
+ }
186
+ function increments(name) {
187
+ return integer(name ?? "").primaryKey({
188
+ autoIncrement: true
189
+ });
190
+ }
175
191
  function defineTable(tableName, schema) {
176
192
  const finalizedSchema = { ...schema };
177
193
  for (const key of Object.keys(finalizedSchema)) {
178
194
  const col = finalizedSchema[key];
195
+ if (!col.name || col.name === "") col.name = key;
179
196
  col.tableName = tableName;
180
197
  }
181
198
  const table = {
@@ -184,7 +201,7 @@ function defineTable(tableName, schema) {
184
201
  // The Drizzle-like type inference properties
185
202
  $inferSelect: {},
186
203
  $inferInsert: {}
187
- // Example: omit 'id' for inserts
204
+ // omit PK columns
188
205
  };
189
206
  for (const [key, col] of Object.entries(finalizedSchema)) {
190
207
  table[key] = col;
@@ -192,6 +209,45 @@ function defineTable(tableName, schema) {
192
209
  return table;
193
210
  }
194
211
 
212
+ // src/orm.ts
213
+ var import_plugin_sql = __toESM(require("@tauri-apps/plugin-sql"));
214
+
215
+ // src/sql-helpers.ts
216
+ function isColumn(value) {
217
+ return typeof value === "object" && value !== null && "_dataType" in value;
218
+ }
219
+ function getQualifiedName(column) {
220
+ if (column.tableName) return `${column.tableName}.${column.name}`;
221
+ return column.name;
222
+ }
223
+ function comparison(operator, column, value) {
224
+ return {
225
+ toSQL: () => {
226
+ if (isColumn(value)) {
227
+ return {
228
+ clause: `${getQualifiedName(column)} ${operator} ${getQualifiedName(
229
+ value
230
+ )}`,
231
+ bindings: []
232
+ };
233
+ }
234
+ return {
235
+ clause: `${getQualifiedName(column)} ${operator} ?`,
236
+ bindings: [value]
237
+ };
238
+ }
239
+ };
240
+ }
241
+ var eq = (column, value) => comparison("=", column, value);
242
+ var ne = (column, value) => comparison("!=", column, value);
243
+ var gt = (column, value) => comparison(">", column, value);
244
+ var gte = (column, value) => comparison(">=", column, value);
245
+ var lt = (column, value) => comparison("<", column, value);
246
+ var lte = (column, value) => comparison("<=", column, value);
247
+ var like = (column, value) => comparison("LIKE", column, value);
248
+ var asc = (column) => `${getQualifiedName(column)} ASC`;
249
+ var desc = (column) => `${getQualifiedName(column)} DESC`;
250
+
195
251
  // src/orm.ts
196
252
  var SelectQueryBuilder = class {
197
253
  _table = null;
@@ -202,7 +258,9 @@ var SelectQueryBuilder = class {
202
258
  _limit = null;
203
259
  _offset = null;
204
260
  _eager = {};
205
- constructor(fields) {
261
+ _dbProvider;
262
+ constructor(dbProvider, fields) {
263
+ this._dbProvider = dbProvider;
206
264
  if (fields) {
207
265
  this._selectedColumns = Object.values(fields).map((c) => c.name);
208
266
  }
@@ -238,7 +296,7 @@ var SelectQueryBuilder = class {
238
296
  if (!this._table) {
239
297
  throw new Error("Cannot execute select query without a 'from' table.");
240
298
  }
241
- const db3 = getDb();
299
+ const db = await this._dbProvider();
242
300
  const bindings = [];
243
301
  let query = `SELECT ${this._selectedColumns.join(", ")} FROM ${this._table._tableName}`;
244
302
  if (this._joins.length > 0) {
@@ -266,7 +324,7 @@ var SelectQueryBuilder = class {
266
324
  query += ` OFFSET ?`;
267
325
  bindings.push(this._offset);
268
326
  }
269
- return db3.select(query, bindings);
327
+ return db.select(query, bindings);
270
328
  }
271
329
  };
272
330
  var TauriORM = class {
@@ -274,15 +332,23 @@ var TauriORM = class {
274
332
  query = {};
275
333
  _tables = null;
276
334
  _relations = null;
335
+ _dbPromise;
336
+ constructor(dbUri) {
337
+ this._dbPromise = import_plugin_sql.default.load(dbUri);
338
+ }
339
+ async getDb() {
340
+ return this._dbPromise;
341
+ }
277
342
  // Deprecated: use configure()
278
343
  configureQuery(tables, relations2) {
279
344
  this.configure(tables, relations2);
280
345
  }
281
346
  select(fields) {
282
- return new SelectQueryBuilder(fields);
347
+ return new SelectQueryBuilder(this.getDb.bind(this), fields);
283
348
  }
284
349
  // --- Drizzle-style CRUD builders ---
285
350
  insert(table) {
351
+ const self = this;
286
352
  return new class InsertBuilder {
287
353
  _table = table;
288
354
  _rows = [];
@@ -291,13 +357,17 @@ var TauriORM = class {
291
357
  return this;
292
358
  }
293
359
  async execute() {
294
- const db3 = getDb();
360
+ const db = await self.getDb();
295
361
  for (const data of this._rows) {
296
362
  const finalData = { ...data };
297
363
  const schema = this._table._schema;
298
364
  for (const [key, col] of Object.entries(schema)) {
299
- if (finalData[key] === void 0 && col.defaultFn) {
300
- finalData[key] = col.defaultFn();
365
+ if (finalData[key] === void 0) {
366
+ if (col.defaultFn) {
367
+ finalData[key] = col.defaultFn();
368
+ } else if (col.onUpdateFn) {
369
+ finalData[key] = col.onUpdateFn();
370
+ }
301
371
  }
302
372
  }
303
373
  const keys = Object.keys(finalData);
@@ -306,12 +376,13 @@ var TauriORM = class {
306
376
  const query = `INSERT INTO ${this._table._tableName} (${keys.join(
307
377
  ", "
308
378
  )}) VALUES (${placeholders})`;
309
- await db3.execute(query, values);
379
+ await db.execute(query, values);
310
380
  }
311
381
  }
312
382
  }();
313
383
  }
314
384
  update(table) {
385
+ const self = this;
315
386
  return new class UpdateBuilder {
316
387
  _table = table;
317
388
  _data = null;
@@ -327,10 +398,17 @@ var TauriORM = class {
327
398
  async execute() {
328
399
  if (!this._data)
329
400
  throw new Error("Update requires set() before execute()");
330
- const db3 = getDb();
331
- const setKeys = Object.keys(this._data);
401
+ const db = await self.getDb();
402
+ const schema = this._table._schema;
403
+ const dataToSet = { ...this._data };
404
+ for (const [key, col] of Object.entries(schema)) {
405
+ if (!(key in dataToSet) && col.onUpdateFn) {
406
+ dataToSet[key] = col.onUpdateFn();
407
+ }
408
+ }
409
+ const setKeys = Object.keys(dataToSet);
332
410
  const setClause = setKeys.map((k) => `${k} = ?`).join(", ");
333
- const bindings = Object.values(this._data);
411
+ const bindings = Object.values(dataToSet);
334
412
  let query = `UPDATE ${this._table._tableName} SET ${setClause}`;
335
413
  if (this._where) {
336
414
  if (typeof this._where.toSQL === "function") {
@@ -345,11 +423,12 @@ var TauriORM = class {
345
423
  }
346
424
  }
347
425
  }
348
- await db3.execute(query, bindings);
426
+ await db.execute(query, bindings);
349
427
  }
350
428
  }();
351
429
  }
352
430
  delete(table) {
431
+ const self = this;
353
432
  return new class DeleteBuilder {
354
433
  _table = table;
355
434
  _where = null;
@@ -358,7 +437,7 @@ var TauriORM = class {
358
437
  return this;
359
438
  }
360
439
  async execute() {
361
- const db3 = getDb();
440
+ const db = await self.getDb();
362
441
  let query = `DELETE FROM ${this._table._tableName}`;
363
442
  const bindings = [];
364
443
  if (this._where) {
@@ -374,7 +453,7 @@ var TauriORM = class {
374
453
  }
375
454
  }
376
455
  }
377
- await db3.execute(query, bindings);
456
+ await db.execute(query, bindings);
378
457
  }
379
458
  }();
380
459
  }
@@ -382,8 +461,8 @@ var TauriORM = class {
382
461
  // legacy direct methods removed in favor of builder APIs
383
462
  // legacy direct methods removed in favor of builder APIs
384
463
  async run(query, bindings = []) {
385
- const db3 = getDb();
386
- await db3.execute(query, bindings);
464
+ const db = await this.getDb();
465
+ await db.execute(query, bindings);
387
466
  }
388
467
  // --- Migrations API ---
389
468
  generateCreateTableSql(table) {
@@ -433,16 +512,16 @@ var TauriORM = class {
433
512
  );
434
513
  }
435
514
  async hasMigration(name) {
436
- const db3 = getDb();
437
- const rows = await db3.select(
515
+ const db = await this.getDb();
516
+ const rows = await db.select(
438
517
  `SELECT name FROM _migrations WHERE name = ?`,
439
518
  [name]
440
519
  );
441
520
  return Array.isArray(rows) && rows.length > 0;
442
521
  }
443
522
  async recordMigration(name) {
444
- const db3 = getDb();
445
- await db3.execute(
523
+ const db = await this.getDb();
524
+ await db.execute(
446
525
  `INSERT INTO _migrations (name, applied_at) VALUES (?, ?)`,
447
526
  [name, Date.now()]
448
527
  );
@@ -464,7 +543,7 @@ var TauriORM = class {
464
543
  configure(tables, relDefs) {
465
544
  this._tables = tables;
466
545
  this._relations = relDefs ?? {};
467
- this.query = makeQueryAPI(tables, this._relations);
546
+ this.query = makeQueryAPI(tables, this._relations, this.getDb.bind(this));
468
547
  return this;
469
548
  }
470
549
  // Convenience: migrate from configured tables
@@ -476,7 +555,7 @@ var TauriORM = class {
476
555
  // --- Schema diff and CLI-like helpers ---
477
556
  async diffSchema() {
478
557
  if (!this._tables) throw new Error("No tables configured.");
479
- const dbi = getDb();
558
+ const dbi = await this.getDb();
480
559
  const configuredNames = Object.values(this._tables).map(
481
560
  (t) => t._tableName
482
561
  );
@@ -551,7 +630,7 @@ var TauriORM = class {
551
630
  return this.pullSchema();
552
631
  }
553
632
  async studio() {
554
- const dbi = getDb();
633
+ const dbi = await this.getDb();
555
634
  return { driver: "sqlite", path: dbi.path };
556
635
  }
557
636
  // --- Schema detection / signature ---
@@ -561,7 +640,7 @@ var TauriORM = class {
561
640
  );
562
641
  }
563
642
  async getSchemaMeta(key) {
564
- const dbi = getDb();
643
+ const dbi = await this.getDb();
565
644
  await this.ensureSchemaMeta();
566
645
  const rows = await dbi.select(
567
646
  `SELECT value FROM _schema_meta WHERE key = ?`,
@@ -570,7 +649,7 @@ var TauriORM = class {
570
649
  return rows?.[0]?.value ?? null;
571
650
  }
572
651
  async setSchemaMeta(key, value) {
573
- const dbi = getDb();
652
+ const dbi = await this.getDb();
574
653
  await this.ensureSchemaMeta();
575
654
  await dbi.execute(
576
655
  `INSERT INTO _schema_meta(key, value) VALUES(?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value`,
@@ -619,7 +698,7 @@ var TauriORM = class {
619
698
  // Pull current DB schema (minimal) for configured tables
620
699
  async pullSchema() {
621
700
  if (!this._tables) throw new Error("No tables configured.");
622
- const dbi = getDb();
701
+ const dbi = await this.getDb();
623
702
  const result = {};
624
703
  for (const tbl of Object.values(this._tables)) {
625
704
  const name = tbl._tableName;
@@ -638,7 +717,7 @@ var TauriORM = class {
638
717
  return this.generateCreateTableSql(table);
639
718
  }
640
719
  async tableExists(name) {
641
- const dbi = getDb();
720
+ const dbi = await this.getDb();
642
721
  const rows = await dbi.select(
643
722
  `SELECT name FROM sqlite_master WHERE type='table' AND name = ?`,
644
723
  [name]
@@ -648,7 +727,7 @@ var TauriORM = class {
648
727
  // Force push model to DB: add missing tables/columns, rebuild tables if incompatible
649
728
  async forcePush(options) {
650
729
  if (!this._tables) throw new Error("No tables configured.");
651
- const dbi = getDb();
730
+ const dbi = await this.getDb();
652
731
  const preserve = options?.preserveData !== false;
653
732
  for (const tbl of Object.values(this._tables)) {
654
733
  const tableName = tbl._tableName;
@@ -718,7 +797,6 @@ var TauriORM = class {
718
797
  await this.setSchemaMeta("schema_signature", this.computeModelSignature());
719
798
  }
720
799
  };
721
- var db2 = new TauriORM();
722
800
  function relations(baseTable, builder) {
723
801
  const ctx = {
724
802
  one: (table, cfg) => ({ kind: "one", table, cfg }),
@@ -744,10 +822,29 @@ function guessChildFk(child, base, rel) {
744
822
  ];
745
823
  return childCols.find((c) => guessNames.includes(c.name)) || childCols.find((c) => /.*_id$/i.test(c.name)) || null;
746
824
  }
825
+ function guessOneRelationJoin(base, rel) {
826
+ const child = rel.table;
827
+ const basePk = getPrimaryKey(base);
828
+ const childCols = Object.values(child._schema);
829
+ if (rel.cfg?.fields && rel.cfg?.references && rel.cfg.fields[0] && rel.cfg.references[0]) {
830
+ const fk = rel.cfg.fields[0];
831
+ const ref = rel.cfg.references[0];
832
+ if (childCols.some((c) => c.name === fk.name)) {
833
+ return { lhsTable: child, lhsCol: fk, rhsTable: base, rhsCol: ref };
834
+ }
835
+ const baseCols = Object.values(base._schema);
836
+ if (baseCols.some((c) => c.name === fk.name)) {
837
+ return { lhsTable: base, lhsCol: fk, rhsTable: child, rhsCol: ref };
838
+ }
839
+ }
840
+ const childFk = guessChildFk(child, base, rel);
841
+ if (!childFk) return null;
842
+ return { lhsTable: child, lhsCol: childFk, rhsTable: base, rhsCol: basePk };
843
+ }
747
844
  function isFlatWith(spec) {
748
845
  return Object.values(spec).every((v) => typeof v === "boolean");
749
846
  }
750
- function makeQueryAPI(tables, relDefs) {
847
+ function makeQueryAPI(tables, relDefs, dbProvider) {
751
848
  const api = {};
752
849
  const tableKeyByName = {};
753
850
  for (const [k, t] of Object.entries(tables)) tableKeyByName[t._tableName] = k;
@@ -756,7 +853,7 @@ function makeQueryAPI(tables, relDefs) {
756
853
  async findMany(opts) {
757
854
  const base = tbl;
758
855
  const withSpec = opts?.with ?? {};
759
- const dbi = getDb();
856
+ const dbi = await dbProvider();
760
857
  const rels = relDefs[tblKey] ?? {};
761
858
  if (opts?.join && isFlatWith(withSpec)) {
762
859
  const baseCols = Object.values(base._schema);
@@ -782,23 +879,43 @@ function makeQueryAPI(tables, relDefs) {
782
879
  const child = rel.table;
783
880
  const childCols = Object.values(child._schema);
784
881
  const childPk = childCols.find((c) => c.isPrimaryKey) || childCols.find((c) => c.name === "id") || null;
785
- const childFk = guessChildFk(child, base, rel);
786
- if (!childFk) continue;
787
- fkMap[relName] = { childFk, childPk };
882
+ if (rel.kind === "one") {
883
+ const mapping = guessOneRelationJoin(base, rel);
884
+ if (!mapping) continue;
885
+ if (mapping.lhsTable._tableName === child._tableName) {
886
+ fkMap[relName] = { childFk: mapping.lhsCol, childPk };
887
+ joins.push(
888
+ `LEFT JOIN ${child._tableName} ON ${mapping.lhsTable._tableName}.${mapping.lhsCol.name} = ${mapping.rhsTable._tableName}.${mapping.rhsCol.name}`
889
+ );
890
+ } else {
891
+ fkMap[relName] = { childFk: mapping.rhsCol, childPk };
892
+ joins.push(
893
+ `LEFT JOIN ${child._tableName} ON ${mapping.lhsTable._tableName}.${mapping.lhsCol.name} = ${mapping.rhsTable._tableName}.${mapping.rhsCol.name}`
894
+ );
895
+ }
896
+ } else {
897
+ const childFk = guessChildFk(child, base, rel);
898
+ if (!childFk) continue;
899
+ fkMap[relName] = { childFk, childPk };
900
+ joins.push(
901
+ `LEFT JOIN ${child._tableName} ON ${child._tableName}.${childFk.name} = ${base._tableName}.${basePk.name}`
902
+ );
903
+ }
788
904
  const selected = typeof enabled === "object" && enabled.columns?.length ? enabled.columns : childCols.map((c) => c.name);
789
905
  relColsMap[relName] = selected;
790
906
  for (const name of selected)
791
907
  selectParts.push(
792
908
  `${child._tableName}.${name} AS __rel_${relName}_${name}`
793
909
  );
794
- joins.push(
795
- `LEFT JOIN ${child._tableName} ON ${child._tableName}.${childFk.name} = ${base._tableName}.${basePk.name}`
796
- );
797
910
  }
798
911
  let sqlText = `SELECT ${selectParts.join(", ")} FROM ${base._tableName}${joins.length ? " " + joins.join(" ") : ""}`;
799
912
  const bindings = [];
800
913
  if (opts?.where) {
801
- if (typeof opts.where.toSQL === "function") {
914
+ if (typeof opts.where === "function") {
915
+ const w = opts.where(base, { eq, ne, gt, gte, lt, lte, like }).toSQL();
916
+ sqlText += ` WHERE ${w.clause}`;
917
+ bindings.push(...w.bindings);
918
+ } else if (typeof opts.where.toSQL === "function") {
802
919
  const w = opts.where.toSQL();
803
920
  sqlText += ` WHERE ${w.clause}`;
804
921
  bindings.push(...w.bindings);
@@ -810,8 +927,9 @@ function makeQueryAPI(tables, relDefs) {
810
927
  }
811
928
  }
812
929
  }
813
- if (opts?.orderBy?.length)
814
- sqlText += ` ORDER BY ${opts.orderBy.join(", ")}`;
930
+ const orderByClauses = typeof opts?.orderBy === "function" ? opts.orderBy(base, { asc, desc }) : opts?.orderBy;
931
+ if (orderByClauses?.length)
932
+ sqlText += ` ORDER BY ${orderByClauses.join(", ")}`;
815
933
  if (typeof opts?.limit === "number")
816
934
  sqlText += ` LIMIT ${opts.limit}`;
817
935
  if (typeof opts?.offset === "number")
@@ -878,7 +996,11 @@ function makeQueryAPI(tables, relDefs) {
878
996
  let baseSql = `SELECT ${baseSelected.join(", ")} FROM ${base._tableName}`;
879
997
  const baseBindings = [];
880
998
  if (opts?.where) {
881
- if (typeof opts.where.toSQL === "function") {
999
+ if (typeof opts.where === "function") {
1000
+ const w = opts.where(base, { eq, ne, gt, gte, lt, lte, like }).toSQL();
1001
+ baseSql += ` WHERE ${w.clause}`;
1002
+ baseBindings.push(...w.bindings);
1003
+ } else if (typeof opts.where.toSQL === "function") {
882
1004
  const w = opts.where.toSQL();
883
1005
  baseSql += ` WHERE ${w.clause}`;
884
1006
  baseBindings.push(...w.bindings);
@@ -890,8 +1012,9 @@ function makeQueryAPI(tables, relDefs) {
890
1012
  }
891
1013
  }
892
1014
  }
893
- if (opts?.orderBy?.length)
894
- baseSql += ` ORDER BY ${opts.orderBy.join(", ")}`;
1015
+ const orderByClauses2 = typeof opts?.orderBy === "function" ? opts.orderBy(base, { asc, desc }) : opts?.orderBy;
1016
+ if (orderByClauses2?.length)
1017
+ baseSql += ` ORDER BY ${orderByClauses2.join(", ")}`;
895
1018
  if (typeof opts?.limit === "number") baseSql += ` LIMIT ${opts.limit}`;
896
1019
  if (typeof opts?.offset === "number")
897
1020
  baseSql += ` OFFSET ${opts.offset}`;
@@ -910,9 +1033,9 @@ function makeQueryAPI(tables, relDefs) {
910
1033
  const child = rel.table;
911
1034
  const childCols = Object.values(child._schema);
912
1035
  const selectCols = enabled?.columns && enabled.columns.length > 0 ? enabled.columns : childCols.map((c) => c.name);
913
- const fkCol = guessChildFk(child, parentTable, rel);
914
- if (!fkCol) continue;
915
1036
  if (rel.kind === "many") {
1037
+ const fkCol = guessChildFk(child, parentTable, rel);
1038
+ if (!fkCol) continue;
916
1039
  const sql2 = `SELECT ${selectCols.join(", ")} FROM ${child._tableName} WHERE ${fkCol.name} IN (${parentIds.map(() => "?").join(", ")})`;
917
1040
  const rows = await dbi.select(sql2, parentIds);
918
1041
  const buckets = /* @__PURE__ */ new Map();
@@ -931,14 +1054,32 @@ function makeQueryAPI(tables, relDefs) {
931
1054
  await loadRelationsFor(children, child, enabled.with);
932
1055
  }
933
1056
  } else {
934
- const sql2 = `SELECT ${selectCols.join(", ")} FROM ${child._tableName} WHERE ${fkCol.name} IN (${parentIds.map(() => "?").join(", ")})`;
935
- const rows = await dbi.select(sql2, parentIds);
936
- const mapOne = /* @__PURE__ */ new Map();
937
- for (const r of rows) mapOne.set(r[fkCol.name], r);
938
- for (const p of parents)
939
- p[relName] = mapOne.get(p[parentPk.name]) ?? null;
1057
+ const mapping = guessOneRelationJoin(parentTable, rel);
1058
+ if (!mapping) continue;
1059
+ if (mapping.lhsTable._tableName === child._tableName) {
1060
+ const sql2 = `SELECT ${selectCols.join(", ")} FROM ${child._tableName} WHERE ${mapping.lhsCol.name} IN (${parentIds.map(() => "?").join(", ")})`;
1061
+ const rows = await dbi.select(sql2, parentIds);
1062
+ const mapOne = /* @__PURE__ */ new Map();
1063
+ for (const r of rows) mapOne.set(r[mapping.lhsCol.name], r);
1064
+ for (const p of parents)
1065
+ p[relName] = mapOne.get(p[parentPk.name]) ?? null;
1066
+ } else {
1067
+ const parentFkName = mapping.lhsCol.name;
1068
+ const childPkName = mapping.rhsCol.name;
1069
+ const childIds = parents.map((p) => p[parentFkName]).filter((v2) => v2 !== void 0 && v2 !== null);
1070
+ if (childIds.length === 0) {
1071
+ for (const p of parents) p[relName] = null;
1072
+ } else {
1073
+ const sql2 = `SELECT ${selectCols.join(", ")} FROM ${child._tableName} WHERE ${childPkName} IN (${childIds.map(() => "?").join(", ")})`;
1074
+ const rows = await dbi.select(sql2, childIds);
1075
+ const mapOne = /* @__PURE__ */ new Map();
1076
+ for (const r of rows) mapOne.set(r[childPkName], r);
1077
+ for (const p of parents)
1078
+ p[relName] = mapOne.get(p[parentFkName]) ?? null;
1079
+ }
1080
+ }
940
1081
  if (enabled?.with) {
941
- const children = parents.map((p) => p[relName]).filter(Boolean);
1082
+ const children = parents.map((p) => p[relName]).filter((x) => Boolean(x));
942
1083
  if (children.length > 0)
943
1084
  await loadRelationsFor(children, child, enabled.with);
944
1085
  }
@@ -949,61 +1090,27 @@ function makeQueryAPI(tables, relDefs) {
949
1090
  await loadRelationsFor(result, base, withSpec);
950
1091
  }
951
1092
  return result;
1093
+ },
1094
+ async findFirst(opts) {
1095
+ const rows = await api[tblKey].findMany({ ...opts, limit: 1 });
1096
+ return rows?.[0] ?? null;
952
1097
  }
953
1098
  };
954
1099
  }
955
1100
  return api;
956
1101
  }
957
-
958
- // src/sql-helpers.ts
959
- function isColumn(value) {
960
- return typeof value === "object" && value !== null && "_dataType" in value;
961
- }
962
- function getQualifiedName(column) {
963
- if (column.tableName) return `${column.tableName}.${column.name}`;
964
- return column.name;
965
- }
966
- function comparison(operator, column, value) {
967
- return {
968
- toSQL: () => {
969
- if (isColumn(value)) {
970
- return {
971
- clause: `${getQualifiedName(column)} ${operator} ${getQualifiedName(
972
- value
973
- )}`,
974
- bindings: []
975
- };
976
- }
977
- return {
978
- clause: `${getQualifiedName(column)} ${operator} ?`,
979
- bindings: [value]
980
- };
981
- }
982
- };
983
- }
984
- var eq = (column, value) => comparison("=", column, value);
985
- var ne = (column, value) => comparison("!=", column, value);
986
- var gt = (column, value) => comparison(">", column, value);
987
- var gte = (column, value) => comparison(">=", column, value);
988
- var lt = (column, value) => comparison("<", column, value);
989
- var lte = (column, value) => comparison("<=", column, value);
990
- var like = (column, value) => comparison("LIKE", column, value);
991
- var asc = (column) => `${column.name} ASC`;
992
- var desc = (column) => `${column.name} DESC`;
993
1102
  // Annotate the CommonJS export names for ESM import in node:
994
1103
  0 && (module.exports = {
995
1104
  TauriORM,
996
1105
  asc,
997
1106
  blob,
998
1107
  boolean,
999
- db,
1000
1108
  defineTable,
1001
1109
  desc,
1002
1110
  eq,
1003
- getDb,
1004
1111
  gt,
1005
1112
  gte,
1006
- initDb,
1113
+ increments,
1007
1114
  integer,
1008
1115
  like,
1009
1116
  lt,