@zeroxsolutions/db 9.5.0 → 10.0.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/CHANGELOG.md +47 -23
- package/README.md +136 -180
- package/dist/base/d1/repository.d.ts +75 -66
- package/dist/base/d1/repository.d.ts.map +1 -1
- package/dist/base/d1/repository.js +134 -122
- package/dist/base/postgres/repository.d.ts +108 -86
- package/dist/base/postgres/repository.d.ts.map +1 -1
- package/dist/base/postgres/repository.js +175 -143
- package/dist/base/read-engine.d.ts +49 -0
- package/dist/base/read-engine.d.ts.map +1 -0
- package/dist/base/read-engine.js +93 -0
- package/dist/utils/filter.d.ts +40 -61
- package/dist/utils/filter.d.ts.map +1 -1
- package/dist/utils/filter.js +51 -85
- package/dist/utils/index.d.ts +3 -5
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +3 -5
- package/dist/utils/read.d.ts +86 -0
- package/dist/utils/read.d.ts.map +1 -0
- package/dist/utils/read.js +124 -0
- package/dist/utils/reads.d.ts +24 -0
- package/dist/utils/reads.d.ts.map +1 -0
- package/dist/utils/reads.js +23 -0
- package/dist/utils/relationships.d.ts +9 -6
- package/dist/utils/relationships.d.ts.map +1 -1
- package/dist/utils/relationships.js +26 -8
- package/package.json +2 -2
- package/dist/utils/assert-queryable-fields.d.ts +0 -27
- package/dist/utils/assert-queryable-fields.d.ts.map +0 -1
- package/dist/utils/assert-queryable-fields.js +0 -47
- package/dist/utils/constants.d.ts +0 -7
- package/dist/utils/constants.d.ts.map +0 -1
- package/dist/utils/constants.js +0 -6
- package/dist/utils/include.d.ts +0 -80
- package/dist/utils/include.d.ts.map +0 -1
- package/dist/utils/include.js +0 -132
- package/dist/utils/table-query.d.ts +0 -41
- package/dist/utils/table-query.d.ts.map +0 -1
- package/dist/utils/table-query.js +0 -1
- package/dist/utils/total-order.d.ts +0 -15
- package/dist/utils/total-order.d.ts.map +0 -1
- package/dist/utils/total-order.js +0 -35
|
@@ -1,67 +1,51 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ExtractTablesWithRelations, InferInsertModel, SQL } from 'drizzle-orm';
|
|
2
|
+
import { type InferSelectModel } from 'drizzle-orm';
|
|
2
3
|
import type { D1Transaction, DrizzleD1Database } from 'drizzle-orm/d1';
|
|
3
4
|
import type { SQLiteTable, TableConfig } from 'drizzle-orm/sqlite-core';
|
|
4
|
-
import type {
|
|
5
|
-
import { type
|
|
6
|
-
|
|
5
|
+
import type { FilterNode } from '../../utils/filter.js';
|
|
6
|
+
import { type ColumnName, type MatchOptions, type OrderEntry, type Read } from '../../utils/read.js';
|
|
7
|
+
import type { Reads } from '../../utils/reads.js';
|
|
8
|
+
/** The tables-with-relations view a drizzle schema expands into, for typing relational queries. */
|
|
7
9
|
export type RelationalSchema<TSchema extends Record<string, unknown>> = ExtractTablesWithRelations<TSchema>;
|
|
8
10
|
/** An in-flight D1 transaction typed against `TFullSchema` and its relations. */
|
|
9
11
|
export type Transaction<TFullSchema extends Record<string, unknown> = Record<string, unknown>> = D1Transaction<TFullSchema, ExtractTablesWithRelations<TFullSchema>>;
|
|
10
12
|
/** Whatever a statement runs on: the D1 database itself, or an open {@link Transaction}. */
|
|
11
13
|
export type Executor<TFullSchema extends Record<string, unknown> = Record<string, unknown>> = DrizzleD1Database<TFullSchema> | Transaction<TFullSchema>;
|
|
12
|
-
/**
|
|
13
|
-
export type
|
|
14
|
-
|
|
15
|
-
limit?: number;
|
|
16
|
-
offset?: number;
|
|
14
|
+
/** A read of one row: what it loads, whether marked rows match, and the instant a `virtual` name is decided at. */
|
|
15
|
+
export type FindOneOptions<TSchema extends Record<string, unknown> = Record<string, unknown>, TTableName extends keyof RelationalSchema<TSchema> = keyof RelationalSchema<TSchema>> = {
|
|
16
|
+
read?: Read<ColumnName<TSchema, TTableName>>;
|
|
17
17
|
softDeleted?: boolean;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
/** A relational config spelled out; where it names a relation `include` reaches too, this one wins. */
|
|
21
|
-
with?: DBQueryConfig<'many', true, RelationalSchema<TSchema>, RelationalSchema<TSchema>[TTableName]>['with'];
|
|
22
|
-
sort?: SortField[];
|
|
23
|
-
} & TableQuery<TSchema, TTableName>;
|
|
24
|
-
/** Query controls for {@link BaseRepository.findAllAndCount}: {@link FindAllOptions} unchanged. */
|
|
25
|
-
export type FindAllAndCountOptions<TSchema extends Record<string, unknown> = Record<string, unknown>, TTableName extends keyof RelationalSchema<TSchema> = keyof RelationalSchema<TSchema>> = FindAllOptions<TSchema, TTableName>;
|
|
18
|
+
at?: Date;
|
|
19
|
+
};
|
|
26
20
|
/**
|
|
27
|
-
* A
|
|
28
|
-
* window
|
|
21
|
+
* A read of many rows: a read of one, and the filter they match, their order (the primary key appended) and their page
|
|
22
|
+
* window. With no `limit` the finder reads every match.
|
|
29
23
|
*/
|
|
30
|
-
export type
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
/**
|
|
24
|
+
export type FindAllOptions<TSchema extends Record<string, unknown> = Record<string, unknown>, TTableName extends keyof RelationalSchema<TSchema> = keyof RelationalSchema<TSchema>> = FindOneOptions<TSchema, TTableName> & {
|
|
25
|
+
filter?: readonly FilterNode[];
|
|
26
|
+
orderBy?: readonly OrderEntry<ColumnName<TSchema, TTableName>>[];
|
|
27
|
+
limit?: number;
|
|
28
|
+
offset?: number;
|
|
29
|
+
};
|
|
30
|
+
/** A count: the options that change which rows match, so a page and its total read the same filter. */
|
|
31
|
+
export type CountOptions = MatchOptions;
|
|
32
|
+
/** Transaction context to enlist a single-row {@link BaseRepository.create} into. */
|
|
39
33
|
export type CreateOptions<TSchema extends Record<string, unknown> = Record<string, unknown>> = {
|
|
40
34
|
tx?: Transaction<TSchema>;
|
|
41
35
|
};
|
|
42
|
-
/**
|
|
36
|
+
/** Transaction context to enlist a bulk {@link BaseRepository.createMany} into. */
|
|
43
37
|
export type CreateManyOptions<TSchema extends Record<string, unknown> = Record<string, unknown>> = {
|
|
44
38
|
tx?: Transaction<TSchema>;
|
|
45
39
|
};
|
|
46
|
-
/**
|
|
40
|
+
/** Transaction context shared by the updates. */
|
|
47
41
|
export type UpdateOptions<TSchema extends Record<string, unknown> = Record<string, unknown>> = {
|
|
48
42
|
tx?: Transaction<TSchema>;
|
|
49
43
|
};
|
|
50
|
-
/**
|
|
44
|
+
/** Transaction context shared by the deletes. */
|
|
51
45
|
export type DeleteOptions<TSchema extends Record<string, unknown> = Record<string, unknown>> = {
|
|
52
46
|
tx?: Transaction<TSchema>;
|
|
53
47
|
};
|
|
54
|
-
/** Transaction
|
|
55
|
-
export type CountOptions<TSchema extends Record<string, unknown> = Record<string, unknown>> = {
|
|
56
|
-
tx?: Transaction<TSchema>;
|
|
57
|
-
softDeleted?: boolean;
|
|
58
|
-
};
|
|
59
|
-
/** Transaction and soft-delete-inclusion controls for {@link BaseRepository.exists}. */
|
|
60
|
-
export type ExistsOptions<TSchema extends Record<string, unknown> = Record<string, unknown>> = {
|
|
61
|
-
tx?: Transaction<TSchema>;
|
|
62
|
-
softDeleted?: boolean;
|
|
63
|
-
};
|
|
64
|
-
/** An optional enclosing transaction for {@link BaseRepository.softDelete}. */
|
|
48
|
+
/** Transaction context shared by the soft deletes. */
|
|
65
49
|
export type SoftDeleteOptions<TSchema extends Record<string, unknown> = Record<string, unknown>> = {
|
|
66
50
|
tx?: Transaction<TSchema>;
|
|
67
51
|
};
|
|
@@ -72,51 +56,76 @@ type InferUpdateModel<TTable extends SQLiteTable<TableConfig>> = Partial<{
|
|
|
72
56
|
export type IdOf<TTable extends SQLiteTable<TableConfig>> = InferSelectModel<TTable> extends {
|
|
73
57
|
id: infer TId;
|
|
74
58
|
} ? TId : string | number;
|
|
75
|
-
/**
|
|
59
|
+
/**
|
|
60
|
+
* What every table repository answers to its callers. No method here takes a condition: a read or a write keyed by
|
|
61
|
+
* anything but the id is a finder the repository names, over the protected methods that take a `where`, as a Spring
|
|
62
|
+
* Data repository's derived queries are.
|
|
63
|
+
*/
|
|
76
64
|
export interface IBaseRepository<TTable extends SQLiteTable<TableConfig>, TSchema extends Record<string, unknown> = Record<string, unknown>, TTableName extends keyof RelationalSchema<TSchema> = keyof RelationalSchema<TSchema>> {
|
|
77
|
-
findAll<R extends Partial<InferSelectModel<TTable>> = InferSelectModel<TTable>>(where: SQL | undefined, options?: FindAllOptions<TSchema, TTableName>): Promise<R[]>;
|
|
78
|
-
findAllAndCount<R extends Partial<InferSelectModel<TTable>> = InferSelectModel<TTable>>(where: SQL | undefined, options?: FindAllAndCountOptions<TSchema, TTableName>): Promise<[R[], number]>;
|
|
79
|
-
findOne<R extends Partial<InferSelectModel<TTable>> = InferSelectModel<TTable>>(where: SQL | undefined, options?: FindOneOptions<TSchema, TTableName>): Promise<R | null>;
|
|
80
65
|
findOneById<R extends Partial<InferSelectModel<TTable>> = InferSelectModel<TTable>>(id: IdOf<TTable>, options?: FindOneOptions<TSchema, TTableName>): Promise<R | null>;
|
|
66
|
+
findAllById<R extends Partial<InferSelectModel<TTable>> = InferSelectModel<TTable>>(ids: readonly IdOf<TTable>[], options?: Omit<FindAllOptions<TSchema, TTableName>, 'limit' | 'offset'>): Promise<R[]>;
|
|
67
|
+
existsById(id: IdOf<TTable>, options?: Pick<CountOptions, 'softDeleted'>): Promise<boolean>;
|
|
68
|
+
findAll<R extends Partial<InferSelectModel<TTable>> = InferSelectModel<TTable>>(options?: FindAllOptions<TSchema, TTableName>): Promise<R[]>;
|
|
69
|
+
findAllAndCount<R extends Partial<InferSelectModel<TTable>> = InferSelectModel<TTable>>(options?: FindAllOptions<TSchema, TTableName>): Promise<[R[], number]>;
|
|
70
|
+
count(options?: CountOptions): Promise<number>;
|
|
81
71
|
create(data: InferInsertModel<TTable>, options?: CreateOptions<TSchema>): Promise<InferSelectModel<TTable>>;
|
|
82
72
|
createMany(data: InferInsertModel<TTable>[], options?: CreateManyOptions<TSchema>): Promise<InferSelectModel<TTable>[]>;
|
|
83
|
-
update(where: SQL | undefined, data: InferUpdateModel<TTable>, options?: UpdateOptions<TSchema>): Promise<InferSelectModel<TTable> | null>;
|
|
84
73
|
updateById(id: IdOf<TTable>, data: InferUpdateModel<TTable>, options?: UpdateOptions<TSchema>): Promise<InferSelectModel<TTable> | null>;
|
|
85
|
-
delete(where: SQL | undefined, options?: DeleteOptions<TSchema>): Promise<void>;
|
|
86
74
|
deleteById(id: IdOf<TTable>, options?: DeleteOptions<TSchema>): Promise<void>;
|
|
87
|
-
|
|
88
|
-
exists(where: SQL | undefined, options?: ExistsOptions<TSchema>): Promise<boolean>;
|
|
89
|
-
softDelete(where: SQL | undefined, options?: SoftDeleteOptions<TSchema>): Promise<void>;
|
|
75
|
+
deleteAllById(ids: readonly IdOf<TTable>[], options?: DeleteOptions<TSchema>): Promise<void>;
|
|
90
76
|
softDeleteById(id: IdOf<TTable>, options?: SoftDeleteOptions<TSchema>): Promise<void>;
|
|
91
|
-
|
|
77
|
+
softDeleteAllById(ids: readonly IdOf<TTable>[], options?: SoftDeleteOptions<TSchema>): Promise<void>;
|
|
92
78
|
}
|
|
93
79
|
/**
|
|
94
|
-
* A D1/SQLite repository over `TTable
|
|
95
|
-
*
|
|
96
|
-
*
|
|
80
|
+
* A D1/SQLite repository over `TTable`: reads that name what they load, soft delete, and writes keyed by id. Every
|
|
81
|
+
* mutator executes immediately; enlisting one in a {@link DrizzleD1UnitOfWork} batch means overriding it to push its
|
|
82
|
+
* statement into that run's collector.
|
|
97
83
|
*/
|
|
98
84
|
export declare abstract class BaseRepository<TTable extends SQLiteTable<TableConfig>, TSchema extends Record<string, unknown> = Record<string, unknown>, TTableName extends keyof RelationalSchema<TSchema> = keyof RelationalSchema<TSchema>> implements IBaseRepository<TTable, TSchema, TTableName> {
|
|
99
85
|
protected db: DrizzleD1Database<TSchema>;
|
|
100
86
|
protected table: TTable;
|
|
101
87
|
protected queryKey?: Extract<TTableName, string> | undefined;
|
|
102
|
-
|
|
103
|
-
|
|
88
|
+
protected reads: Reads<TSchema>;
|
|
89
|
+
/**
|
|
90
|
+
* @param queryKey - the table's EXPORT name in the schema; omitted, a read that loads a relation throws
|
|
91
|
+
* @param reads - the context's `READS`: each table's order as a relation, and its `virtual` names
|
|
92
|
+
*/
|
|
93
|
+
constructor(db: DrizzleD1Database<TSchema>, table: TTable, queryKey?: Extract<TTableName, string> | undefined, reads?: Reads<TSchema>);
|
|
104
94
|
protected getExecutor(tx?: Transaction<TSchema>): Executor<TSchema>;
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
findOne<R extends Partial<InferSelectModel<TTable>> = InferSelectModel<TTable>>(where: SQL | undefined, options?: FindOneOptions<TSchema, TTableName>): Promise<R | null>;
|
|
95
|
+
private get source();
|
|
96
|
+
private idColumn;
|
|
108
97
|
findOneById<R extends Partial<InferSelectModel<TTable>> = InferSelectModel<TTable>>(id: IdOf<TTable>, options?: FindOneOptions<TSchema, TTableName>): Promise<R | null>;
|
|
98
|
+
findAllById<R extends Partial<InferSelectModel<TTable>> = InferSelectModel<TTable>>(ids: readonly IdOf<TTable>[], options?: Omit<FindAllOptions<TSchema, TTableName>, 'limit' | 'offset'>): Promise<R[]>;
|
|
99
|
+
existsById(id: IdOf<TTable>, options?: Pick<CountOptions, 'softDeleted'>): Promise<boolean>;
|
|
100
|
+
findAll<R extends Partial<InferSelectModel<TTable>> = InferSelectModel<TTable>>(options?: FindAllOptions<TSchema, TTableName>): Promise<R[]>;
|
|
101
|
+
findAllAndCount<R extends Partial<InferSelectModel<TTable>> = InferSelectModel<TTable>>(options?: FindAllOptions<TSchema, TTableName>): Promise<[R[], number]>;
|
|
102
|
+
count(options?: CountOptions): Promise<number>;
|
|
103
|
+
/** The rows matching `where` and the options, in their order and page window. */
|
|
104
|
+
protected findAllWhere<R extends Partial<InferSelectModel<TTable>> = InferSelectModel<TTable>>(where: SQL | undefined, options?: FindAllOptions<TSchema, TTableName>): Promise<R[]>;
|
|
105
|
+
/** {@link findAllWhere} and {@link countWhere} over the same `where` and filter, so the total matches the page. */
|
|
106
|
+
protected findAllAndCountWhere<R extends Partial<InferSelectModel<TTable>> = InferSelectModel<TTable>>(where: SQL | undefined, options?: FindAllOptions<TSchema, TTableName>): Promise<[R[], number]>;
|
|
107
|
+
/** The first row matching `where`, loaded as the options' `read` names. */
|
|
108
|
+
protected findOneWhere<R extends Partial<InferSelectModel<TTable>> = InferSelectModel<TTable>>(where: SQL | undefined, options?: FindOneOptions<TSchema, TTableName>): Promise<R | null>;
|
|
109
|
+
/** How many rows match `where` and the options' filter. */
|
|
110
|
+
protected countWhere(where: SQL | undefined, options?: CountOptions): Promise<number>;
|
|
111
|
+
/** Whether any row matches `where` and the options' filter. */
|
|
112
|
+
protected existsWhere(where: SQL | undefined, options?: CountOptions): Promise<boolean>;
|
|
113
|
+
private plainSelection;
|
|
109
114
|
create(data: InferInsertModel<TTable>, options?: CreateOptions<TSchema>): Promise<InferSelectModel<TTable>>;
|
|
110
115
|
createMany(data: InferInsertModel<TTable>[], options?: CreateManyOptions<TSchema>): Promise<InferSelectModel<TTable>[]>;
|
|
111
|
-
update(where: SQL | undefined, data: InferUpdateModel<TTable>, options?: UpdateOptions<TSchema>): Promise<InferSelectModel<TTable> | null>;
|
|
112
116
|
updateById(id: IdOf<TTable>, data: InferUpdateModel<TTable>, options?: UpdateOptions<TSchema>): Promise<InferSelectModel<TTable> | null>;
|
|
113
|
-
delete(where: SQL | undefined, options?: DeleteOptions<TSchema>): Promise<void>;
|
|
114
117
|
deleteById(id: IdOf<TTable>, options?: DeleteOptions<TSchema>): Promise<void>;
|
|
115
|
-
|
|
116
|
-
exists(where: SQL | undefined, options?: ExistsOptions<TSchema>): Promise<boolean>;
|
|
117
|
-
softDelete(where: SQL | undefined, options?: SoftDeleteOptions<TSchema>): Promise<void>;
|
|
118
|
+
deleteAllById(ids: readonly IdOf<TTable>[], options?: DeleteOptions<TSchema>): Promise<void>;
|
|
118
119
|
softDeleteById(id: IdOf<TTable>, options?: SoftDeleteOptions<TSchema>): Promise<void>;
|
|
119
|
-
|
|
120
|
+
softDeleteAllById(ids: readonly IdOf<TTable>[], options?: SoftDeleteOptions<TSchema>): Promise<void>;
|
|
121
|
+
/** Updates the rows matching `where`, answering the first. */
|
|
122
|
+
protected updateWhere(where: SQL | undefined, data: InferUpdateModel<TTable>, options?: UpdateOptions<TSchema>): Promise<InferSelectModel<TTable> | null>;
|
|
123
|
+
/** Removes the rows matching `where`. */
|
|
124
|
+
protected deleteWhere(where: SQL | undefined, options?: DeleteOptions<TSchema>): Promise<void>;
|
|
125
|
+
/** Marks the rows matching `where` deleted. */
|
|
126
|
+
protected softDeleteWhere(where: SQL | undefined, options?: SoftDeleteOptions<TSchema>): Promise<void>;
|
|
127
|
+
/** Sets `field` to null on every row whose `field` holds `value`. */
|
|
128
|
+
protected nullifyBy(field: keyof TTable, value: string | number, options?: UpdateOptions<TSchema>): Promise<void>;
|
|
120
129
|
}
|
|
121
130
|
export {};
|
|
122
131
|
//# sourceMappingURL=repository.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../../src/base/d1/repository.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../../src/base/d1/repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,21 +1,25 @@
|
|
|
1
|
-
import { and, count, eq, getTableColumns,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { totalOrder } from '../../utils/total-order.js';
|
|
1
|
+
import { and, count, eq, getTableColumns, inArray, sql } from 'drizzle-orm';
|
|
2
|
+
import { plainColumns } from '../../utils/read.js';
|
|
3
|
+
import { conditionOf, liveCondition, loadsRelations, orderClausesOf, primaryKeyFields, queryDelegateOf, relationalReadOf, } from '../read-engine.js';
|
|
5
4
|
/**
|
|
6
|
-
* A D1/SQLite repository over `TTable
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* A D1/SQLite repository over `TTable`: reads that name what they load, soft delete, and writes keyed by id. Every
|
|
6
|
+
* mutator executes immediately; enlisting one in a {@link DrizzleD1UnitOfWork} batch means overriding it to push its
|
|
7
|
+
* statement into that run's collector.
|
|
9
8
|
*/
|
|
10
9
|
export class BaseRepository {
|
|
11
10
|
db;
|
|
12
11
|
table;
|
|
13
12
|
queryKey;
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
reads;
|
|
14
|
+
/**
|
|
15
|
+
* @param queryKey - the table's EXPORT name in the schema; omitted, a read that loads a relation throws
|
|
16
|
+
* @param reads - the context's `READS`: each table's order as a relation, and its `virtual` names
|
|
17
|
+
*/
|
|
18
|
+
constructor(db, table, queryKey, reads = {}) {
|
|
16
19
|
this.db = db;
|
|
17
20
|
this.table = table;
|
|
18
21
|
this.queryKey = queryKey;
|
|
22
|
+
this.reads = reads;
|
|
19
23
|
}
|
|
20
24
|
getExecutor(tx) {
|
|
21
25
|
const executor = tx ?? this.db;
|
|
@@ -23,82 +27,111 @@ export class BaseRepository {
|
|
|
23
27
|
throw new Error('Database executor is not available');
|
|
24
28
|
return executor;
|
|
25
29
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
30
|
+
get source() {
|
|
31
|
+
return {
|
|
32
|
+
table: this.table,
|
|
33
|
+
queryKey: this.queryKey,
|
|
34
|
+
reads: this.reads,
|
|
35
|
+
caseInsensitiveOperator: false,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
idColumn(action) {
|
|
39
|
+
const column = getTableColumns(this.table)['id'];
|
|
40
|
+
if (!column)
|
|
41
|
+
throw new Error(`${action} by id is not supported for this table`);
|
|
42
|
+
return column;
|
|
43
|
+
}
|
|
44
|
+
async findOneById(id, options) {
|
|
45
|
+
return this.findOneWhere(eq(this.idColumn('Find one'), id), options);
|
|
46
|
+
}
|
|
47
|
+
async findAllById(ids, options) {
|
|
48
|
+
const column = this.idColumn('Find all');
|
|
49
|
+
if (ids.length === 0)
|
|
50
|
+
return [];
|
|
51
|
+
return this.findAllWhere(inArray(column, [...ids]), options);
|
|
52
|
+
}
|
|
53
|
+
async existsById(id, options) {
|
|
54
|
+
return this.existsWhere(eq(this.idColumn('Exists'), id), options);
|
|
55
|
+
}
|
|
56
|
+
async findAll(options) {
|
|
57
|
+
return this.findAllWhere(undefined, options);
|
|
58
|
+
}
|
|
59
|
+
async findAllAndCount(options) {
|
|
60
|
+
return this.findAllAndCountWhere(undefined, options);
|
|
61
|
+
}
|
|
62
|
+
async count(options) {
|
|
63
|
+
return this.countWhere(undefined, options);
|
|
64
|
+
}
|
|
65
|
+
/** The rows matching `where` and the options, in their order and page window. */
|
|
66
|
+
async findAllWhere(where, options) {
|
|
67
|
+
const executor = this.getExecutor();
|
|
68
|
+
const condition = conditionOf(this.source, executor, where, options);
|
|
69
|
+
const order = orderClausesOf(this.source, executor, options);
|
|
70
|
+
if (loadsRelations(options?.read)) {
|
|
71
|
+
const config = relationalReadOf(this.source, executor, options?.read);
|
|
72
|
+
return queryDelegateOf(executor, String(this.queryKey)).findMany({
|
|
73
|
+
...config,
|
|
74
|
+
where: condition,
|
|
75
|
+
orderBy: order,
|
|
76
|
+
limit: options?.limit,
|
|
77
|
+
offset: options?.offset,
|
|
53
78
|
});
|
|
54
79
|
}
|
|
55
|
-
|
|
56
|
-
.select(
|
|
80
|
+
let query = executor
|
|
81
|
+
.select(this.plainSelection(options?.read))
|
|
57
82
|
.from(this.table)
|
|
58
|
-
.
|
|
59
|
-
.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
return await
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (!queryDelegate)
|
|
81
|
-
throw new Error(`Invalid queryKey: ${safeQueryKey}`);
|
|
82
|
-
const result = await queryDelegate.findFirst({
|
|
83
|
-
where: _where,
|
|
84
|
-
columns: read.columns,
|
|
85
|
-
with: read.with,
|
|
83
|
+
.where(condition)
|
|
84
|
+
.orderBy(...order)
|
|
85
|
+
.$dynamic();
|
|
86
|
+
if (options?.limit !== undefined)
|
|
87
|
+
query = query.limit(options.limit);
|
|
88
|
+
if (options?.offset !== undefined)
|
|
89
|
+
query = query.offset(options.offset);
|
|
90
|
+
return (await query);
|
|
91
|
+
}
|
|
92
|
+
/** {@link findAllWhere} and {@link countWhere} over the same `where` and filter, so the total matches the page. */
|
|
93
|
+
async findAllAndCountWhere(where, options) {
|
|
94
|
+
return await Promise.all([this.findAllWhere(where, options), this.countWhere(where, options)]);
|
|
95
|
+
}
|
|
96
|
+
/** The first row matching `where`, loaded as the options' `read` names. */
|
|
97
|
+
async findOneWhere(where, options) {
|
|
98
|
+
const executor = this.getExecutor();
|
|
99
|
+
const condition = and(where, liveCondition(this.table, options?.softDeleted));
|
|
100
|
+
if (loadsRelations(options?.read)) {
|
|
101
|
+
const config = relationalReadOf(this.source, executor, options?.read);
|
|
102
|
+
const row = await queryDelegateOf(executor, String(this.queryKey)).findFirst({
|
|
103
|
+
...config,
|
|
104
|
+
where: condition,
|
|
86
105
|
});
|
|
87
|
-
return
|
|
106
|
+
return row ?? null;
|
|
88
107
|
}
|
|
89
108
|
const rows = await executor
|
|
90
|
-
.select(
|
|
109
|
+
.select(this.plainSelection(options?.read))
|
|
91
110
|
.from(this.table)
|
|
92
|
-
.where(
|
|
111
|
+
.where(condition)
|
|
93
112
|
.limit(1);
|
|
94
113
|
return rows[0] ?? null;
|
|
95
114
|
}
|
|
96
|
-
|
|
115
|
+
/** How many rows match `where` and the options' filter. */
|
|
116
|
+
async countWhere(where, options) {
|
|
117
|
+
const result = await this.getExecutor()
|
|
118
|
+
.select({ count: count() })
|
|
119
|
+
.from(this.table)
|
|
120
|
+
.where(conditionOf(this.source, this.getExecutor(), where, options));
|
|
121
|
+
return result[0]?.count ?? 0;
|
|
122
|
+
}
|
|
123
|
+
/** Whether any row matches `where` and the options' filter. */
|
|
124
|
+
async existsWhere(where, options) {
|
|
125
|
+
const result = await this.getExecutor()
|
|
126
|
+
.select({ value: sql `1` })
|
|
127
|
+
.from(this.table)
|
|
128
|
+
.where(conditionOf(this.source, this.getExecutor(), where, options))
|
|
129
|
+
.limit(1);
|
|
130
|
+
return result.length > 0;
|
|
131
|
+
}
|
|
132
|
+
plainSelection(read) {
|
|
97
133
|
const columns = getTableColumns(this.table);
|
|
98
|
-
|
|
99
|
-
throw new Error('Find one by id is not supported for this table');
|
|
100
|
-
}
|
|
101
|
-
return this.findOne(eq(columns.id, id), options);
|
|
134
|
+
return plainColumns(columns, primaryKeyFields(this.table), read, String(this.queryKey ?? 'table'));
|
|
102
135
|
}
|
|
103
136
|
async create(data, options) {
|
|
104
137
|
const rows = await this.getExecutor(options?.tx)
|
|
@@ -114,53 +147,38 @@ export class BaseRepository {
|
|
|
114
147
|
.returning();
|
|
115
148
|
return rows;
|
|
116
149
|
}
|
|
117
|
-
async update(where, data, options) {
|
|
118
|
-
const rows = await this.getExecutor(options?.tx).update(this.table).set(data).where(where).returning();
|
|
119
|
-
return rows[0];
|
|
120
|
-
}
|
|
121
150
|
async updateById(id, data, options) {
|
|
122
|
-
|
|
123
|
-
if (!columns.id) {
|
|
124
|
-
throw new Error('Update by id is not supported for this table');
|
|
125
|
-
}
|
|
126
|
-
return await this.update(eq(columns.id, id), data, options);
|
|
127
|
-
}
|
|
128
|
-
async delete(where, options) {
|
|
129
|
-
await this.getExecutor(options?.tx).delete(this.table).where(where);
|
|
151
|
+
return await this.updateWhere(eq(this.idColumn('Update'), id), data, options);
|
|
130
152
|
}
|
|
131
153
|
async deleteById(id, options) {
|
|
132
|
-
|
|
133
|
-
if (!columns.id) {
|
|
134
|
-
throw new Error('Delete by id is not supported for this table');
|
|
135
|
-
}
|
|
136
|
-
await this.delete(eq(columns.id, id), options);
|
|
154
|
+
await this.deleteWhere(eq(this.idColumn('Delete'), id), options);
|
|
137
155
|
}
|
|
138
|
-
async
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
_where = and(where, isNull(columns.deletedAt));
|
|
144
|
-
const result = await executor
|
|
145
|
-
.select({ count: count() })
|
|
146
|
-
.from(this.table)
|
|
147
|
-
.where(_where);
|
|
148
|
-
return result[0]?.count ?? 0;
|
|
156
|
+
async deleteAllById(ids, options) {
|
|
157
|
+
const column = this.idColumn('Delete all');
|
|
158
|
+
if (ids.length === 0)
|
|
159
|
+
return;
|
|
160
|
+
await this.deleteWhere(inArray(column, [...ids]), options);
|
|
149
161
|
}
|
|
150
|
-
async
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
+
async softDeleteById(id, options) {
|
|
163
|
+
await this.softDeleteWhere(eq(this.idColumn('Soft delete'), id), options);
|
|
164
|
+
}
|
|
165
|
+
async softDeleteAllById(ids, options) {
|
|
166
|
+
const column = this.idColumn('Soft delete all');
|
|
167
|
+
if (ids.length === 0)
|
|
168
|
+
return;
|
|
169
|
+
await this.softDeleteWhere(inArray(column, [...ids]), options);
|
|
170
|
+
}
|
|
171
|
+
/** Updates the rows matching `where`, answering the first. */
|
|
172
|
+
async updateWhere(where, data, options) {
|
|
173
|
+
const rows = await this.getExecutor(options?.tx).update(this.table).set(data).where(where).returning();
|
|
174
|
+
return rows[0] ?? null;
|
|
162
175
|
}
|
|
163
|
-
|
|
176
|
+
/** Removes the rows matching `where`. */
|
|
177
|
+
async deleteWhere(where, options) {
|
|
178
|
+
await this.getExecutor(options?.tx).delete(this.table).where(where);
|
|
179
|
+
}
|
|
180
|
+
/** Marks the rows matching `where` deleted. */
|
|
181
|
+
async softDeleteWhere(where, options) {
|
|
164
182
|
const columns = getTableColumns(this.table);
|
|
165
183
|
if (!columns.deletedAt) {
|
|
166
184
|
throw new Error('Soft delete is not supported for this table');
|
|
@@ -170,13 +188,7 @@ export class BaseRepository {
|
|
|
170
188
|
.set({ deletedAt: new Date().toISOString() })
|
|
171
189
|
.where(where);
|
|
172
190
|
}
|
|
173
|
-
|
|
174
|
-
const columns = getTableColumns(this.table);
|
|
175
|
-
if (!columns.id || !columns.deletedAt) {
|
|
176
|
-
throw new Error('Soft delete by id is not supported for this table');
|
|
177
|
-
}
|
|
178
|
-
await this.softDelete(eq(columns.id, id), options);
|
|
179
|
-
}
|
|
191
|
+
/** Sets `field` to null on every row whose `field` holds `value`. */
|
|
180
192
|
async nullifyBy(field, value, options) {
|
|
181
193
|
const columns = getTableColumns(this.table);
|
|
182
194
|
const column = columns[field];
|