@type32/tauri-sqlite-orm 0.2.15 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aggregates.d.ts +12 -0
- package/dist/aggregates.js +9 -0
- package/dist/builders/delete.d.ts +23 -0
- package/dist/builders/delete.js +73 -0
- package/dist/builders/index.d.ts +7 -0
- package/dist/builders/index.js +7 -0
- package/dist/builders/insert.d.ts +31 -0
- package/dist/builders/insert.js +141 -0
- package/dist/builders/query-base.d.ts +1 -0
- package/dist/builders/query-base.js +1 -0
- package/dist/builders/relations.d.ts +11 -0
- package/dist/builders/relations.js +1 -0
- package/dist/builders/select.d.ts +54 -0
- package/dist/builders/select.js +427 -0
- package/dist/builders/update.d.ts +30 -0
- package/dist/builders/update.js +124 -0
- package/dist/builders/with.d.ts +17 -0
- package/dist/builders/with.js +34 -0
- package/dist/column-helpers.d.ts +22 -0
- package/dist/column-helpers.js +17 -0
- package/dist/dialect.d.ts +21 -0
- package/dist/dialect.js +67 -0
- package/dist/errors.d.ts +30 -0
- package/dist/errors.js +66 -0
- package/dist/index.d.mts +150 -4
- package/dist/index.d.ts +150 -4
- package/dist/index.js +270 -108
- package/dist/index.mjs +263 -104
- package/dist/operators.d.ts +30 -0
- package/dist/operators.js +84 -0
- package/dist/orm.d.ts +180 -0
- package/dist/orm.js +556 -0
- package/dist/relational-types.d.ts +87 -0
- package/dist/relational-types.js +1 -0
- package/dist/relations-v2.d.ts +77 -0
- package/dist/relations-v2.js +157 -0
- package/dist/serialization.d.ts +14 -0
- package/dist/serialization.js +135 -0
- package/dist/subquery.d.ts +5 -0
- package/dist/subquery.js +6 -0
- package/dist/types.d.ts +58 -0
- package/dist/types.js +1 -0
- package/package.json +2 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { DatabaseIntrospector, Dialect, DialectAdapter, Driver, Kysely, QueryCompiler } from 'kysely';
|
|
2
|
+
/**
|
|
3
|
+
* Minimal interface that any SQLite-over-Tauri (or compatible mock) database must satisfy.
|
|
4
|
+
* Using this instead of the concrete `@tauri-apps/plugin-sql` type keeps the dialect
|
|
5
|
+
* portable and testable outside a Tauri runtime.
|
|
6
|
+
*/
|
|
7
|
+
export interface DatabaseLike {
|
|
8
|
+
select<T>(query: string, params?: any[]): Promise<T>;
|
|
9
|
+
execute(query: string, params?: any[]): Promise<{
|
|
10
|
+
lastInsertId: number;
|
|
11
|
+
rowsAffected: number;
|
|
12
|
+
}>;
|
|
13
|
+
}
|
|
14
|
+
export declare class TauriDialect implements Dialect {
|
|
15
|
+
private readonly db;
|
|
16
|
+
constructor(db: DatabaseLike);
|
|
17
|
+
createAdapter(): DialectAdapter;
|
|
18
|
+
createDriver(): Driver;
|
|
19
|
+
createIntrospector(db: Kysely<any>): DatabaseIntrospector;
|
|
20
|
+
createQueryCompiler(): QueryCompiler;
|
|
21
|
+
}
|
package/dist/dialect.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { CompiledQuery, SqliteAdapter, SqliteIntrospector, SqliteQueryCompiler, } from 'kysely';
|
|
2
|
+
class TauriConnection {
|
|
3
|
+
db;
|
|
4
|
+
constructor(db) {
|
|
5
|
+
this.db = db;
|
|
6
|
+
}
|
|
7
|
+
async executeQuery(compiledQuery) {
|
|
8
|
+
const { sql, parameters } = compiledQuery;
|
|
9
|
+
const params = parameters;
|
|
10
|
+
const trimmed = sql.trimStart();
|
|
11
|
+
const isSelect = /^\s*(SELECT|WITH|PRAGMA)/i.test(trimmed);
|
|
12
|
+
const hasReturning = /\bRETURNING\b/i.test(sql);
|
|
13
|
+
// INSERT/UPDATE/DELETE with RETURNING returns rows; use select() not execute()
|
|
14
|
+
if (isSelect || hasReturning) {
|
|
15
|
+
const rows = await this.db.select(sql, params);
|
|
16
|
+
return { rows };
|
|
17
|
+
}
|
|
18
|
+
const result = await this.db.execute(sql, params);
|
|
19
|
+
return {
|
|
20
|
+
rows: [],
|
|
21
|
+
insertId: BigInt(Math.round(result.lastInsertId ?? 0)),
|
|
22
|
+
numAffectedRows: BigInt(result.rowsAffected ?? 0),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
async *streamQuery(_compiledQuery) {
|
|
26
|
+
throw new Error('Streaming queries are not supported by @tauri-apps/plugin-sql');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
class TauriDriver {
|
|
30
|
+
db;
|
|
31
|
+
constructor(db) {
|
|
32
|
+
this.db = db;
|
|
33
|
+
}
|
|
34
|
+
async init() { }
|
|
35
|
+
async acquireConnection() {
|
|
36
|
+
return new TauriConnection(this.db);
|
|
37
|
+
}
|
|
38
|
+
async beginTransaction(conn, _settings) {
|
|
39
|
+
await conn.executeQuery(CompiledQuery.raw('BEGIN'));
|
|
40
|
+
}
|
|
41
|
+
async commitTransaction(conn) {
|
|
42
|
+
await conn.executeQuery(CompiledQuery.raw('COMMIT'));
|
|
43
|
+
}
|
|
44
|
+
async rollbackTransaction(conn) {
|
|
45
|
+
await conn.executeQuery(CompiledQuery.raw('ROLLBACK'));
|
|
46
|
+
}
|
|
47
|
+
async releaseConnection(_conn) { }
|
|
48
|
+
async destroy() { }
|
|
49
|
+
}
|
|
50
|
+
export class TauriDialect {
|
|
51
|
+
db;
|
|
52
|
+
constructor(db) {
|
|
53
|
+
this.db = db;
|
|
54
|
+
}
|
|
55
|
+
createAdapter() {
|
|
56
|
+
return new SqliteAdapter();
|
|
57
|
+
}
|
|
58
|
+
createDriver() {
|
|
59
|
+
return new TauriDriver(this.db);
|
|
60
|
+
}
|
|
61
|
+
createIntrospector(db) {
|
|
62
|
+
return new SqliteIntrospector(db);
|
|
63
|
+
}
|
|
64
|
+
createQueryCompiler() {
|
|
65
|
+
return new SqliteQueryCompiler();
|
|
66
|
+
}
|
|
67
|
+
}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export declare class TauriORMError extends Error {
|
|
2
|
+
constructor(message: string);
|
|
3
|
+
}
|
|
4
|
+
export declare class QueryBuilderError extends TauriORMError {
|
|
5
|
+
constructor(message: string);
|
|
6
|
+
}
|
|
7
|
+
export declare class MissingWhereClauseError extends QueryBuilderError {
|
|
8
|
+
constructor(operation: 'UPDATE' | 'DELETE', tableName: string);
|
|
9
|
+
}
|
|
10
|
+
export declare class ValidationError extends TauriORMError {
|
|
11
|
+
constructor(message: string);
|
|
12
|
+
}
|
|
13
|
+
export declare class InsertValidationError extends ValidationError {
|
|
14
|
+
constructor(message: string);
|
|
15
|
+
}
|
|
16
|
+
export declare class UpdateValidationError extends ValidationError {
|
|
17
|
+
constructor(message: string);
|
|
18
|
+
}
|
|
19
|
+
export declare class MigrationError extends TauriORMError {
|
|
20
|
+
constructor(message: string);
|
|
21
|
+
}
|
|
22
|
+
export declare class RelationError extends TauriORMError {
|
|
23
|
+
constructor(message: string);
|
|
24
|
+
}
|
|
25
|
+
export declare class ColumnNotFoundError extends TauriORMError {
|
|
26
|
+
constructor(columnName: string, tableName: string);
|
|
27
|
+
}
|
|
28
|
+
export declare class TableNotFoundError extends TauriORMError {
|
|
29
|
+
constructor(tableName: string);
|
|
30
|
+
}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Custom error classes for better error handling
|
|
2
|
+
export class TauriORMError extends Error {
|
|
3
|
+
constructor(message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = 'TauriORMError';
|
|
6
|
+
// Maintains proper stack trace for where our error was thrown (only available on V8)
|
|
7
|
+
if (Error.captureStackTrace) {
|
|
8
|
+
Error.captureStackTrace(this, this.constructor);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class QueryBuilderError extends TauriORMError {
|
|
13
|
+
constructor(message) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = 'QueryBuilderError';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export class MissingWhereClauseError extends QueryBuilderError {
|
|
19
|
+
constructor(operation, tableName) {
|
|
20
|
+
super(`${operation} operation on table "${tableName}" requires a WHERE clause to prevent accidental data loss. ` +
|
|
21
|
+
`Use .where() to specify conditions, or use .allowGlobalOperation() to explicitly allow operations without WHERE.`);
|
|
22
|
+
this.name = 'MissingWhereClauseError';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export class ValidationError extends TauriORMError {
|
|
26
|
+
constructor(message) {
|
|
27
|
+
super(message);
|
|
28
|
+
this.name = 'ValidationError';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export class InsertValidationError extends ValidationError {
|
|
32
|
+
constructor(message) {
|
|
33
|
+
super(message);
|
|
34
|
+
this.name = 'InsertValidationError';
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export class UpdateValidationError extends ValidationError {
|
|
38
|
+
constructor(message) {
|
|
39
|
+
super(message);
|
|
40
|
+
this.name = 'UpdateValidationError';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export class MigrationError extends TauriORMError {
|
|
44
|
+
constructor(message) {
|
|
45
|
+
super(message);
|
|
46
|
+
this.name = 'MigrationError';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export class RelationError extends TauriORMError {
|
|
50
|
+
constructor(message) {
|
|
51
|
+
super(message);
|
|
52
|
+
this.name = 'RelationError';
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export class ColumnNotFoundError extends TauriORMError {
|
|
56
|
+
constructor(columnName, tableName) {
|
|
57
|
+
super(`Column "${columnName}" does not exist on table "${tableName}"`);
|
|
58
|
+
this.name = 'ColumnNotFoundError';
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export class TableNotFoundError extends TauriORMError {
|
|
62
|
+
constructor(tableName) {
|
|
63
|
+
super(`Table "${tableName}" not found in schema`);
|
|
64
|
+
this.name = 'TableNotFoundError';
|
|
65
|
+
}
|
|
66
|
+
}
|
package/dist/index.d.mts
CHANGED
|
@@ -56,8 +56,28 @@ type RelationType = 'one' | 'many';
|
|
|
56
56
|
interface RelationConfig {
|
|
57
57
|
type: RelationType;
|
|
58
58
|
foreignTable: AnyTable;
|
|
59
|
+
/** For one: local FK columns. For many (v2): foreign table's FK columns. */
|
|
59
60
|
fields?: AnySQLiteColumn[];
|
|
61
|
+
/** For one: foreign PK columns. For many (v2): parent table's PK columns. */
|
|
60
62
|
references?: AnySQLiteColumn[];
|
|
63
|
+
/** For many-to-many via through(): junction table between parent and foreign */
|
|
64
|
+
junctionTable?: AnyTable;
|
|
65
|
+
/** Parent column -> junction column (parent PK = junction FK to parent) */
|
|
66
|
+
fromJunction?: {
|
|
67
|
+
column: AnySQLiteColumn;
|
|
68
|
+
junctionColumn: AnySQLiteColumn;
|
|
69
|
+
};
|
|
70
|
+
/** Junction column -> foreign column (junction FK to foreign = foreign PK) */
|
|
71
|
+
toJunction?: {
|
|
72
|
+
junctionColumn: AnySQLiteColumn;
|
|
73
|
+
column: AnySQLiteColumn;
|
|
74
|
+
};
|
|
75
|
+
/** When false, one relation is required (type-level: T not T | null) */
|
|
76
|
+
optional?: boolean;
|
|
77
|
+
/** Alias for the relation (e.g. for self-referential disambiguation) */
|
|
78
|
+
alias?: string;
|
|
79
|
+
/** Predefined filter for many relations: (alias) => Condition. Receives the joined table alias. */
|
|
80
|
+
where?: (alias: string) => unknown;
|
|
61
81
|
}
|
|
62
82
|
|
|
63
83
|
type Condition = Expression<SqlBool>;
|
|
@@ -233,6 +253,8 @@ type RelationsBuilder = {
|
|
|
233
253
|
one: <U extends AnyTable>(table: U, config?: {
|
|
234
254
|
fields: AnySQLiteColumn[];
|
|
235
255
|
references: AnySQLiteColumn[];
|
|
256
|
+
optional?: boolean;
|
|
257
|
+
alias?: string;
|
|
236
258
|
}) => OneRelation<U>;
|
|
237
259
|
many: <U extends AnyTable>(table: U) => ManyRelation<U>;
|
|
238
260
|
};
|
|
@@ -361,14 +383,53 @@ declare class OneRelation<T extends AnyTable = AnyTable> extends Relation<T> {
|
|
|
361
383
|
config?: {
|
|
362
384
|
fields: AnySQLiteColumn[];
|
|
363
385
|
references: AnySQLiteColumn[];
|
|
386
|
+
optional?: boolean;
|
|
387
|
+
alias?: string;
|
|
364
388
|
} | undefined;
|
|
365
389
|
constructor(foreignTable: T, config?: {
|
|
366
390
|
fields: AnySQLiteColumn[];
|
|
367
391
|
references: AnySQLiteColumn[];
|
|
392
|
+
optional?: boolean;
|
|
393
|
+
alias?: string;
|
|
368
394
|
} | undefined);
|
|
369
395
|
}
|
|
370
396
|
declare class ManyRelation<T extends AnyTable = AnyTable> extends Relation<T> {
|
|
371
|
-
|
|
397
|
+
config?: {
|
|
398
|
+
from?: AnySQLiteColumn[];
|
|
399
|
+
to?: AnySQLiteColumn[];
|
|
400
|
+
through?: {
|
|
401
|
+
junctionTable: AnyTable;
|
|
402
|
+
fromRef: {
|
|
403
|
+
column: AnySQLiteColumn;
|
|
404
|
+
junctionColumn: AnySQLiteColumn;
|
|
405
|
+
};
|
|
406
|
+
toRef: {
|
|
407
|
+
column: AnySQLiteColumn;
|
|
408
|
+
junctionColumn: AnySQLiteColumn;
|
|
409
|
+
};
|
|
410
|
+
};
|
|
411
|
+
optional?: boolean;
|
|
412
|
+
alias?: string;
|
|
413
|
+
where?: (alias: string) => unknown;
|
|
414
|
+
} | undefined;
|
|
415
|
+
constructor(foreignTable: T, config?: {
|
|
416
|
+
from?: AnySQLiteColumn[];
|
|
417
|
+
to?: AnySQLiteColumn[];
|
|
418
|
+
through?: {
|
|
419
|
+
junctionTable: AnyTable;
|
|
420
|
+
fromRef: {
|
|
421
|
+
column: AnySQLiteColumn;
|
|
422
|
+
junctionColumn: AnySQLiteColumn;
|
|
423
|
+
};
|
|
424
|
+
toRef: {
|
|
425
|
+
column: AnySQLiteColumn;
|
|
426
|
+
junctionColumn: AnySQLiteColumn;
|
|
427
|
+
};
|
|
428
|
+
};
|
|
429
|
+
optional?: boolean;
|
|
430
|
+
alias?: string;
|
|
431
|
+
where?: (alias: string) => unknown;
|
|
432
|
+
} | undefined);
|
|
372
433
|
}
|
|
373
434
|
declare const relations: <T extends AnyTable, R extends Record<string, Relation>>(table: T, relationsCallback: (helpers: RelationsBuilder) => R) => R;
|
|
374
435
|
declare const getTableColumns: <T extends AnyTable>(table: T) => Record<string, AnySQLiteColumn>;
|
|
@@ -411,9 +472,18 @@ declare const enumType: <TName extends string, TValues extends readonly [string,
|
|
|
411
472
|
|
|
412
473
|
/** Maps relations() return type to typed relation configs with foreign table preserved */
|
|
413
474
|
type InferRelationsMap<R extends Record<string, OneRelation | ManyRelation>> = {
|
|
414
|
-
[K in keyof R]: R[K] extends OneRelation<infer T> ? {
|
|
475
|
+
[K in keyof R]: R[K] extends OneRelation<infer T> ? R[K] extends {
|
|
476
|
+
config?: {
|
|
477
|
+
optional?: infer O;
|
|
478
|
+
};
|
|
479
|
+
} ? {
|
|
480
|
+
type: 'one';
|
|
481
|
+
foreignTable: T;
|
|
482
|
+
optional: O;
|
|
483
|
+
} : {
|
|
415
484
|
type: 'one';
|
|
416
485
|
foreignTable: T;
|
|
486
|
+
optional?: true;
|
|
417
487
|
} : R[K] extends ManyRelation<infer T> ? {
|
|
418
488
|
type: 'many';
|
|
419
489
|
foreignTable: T;
|
|
@@ -440,7 +510,8 @@ type InferRelationFields<TTable extends AnyTable, TRelationsMap extends Record<s
|
|
|
440
510
|
[K in keyof TWith & keyof TRelationsMap]: TWith[K] extends false | undefined ? never : TRelationsMap[K] extends {
|
|
441
511
|
type: 'one';
|
|
442
512
|
foreignTable: infer T;
|
|
443
|
-
|
|
513
|
+
optional?: infer O;
|
|
514
|
+
} ? T extends AnyTable ? ([O] extends [false] ? InferSelectModel<T> & InferNestedFields<T, TWith[K], TAllRelations> : (InferSelectModel<T> & InferNestedFields<T, TWith[K], TAllRelations>) | null) : never : TRelationsMap[K] extends {
|
|
444
515
|
type: 'many';
|
|
445
516
|
foreignTable: infer T;
|
|
446
517
|
} ? T extends AnyTable ? (InferSelectModel<T> & InferNestedFields<T, TWith[K], TAllRelations>)[] : never : never;
|
|
@@ -484,6 +555,81 @@ type InferRelationalSelectModel<TTable extends AnyTable, TRelations extends Reco
|
|
|
484
555
|
[K in TTable['_']['name']]: TRelations;
|
|
485
556
|
}> = InferSelectModel<TTable> & InferRelationFields<TTable, InferRelationsMap<TRelations>, TAllRelations, TWith>;
|
|
486
557
|
|
|
558
|
+
/**
|
|
559
|
+
* Relations v2 API - Drizzle-style defineRelations with from/to and many-without-one.
|
|
560
|
+
* Use defineRelations() for a single place to define all relations, or defineRelationsPart() to split into parts.
|
|
561
|
+
*/
|
|
562
|
+
|
|
563
|
+
/** Options for one() relation - from/to replace fields/references */
|
|
564
|
+
interface OneRelationOptions {
|
|
565
|
+
from: AnySQLiteColumn | AnySQLiteColumn[];
|
|
566
|
+
to: AnySQLiteColumn | AnySQLiteColumn[];
|
|
567
|
+
optional?: boolean;
|
|
568
|
+
alias?: string;
|
|
569
|
+
}
|
|
570
|
+
/** Reference for through() - column with junction column for many-to-many */
|
|
571
|
+
interface ThroughRef {
|
|
572
|
+
column: AnySQLiteColumn;
|
|
573
|
+
junctionColumn: AnySQLiteColumn;
|
|
574
|
+
junctionTable: AnyTable;
|
|
575
|
+
}
|
|
576
|
+
/** Create a through reference for many-to-many: through(column, junctionColumn, junctionTable) */
|
|
577
|
+
declare function through(column: AnySQLiteColumn, junctionColumn: AnySQLiteColumn, junctionTable: AnyTable): ThroughRef;
|
|
578
|
+
/** Options for many() relation - optional explicit from/to for many-without-one, or through() for many-to-many */
|
|
579
|
+
interface ManyRelationOptions {
|
|
580
|
+
from?: AnySQLiteColumn | AnySQLiteColumn[] | ThroughRef;
|
|
581
|
+
to?: AnySQLiteColumn | AnySQLiteColumn[] | ThroughRef;
|
|
582
|
+
optional?: boolean;
|
|
583
|
+
alias?: string;
|
|
584
|
+
/** Predefined filter: (alias) => Condition. Applied to the joined relation table. */
|
|
585
|
+
where?: (alias: string) => Condition;
|
|
586
|
+
}
|
|
587
|
+
/** Extract table keys from schema (values that extend AnyTable) */
|
|
588
|
+
type ExtractTableKeys<T> = {
|
|
589
|
+
[K in keyof T]: T[K] extends AnyTable ? K : never;
|
|
590
|
+
}[keyof T];
|
|
591
|
+
type ExtractTables<T extends Record<string, unknown>> = Pick<T, Extract<ExtractTableKeys<T>, keyof T>> extends infer R ? R extends Record<string, AnyTable> ? R : Record<string, AnyTable> : Record<string, AnyTable>;
|
|
592
|
+
/** Build the r object passed to defineRelations callback - all properties required to avoid TS2722 */
|
|
593
|
+
type BuildR<Tables extends Record<string, AnyTable>> = {
|
|
594
|
+
[K in keyof Tables]: Tables[K]['_']['columns'];
|
|
595
|
+
} & {
|
|
596
|
+
one: {
|
|
597
|
+
[K in keyof Tables]: (opts: OneRelationOptions) => OneRelation<Tables[K]>;
|
|
598
|
+
};
|
|
599
|
+
many: {
|
|
600
|
+
[K in keyof Tables]: (opts?: ManyRelationOptions) => ManyRelation<Tables[K]>;
|
|
601
|
+
};
|
|
602
|
+
};
|
|
603
|
+
type DefineRelationsCallback<Tables extends Record<string, AnyTable>> = (r: BuildR<Tables>) => {
|
|
604
|
+
[K in keyof Tables]?: Record<string, OneRelation | ManyRelation>;
|
|
605
|
+
};
|
|
606
|
+
/**
|
|
607
|
+
* Define all relations for your schema in one place (v2 API).
|
|
608
|
+
* Uses from/to instead of fields/references, and supports many-without-one.
|
|
609
|
+
*
|
|
610
|
+
* @example
|
|
611
|
+
* ```ts
|
|
612
|
+
* import * as schema from './schema'
|
|
613
|
+
* import { defineRelations } from '@type32/tauri-sqlite-orm'
|
|
614
|
+
*
|
|
615
|
+
* export const relations = defineRelations(schema, (r) => ({
|
|
616
|
+
* users: {
|
|
617
|
+
* posts: r.many.posts({ from: r.users.id, to: r.posts.userId }),
|
|
618
|
+
* },
|
|
619
|
+
* posts: {
|
|
620
|
+
* user: r.one.users({ from: r.posts.userId, to: r.users.id }),
|
|
621
|
+
* postTags: r.many.postTags({ from: r.posts.id, to: r.postTags.postId }),
|
|
622
|
+
* },
|
|
623
|
+
* }))
|
|
624
|
+
* ```
|
|
625
|
+
*/
|
|
626
|
+
declare function defineRelations<TSchema extends Record<string, unknown>>(schema: TSchema, callback: DefineRelationsCallback<ExtractTables<TSchema>>): Record<string, Record<string, OneRelation | ManyRelation>>;
|
|
627
|
+
/**
|
|
628
|
+
* Define a part of relations - merge multiple parts when passing to TauriORM.
|
|
629
|
+
* Useful for splitting large schema definitions.
|
|
630
|
+
*/
|
|
631
|
+
declare function defineRelationsPart<TSchema extends Record<string, unknown>>(schema: TSchema, callback: DefineRelationsCallback<Record<string, AnyTable>>): Record<string, Record<string, OneRelation | ManyRelation>>;
|
|
632
|
+
|
|
487
633
|
declare class TauriORMError extends Error {
|
|
488
634
|
constructor(message: string);
|
|
489
635
|
}
|
|
@@ -515,4 +661,4 @@ declare class TableNotFoundError extends TauriORMError {
|
|
|
515
661
|
constructor(tableName: string);
|
|
516
662
|
}
|
|
517
663
|
|
|
518
|
-
export { type AnySQLiteColumn, type AnyTable, type ColumnDataType, ColumnNotFoundError, type ColumnOptions, type ColumnValueTypes, type Condition, type DatabaseLike, DeleteQueryBuilder, type ExtractColumnType, type InferInsertModel, type InferRelationalSelectModel, type InferRelationsMap, type InferSelectModel, InsertQueryBuilder, InsertValidationError, ManyRelation, MigrationError, MissingWhereClauseError, type Mode, OneRelation, QueryBuilderError, Relation, type RelationConfig, RelationError, type RelationType, type RelationsBuilder, type SQLAggregate, type SQLCondition, type SQLSubquery, SQLiteColumn, SelectQueryBuilder, Table, TableNotFoundError, TauriDialect, TauriORM, TauriORMError, UpdateQueryBuilder, UpdateValidationError, ValidationError, WithQueryBuilder, alias, and, as, asc, avg, between, blob, boolean, contains, count, countDistinct, desc, endsWith, enumType, eq, eqSubquery, exists, getTableColumns, groupConcat, gt, gtSubquery, gte, gteSubquery, ilike, inArray, integer, isNotNull, isNull, like, lt, ltSubquery, lte, lteSubquery, max, min, ne, neSubquery, not, notExists, notIn, numeric, or, real, relations, scalarSubquery, sqliteTable, startsWith, subquery, sum, text };
|
|
664
|
+
export { type AnySQLiteColumn, type AnyTable, type BuildR, type ColumnDataType, ColumnNotFoundError, type ColumnOptions, type ColumnValueTypes, type Condition, type DatabaseLike, type DefineRelationsCallback, DeleteQueryBuilder, type ExtractColumnType, type InferInsertModel, type InferRelationalSelectModel, type InferRelationsMap, type InferSelectModel, InsertQueryBuilder, InsertValidationError, ManyRelation, type ManyRelationOptions, MigrationError, MissingWhereClauseError, type Mode, OneRelation, type OneRelationOptions, QueryBuilderError, Relation, type RelationConfig, RelationError, type RelationType, type RelationsBuilder, type SQLAggregate, type SQLCondition, type SQLSubquery, SQLiteColumn, SelectQueryBuilder, Table, TableNotFoundError, TauriDialect, TauriORM, TauriORMError, type ThroughRef, UpdateQueryBuilder, UpdateValidationError, ValidationError, WithQueryBuilder, alias, and, as, asc, avg, between, blob, boolean, contains, count, countDistinct, defineRelations, defineRelationsPart, desc, endsWith, enumType, eq, eqSubquery, exists, getTableColumns, groupConcat, gt, gtSubquery, gte, gteSubquery, ilike, inArray, integer, isNotNull, isNull, like, lt, ltSubquery, lte, lteSubquery, max, min, ne, neSubquery, not, notExists, notIn, numeric, or, real, relations, scalarSubquery, sqliteTable, startsWith, subquery, sum, text, through };
|
package/dist/index.d.ts
CHANGED
|
@@ -56,8 +56,28 @@ type RelationType = 'one' | 'many';
|
|
|
56
56
|
interface RelationConfig {
|
|
57
57
|
type: RelationType;
|
|
58
58
|
foreignTable: AnyTable;
|
|
59
|
+
/** For one: local FK columns. For many (v2): foreign table's FK columns. */
|
|
59
60
|
fields?: AnySQLiteColumn[];
|
|
61
|
+
/** For one: foreign PK columns. For many (v2): parent table's PK columns. */
|
|
60
62
|
references?: AnySQLiteColumn[];
|
|
63
|
+
/** For many-to-many via through(): junction table between parent and foreign */
|
|
64
|
+
junctionTable?: AnyTable;
|
|
65
|
+
/** Parent column -> junction column (parent PK = junction FK to parent) */
|
|
66
|
+
fromJunction?: {
|
|
67
|
+
column: AnySQLiteColumn;
|
|
68
|
+
junctionColumn: AnySQLiteColumn;
|
|
69
|
+
};
|
|
70
|
+
/** Junction column -> foreign column (junction FK to foreign = foreign PK) */
|
|
71
|
+
toJunction?: {
|
|
72
|
+
junctionColumn: AnySQLiteColumn;
|
|
73
|
+
column: AnySQLiteColumn;
|
|
74
|
+
};
|
|
75
|
+
/** When false, one relation is required (type-level: T not T | null) */
|
|
76
|
+
optional?: boolean;
|
|
77
|
+
/** Alias for the relation (e.g. for self-referential disambiguation) */
|
|
78
|
+
alias?: string;
|
|
79
|
+
/** Predefined filter for many relations: (alias) => Condition. Receives the joined table alias. */
|
|
80
|
+
where?: (alias: string) => unknown;
|
|
61
81
|
}
|
|
62
82
|
|
|
63
83
|
type Condition = Expression<SqlBool>;
|
|
@@ -233,6 +253,8 @@ type RelationsBuilder = {
|
|
|
233
253
|
one: <U extends AnyTable>(table: U, config?: {
|
|
234
254
|
fields: AnySQLiteColumn[];
|
|
235
255
|
references: AnySQLiteColumn[];
|
|
256
|
+
optional?: boolean;
|
|
257
|
+
alias?: string;
|
|
236
258
|
}) => OneRelation<U>;
|
|
237
259
|
many: <U extends AnyTable>(table: U) => ManyRelation<U>;
|
|
238
260
|
};
|
|
@@ -361,14 +383,53 @@ declare class OneRelation<T extends AnyTable = AnyTable> extends Relation<T> {
|
|
|
361
383
|
config?: {
|
|
362
384
|
fields: AnySQLiteColumn[];
|
|
363
385
|
references: AnySQLiteColumn[];
|
|
386
|
+
optional?: boolean;
|
|
387
|
+
alias?: string;
|
|
364
388
|
} | undefined;
|
|
365
389
|
constructor(foreignTable: T, config?: {
|
|
366
390
|
fields: AnySQLiteColumn[];
|
|
367
391
|
references: AnySQLiteColumn[];
|
|
392
|
+
optional?: boolean;
|
|
393
|
+
alias?: string;
|
|
368
394
|
} | undefined);
|
|
369
395
|
}
|
|
370
396
|
declare class ManyRelation<T extends AnyTable = AnyTable> extends Relation<T> {
|
|
371
|
-
|
|
397
|
+
config?: {
|
|
398
|
+
from?: AnySQLiteColumn[];
|
|
399
|
+
to?: AnySQLiteColumn[];
|
|
400
|
+
through?: {
|
|
401
|
+
junctionTable: AnyTable;
|
|
402
|
+
fromRef: {
|
|
403
|
+
column: AnySQLiteColumn;
|
|
404
|
+
junctionColumn: AnySQLiteColumn;
|
|
405
|
+
};
|
|
406
|
+
toRef: {
|
|
407
|
+
column: AnySQLiteColumn;
|
|
408
|
+
junctionColumn: AnySQLiteColumn;
|
|
409
|
+
};
|
|
410
|
+
};
|
|
411
|
+
optional?: boolean;
|
|
412
|
+
alias?: string;
|
|
413
|
+
where?: (alias: string) => unknown;
|
|
414
|
+
} | undefined;
|
|
415
|
+
constructor(foreignTable: T, config?: {
|
|
416
|
+
from?: AnySQLiteColumn[];
|
|
417
|
+
to?: AnySQLiteColumn[];
|
|
418
|
+
through?: {
|
|
419
|
+
junctionTable: AnyTable;
|
|
420
|
+
fromRef: {
|
|
421
|
+
column: AnySQLiteColumn;
|
|
422
|
+
junctionColumn: AnySQLiteColumn;
|
|
423
|
+
};
|
|
424
|
+
toRef: {
|
|
425
|
+
column: AnySQLiteColumn;
|
|
426
|
+
junctionColumn: AnySQLiteColumn;
|
|
427
|
+
};
|
|
428
|
+
};
|
|
429
|
+
optional?: boolean;
|
|
430
|
+
alias?: string;
|
|
431
|
+
where?: (alias: string) => unknown;
|
|
432
|
+
} | undefined);
|
|
372
433
|
}
|
|
373
434
|
declare const relations: <T extends AnyTable, R extends Record<string, Relation>>(table: T, relationsCallback: (helpers: RelationsBuilder) => R) => R;
|
|
374
435
|
declare const getTableColumns: <T extends AnyTable>(table: T) => Record<string, AnySQLiteColumn>;
|
|
@@ -411,9 +472,18 @@ declare const enumType: <TName extends string, TValues extends readonly [string,
|
|
|
411
472
|
|
|
412
473
|
/** Maps relations() return type to typed relation configs with foreign table preserved */
|
|
413
474
|
type InferRelationsMap<R extends Record<string, OneRelation | ManyRelation>> = {
|
|
414
|
-
[K in keyof R]: R[K] extends OneRelation<infer T> ? {
|
|
475
|
+
[K in keyof R]: R[K] extends OneRelation<infer T> ? R[K] extends {
|
|
476
|
+
config?: {
|
|
477
|
+
optional?: infer O;
|
|
478
|
+
};
|
|
479
|
+
} ? {
|
|
480
|
+
type: 'one';
|
|
481
|
+
foreignTable: T;
|
|
482
|
+
optional: O;
|
|
483
|
+
} : {
|
|
415
484
|
type: 'one';
|
|
416
485
|
foreignTable: T;
|
|
486
|
+
optional?: true;
|
|
417
487
|
} : R[K] extends ManyRelation<infer T> ? {
|
|
418
488
|
type: 'many';
|
|
419
489
|
foreignTable: T;
|
|
@@ -440,7 +510,8 @@ type InferRelationFields<TTable extends AnyTable, TRelationsMap extends Record<s
|
|
|
440
510
|
[K in keyof TWith & keyof TRelationsMap]: TWith[K] extends false | undefined ? never : TRelationsMap[K] extends {
|
|
441
511
|
type: 'one';
|
|
442
512
|
foreignTable: infer T;
|
|
443
|
-
|
|
513
|
+
optional?: infer O;
|
|
514
|
+
} ? T extends AnyTable ? ([O] extends [false] ? InferSelectModel<T> & InferNestedFields<T, TWith[K], TAllRelations> : (InferSelectModel<T> & InferNestedFields<T, TWith[K], TAllRelations>) | null) : never : TRelationsMap[K] extends {
|
|
444
515
|
type: 'many';
|
|
445
516
|
foreignTable: infer T;
|
|
446
517
|
} ? T extends AnyTable ? (InferSelectModel<T> & InferNestedFields<T, TWith[K], TAllRelations>)[] : never : never;
|
|
@@ -484,6 +555,81 @@ type InferRelationalSelectModel<TTable extends AnyTable, TRelations extends Reco
|
|
|
484
555
|
[K in TTable['_']['name']]: TRelations;
|
|
485
556
|
}> = InferSelectModel<TTable> & InferRelationFields<TTable, InferRelationsMap<TRelations>, TAllRelations, TWith>;
|
|
486
557
|
|
|
558
|
+
/**
|
|
559
|
+
* Relations v2 API - Drizzle-style defineRelations with from/to and many-without-one.
|
|
560
|
+
* Use defineRelations() for a single place to define all relations, or defineRelationsPart() to split into parts.
|
|
561
|
+
*/
|
|
562
|
+
|
|
563
|
+
/** Options for one() relation - from/to replace fields/references */
|
|
564
|
+
interface OneRelationOptions {
|
|
565
|
+
from: AnySQLiteColumn | AnySQLiteColumn[];
|
|
566
|
+
to: AnySQLiteColumn | AnySQLiteColumn[];
|
|
567
|
+
optional?: boolean;
|
|
568
|
+
alias?: string;
|
|
569
|
+
}
|
|
570
|
+
/** Reference for through() - column with junction column for many-to-many */
|
|
571
|
+
interface ThroughRef {
|
|
572
|
+
column: AnySQLiteColumn;
|
|
573
|
+
junctionColumn: AnySQLiteColumn;
|
|
574
|
+
junctionTable: AnyTable;
|
|
575
|
+
}
|
|
576
|
+
/** Create a through reference for many-to-many: through(column, junctionColumn, junctionTable) */
|
|
577
|
+
declare function through(column: AnySQLiteColumn, junctionColumn: AnySQLiteColumn, junctionTable: AnyTable): ThroughRef;
|
|
578
|
+
/** Options for many() relation - optional explicit from/to for many-without-one, or through() for many-to-many */
|
|
579
|
+
interface ManyRelationOptions {
|
|
580
|
+
from?: AnySQLiteColumn | AnySQLiteColumn[] | ThroughRef;
|
|
581
|
+
to?: AnySQLiteColumn | AnySQLiteColumn[] | ThroughRef;
|
|
582
|
+
optional?: boolean;
|
|
583
|
+
alias?: string;
|
|
584
|
+
/** Predefined filter: (alias) => Condition. Applied to the joined relation table. */
|
|
585
|
+
where?: (alias: string) => Condition;
|
|
586
|
+
}
|
|
587
|
+
/** Extract table keys from schema (values that extend AnyTable) */
|
|
588
|
+
type ExtractTableKeys<T> = {
|
|
589
|
+
[K in keyof T]: T[K] extends AnyTable ? K : never;
|
|
590
|
+
}[keyof T];
|
|
591
|
+
type ExtractTables<T extends Record<string, unknown>> = Pick<T, Extract<ExtractTableKeys<T>, keyof T>> extends infer R ? R extends Record<string, AnyTable> ? R : Record<string, AnyTable> : Record<string, AnyTable>;
|
|
592
|
+
/** Build the r object passed to defineRelations callback - all properties required to avoid TS2722 */
|
|
593
|
+
type BuildR<Tables extends Record<string, AnyTable>> = {
|
|
594
|
+
[K in keyof Tables]: Tables[K]['_']['columns'];
|
|
595
|
+
} & {
|
|
596
|
+
one: {
|
|
597
|
+
[K in keyof Tables]: (opts: OneRelationOptions) => OneRelation<Tables[K]>;
|
|
598
|
+
};
|
|
599
|
+
many: {
|
|
600
|
+
[K in keyof Tables]: (opts?: ManyRelationOptions) => ManyRelation<Tables[K]>;
|
|
601
|
+
};
|
|
602
|
+
};
|
|
603
|
+
type DefineRelationsCallback<Tables extends Record<string, AnyTable>> = (r: BuildR<Tables>) => {
|
|
604
|
+
[K in keyof Tables]?: Record<string, OneRelation | ManyRelation>;
|
|
605
|
+
};
|
|
606
|
+
/**
|
|
607
|
+
* Define all relations for your schema in one place (v2 API).
|
|
608
|
+
* Uses from/to instead of fields/references, and supports many-without-one.
|
|
609
|
+
*
|
|
610
|
+
* @example
|
|
611
|
+
* ```ts
|
|
612
|
+
* import * as schema from './schema'
|
|
613
|
+
* import { defineRelations } from '@type32/tauri-sqlite-orm'
|
|
614
|
+
*
|
|
615
|
+
* export const relations = defineRelations(schema, (r) => ({
|
|
616
|
+
* users: {
|
|
617
|
+
* posts: r.many.posts({ from: r.users.id, to: r.posts.userId }),
|
|
618
|
+
* },
|
|
619
|
+
* posts: {
|
|
620
|
+
* user: r.one.users({ from: r.posts.userId, to: r.users.id }),
|
|
621
|
+
* postTags: r.many.postTags({ from: r.posts.id, to: r.postTags.postId }),
|
|
622
|
+
* },
|
|
623
|
+
* }))
|
|
624
|
+
* ```
|
|
625
|
+
*/
|
|
626
|
+
declare function defineRelations<TSchema extends Record<string, unknown>>(schema: TSchema, callback: DefineRelationsCallback<ExtractTables<TSchema>>): Record<string, Record<string, OneRelation | ManyRelation>>;
|
|
627
|
+
/**
|
|
628
|
+
* Define a part of relations - merge multiple parts when passing to TauriORM.
|
|
629
|
+
* Useful for splitting large schema definitions.
|
|
630
|
+
*/
|
|
631
|
+
declare function defineRelationsPart<TSchema extends Record<string, unknown>>(schema: TSchema, callback: DefineRelationsCallback<Record<string, AnyTable>>): Record<string, Record<string, OneRelation | ManyRelation>>;
|
|
632
|
+
|
|
487
633
|
declare class TauriORMError extends Error {
|
|
488
634
|
constructor(message: string);
|
|
489
635
|
}
|
|
@@ -515,4 +661,4 @@ declare class TableNotFoundError extends TauriORMError {
|
|
|
515
661
|
constructor(tableName: string);
|
|
516
662
|
}
|
|
517
663
|
|
|
518
|
-
export { type AnySQLiteColumn, type AnyTable, type ColumnDataType, ColumnNotFoundError, type ColumnOptions, type ColumnValueTypes, type Condition, type DatabaseLike, DeleteQueryBuilder, type ExtractColumnType, type InferInsertModel, type InferRelationalSelectModel, type InferRelationsMap, type InferSelectModel, InsertQueryBuilder, InsertValidationError, ManyRelation, MigrationError, MissingWhereClauseError, type Mode, OneRelation, QueryBuilderError, Relation, type RelationConfig, RelationError, type RelationType, type RelationsBuilder, type SQLAggregate, type SQLCondition, type SQLSubquery, SQLiteColumn, SelectQueryBuilder, Table, TableNotFoundError, TauriDialect, TauriORM, TauriORMError, UpdateQueryBuilder, UpdateValidationError, ValidationError, WithQueryBuilder, alias, and, as, asc, avg, between, blob, boolean, contains, count, countDistinct, desc, endsWith, enumType, eq, eqSubquery, exists, getTableColumns, groupConcat, gt, gtSubquery, gte, gteSubquery, ilike, inArray, integer, isNotNull, isNull, like, lt, ltSubquery, lte, lteSubquery, max, min, ne, neSubquery, not, notExists, notIn, numeric, or, real, relations, scalarSubquery, sqliteTable, startsWith, subquery, sum, text };
|
|
664
|
+
export { type AnySQLiteColumn, type AnyTable, type BuildR, type ColumnDataType, ColumnNotFoundError, type ColumnOptions, type ColumnValueTypes, type Condition, type DatabaseLike, type DefineRelationsCallback, DeleteQueryBuilder, type ExtractColumnType, type InferInsertModel, type InferRelationalSelectModel, type InferRelationsMap, type InferSelectModel, InsertQueryBuilder, InsertValidationError, ManyRelation, type ManyRelationOptions, MigrationError, MissingWhereClauseError, type Mode, OneRelation, type OneRelationOptions, QueryBuilderError, Relation, type RelationConfig, RelationError, type RelationType, type RelationsBuilder, type SQLAggregate, type SQLCondition, type SQLSubquery, SQLiteColumn, SelectQueryBuilder, Table, TableNotFoundError, TauriDialect, TauriORM, TauriORMError, type ThroughRef, UpdateQueryBuilder, UpdateValidationError, ValidationError, WithQueryBuilder, alias, and, as, asc, avg, between, blob, boolean, contains, count, countDistinct, defineRelations, defineRelationsPart, desc, endsWith, enumType, eq, eqSubquery, exists, getTableColumns, groupConcat, gt, gtSubquery, gte, gteSubquery, ilike, inArray, integer, isNotNull, isNull, like, lt, ltSubquery, lte, lteSubquery, max, min, ne, neSubquery, not, notExists, notIn, numeric, or, real, relations, scalarSubquery, sqliteTable, startsWith, subquery, sum, text, through };
|