@type32/tauri-sqlite-orm 0.1.7 → 0.1.9
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.d.mts +40 -15
- package/dist/index.d.ts +40 -15
- package/dist/index.js +134 -29
- package/dist/index.mjs +134 -29
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -188,6 +188,12 @@ declare const notExists: (subquery: SQL | {
|
|
|
188
188
|
declare const asc: (column: Column) => string;
|
|
189
189
|
declare const desc: (column: Column) => string;
|
|
190
190
|
|
|
191
|
+
type InferInsert<T> = T extends {
|
|
192
|
+
$inferInsert: infer I;
|
|
193
|
+
} ? I : never;
|
|
194
|
+
type InferSelect<T> = T extends {
|
|
195
|
+
$inferSelect: infer S;
|
|
196
|
+
} ? S : never;
|
|
191
197
|
declare class SelectQueryBuilder<T> {
|
|
192
198
|
private _table;
|
|
193
199
|
private _selectedColumns;
|
|
@@ -222,11 +228,17 @@ declare class TauriORM {
|
|
|
222
228
|
constructor(dbUri: string);
|
|
223
229
|
private getDb;
|
|
224
230
|
configureQuery(tables: Record<string, Table<any>>, relations: Record<string, Record<string, RelationConfig>>): void;
|
|
225
|
-
select<
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
231
|
+
select<TFields extends Record<string, Column<any>>>(fields: TFields): SelectQueryBuilder<{
|
|
232
|
+
[K in keyof TFields]: TFields[K]["_dataType"];
|
|
233
|
+
}>;
|
|
234
|
+
select<T = any>(fields?: undefined): SelectQueryBuilder<T>;
|
|
235
|
+
selectDistinct<TFields extends Record<string, Column<any>>>(fields: TFields): SelectQueryBuilder<{
|
|
236
|
+
[K in keyof TFields]: TFields[K]["_dataType"];
|
|
237
|
+
}>;
|
|
238
|
+
selectDistinct<T = any>(fields?: undefined): SelectQueryBuilder<T>;
|
|
239
|
+
insert<TTable extends Table<any>>(table: TTable): {
|
|
240
|
+
_table: TTable;
|
|
241
|
+
_rows: Array<InferInsert<TTable>>;
|
|
230
242
|
_selectSql: {
|
|
231
243
|
clause: string;
|
|
232
244
|
bindings: any[];
|
|
@@ -243,7 +255,7 @@ declare class TauriORM {
|
|
|
243
255
|
setWhere?: SQL;
|
|
244
256
|
};
|
|
245
257
|
_returning: null | "__RETURNING_ID__" | Record<string, Column<any>>;
|
|
246
|
-
values(rowOrRows:
|
|
258
|
+
values(rowOrRows: InferInsert<TTable> | Array<InferInsert<TTable>>): /*elided*/ any;
|
|
247
259
|
select(qb: {
|
|
248
260
|
toSQL?: () => {
|
|
249
261
|
clause: string;
|
|
@@ -266,15 +278,15 @@ declare class TauriORM {
|
|
|
266
278
|
_buildConflictClause(): string;
|
|
267
279
|
_executeWithReturning(db: any, query: string, bindings: any[]): Promise<any>;
|
|
268
280
|
};
|
|
269
|
-
update(table:
|
|
270
|
-
_table:
|
|
271
|
-
_data:
|
|
281
|
+
update<TTable extends Table<any>>(table: TTable): {
|
|
282
|
+
_table: TTable;
|
|
283
|
+
_data: Partial<InferInsert<TTable>> | null;
|
|
272
284
|
_where: Record<string, any> | SQL | null;
|
|
273
285
|
_orderBy: Array<string | SQL>;
|
|
274
286
|
_limit: number | null;
|
|
275
287
|
_from: Table<any> | null;
|
|
276
288
|
_returning: null | Record<string, Column<any>>;
|
|
277
|
-
set(data:
|
|
289
|
+
set(data: Partial<InferInsert<TTable>>): /*elided*/ any;
|
|
278
290
|
where(cond: Record<string, any> | SQL): /*elided*/ any;
|
|
279
291
|
orderBy(...clauses: (string | Column<any> | SQL)[]): /*elided*/ any;
|
|
280
292
|
limit(n: number): /*elided*/ any;
|
|
@@ -282,22 +294,25 @@ declare class TauriORM {
|
|
|
282
294
|
returning(fields?: Record<string, Column<any>>): any;
|
|
283
295
|
execute(): Promise<unknown>;
|
|
284
296
|
};
|
|
285
|
-
delete(table:
|
|
286
|
-
_table:
|
|
287
|
-
_where:
|
|
297
|
+
delete<TTable extends Table<any>>(table: TTable): {
|
|
298
|
+
_table: TTable;
|
|
299
|
+
_where: Partial<InferInsert<TTable>> | SQL | null;
|
|
288
300
|
_orderBy: Array<string | SQL>;
|
|
289
301
|
_limit: number | null;
|
|
290
302
|
_returning: null | Record<string, Column<any>>;
|
|
291
|
-
where(cond:
|
|
303
|
+
where(cond: Partial<InferInsert<TTable>> | SQL): /*elided*/ any;
|
|
292
304
|
orderBy(...clauses: (string | Column<any> | SQL)[]): /*elided*/ any;
|
|
293
305
|
limit(n: number): /*elided*/ any;
|
|
294
306
|
returning(fields?: Record<string, Column<any>>): any;
|
|
295
307
|
execute(): Promise<unknown>;
|
|
296
308
|
};
|
|
297
309
|
run(query: string, bindings?: any[]): Promise<void>;
|
|
310
|
+
private formatDefaultValue;
|
|
298
311
|
private generateCreateTableSql;
|
|
299
312
|
createTableIfNotExists(table: Table<any>): Promise<void>;
|
|
300
313
|
createTablesIfNotExist(tables: Table<any>[]): Promise<void>;
|
|
314
|
+
private generateCreateIndexSqls;
|
|
315
|
+
private createIndexesForTable;
|
|
301
316
|
private ensureMigrationsTable;
|
|
302
317
|
private hasMigration;
|
|
303
318
|
private recordMigration;
|
|
@@ -305,7 +320,14 @@ declare class TauriORM {
|
|
|
305
320
|
name?: string;
|
|
306
321
|
track?: boolean;
|
|
307
322
|
}): Promise<void>;
|
|
308
|
-
configure
|
|
323
|
+
configure<TTables extends Record<string, Table<any>>, TRelDefs extends Record<string, Record<string, RelationConfig>> = Record<string, Record<string, RelationConfig>>>(tables: TTables, relDefs?: TRelDefs): this & {
|
|
324
|
+
query: {
|
|
325
|
+
[K in keyof TTables]: {
|
|
326
|
+
findMany: (opts?: any) => Promise<Array<InferSelect<TTables[K]>>>;
|
|
327
|
+
findFirst: (opts?: any) => Promise<InferSelect<TTables[K]> | null>;
|
|
328
|
+
};
|
|
329
|
+
};
|
|
330
|
+
};
|
|
309
331
|
migrateConfigured(options?: {
|
|
310
332
|
name?: string;
|
|
311
333
|
track?: boolean;
|
|
@@ -348,6 +370,8 @@ declare class TauriORM {
|
|
|
348
370
|
private setSchemaMeta;
|
|
349
371
|
private normalizeColumn;
|
|
350
372
|
private computeModelSignature;
|
|
373
|
+
getSchemaSignature(): string;
|
|
374
|
+
printSchemaDiff(): Promise<void>;
|
|
351
375
|
isSchemaDirty(): Promise<{
|
|
352
376
|
dirty: boolean;
|
|
353
377
|
current: string;
|
|
@@ -364,6 +388,7 @@ declare class TauriORM {
|
|
|
364
388
|
dropExtraColumns?: boolean;
|
|
365
389
|
preserveData?: boolean;
|
|
366
390
|
}): Promise<void>;
|
|
391
|
+
private forcePushForTables;
|
|
367
392
|
}
|
|
368
393
|
type OneConfig = {
|
|
369
394
|
fields?: Column[];
|
package/dist/index.d.ts
CHANGED
|
@@ -188,6 +188,12 @@ declare const notExists: (subquery: SQL | {
|
|
|
188
188
|
declare const asc: (column: Column) => string;
|
|
189
189
|
declare const desc: (column: Column) => string;
|
|
190
190
|
|
|
191
|
+
type InferInsert<T> = T extends {
|
|
192
|
+
$inferInsert: infer I;
|
|
193
|
+
} ? I : never;
|
|
194
|
+
type InferSelect<T> = T extends {
|
|
195
|
+
$inferSelect: infer S;
|
|
196
|
+
} ? S : never;
|
|
191
197
|
declare class SelectQueryBuilder<T> {
|
|
192
198
|
private _table;
|
|
193
199
|
private _selectedColumns;
|
|
@@ -222,11 +228,17 @@ declare class TauriORM {
|
|
|
222
228
|
constructor(dbUri: string);
|
|
223
229
|
private getDb;
|
|
224
230
|
configureQuery(tables: Record<string, Table<any>>, relations: Record<string, Record<string, RelationConfig>>): void;
|
|
225
|
-
select<
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
231
|
+
select<TFields extends Record<string, Column<any>>>(fields: TFields): SelectQueryBuilder<{
|
|
232
|
+
[K in keyof TFields]: TFields[K]["_dataType"];
|
|
233
|
+
}>;
|
|
234
|
+
select<T = any>(fields?: undefined): SelectQueryBuilder<T>;
|
|
235
|
+
selectDistinct<TFields extends Record<string, Column<any>>>(fields: TFields): SelectQueryBuilder<{
|
|
236
|
+
[K in keyof TFields]: TFields[K]["_dataType"];
|
|
237
|
+
}>;
|
|
238
|
+
selectDistinct<T = any>(fields?: undefined): SelectQueryBuilder<T>;
|
|
239
|
+
insert<TTable extends Table<any>>(table: TTable): {
|
|
240
|
+
_table: TTable;
|
|
241
|
+
_rows: Array<InferInsert<TTable>>;
|
|
230
242
|
_selectSql: {
|
|
231
243
|
clause: string;
|
|
232
244
|
bindings: any[];
|
|
@@ -243,7 +255,7 @@ declare class TauriORM {
|
|
|
243
255
|
setWhere?: SQL;
|
|
244
256
|
};
|
|
245
257
|
_returning: null | "__RETURNING_ID__" | Record<string, Column<any>>;
|
|
246
|
-
values(rowOrRows:
|
|
258
|
+
values(rowOrRows: InferInsert<TTable> | Array<InferInsert<TTable>>): /*elided*/ any;
|
|
247
259
|
select(qb: {
|
|
248
260
|
toSQL?: () => {
|
|
249
261
|
clause: string;
|
|
@@ -266,15 +278,15 @@ declare class TauriORM {
|
|
|
266
278
|
_buildConflictClause(): string;
|
|
267
279
|
_executeWithReturning(db: any, query: string, bindings: any[]): Promise<any>;
|
|
268
280
|
};
|
|
269
|
-
update(table:
|
|
270
|
-
_table:
|
|
271
|
-
_data:
|
|
281
|
+
update<TTable extends Table<any>>(table: TTable): {
|
|
282
|
+
_table: TTable;
|
|
283
|
+
_data: Partial<InferInsert<TTable>> | null;
|
|
272
284
|
_where: Record<string, any> | SQL | null;
|
|
273
285
|
_orderBy: Array<string | SQL>;
|
|
274
286
|
_limit: number | null;
|
|
275
287
|
_from: Table<any> | null;
|
|
276
288
|
_returning: null | Record<string, Column<any>>;
|
|
277
|
-
set(data:
|
|
289
|
+
set(data: Partial<InferInsert<TTable>>): /*elided*/ any;
|
|
278
290
|
where(cond: Record<string, any> | SQL): /*elided*/ any;
|
|
279
291
|
orderBy(...clauses: (string | Column<any> | SQL)[]): /*elided*/ any;
|
|
280
292
|
limit(n: number): /*elided*/ any;
|
|
@@ -282,22 +294,25 @@ declare class TauriORM {
|
|
|
282
294
|
returning(fields?: Record<string, Column<any>>): any;
|
|
283
295
|
execute(): Promise<unknown>;
|
|
284
296
|
};
|
|
285
|
-
delete(table:
|
|
286
|
-
_table:
|
|
287
|
-
_where:
|
|
297
|
+
delete<TTable extends Table<any>>(table: TTable): {
|
|
298
|
+
_table: TTable;
|
|
299
|
+
_where: Partial<InferInsert<TTable>> | SQL | null;
|
|
288
300
|
_orderBy: Array<string | SQL>;
|
|
289
301
|
_limit: number | null;
|
|
290
302
|
_returning: null | Record<string, Column<any>>;
|
|
291
|
-
where(cond:
|
|
303
|
+
where(cond: Partial<InferInsert<TTable>> | SQL): /*elided*/ any;
|
|
292
304
|
orderBy(...clauses: (string | Column<any> | SQL)[]): /*elided*/ any;
|
|
293
305
|
limit(n: number): /*elided*/ any;
|
|
294
306
|
returning(fields?: Record<string, Column<any>>): any;
|
|
295
307
|
execute(): Promise<unknown>;
|
|
296
308
|
};
|
|
297
309
|
run(query: string, bindings?: any[]): Promise<void>;
|
|
310
|
+
private formatDefaultValue;
|
|
298
311
|
private generateCreateTableSql;
|
|
299
312
|
createTableIfNotExists(table: Table<any>): Promise<void>;
|
|
300
313
|
createTablesIfNotExist(tables: Table<any>[]): Promise<void>;
|
|
314
|
+
private generateCreateIndexSqls;
|
|
315
|
+
private createIndexesForTable;
|
|
301
316
|
private ensureMigrationsTable;
|
|
302
317
|
private hasMigration;
|
|
303
318
|
private recordMigration;
|
|
@@ -305,7 +320,14 @@ declare class TauriORM {
|
|
|
305
320
|
name?: string;
|
|
306
321
|
track?: boolean;
|
|
307
322
|
}): Promise<void>;
|
|
308
|
-
configure
|
|
323
|
+
configure<TTables extends Record<string, Table<any>>, TRelDefs extends Record<string, Record<string, RelationConfig>> = Record<string, Record<string, RelationConfig>>>(tables: TTables, relDefs?: TRelDefs): this & {
|
|
324
|
+
query: {
|
|
325
|
+
[K in keyof TTables]: {
|
|
326
|
+
findMany: (opts?: any) => Promise<Array<InferSelect<TTables[K]>>>;
|
|
327
|
+
findFirst: (opts?: any) => Promise<InferSelect<TTables[K]> | null>;
|
|
328
|
+
};
|
|
329
|
+
};
|
|
330
|
+
};
|
|
309
331
|
migrateConfigured(options?: {
|
|
310
332
|
name?: string;
|
|
311
333
|
track?: boolean;
|
|
@@ -348,6 +370,8 @@ declare class TauriORM {
|
|
|
348
370
|
private setSchemaMeta;
|
|
349
371
|
private normalizeColumn;
|
|
350
372
|
private computeModelSignature;
|
|
373
|
+
getSchemaSignature(): string;
|
|
374
|
+
printSchemaDiff(): Promise<void>;
|
|
351
375
|
isSchemaDirty(): Promise<{
|
|
352
376
|
dirty: boolean;
|
|
353
377
|
current: string;
|
|
@@ -364,6 +388,7 @@ declare class TauriORM {
|
|
|
364
388
|
dropExtraColumns?: boolean;
|
|
365
389
|
preserveData?: boolean;
|
|
366
390
|
}): Promise<void>;
|
|
391
|
+
private forcePushForTables;
|
|
367
392
|
}
|
|
368
393
|
type OneConfig = {
|
|
369
394
|
fields?: Column[];
|
package/dist/index.js
CHANGED
|
@@ -213,12 +213,19 @@ function unique(name) {
|
|
|
213
213
|
return {
|
|
214
214
|
on: (...cols) => ({
|
|
215
215
|
name,
|
|
216
|
-
columns: cols.map((c) => c.name)
|
|
216
|
+
columns: cols.map((c) => c.name),
|
|
217
|
+
// runtime marker for DDL rendering
|
|
218
|
+
kind: "unique"
|
|
217
219
|
})
|
|
218
220
|
};
|
|
219
221
|
}
|
|
220
222
|
function primaryKey(opts) {
|
|
221
|
-
return {
|
|
223
|
+
return {
|
|
224
|
+
name: opts.name,
|
|
225
|
+
columns: opts.columns.map((c) => c.name),
|
|
226
|
+
// runtime marker for DDL rendering
|
|
227
|
+
kind: "primaryKey"
|
|
228
|
+
};
|
|
222
229
|
}
|
|
223
230
|
function check(name, expr) {
|
|
224
231
|
return { name, expr };
|
|
@@ -647,7 +654,10 @@ var TauriORM = class {
|
|
|
647
654
|
_relations = null;
|
|
648
655
|
_dbPromise;
|
|
649
656
|
constructor(dbUri) {
|
|
650
|
-
this._dbPromise = import_plugin_sql.default.load(dbUri)
|
|
657
|
+
this._dbPromise = import_plugin_sql.default.load(dbUri).then(async (db) => {
|
|
658
|
+
await db.execute("PRAGMA foreign_keys = ON");
|
|
659
|
+
return db;
|
|
660
|
+
});
|
|
651
661
|
}
|
|
652
662
|
async getDb() {
|
|
653
663
|
return this._dbPromise;
|
|
@@ -721,7 +731,7 @@ var TauriORM = class {
|
|
|
721
731
|
return ret;
|
|
722
732
|
}
|
|
723
733
|
for (const data of this._rows) {
|
|
724
|
-
const finalData = {
|
|
734
|
+
const finalData = Object.assign({}, data);
|
|
725
735
|
const schema = this._table._schema;
|
|
726
736
|
for (const [key, col] of Object.entries(schema)) {
|
|
727
737
|
if (finalData[key] === void 0) {
|
|
@@ -975,6 +985,25 @@ var TauriORM = class {
|
|
|
975
985
|
await db.execute(query, bindings);
|
|
976
986
|
}
|
|
977
987
|
// --- Migrations API ---
|
|
988
|
+
formatDefaultValue(col) {
|
|
989
|
+
const dv = col.defaultValue;
|
|
990
|
+
if (dv === void 0) return null;
|
|
991
|
+
if (dv && typeof dv === "object" && "raw" in dv) {
|
|
992
|
+
return dv.raw;
|
|
993
|
+
}
|
|
994
|
+
if (dv instanceof Date) {
|
|
995
|
+
const isMs = col.mode === "timestamp_ms";
|
|
996
|
+
const num = isMs ? dv.getTime() : Math.floor(dv.getTime() / 1e3);
|
|
997
|
+
return String(num);
|
|
998
|
+
}
|
|
999
|
+
if (col.mode === "boolean") {
|
|
1000
|
+
return String(dv ? 1 : 0);
|
|
1001
|
+
}
|
|
1002
|
+
if (typeof dv === "string") {
|
|
1003
|
+
return `'${dv.replace(/'/g, "''")}'`;
|
|
1004
|
+
}
|
|
1005
|
+
return String(dv);
|
|
1006
|
+
}
|
|
978
1007
|
generateCreateTableSql(table) {
|
|
979
1008
|
const tableName = table._tableName;
|
|
980
1009
|
const columns = Object.values(table._schema);
|
|
@@ -985,14 +1014,8 @@ var TauriORM = class {
|
|
|
985
1014
|
}
|
|
986
1015
|
if (col.isNotNull) def += " NOT NULL";
|
|
987
1016
|
if (col.defaultValue !== void 0) {
|
|
988
|
-
const
|
|
989
|
-
if (
|
|
990
|
-
def += ` DEFAULT ${dv.raw}`;
|
|
991
|
-
} else if (typeof dv === "string") {
|
|
992
|
-
def += ` DEFAULT '${dv.replace(/'/g, "''")}'`;
|
|
993
|
-
} else {
|
|
994
|
-
def += ` DEFAULT ${dv}`;
|
|
995
|
-
}
|
|
1017
|
+
const formatted = this.formatDefaultValue(col);
|
|
1018
|
+
if (formatted !== null) def += ` DEFAULT ${formatted}`;
|
|
996
1019
|
}
|
|
997
1020
|
if (col.references && !col.isPrimaryKey) {
|
|
998
1021
|
def += ` REFERENCES ${col.references.table} (${col.references.column})`;
|
|
@@ -1003,19 +1026,86 @@ var TauriORM = class {
|
|
|
1003
1026
|
}
|
|
1004
1027
|
return def;
|
|
1005
1028
|
});
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
)
|
|
1029
|
+
const tableConstraints = [];
|
|
1030
|
+
const constraints = table._constraints;
|
|
1031
|
+
if (constraints && constraints.length) {
|
|
1032
|
+
for (const spec of constraints) {
|
|
1033
|
+
if (spec.expr) {
|
|
1034
|
+
const name = spec.name;
|
|
1035
|
+
const expr = spec.expr.raw ?? spec.expr?.raw ?? String(spec.expr);
|
|
1036
|
+
tableConstraints.push(
|
|
1037
|
+
name ? `CONSTRAINT ${name} CHECK (${expr})` : `CHECK (${expr})`
|
|
1038
|
+
);
|
|
1039
|
+
continue;
|
|
1040
|
+
}
|
|
1041
|
+
if (spec.foreignColumns) {
|
|
1042
|
+
const name = spec.name;
|
|
1043
|
+
const cols = spec.columns.join(", ");
|
|
1044
|
+
const fTable = spec.foreignTable;
|
|
1045
|
+
const fCols = spec.foreignColumns.join(", ");
|
|
1046
|
+
let clause = `${name ? `CONSTRAINT ${name} ` : ""}FOREIGN KEY (${cols}) REFERENCES ${fTable} (${fCols})`;
|
|
1047
|
+
if (spec.onDelete)
|
|
1048
|
+
clause += ` ON DELETE ${String(
|
|
1049
|
+
spec.onDelete
|
|
1050
|
+
).toUpperCase()}`;
|
|
1051
|
+
if (spec.onUpdate)
|
|
1052
|
+
clause += ` ON UPDATE ${String(
|
|
1053
|
+
spec.onUpdate
|
|
1054
|
+
).toUpperCase()}`;
|
|
1055
|
+
tableConstraints.push(clause);
|
|
1056
|
+
continue;
|
|
1057
|
+
}
|
|
1058
|
+
if (spec.columns) {
|
|
1059
|
+
const cols = spec.columns.join(", ");
|
|
1060
|
+
const name = spec.name;
|
|
1061
|
+
const isPk = spec.kind === "primaryKey" || name && name.toLowerCase().includes("pk");
|
|
1062
|
+
if (isPk) {
|
|
1063
|
+
tableConstraints.push(
|
|
1064
|
+
name ? `CONSTRAINT ${name} PRIMARY KEY (${cols})` : `PRIMARY KEY (${cols})`
|
|
1065
|
+
);
|
|
1066
|
+
} else {
|
|
1067
|
+
tableConstraints.push(
|
|
1068
|
+
name ? `CONSTRAINT ${name} UNIQUE (${cols})` : `UNIQUE (${cols})`
|
|
1069
|
+
);
|
|
1070
|
+
}
|
|
1071
|
+
continue;
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
const parts = [...columnDefs, ...tableConstraints];
|
|
1076
|
+
return `CREATE TABLE IF NOT EXISTS ${tableName} (${parts.join(", ")});`;
|
|
1009
1077
|
}
|
|
1010
1078
|
async createTableIfNotExists(table) {
|
|
1011
1079
|
const sql2 = this.generateCreateTableSql(table);
|
|
1012
1080
|
await this.run(sql2);
|
|
1081
|
+
await this.createIndexesForTable(table);
|
|
1013
1082
|
}
|
|
1014
1083
|
async createTablesIfNotExist(tables) {
|
|
1015
1084
|
for (const t of tables) {
|
|
1016
1085
|
await this.createTableIfNotExists(t);
|
|
1017
1086
|
}
|
|
1018
1087
|
}
|
|
1088
|
+
generateCreateIndexSqls(table) {
|
|
1089
|
+
const tableName = table._tableName;
|
|
1090
|
+
const indexes = table._indexes || [];
|
|
1091
|
+
const stmts = [];
|
|
1092
|
+
for (const idx of indexes) {
|
|
1093
|
+
const unique2 = idx.unique ? "UNIQUE " : "";
|
|
1094
|
+
if (!idx.name) continue;
|
|
1095
|
+
const colList = Array.isArray(idx.columns) ? idx.columns : [];
|
|
1096
|
+
if (colList.length === 0) continue;
|
|
1097
|
+
const cols = `(${colList.join(", ")})`;
|
|
1098
|
+
const where = idx.where?.raw ? ` WHERE ${idx.where.raw}` : "";
|
|
1099
|
+
stmts.push(
|
|
1100
|
+
`CREATE ${unique2}INDEX IF NOT EXISTS ${idx.name} ON ${tableName} ${cols}${where};`
|
|
1101
|
+
);
|
|
1102
|
+
}
|
|
1103
|
+
return stmts;
|
|
1104
|
+
}
|
|
1105
|
+
async createIndexesForTable(table) {
|
|
1106
|
+
const stmts = this.generateCreateIndexSqls(table);
|
|
1107
|
+
for (const s of stmts) await this.run(s);
|
|
1108
|
+
}
|
|
1019
1109
|
async ensureMigrationsTable() {
|
|
1020
1110
|
await this.run(
|
|
1021
1111
|
`CREATE TABLE IF NOT EXISTS _migrations (name TEXT PRIMARY KEY, applied_at INTEGER NOT NULL)`
|
|
@@ -1040,20 +1130,23 @@ var TauriORM = class {
|
|
|
1040
1130
|
const track = options?.track ?? true;
|
|
1041
1131
|
if (track) {
|
|
1042
1132
|
await this.ensureMigrationsTable();
|
|
1133
|
+
}
|
|
1134
|
+
await this.forcePushForTables(tables, { preserveData: true });
|
|
1135
|
+
if (track) {
|
|
1043
1136
|
const name = options?.name ?? `init:${tables.map((t) => t._tableName).join(",")}`;
|
|
1044
1137
|
const already = await this.hasMigration(name);
|
|
1045
|
-
if (already)
|
|
1046
|
-
await this.createTablesIfNotExist(tables);
|
|
1047
|
-
await this.recordMigration(name);
|
|
1048
|
-
return;
|
|
1138
|
+
if (!already) await this.recordMigration(name);
|
|
1049
1139
|
}
|
|
1050
|
-
await this.createTablesIfNotExist(tables);
|
|
1051
1140
|
}
|
|
1052
1141
|
// Configure schema and relations, and generate db.query automatically
|
|
1053
1142
|
configure(tables, relDefs) {
|
|
1054
1143
|
this._tables = tables;
|
|
1055
1144
|
this._relations = relDefs ?? {};
|
|
1056
|
-
this.query = makeQueryAPI(
|
|
1145
|
+
this.query = makeQueryAPI(
|
|
1146
|
+
tables,
|
|
1147
|
+
this._relations ?? {},
|
|
1148
|
+
this.getDb.bind(this)
|
|
1149
|
+
);
|
|
1057
1150
|
return this;
|
|
1058
1151
|
}
|
|
1059
1152
|
// Convenience: migrate from configured tables
|
|
@@ -1061,6 +1154,7 @@ var TauriORM = class {
|
|
|
1061
1154
|
if (!this._tables)
|
|
1062
1155
|
throw new Error("No tables configured. Call db.configure({...}) first.");
|
|
1063
1156
|
await this.migrate(Object.values(this._tables), options);
|
|
1157
|
+
await this.setSchemaMeta("schema_signature", this.computeModelSignature());
|
|
1064
1158
|
}
|
|
1065
1159
|
// --- Schema diff and CLI-like helpers ---
|
|
1066
1160
|
async diffSchema() {
|
|
@@ -1187,6 +1281,13 @@ var TauriORM = class {
|
|
|
1187
1281
|
entries.sort((a, b) => a.table.localeCompare(b.table));
|
|
1188
1282
|
return JSON.stringify(entries);
|
|
1189
1283
|
}
|
|
1284
|
+
getSchemaSignature() {
|
|
1285
|
+
return this.computeModelSignature();
|
|
1286
|
+
}
|
|
1287
|
+
async printSchemaDiff() {
|
|
1288
|
+
const diff = await this.diffSchema();
|
|
1289
|
+
console.log("Schema diff:", JSON.stringify(diff, null, 2));
|
|
1290
|
+
}
|
|
1190
1291
|
async isSchemaDirty() {
|
|
1191
1292
|
const sig = this.computeModelSignature();
|
|
1192
1293
|
const stored = await this.getSchemaMeta("schema_signature");
|
|
@@ -1196,7 +1297,9 @@ var TauriORM = class {
|
|
|
1196
1297
|
const status = await this.isSchemaDirty();
|
|
1197
1298
|
if (!this._tables) throw new Error("No tables configured.");
|
|
1198
1299
|
if (status.dirty) {
|
|
1199
|
-
await this.
|
|
1300
|
+
await this.forcePushForTables(Object.values(this._tables), {
|
|
1301
|
+
preserveData: true
|
|
1302
|
+
});
|
|
1200
1303
|
await this.setSchemaMeta(
|
|
1201
1304
|
"schema_signature",
|
|
1202
1305
|
this.computeModelSignature()
|
|
@@ -1237,13 +1340,17 @@ var TauriORM = class {
|
|
|
1237
1340
|
// Force push model to DB: add missing tables/columns, rebuild tables if incompatible
|
|
1238
1341
|
async forcePush(options) {
|
|
1239
1342
|
if (!this._tables) throw new Error("No tables configured.");
|
|
1343
|
+
await this.forcePushForTables(Object.values(this._tables), options);
|
|
1344
|
+
}
|
|
1345
|
+
async forcePushForTables(tables, options) {
|
|
1240
1346
|
const dbi = await this.getDb();
|
|
1241
1347
|
const preserve = options?.preserveData !== false;
|
|
1242
|
-
for (const tbl of
|
|
1348
|
+
for (const tbl of tables) {
|
|
1243
1349
|
const tableName = tbl._tableName;
|
|
1244
1350
|
const exists2 = await this.tableExists(tableName);
|
|
1245
1351
|
if (!exists2) {
|
|
1246
1352
|
await this.run(this.buildCreateTableSQL(tbl));
|
|
1353
|
+
await this.createIndexesForTable(tbl);
|
|
1247
1354
|
continue;
|
|
1248
1355
|
}
|
|
1249
1356
|
const existingCols = await dbi.select(
|
|
@@ -1288,20 +1395,18 @@ var TauriORM = class {
|
|
|
1288
1395
|
}
|
|
1289
1396
|
await this.run(`DROP TABLE ${tableName}`);
|
|
1290
1397
|
await this.run(`ALTER TABLE ${tmp} RENAME TO ${tableName}`);
|
|
1398
|
+
await this.createIndexesForTable(tbl);
|
|
1291
1399
|
} else {
|
|
1292
1400
|
for (const m of missing) {
|
|
1293
1401
|
let clause = `${m.name} ${m.type}`;
|
|
1294
1402
|
if (m.isNotNull) clause += " NOT NULL";
|
|
1295
1403
|
if (m.defaultValue !== void 0) {
|
|
1296
|
-
const
|
|
1297
|
-
if (
|
|
1298
|
-
clause += ` DEFAULT ${dv.raw}`;
|
|
1299
|
-
else if (typeof dv === "string")
|
|
1300
|
-
clause += ` DEFAULT '${dv.replace(/'/g, "''")}'`;
|
|
1301
|
-
else clause += ` DEFAULT ${dv}`;
|
|
1404
|
+
const formatted = this.formatDefaultValue(m);
|
|
1405
|
+
if (formatted !== null) clause += ` DEFAULT ${formatted}`;
|
|
1302
1406
|
}
|
|
1303
1407
|
await this.run(`ALTER TABLE ${tableName} ADD COLUMN ${clause}`);
|
|
1304
1408
|
}
|
|
1409
|
+
await this.createIndexesForTable(tbl);
|
|
1305
1410
|
}
|
|
1306
1411
|
}
|
|
1307
1412
|
await this.setSchemaMeta("schema_signature", this.computeModelSignature());
|
package/dist/index.mjs
CHANGED
|
@@ -135,12 +135,19 @@ function unique(name) {
|
|
|
135
135
|
return {
|
|
136
136
|
on: (...cols) => ({
|
|
137
137
|
name,
|
|
138
|
-
columns: cols.map((c) => c.name)
|
|
138
|
+
columns: cols.map((c) => c.name),
|
|
139
|
+
// runtime marker for DDL rendering
|
|
140
|
+
kind: "unique"
|
|
139
141
|
})
|
|
140
142
|
};
|
|
141
143
|
}
|
|
142
144
|
function primaryKey(opts) {
|
|
143
|
-
return {
|
|
145
|
+
return {
|
|
146
|
+
name: opts.name,
|
|
147
|
+
columns: opts.columns.map((c) => c.name),
|
|
148
|
+
// runtime marker for DDL rendering
|
|
149
|
+
kind: "primaryKey"
|
|
150
|
+
};
|
|
144
151
|
}
|
|
145
152
|
function check(name, expr) {
|
|
146
153
|
return { name, expr };
|
|
@@ -569,7 +576,10 @@ var TauriORM = class {
|
|
|
569
576
|
_relations = null;
|
|
570
577
|
_dbPromise;
|
|
571
578
|
constructor(dbUri) {
|
|
572
|
-
this._dbPromise = Database.load(dbUri)
|
|
579
|
+
this._dbPromise = Database.load(dbUri).then(async (db) => {
|
|
580
|
+
await db.execute("PRAGMA foreign_keys = ON");
|
|
581
|
+
return db;
|
|
582
|
+
});
|
|
573
583
|
}
|
|
574
584
|
async getDb() {
|
|
575
585
|
return this._dbPromise;
|
|
@@ -643,7 +653,7 @@ var TauriORM = class {
|
|
|
643
653
|
return ret;
|
|
644
654
|
}
|
|
645
655
|
for (const data of this._rows) {
|
|
646
|
-
const finalData = {
|
|
656
|
+
const finalData = Object.assign({}, data);
|
|
647
657
|
const schema = this._table._schema;
|
|
648
658
|
for (const [key, col] of Object.entries(schema)) {
|
|
649
659
|
if (finalData[key] === void 0) {
|
|
@@ -897,6 +907,25 @@ var TauriORM = class {
|
|
|
897
907
|
await db.execute(query, bindings);
|
|
898
908
|
}
|
|
899
909
|
// --- Migrations API ---
|
|
910
|
+
formatDefaultValue(col) {
|
|
911
|
+
const dv = col.defaultValue;
|
|
912
|
+
if (dv === void 0) return null;
|
|
913
|
+
if (dv && typeof dv === "object" && "raw" in dv) {
|
|
914
|
+
return dv.raw;
|
|
915
|
+
}
|
|
916
|
+
if (dv instanceof Date) {
|
|
917
|
+
const isMs = col.mode === "timestamp_ms";
|
|
918
|
+
const num = isMs ? dv.getTime() : Math.floor(dv.getTime() / 1e3);
|
|
919
|
+
return String(num);
|
|
920
|
+
}
|
|
921
|
+
if (col.mode === "boolean") {
|
|
922
|
+
return String(dv ? 1 : 0);
|
|
923
|
+
}
|
|
924
|
+
if (typeof dv === "string") {
|
|
925
|
+
return `'${dv.replace(/'/g, "''")}'`;
|
|
926
|
+
}
|
|
927
|
+
return String(dv);
|
|
928
|
+
}
|
|
900
929
|
generateCreateTableSql(table) {
|
|
901
930
|
const tableName = table._tableName;
|
|
902
931
|
const columns = Object.values(table._schema);
|
|
@@ -907,14 +936,8 @@ var TauriORM = class {
|
|
|
907
936
|
}
|
|
908
937
|
if (col.isNotNull) def += " NOT NULL";
|
|
909
938
|
if (col.defaultValue !== void 0) {
|
|
910
|
-
const
|
|
911
|
-
if (
|
|
912
|
-
def += ` DEFAULT ${dv.raw}`;
|
|
913
|
-
} else if (typeof dv === "string") {
|
|
914
|
-
def += ` DEFAULT '${dv.replace(/'/g, "''")}'`;
|
|
915
|
-
} else {
|
|
916
|
-
def += ` DEFAULT ${dv}`;
|
|
917
|
-
}
|
|
939
|
+
const formatted = this.formatDefaultValue(col);
|
|
940
|
+
if (formatted !== null) def += ` DEFAULT ${formatted}`;
|
|
918
941
|
}
|
|
919
942
|
if (col.references && !col.isPrimaryKey) {
|
|
920
943
|
def += ` REFERENCES ${col.references.table} (${col.references.column})`;
|
|
@@ -925,19 +948,86 @@ var TauriORM = class {
|
|
|
925
948
|
}
|
|
926
949
|
return def;
|
|
927
950
|
});
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
)
|
|
951
|
+
const tableConstraints = [];
|
|
952
|
+
const constraints = table._constraints;
|
|
953
|
+
if (constraints && constraints.length) {
|
|
954
|
+
for (const spec of constraints) {
|
|
955
|
+
if (spec.expr) {
|
|
956
|
+
const name = spec.name;
|
|
957
|
+
const expr = spec.expr.raw ?? spec.expr?.raw ?? String(spec.expr);
|
|
958
|
+
tableConstraints.push(
|
|
959
|
+
name ? `CONSTRAINT ${name} CHECK (${expr})` : `CHECK (${expr})`
|
|
960
|
+
);
|
|
961
|
+
continue;
|
|
962
|
+
}
|
|
963
|
+
if (spec.foreignColumns) {
|
|
964
|
+
const name = spec.name;
|
|
965
|
+
const cols = spec.columns.join(", ");
|
|
966
|
+
const fTable = spec.foreignTable;
|
|
967
|
+
const fCols = spec.foreignColumns.join(", ");
|
|
968
|
+
let clause = `${name ? `CONSTRAINT ${name} ` : ""}FOREIGN KEY (${cols}) REFERENCES ${fTable} (${fCols})`;
|
|
969
|
+
if (spec.onDelete)
|
|
970
|
+
clause += ` ON DELETE ${String(
|
|
971
|
+
spec.onDelete
|
|
972
|
+
).toUpperCase()}`;
|
|
973
|
+
if (spec.onUpdate)
|
|
974
|
+
clause += ` ON UPDATE ${String(
|
|
975
|
+
spec.onUpdate
|
|
976
|
+
).toUpperCase()}`;
|
|
977
|
+
tableConstraints.push(clause);
|
|
978
|
+
continue;
|
|
979
|
+
}
|
|
980
|
+
if (spec.columns) {
|
|
981
|
+
const cols = spec.columns.join(", ");
|
|
982
|
+
const name = spec.name;
|
|
983
|
+
const isPk = spec.kind === "primaryKey" || name && name.toLowerCase().includes("pk");
|
|
984
|
+
if (isPk) {
|
|
985
|
+
tableConstraints.push(
|
|
986
|
+
name ? `CONSTRAINT ${name} PRIMARY KEY (${cols})` : `PRIMARY KEY (${cols})`
|
|
987
|
+
);
|
|
988
|
+
} else {
|
|
989
|
+
tableConstraints.push(
|
|
990
|
+
name ? `CONSTRAINT ${name} UNIQUE (${cols})` : `UNIQUE (${cols})`
|
|
991
|
+
);
|
|
992
|
+
}
|
|
993
|
+
continue;
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
const parts = [...columnDefs, ...tableConstraints];
|
|
998
|
+
return `CREATE TABLE IF NOT EXISTS ${tableName} (${parts.join(", ")});`;
|
|
931
999
|
}
|
|
932
1000
|
async createTableIfNotExists(table) {
|
|
933
1001
|
const sql2 = this.generateCreateTableSql(table);
|
|
934
1002
|
await this.run(sql2);
|
|
1003
|
+
await this.createIndexesForTable(table);
|
|
935
1004
|
}
|
|
936
1005
|
async createTablesIfNotExist(tables) {
|
|
937
1006
|
for (const t of tables) {
|
|
938
1007
|
await this.createTableIfNotExists(t);
|
|
939
1008
|
}
|
|
940
1009
|
}
|
|
1010
|
+
generateCreateIndexSqls(table) {
|
|
1011
|
+
const tableName = table._tableName;
|
|
1012
|
+
const indexes = table._indexes || [];
|
|
1013
|
+
const stmts = [];
|
|
1014
|
+
for (const idx of indexes) {
|
|
1015
|
+
const unique2 = idx.unique ? "UNIQUE " : "";
|
|
1016
|
+
if (!idx.name) continue;
|
|
1017
|
+
const colList = Array.isArray(idx.columns) ? idx.columns : [];
|
|
1018
|
+
if (colList.length === 0) continue;
|
|
1019
|
+
const cols = `(${colList.join(", ")})`;
|
|
1020
|
+
const where = idx.where?.raw ? ` WHERE ${idx.where.raw}` : "";
|
|
1021
|
+
stmts.push(
|
|
1022
|
+
`CREATE ${unique2}INDEX IF NOT EXISTS ${idx.name} ON ${tableName} ${cols}${where};`
|
|
1023
|
+
);
|
|
1024
|
+
}
|
|
1025
|
+
return stmts;
|
|
1026
|
+
}
|
|
1027
|
+
async createIndexesForTable(table) {
|
|
1028
|
+
const stmts = this.generateCreateIndexSqls(table);
|
|
1029
|
+
for (const s of stmts) await this.run(s);
|
|
1030
|
+
}
|
|
941
1031
|
async ensureMigrationsTable() {
|
|
942
1032
|
await this.run(
|
|
943
1033
|
`CREATE TABLE IF NOT EXISTS _migrations (name TEXT PRIMARY KEY, applied_at INTEGER NOT NULL)`
|
|
@@ -962,20 +1052,23 @@ var TauriORM = class {
|
|
|
962
1052
|
const track = options?.track ?? true;
|
|
963
1053
|
if (track) {
|
|
964
1054
|
await this.ensureMigrationsTable();
|
|
1055
|
+
}
|
|
1056
|
+
await this.forcePushForTables(tables, { preserveData: true });
|
|
1057
|
+
if (track) {
|
|
965
1058
|
const name = options?.name ?? `init:${tables.map((t) => t._tableName).join(",")}`;
|
|
966
1059
|
const already = await this.hasMigration(name);
|
|
967
|
-
if (already)
|
|
968
|
-
await this.createTablesIfNotExist(tables);
|
|
969
|
-
await this.recordMigration(name);
|
|
970
|
-
return;
|
|
1060
|
+
if (!already) await this.recordMigration(name);
|
|
971
1061
|
}
|
|
972
|
-
await this.createTablesIfNotExist(tables);
|
|
973
1062
|
}
|
|
974
1063
|
// Configure schema and relations, and generate db.query automatically
|
|
975
1064
|
configure(tables, relDefs) {
|
|
976
1065
|
this._tables = tables;
|
|
977
1066
|
this._relations = relDefs ?? {};
|
|
978
|
-
this.query = makeQueryAPI(
|
|
1067
|
+
this.query = makeQueryAPI(
|
|
1068
|
+
tables,
|
|
1069
|
+
this._relations ?? {},
|
|
1070
|
+
this.getDb.bind(this)
|
|
1071
|
+
);
|
|
979
1072
|
return this;
|
|
980
1073
|
}
|
|
981
1074
|
// Convenience: migrate from configured tables
|
|
@@ -983,6 +1076,7 @@ var TauriORM = class {
|
|
|
983
1076
|
if (!this._tables)
|
|
984
1077
|
throw new Error("No tables configured. Call db.configure({...}) first.");
|
|
985
1078
|
await this.migrate(Object.values(this._tables), options);
|
|
1079
|
+
await this.setSchemaMeta("schema_signature", this.computeModelSignature());
|
|
986
1080
|
}
|
|
987
1081
|
// --- Schema diff and CLI-like helpers ---
|
|
988
1082
|
async diffSchema() {
|
|
@@ -1109,6 +1203,13 @@ var TauriORM = class {
|
|
|
1109
1203
|
entries.sort((a, b) => a.table.localeCompare(b.table));
|
|
1110
1204
|
return JSON.stringify(entries);
|
|
1111
1205
|
}
|
|
1206
|
+
getSchemaSignature() {
|
|
1207
|
+
return this.computeModelSignature();
|
|
1208
|
+
}
|
|
1209
|
+
async printSchemaDiff() {
|
|
1210
|
+
const diff = await this.diffSchema();
|
|
1211
|
+
console.log("Schema diff:", JSON.stringify(diff, null, 2));
|
|
1212
|
+
}
|
|
1112
1213
|
async isSchemaDirty() {
|
|
1113
1214
|
const sig = this.computeModelSignature();
|
|
1114
1215
|
const stored = await this.getSchemaMeta("schema_signature");
|
|
@@ -1118,7 +1219,9 @@ var TauriORM = class {
|
|
|
1118
1219
|
const status = await this.isSchemaDirty();
|
|
1119
1220
|
if (!this._tables) throw new Error("No tables configured.");
|
|
1120
1221
|
if (status.dirty) {
|
|
1121
|
-
await this.
|
|
1222
|
+
await this.forcePushForTables(Object.values(this._tables), {
|
|
1223
|
+
preserveData: true
|
|
1224
|
+
});
|
|
1122
1225
|
await this.setSchemaMeta(
|
|
1123
1226
|
"schema_signature",
|
|
1124
1227
|
this.computeModelSignature()
|
|
@@ -1159,13 +1262,17 @@ var TauriORM = class {
|
|
|
1159
1262
|
// Force push model to DB: add missing tables/columns, rebuild tables if incompatible
|
|
1160
1263
|
async forcePush(options) {
|
|
1161
1264
|
if (!this._tables) throw new Error("No tables configured.");
|
|
1265
|
+
await this.forcePushForTables(Object.values(this._tables), options);
|
|
1266
|
+
}
|
|
1267
|
+
async forcePushForTables(tables, options) {
|
|
1162
1268
|
const dbi = await this.getDb();
|
|
1163
1269
|
const preserve = options?.preserveData !== false;
|
|
1164
|
-
for (const tbl of
|
|
1270
|
+
for (const tbl of tables) {
|
|
1165
1271
|
const tableName = tbl._tableName;
|
|
1166
1272
|
const exists2 = await this.tableExists(tableName);
|
|
1167
1273
|
if (!exists2) {
|
|
1168
1274
|
await this.run(this.buildCreateTableSQL(tbl));
|
|
1275
|
+
await this.createIndexesForTable(tbl);
|
|
1169
1276
|
continue;
|
|
1170
1277
|
}
|
|
1171
1278
|
const existingCols = await dbi.select(
|
|
@@ -1210,20 +1317,18 @@ var TauriORM = class {
|
|
|
1210
1317
|
}
|
|
1211
1318
|
await this.run(`DROP TABLE ${tableName}`);
|
|
1212
1319
|
await this.run(`ALTER TABLE ${tmp} RENAME TO ${tableName}`);
|
|
1320
|
+
await this.createIndexesForTable(tbl);
|
|
1213
1321
|
} else {
|
|
1214
1322
|
for (const m of missing) {
|
|
1215
1323
|
let clause = `${m.name} ${m.type}`;
|
|
1216
1324
|
if (m.isNotNull) clause += " NOT NULL";
|
|
1217
1325
|
if (m.defaultValue !== void 0) {
|
|
1218
|
-
const
|
|
1219
|
-
if (
|
|
1220
|
-
clause += ` DEFAULT ${dv.raw}`;
|
|
1221
|
-
else if (typeof dv === "string")
|
|
1222
|
-
clause += ` DEFAULT '${dv.replace(/'/g, "''")}'`;
|
|
1223
|
-
else clause += ` DEFAULT ${dv}`;
|
|
1326
|
+
const formatted = this.formatDefaultValue(m);
|
|
1327
|
+
if (formatted !== null) clause += ` DEFAULT ${formatted}`;
|
|
1224
1328
|
}
|
|
1225
1329
|
await this.run(`ALTER TABLE ${tableName} ADD COLUMN ${clause}`);
|
|
1226
1330
|
}
|
|
1331
|
+
await this.createIndexesForTable(tbl);
|
|
1227
1332
|
}
|
|
1228
1333
|
}
|
|
1229
1334
|
await this.setSchemaMeta("schema_signature", this.computeModelSignature());
|