@tstdl/base 0.91.50 → 0.91.52
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/ai/data-extracting.d.ts +1 -0
- package/ai/data-extracting.js +62 -0
- package/authentication/server/authentication.api-controller.js +4 -4
- package/cancellation/token.d.ts +1 -2
- package/cancellation/token.js +1 -1
- package/core.d.ts +1 -1
- package/core.js +1 -1
- package/document-management/api/document-management.api.d.ts +753 -0
- package/document-management/api/document-management.api.js +222 -0
- package/document-management/api/index.d.ts +1 -0
- package/document-management/api/index.js +1 -0
- package/document-management/drizzle/0000_wakeful_firebrand.sql +228 -0
- package/document-management/drizzle/meta/0000_snapshot.json +1538 -0
- package/document-management/drizzle/meta/_journal.json +13 -0
- package/document-management/drizzle.config.d.ts +2 -0
- package/document-management/drizzle.config.js +11 -0
- package/document-management/index.d.ts +5 -0
- package/document-management/index.js +5 -0
- package/document-management/localizations/english.d.ts +2 -0
- package/document-management/localizations/english.js +9 -0
- package/document-management/localizations/german.d.ts +2 -0
- package/document-management/localizations/german.js +9 -0
- package/document-management/localizations/index.d.ts +5 -0
- package/document-management/localizations/index.js +9 -0
- package/document-management/localizations/localization.d.ts +9 -0
- package/document-management/localizations/localization.js +2 -0
- package/document-management/models/document-category.model.d.ts +4 -0
- package/document-management/models/document-category.model.js +18 -0
- package/document-management/models/document-collection-document.model.d.ts +7 -0
- package/document-management/models/document-collection-document.model.js +33 -0
- package/document-management/models/document-collection.model.d.ts +3 -0
- package/document-management/models/document-collection.model.js +14 -0
- package/document-management/models/document-file.model.d.ts +7 -0
- package/document-management/models/document-file.model.js +33 -0
- package/document-management/models/document-property-value.model.d.ts +21 -0
- package/document-management/models/document-property-value.model.js +58 -0
- package/document-management/models/document-property.model.d.ts +11 -0
- package/document-management/models/document-property.model.js +30 -0
- package/document-management/models/document-request-collection.model.d.ts +6 -0
- package/document-management/models/document-request-collection.model.js +28 -0
- package/document-management/models/document-request-file.model.d.ts +11 -0
- package/document-management/models/document-request-file.model.js +56 -0
- package/document-management/models/document-request-template.d.ts +10 -0
- package/document-management/models/document-request-template.js +39 -0
- package/document-management/models/document-request.model.d.ts +9 -0
- package/document-management/models/document-request.model.js +37 -0
- package/document-management/models/document-requests-template.d.ts +5 -0
- package/document-management/models/document-requests-template.js +23 -0
- package/document-management/models/document-type-property.model.d.ts +6 -0
- package/document-management/models/document-type-property.model.js +28 -0
- package/document-management/models/document-type.model.d.ts +7 -0
- package/document-management/models/document-type.model.js +32 -0
- package/document-management/models/document.model.d.ts +9 -0
- package/document-management/models/document.model.js +44 -0
- package/document-management/models/index.d.ts +15 -0
- package/document-management/models/index.js +15 -0
- package/document-management/models/schemas.d.ts +33 -0
- package/document-management/models/schemas.js +34 -0
- package/document-management/models/service-models/categories-and-types.view-model.d.ts +6 -0
- package/document-management/models/service-models/categories-and-types.view-model.js +24 -0
- package/document-management/models/service-models/document-folders.view-model.d.ts +22 -0
- package/document-management/models/service-models/document-folders.view-model.js +56 -0
- package/document-management/models/service-models/document-requests-template.view-model.d.ts +8 -0
- package/document-management/models/service-models/document-requests-template.view-model.js +26 -0
- package/document-management/models/service-models/document.service-model.d.ts +262 -0
- package/document-management/models/service-models/document.service-model.js +50 -0
- package/document-management/models/service-models/document.view-model.d.ts +33 -0
- package/document-management/models/service-models/document.view-model.js +99 -0
- package/document-management/models/service-models/index.d.ts +8 -0
- package/document-management/models/service-models/index.js +8 -0
- package/document-management/models/service-models/normalized-document-collection-view.model.d.ts +73 -0
- package/document-management/models/service-models/normalized-document-collection-view.model.js +110 -0
- package/document-management/models/service-models/normalized-requests-template-data.model.d.ts +16 -0
- package/document-management/models/service-models/normalized-requests-template-data.model.js +13 -0
- package/document-management/models/service-models/stats.view-model.d.ts +6 -0
- package/document-management/models/service-models/stats.view-model.js +32 -0
- package/document-management/module.d.ts +11 -0
- package/document-management/module.js +27 -0
- package/document-management/services/document-management.service.d.ts +65 -0
- package/document-management/services/document-management.service.js +376 -0
- package/document-management/services/index.d.ts +1 -0
- package/document-management/services/index.js +1 -0
- package/examples/document-management/main.d.ts +1 -0
- package/examples/document-management/main.js +30 -0
- package/examples/orm/drizzle.config.js +2 -1
- package/examples/orm/schemas.d.ts +1 -1
- package/examples/orm/user.model.d.ts +1 -2
- package/examples/orm/user.model.js +0 -1
- package/http/server/node/node-http-server.js +5 -5
- package/injector/injector.d.ts +4 -1
- package/injector/injector.js +4 -1
- package/injector/interfaces.d.ts +3 -3
- package/json-path/json-path.d.ts +2 -0
- package/json-path/json-path.js +7 -0
- package/message-bus/message-bus.d.ts +4 -6
- package/orm/database-schema.d.ts +3 -0
- package/orm/database-schema.js +6 -2
- package/orm/database.d.ts +6 -0
- package/orm/database.js +14 -0
- package/orm/decorators.d.ts +25 -2
- package/orm/decorators.js +15 -0
- package/orm/drizzle/index.d.ts +1 -0
- package/orm/drizzle/index.js +1 -0
- package/orm/drizzle/schema-converter.d.ts +37 -8
- package/orm/drizzle/schema-converter.js +121 -40
- package/orm/entity.d.ts +15 -12
- package/orm/entity.js +24 -11
- package/orm/index.d.ts +3 -2
- package/orm/index.js +3 -2
- package/orm/module.d.ts +6 -0
- package/orm/module.js +15 -0
- package/orm/query-converter.d.ts +5 -0
- package/orm/query-converter.js +114 -0
- package/orm/query.d.ts +15 -13
- package/orm/repository.d.ts +90 -31
- package/orm/repository.js +357 -55
- package/orm/schemas/index.d.ts +3 -0
- package/orm/schemas/index.js +3 -0
- package/orm/schemas/json.d.ts +9 -0
- package/orm/schemas/json.js +19 -0
- package/orm/schemas/numeric-date.d.ts +8 -0
- package/orm/schemas/numeric-date.js +13 -0
- package/orm/schemas/timestamp.d.ts +10 -0
- package/orm/schemas/timestamp.js +20 -0
- package/orm/transaction.d.ts +29 -0
- package/orm/transaction.js +73 -0
- package/orm/types.d.ts +15 -8
- package/orm/types.js +3 -2
- package/package.json +23 -12
- package/{rxjs → rxjs-utils}/reject-error.d.ts +1 -1
- package/{rxjs → rxjs-utils}/retry-backoff.d.ts +2 -2
- package/{rxjs → rxjs-utils}/slow-array.d.ts +7 -7
- package/{rxjs → rxjs-utils}/slow-array.js +2 -2
- package/{rxjs → rxjs-utils}/start-with-provider.d.ts +1 -1
- package/{rxjs → rxjs-utils}/teardown.d.ts +1 -1
- package/{rxjs → rxjs-utils}/untrack.d.ts +1 -1
- package/schema/decorators/types.d.ts +2 -2
- package/schema/schemas/number.d.ts +1 -1
- package/signals/pipe.d.ts +1 -1
- package/signals/pipe.js +1 -2
- package/sse/server-sent-events.d.ts +54 -0
- package/sse/server-sent-events.js +54 -0
- package/types.d.ts +5 -1
- package/utils/comparison.d.ts +2 -1
- package/utils/comparison.js +4 -3
- package/utils/compression.d.ts +4 -4
- package/utils/compression.js +35 -43
- package/utils/object/dereference.d.ts +6 -4
- package/utils/object/dereference.js +20 -8
- package/utils/object/object.d.ts +2 -0
- package/utils/object/object.js +20 -0
- /package/{rxjs → rxjs-utils}/cast.d.ts +0 -0
- /package/{rxjs → rxjs-utils}/cast.js +0 -0
- /package/{rxjs → rxjs-utils}/index.d.ts +0 -0
- /package/{rxjs → rxjs-utils}/index.js +0 -0
- /package/{rxjs → rxjs-utils}/noop.d.ts +0 -0
- /package/{rxjs → rxjs-utils}/noop.js +0 -0
- /package/{rxjs → rxjs-utils}/reject-error.js +0 -0
- /package/{rxjs → rxjs-utils}/retry-backoff.js +0 -0
- /package/{rxjs → rxjs-utils}/start-with-provider.js +0 -0
- /package/{rxjs → rxjs-utils}/teardown.js +0 -0
- /package/{rxjs → rxjs-utils}/timing.d.ts +0 -0
- /package/{rxjs → rxjs-utils}/timing.js +0 -0
- /package/{rxjs → rxjs-utils}/untrack.js +0 -0
package/orm/repository.js
CHANGED
|
@@ -5,22 +5,77 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
6
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
7
|
};
|
|
8
|
-
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
import { count, eq, inArray, sql } from 'drizzle-orm';
|
|
12
|
+
import { PgTransaction as DrizzlePgTransaction } from 'drizzle-orm/pg-core';
|
|
9
13
|
import { NotFoundError } from '../errors/not-found.error.js';
|
|
10
|
-
import { NotImplementedError } from '../errors/not-implemented.error.js';
|
|
11
|
-
import { NotSupportedError } from '../errors/not-supported.error.js';
|
|
12
14
|
import { Singleton } from '../injector/decorators.js';
|
|
13
|
-
import { inject } from '../injector/inject.js';
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
15
|
+
import { inject, injectArgument } from '../injector/inject.js';
|
|
16
|
+
import { Schema } from '../schema/schema.js';
|
|
17
|
+
import { toArray } from '../utils/array/array.js';
|
|
18
|
+
import { fromDeepObjectEntries } from '../utils/object/object.js';
|
|
19
|
+
import { assertDefinedPass, assertNotNullPass, isNotNull, isUndefined } from '../utils/type-guards.js';
|
|
20
|
+
import { Database } from './database.js';
|
|
21
|
+
import { getColumnDefinitions, getDrizzleTableFromType } from './drizzle/schema-converter.js';
|
|
22
|
+
import { convertQuery } from './query-converter.js';
|
|
23
|
+
import { DrizzleTransaction } from './transaction.js';
|
|
18
24
|
export const repositoryType = Symbol('repositoryType');
|
|
19
|
-
export
|
|
25
|
+
export class EntityRepositoryConfig {
|
|
26
|
+
schema;
|
|
27
|
+
}
|
|
28
|
+
const TRANSACTION_TIMESTAMP = sql `transaction_timestamp()`;
|
|
20
29
|
let EntityRepository = class EntityRepository {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
30
|
+
#repositoryConstructor;
|
|
31
|
+
#withTransactionCache = new WeakMap();
|
|
32
|
+
type;
|
|
33
|
+
table;
|
|
34
|
+
columnDefinitions;
|
|
35
|
+
columnDefinitionsMap;
|
|
36
|
+
session;
|
|
37
|
+
isInTransaction;
|
|
38
|
+
get tx() {
|
|
39
|
+
return this.session;
|
|
40
|
+
}
|
|
41
|
+
constructor(type, table, columnDefinitions, columnDefinitionsMap, session) {
|
|
42
|
+
this.#repositoryConstructor = new.target;
|
|
43
|
+
this.type = type ?? injectArgument(this);
|
|
44
|
+
this.table = table ?? getDrizzleTableFromType(this.type, inject(EntityRepositoryConfig).schema);
|
|
45
|
+
this.columnDefinitions = columnDefinitions ?? getColumnDefinitions(this.table);
|
|
46
|
+
this.columnDefinitionsMap = columnDefinitionsMap ?? new Map(this.columnDefinitions.map((column) => [column.objectPath.path, column]));
|
|
47
|
+
this.session = session ?? inject(Database);
|
|
48
|
+
this.isInTransaction = this.session instanceof DrizzlePgTransaction;
|
|
49
|
+
}
|
|
50
|
+
withOptionalTransaction(transaction) {
|
|
51
|
+
if (isUndefined(transaction)) {
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
54
|
+
return this.withTransaction(transaction);
|
|
55
|
+
}
|
|
56
|
+
withTransaction(transaction) {
|
|
57
|
+
if (this.#withTransactionCache.has(transaction)) {
|
|
58
|
+
return this.#withTransactionCache.get(transaction);
|
|
59
|
+
}
|
|
60
|
+
const repositoryWithTransaction = new this.#repositoryConstructor(this.type, this.table, this.columnDefinitions, this.columnDefinitionsMap, transaction.transaction);
|
|
61
|
+
this.#withTransactionCache.set(transaction, repositoryWithTransaction);
|
|
62
|
+
return repositoryWithTransaction;
|
|
63
|
+
}
|
|
64
|
+
async startTransaction(config) {
|
|
65
|
+
return DrizzleTransaction.create(this.session, config);
|
|
66
|
+
}
|
|
67
|
+
async useTransaction(transaction, handler) {
|
|
68
|
+
if (isUndefined(transaction)) {
|
|
69
|
+
return this.transaction(handler);
|
|
70
|
+
}
|
|
71
|
+
const repository = this.withTransaction(transaction);
|
|
72
|
+
return transaction.use(async () => handler(repository, transaction));
|
|
73
|
+
}
|
|
74
|
+
async transaction(handler, config) {
|
|
75
|
+
const transaction = await DrizzleTransaction.create(this.session, config);
|
|
76
|
+
const repository = this.withTransaction(transaction);
|
|
77
|
+
return transaction.use(async () => handler(repository, transaction));
|
|
78
|
+
}
|
|
24
79
|
async load(id) {
|
|
25
80
|
const entity = await this.tryLoad(id);
|
|
26
81
|
if (isUndefined(entity)) {
|
|
@@ -29,7 +84,7 @@ let EntityRepository = class EntityRepository {
|
|
|
29
84
|
return entity;
|
|
30
85
|
}
|
|
31
86
|
async tryLoad(id) {
|
|
32
|
-
return this.tryLoadByQuery(eq(this.
|
|
87
|
+
return this.tryLoadByQuery(eq(this.table.id, id));
|
|
33
88
|
}
|
|
34
89
|
async loadByQuery(query, options) {
|
|
35
90
|
const entity = await this.tryLoadByQuery(query, options);
|
|
@@ -39,90 +94,337 @@ let EntityRepository = class EntityRepository {
|
|
|
39
94
|
return entity;
|
|
40
95
|
}
|
|
41
96
|
async tryLoadByQuery(query, options) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
.from(this.schema)
|
|
47
|
-
.where(query)
|
|
97
|
+
const sqlQuery = this.convertQuery(query);
|
|
98
|
+
const dbQuery = this.session.select()
|
|
99
|
+
.from(this.table)
|
|
100
|
+
.where(sqlQuery)
|
|
48
101
|
.offset(options?.offset);
|
|
49
|
-
const [
|
|
50
|
-
|
|
102
|
+
const [row] = await dbQuery;
|
|
103
|
+
if (isUndefined(row)) {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
return this.mapToEntity(row);
|
|
51
107
|
}
|
|
52
108
|
async loadMany(ids, options) {
|
|
53
|
-
return this.loadManyByQuery(inArray(this.
|
|
109
|
+
return this.loadManyByQuery(inArray(this.table.id, ids), options);
|
|
54
110
|
}
|
|
55
111
|
async *loadManyCursor(ids, options) {
|
|
56
112
|
const entities = await this.loadMany(ids, options);
|
|
57
113
|
yield* entities;
|
|
58
114
|
}
|
|
59
115
|
async loadManyByQuery(query, options) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
.from(this.schema)
|
|
65
|
-
.where(query)
|
|
116
|
+
const sqlQuery = this.convertQuery(query);
|
|
117
|
+
const rows = await this.session.select()
|
|
118
|
+
.from(this.table)
|
|
119
|
+
.where(sqlQuery)
|
|
66
120
|
.offset(options?.offset)
|
|
67
121
|
.limit(options?.limit);
|
|
68
|
-
return
|
|
122
|
+
return rows.map((entity) => this.mapToEntity(entity));
|
|
69
123
|
}
|
|
70
124
|
async *loadManyByQueryCursor(query, options) {
|
|
71
125
|
const entities = await this.loadManyByQuery(query, options);
|
|
72
126
|
yield* entities;
|
|
73
127
|
}
|
|
74
128
|
async loadAll(options) {
|
|
75
|
-
return this.loadManyByQuery(
|
|
129
|
+
return this.loadManyByQuery({}, options);
|
|
76
130
|
}
|
|
77
131
|
async *loadAllCursor(options) {
|
|
78
132
|
const entities = await this.loadAll(options);
|
|
79
133
|
yield* entities;
|
|
80
134
|
}
|
|
81
135
|
async count() {
|
|
82
|
-
const dbQuery = this.
|
|
136
|
+
const dbQuery = this.session
|
|
83
137
|
.select({ count: count() })
|
|
84
|
-
.from(this.
|
|
138
|
+
.from(this.table);
|
|
85
139
|
const [result] = await dbQuery;
|
|
86
140
|
return assertDefinedPass(result).count;
|
|
87
141
|
}
|
|
88
142
|
async countByQuery(query) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
const dbQuery = this.database
|
|
143
|
+
const sqlQuery = this.convertQuery(query);
|
|
144
|
+
const dbQuery = this.session
|
|
93
145
|
.select({ count: count() })
|
|
94
|
-
.from(this.
|
|
95
|
-
.where(
|
|
146
|
+
.from(this.table)
|
|
147
|
+
.where(sqlQuery);
|
|
96
148
|
const [result] = await dbQuery;
|
|
97
149
|
return assertDefinedPass(result).count;
|
|
98
150
|
}
|
|
99
151
|
async has(id) {
|
|
100
|
-
return this.hasByQuery(eq(this.
|
|
152
|
+
return this.hasByQuery(eq(this.table.id, id));
|
|
101
153
|
}
|
|
102
154
|
async hasByQuery(query) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const dbQuery = this.database
|
|
108
|
-
.select({
|
|
109
|
-
exists: sql `SELECT EXISTS(SELECT 1 FROM ${this.schema} WHERE ${query})`
|
|
110
|
-
})
|
|
111
|
-
.from(this.schema)
|
|
112
|
-
.where(query);
|
|
155
|
+
const sqlQuery = this.convertQuery(query);
|
|
156
|
+
const dbQuery = this.session
|
|
157
|
+
.select({ exists: sql `SELECT EXISTS(SELECT 1 FROM ${this.table} WHERE ${sqlQuery})` })
|
|
158
|
+
.from(this.table);
|
|
113
159
|
const [result] = await dbQuery;
|
|
114
160
|
return assertDefinedPass(result).exists;
|
|
115
161
|
}
|
|
116
162
|
async hasAll(ids) {
|
|
117
|
-
const result = await this.
|
|
118
|
-
|
|
163
|
+
const result = await this.session
|
|
164
|
+
.select({ contains: sql `array_agg(${this.table.id}) @> ${ids}`.as('contains') })
|
|
165
|
+
.from(this.table);
|
|
166
|
+
return assertDefinedPass(result[0]).contains;
|
|
167
|
+
}
|
|
168
|
+
async insert(entity) {
|
|
169
|
+
const columns = this.mapToInsertColumns(entity);
|
|
170
|
+
const [row] = await this.session
|
|
171
|
+
.insert(this.table)
|
|
172
|
+
.values(columns)
|
|
173
|
+
.returning();
|
|
174
|
+
return this.mapToEntity(row);
|
|
175
|
+
}
|
|
176
|
+
async insertMany(entities) {
|
|
177
|
+
const columns = entities.map((entity) => this.mapToInsertColumns(entity));
|
|
178
|
+
const rows = await this.session.insert(this.table).values(columns).returning();
|
|
179
|
+
return rows.map((row) => this.mapToEntity(row));
|
|
180
|
+
}
|
|
181
|
+
async upsert(target, entity, update) {
|
|
182
|
+
const targetColumns = toArray(target).map((path) => {
|
|
183
|
+
const columnName = assertDefinedPass(this.columnDefinitionsMap.get(path), `Could not map ${path} to column.`).name;
|
|
184
|
+
return this.table[columnName];
|
|
185
|
+
});
|
|
186
|
+
const columns = this.mapToInsertColumns(entity);
|
|
187
|
+
const mappedUpdate = this.mapUpdate(update ?? entity);
|
|
188
|
+
const [row] = await this.session
|
|
189
|
+
.insert(this.table)
|
|
190
|
+
.values(columns)
|
|
191
|
+
.onConflictDoUpdate({
|
|
192
|
+
target: targetColumns,
|
|
193
|
+
set: mappedUpdate
|
|
194
|
+
})
|
|
195
|
+
.returning();
|
|
196
|
+
return this.mapToEntity(row);
|
|
197
|
+
}
|
|
198
|
+
async upsertMany(target, entities, update) {
|
|
199
|
+
const targetColumns = toArray(target).map((path) => {
|
|
200
|
+
const columnName = assertDefinedPass(this.columnDefinitionsMap.get(path), `Could not map ${path} to column.`).name;
|
|
201
|
+
return this.table[columnName];
|
|
202
|
+
});
|
|
203
|
+
const columns = entities.map((entity) => this.mapToColumns(entity));
|
|
204
|
+
const mappedUpdate = this.mapUpdate(update);
|
|
205
|
+
const rows = await this.session
|
|
206
|
+
.insert(this.table)
|
|
207
|
+
.values(columns)
|
|
208
|
+
.onConflictDoUpdate({
|
|
209
|
+
target: targetColumns,
|
|
210
|
+
set: mappedUpdate
|
|
211
|
+
})
|
|
212
|
+
.returning();
|
|
213
|
+
return rows.map((row) => this.mapToEntity(row));
|
|
214
|
+
}
|
|
215
|
+
async update(id, update) {
|
|
216
|
+
const entity = await this.tryUpdate(id, update);
|
|
217
|
+
if (isUndefined(entity)) {
|
|
218
|
+
throw new NotFoundError(`${this.type.entityName} ${id} not found.`);
|
|
219
|
+
}
|
|
220
|
+
return entity;
|
|
221
|
+
}
|
|
222
|
+
async tryUpdate(id, update) {
|
|
223
|
+
const mappedUpdate = this.mapUpdate(update);
|
|
224
|
+
const [row] = await this.session
|
|
225
|
+
.update(this.table)
|
|
226
|
+
.set(mappedUpdate)
|
|
227
|
+
.where(eq(this.table.id, id))
|
|
228
|
+
.returning();
|
|
229
|
+
if (isUndefined(row)) {
|
|
230
|
+
return undefined;
|
|
231
|
+
}
|
|
232
|
+
return this.mapToEntity(row);
|
|
233
|
+
}
|
|
234
|
+
async updateByQuery(query, update) {
|
|
235
|
+
const entity = await this.tryUpdateByQuery(query, update);
|
|
236
|
+
if (isUndefined(entity)) {
|
|
237
|
+
throw new NotFoundError(`${this.type.entityName} not found.`);
|
|
238
|
+
}
|
|
239
|
+
return entity;
|
|
240
|
+
}
|
|
241
|
+
async tryUpdateByQuery(query, update) {
|
|
242
|
+
const mappedUpdate = this.mapUpdate(update);
|
|
243
|
+
const idQuery = this.getIdLimitQuery(query);
|
|
244
|
+
const [row] = await this.session
|
|
245
|
+
.with(idQuery)
|
|
246
|
+
.update(this.table)
|
|
247
|
+
.set(mappedUpdate)
|
|
248
|
+
.where(inArray(this.table.id, idQuery))
|
|
249
|
+
.returning();
|
|
250
|
+
if (isUndefined(row)) {
|
|
251
|
+
return undefined;
|
|
252
|
+
}
|
|
253
|
+
return this.mapToEntity(row);
|
|
254
|
+
}
|
|
255
|
+
async updateMany(ids, update) {
|
|
256
|
+
return this.updateManyByQuery(inArray(this.table.id, ids), update);
|
|
119
257
|
}
|
|
120
|
-
async
|
|
121
|
-
|
|
122
|
-
|
|
258
|
+
async updateManyByQuery(query, update) {
|
|
259
|
+
const sqlQuery = this.convertQuery(query);
|
|
260
|
+
const mappedUpdate = this.mapUpdate(update);
|
|
261
|
+
const rows = await this.session
|
|
262
|
+
.update(this.table)
|
|
263
|
+
.set(mappedUpdate)
|
|
264
|
+
.where(sqlQuery)
|
|
265
|
+
.returning();
|
|
266
|
+
return rows.map((entity) => this.mapToEntity(entity));
|
|
267
|
+
}
|
|
268
|
+
async delete(id, metadataUpdate) {
|
|
269
|
+
const entity = await this.tryDelete(id, metadataUpdate);
|
|
270
|
+
if (isUndefined(entity)) {
|
|
271
|
+
throw new NotFoundError(`${this.type.entityName} ${id} not found.`);
|
|
272
|
+
}
|
|
273
|
+
return entity;
|
|
274
|
+
}
|
|
275
|
+
async tryDelete(id, metadataUpdate) {
|
|
276
|
+
const [row] = await this.session
|
|
277
|
+
.update(this.table)
|
|
278
|
+
.set({
|
|
279
|
+
deleteTimestamp: TRANSACTION_TIMESTAMP,
|
|
280
|
+
attributes: this.getAttributesUpdate(metadataUpdate?.attributes)
|
|
281
|
+
})
|
|
282
|
+
.where(eq(this.table.id, id))
|
|
283
|
+
.returning();
|
|
284
|
+
if (isUndefined(row)) {
|
|
285
|
+
return undefined;
|
|
286
|
+
}
|
|
287
|
+
return this.mapToEntity(row);
|
|
288
|
+
}
|
|
289
|
+
async deleteByQuery(query, metadataUpdate) {
|
|
290
|
+
const entity = await this.tryDeleteByQuery(query, metadataUpdate);
|
|
291
|
+
if (isUndefined(entity)) {
|
|
292
|
+
throw new NotFoundError(`${this.type.entityName} not found.`);
|
|
293
|
+
}
|
|
294
|
+
return entity;
|
|
295
|
+
}
|
|
296
|
+
async tryDeleteByQuery(query, metadataUpdate) {
|
|
297
|
+
const idQuery = this.getIdLimitQuery(query);
|
|
298
|
+
const [row] = await this.session
|
|
299
|
+
.update(this.table)
|
|
300
|
+
.set({
|
|
301
|
+
deleteTimestamp: TRANSACTION_TIMESTAMP,
|
|
302
|
+
attributes: this.getAttributesUpdate(metadataUpdate?.attributes)
|
|
303
|
+
})
|
|
304
|
+
.where(inArray(this.table.id, idQuery))
|
|
305
|
+
.returning();
|
|
306
|
+
if (isUndefined(row)) {
|
|
307
|
+
return undefined;
|
|
308
|
+
}
|
|
309
|
+
return this.mapToEntity(row);
|
|
310
|
+
}
|
|
311
|
+
async deleteMany(ids, metadataUpdate) {
|
|
312
|
+
return this.deleteManyByQuery(inArray(this.table.id, ids), metadataUpdate);
|
|
313
|
+
}
|
|
314
|
+
async deleteManyByQuery(query, metadataUpdate) {
|
|
315
|
+
const sqlQuery = this.convertQuery(query);
|
|
316
|
+
const rows = await this.session
|
|
317
|
+
.update(this.table)
|
|
318
|
+
.set({
|
|
319
|
+
deleteTimestamp: TRANSACTION_TIMESTAMP,
|
|
320
|
+
attributes: this.getAttributesUpdate(metadataUpdate?.attributes)
|
|
321
|
+
})
|
|
322
|
+
.where(sqlQuery)
|
|
323
|
+
.returning();
|
|
324
|
+
return rows.map((row) => this.mapToEntity(row));
|
|
325
|
+
}
|
|
326
|
+
async hardDelete(id) {
|
|
327
|
+
const result = await this.tryHardDelete(id);
|
|
328
|
+
if (!result) {
|
|
329
|
+
throw new NotFoundError(`${this.type.entityName} ${id} not found.`);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
async tryHardDelete(id) {
|
|
333
|
+
const result = await this.session.delete(this.table).where(eq(this.table.id, id));
|
|
334
|
+
console.log({ deleteResult: result });
|
|
335
|
+
return isNotNull(result.rowCount) && (result.rowCount > 0);
|
|
336
|
+
}
|
|
337
|
+
async hardDeleteByQuery(query) {
|
|
338
|
+
const idQuery = this.getIdLimitQuery(query);
|
|
339
|
+
const result = await this.session
|
|
340
|
+
.with(idQuery)
|
|
341
|
+
.delete(this.table)
|
|
342
|
+
.where(inArray(this.table.id, idQuery));
|
|
343
|
+
console.log({ deleteResult: result });
|
|
344
|
+
return isNotNull(result.rowCount) && (result.rowCount > 0);
|
|
345
|
+
}
|
|
346
|
+
async hardDeleteMany(ids) {
|
|
347
|
+
return this.hardDeleteManyByQuery(inArray(this.table.id, ids));
|
|
348
|
+
}
|
|
349
|
+
async hardDeleteManyByQuery(query) {
|
|
350
|
+
const sqlQuery = this.convertQuery(query);
|
|
351
|
+
const result = await this.session.delete(this.table).where(sqlQuery);
|
|
352
|
+
console.log({ deleteResult: result });
|
|
353
|
+
return assertNotNullPass(result.rowCount);
|
|
354
|
+
}
|
|
355
|
+
convertQuery(query) {
|
|
356
|
+
return convertQuery(query, this.table, this.columnDefinitionsMap);
|
|
357
|
+
}
|
|
358
|
+
mapToEntity(columns) {
|
|
359
|
+
const entries = this.columnDefinitions.map((def) => [def.objectPath, columns[def.name]]);
|
|
360
|
+
const obj = fromDeepObjectEntries(entries);
|
|
361
|
+
return Schema.parse(this.type, obj);
|
|
362
|
+
}
|
|
363
|
+
mapToColumns(obj) {
|
|
364
|
+
const columns = {};
|
|
365
|
+
for (const def of this.columnDefinitions) {
|
|
366
|
+
columns[def.name] = def.dereferenceObjectPath(obj);
|
|
367
|
+
}
|
|
368
|
+
return columns;
|
|
369
|
+
}
|
|
370
|
+
mapToInsertColumns(obj) {
|
|
371
|
+
const mapped = this.mapToColumns(obj);
|
|
372
|
+
return {
|
|
373
|
+
...mapped,
|
|
374
|
+
revision: 1,
|
|
375
|
+
revisionTimestamp: TRANSACTION_TIMESTAMP,
|
|
376
|
+
createTimestamp: TRANSACTION_TIMESTAMP
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
mapUpdate(update) {
|
|
380
|
+
const mappedUpdate = {};
|
|
381
|
+
for (const column of this.columnDefinitions) {
|
|
382
|
+
const value = column.dereferenceObjectPath(update);
|
|
383
|
+
if (isUndefined(value)) {
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
mappedUpdate[column.name] = value;
|
|
387
|
+
}
|
|
388
|
+
return {
|
|
389
|
+
...mappedUpdate,
|
|
390
|
+
attributes: this.getAttributesUpdate(update.metadata?.attributes),
|
|
391
|
+
revision: sql `${this.table.revision} + 1`,
|
|
392
|
+
revisionTimestamp: sql `transaction_timestamp()`
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
getIdLimitQuery(query) {
|
|
396
|
+
const sqlQuery = this.convertQuery(query);
|
|
397
|
+
return this.session.$with('id').as(this.session.select({ id: this.table.id })
|
|
398
|
+
.from(this.table)
|
|
399
|
+
.where(sqlQuery)
|
|
400
|
+
.limit(1));
|
|
401
|
+
}
|
|
402
|
+
getAttributesUpdate(attributes) {
|
|
403
|
+
if (isUndefined(attributes)) {
|
|
404
|
+
return undefined;
|
|
405
|
+
}
|
|
406
|
+
return sql `${this.table.attributes} || '${JSON.stringify(attributes)}'::jsonb`;
|
|
123
407
|
}
|
|
124
408
|
};
|
|
125
409
|
EntityRepository = __decorate([
|
|
126
|
-
Singleton(
|
|
410
|
+
Singleton({
|
|
411
|
+
provider: {
|
|
412
|
+
useFactory: () => new EntityRepository()
|
|
413
|
+
}
|
|
414
|
+
}),
|
|
415
|
+
__metadata("design:paramtypes", [Object, Object, Array, Map, Object])
|
|
127
416
|
], EntityRepository);
|
|
128
417
|
export { EntityRepository };
|
|
418
|
+
export function injectRepository(type) {
|
|
419
|
+
return inject((EntityRepository), type);
|
|
420
|
+
}
|
|
421
|
+
export function getRepository(type, config) {
|
|
422
|
+
const className = `${type.name}Service`;
|
|
423
|
+
const entityRepositoryClass = {
|
|
424
|
+
[className]: class extends EntityRepository {
|
|
425
|
+
}
|
|
426
|
+
}[className];
|
|
427
|
+
const injectorDecorator = Singleton({ providers: [{ provide: EntityRepositoryConfig, useValue: config }] });
|
|
428
|
+
injectorDecorator(entityRepositoryClass);
|
|
429
|
+
return entityRepositoryClass;
|
|
430
|
+
}
|
package/orm/schemas/index.d.ts
CHANGED
package/orm/schemas/index.js
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type Decorator } from '../../reflection/index.js';
|
|
2
|
+
import { ObjectSchema, type ObjectSchemaOptions, type SchemaPropertyDecoratorOptions } from '../../schema/index.js';
|
|
3
|
+
export type JsonSchemaOptions = Pick<ObjectSchemaOptions, 'factory'>;
|
|
4
|
+
export declare class JsonSchema extends ObjectSchema {
|
|
5
|
+
readonly name = "Json";
|
|
6
|
+
constructor(options?: JsonSchemaOptions);
|
|
7
|
+
}
|
|
8
|
+
export declare function json(options?: JsonSchemaOptions): JsonSchema;
|
|
9
|
+
export declare function Json(options?: JsonSchemaOptions & SchemaPropertyDecoratorOptions): Decorator<'class' | 'property' | 'accessor'>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { createDecorator } from '../../reflection/index.js';
|
|
2
|
+
import { any, Class, ObjectSchema, Property } from '../../schema/index.js';
|
|
3
|
+
export class JsonSchema extends ObjectSchema {
|
|
4
|
+
name = 'Json';
|
|
5
|
+
constructor(options) {
|
|
6
|
+
super({}, { ...options, unknownPropertiesKey: any(), unknownProperties: any() });
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export function json(options) {
|
|
10
|
+
return new JsonSchema(options);
|
|
11
|
+
}
|
|
12
|
+
export function Json(options) {
|
|
13
|
+
return createDecorator({ class: true, property: true, accessor: true }, (data, metadata, args) => {
|
|
14
|
+
if (data.type == 'class') {
|
|
15
|
+
return Class({ schema: json({ factory: { type: data.constructor } }) })(args[0]);
|
|
16
|
+
}
|
|
17
|
+
return Property(json({ factory: { type: metadata.type } }), options)(args[0], args[1], args[2]);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { NumberSchema, type NumberSchemaOptions, type SchemaPropertyDecorator, type SchemaPropertyDecoratorOptions, type SimpleSchemaOptions } from '../../schema/index.js';
|
|
2
|
+
export type NumericDateSchemaOptions = SimpleSchemaOptions & Pick<NumberSchemaOptions, 'minimum' | 'maximum'>;
|
|
3
|
+
export declare class NumericDateSchema extends NumberSchema {
|
|
4
|
+
readonly name = "NumericDate";
|
|
5
|
+
constructor(options?: NumericDateSchemaOptions);
|
|
6
|
+
}
|
|
7
|
+
export declare function numericDate(options?: NumericDateSchemaOptions): NumericDateSchema;
|
|
8
|
+
export declare function NumericDate(options?: NumericDateSchemaOptions & SchemaPropertyDecoratorOptions): SchemaPropertyDecorator;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { NumberSchema, Property } from '../../schema/index.js';
|
|
2
|
+
export class NumericDateSchema extends NumberSchema {
|
|
3
|
+
name = 'NumericDate';
|
|
4
|
+
constructor(options) {
|
|
5
|
+
super({ ...options, integer: true });
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export function numericDate(options) {
|
|
9
|
+
return new NumericDateSchema(options);
|
|
10
|
+
}
|
|
11
|
+
export function NumericDate(options) {
|
|
12
|
+
return Property(numericDate(options), options);
|
|
13
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { JsonPath } from '../../json-path/json-path.js';
|
|
2
|
+
import { NumberSchema, type NumberSchemaOptions, type SchemaPropertyDecorator, type SchemaPropertyDecoratorOptions, type SchemaTestOptions, type SchemaTestResult, type SimpleSchemaOptions } from '../../schema/index.js';
|
|
3
|
+
export type TimestampSchemaOptions = SimpleSchemaOptions & Pick<NumberSchemaOptions, 'minimum' | 'maximum'>;
|
|
4
|
+
export declare class TimestampSchema extends NumberSchema {
|
|
5
|
+
readonly name = "Timestamp";
|
|
6
|
+
constructor(options?: TimestampSchemaOptions);
|
|
7
|
+
_test(value: any, path: JsonPath, options: SchemaTestOptions): SchemaTestResult<number>;
|
|
8
|
+
}
|
|
9
|
+
export declare function timestamp(options?: TimestampSchemaOptions): TimestampSchema;
|
|
10
|
+
export declare function Timestamp(options?: TimestampSchemaOptions & SchemaPropertyDecoratorOptions): SchemaPropertyDecorator;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { NumberSchema, Property } from '../../schema/index.js';
|
|
2
|
+
import { isDate } from '../../utils/type-guards.js';
|
|
3
|
+
export class TimestampSchema extends NumberSchema {
|
|
4
|
+
name = 'Timestamp';
|
|
5
|
+
constructor(options) {
|
|
6
|
+
super({ ...options, integer: true });
|
|
7
|
+
}
|
|
8
|
+
_test(value, path, options) {
|
|
9
|
+
if (isDate(value)) {
|
|
10
|
+
return super._test(value.getTime(), path, options);
|
|
11
|
+
}
|
|
12
|
+
return super._test(value, path, options);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export function timestamp(options) {
|
|
16
|
+
return new TimestampSchema(options);
|
|
17
|
+
}
|
|
18
|
+
export function Timestamp(options) {
|
|
19
|
+
return Property(timestamp(options), options);
|
|
20
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { DeferredPromise } from '../promise/deferred-promise.js';
|
|
2
|
+
import type { PgTransaction as DrizzlePgTransaction, PgTransactionConfig } from 'drizzle-orm/pg-core';
|
|
3
|
+
import type { Database } from './database.js';
|
|
4
|
+
type PgTransaction = DrizzlePgTransaction<any, any, any>;
|
|
5
|
+
export type TransactionConfig = PgTransactionConfig;
|
|
6
|
+
export declare abstract class Transaction {
|
|
7
|
+
#private;
|
|
8
|
+
readonly afterCommit$: import("rxjs").Observable<void>;
|
|
9
|
+
manualCommit: boolean;
|
|
10
|
+
withManualCommit(): void;
|
|
11
|
+
/**
|
|
12
|
+
* Enters automatic transaction handling. Transaction will be commited when all use-calls are done or rolled back when one throws.
|
|
13
|
+
*/
|
|
14
|
+
use<T>(handler: () => Promise<T>): Promise<T>;
|
|
15
|
+
commit(): Promise<void>;
|
|
16
|
+
rollback(): void;
|
|
17
|
+
protected abstract _commit(): Promise<void>;
|
|
18
|
+
protected abstract _rollback(): void;
|
|
19
|
+
}
|
|
20
|
+
export declare class DrizzleTransaction extends Transaction {
|
|
21
|
+
readonly transaction: PgTransaction;
|
|
22
|
+
readonly deferPromise: DeferredPromise<void>;
|
|
23
|
+
readonly pgTransactionPromise: Promise<void>;
|
|
24
|
+
constructor(transaction: PgTransaction, pgTransactionPromise: Promise<void>);
|
|
25
|
+
static create(session: Database | PgTransaction, config?: TransactionConfig): Promise<DrizzleTransaction>;
|
|
26
|
+
protected _commit(): Promise<void>;
|
|
27
|
+
protected _rollback(): void;
|
|
28
|
+
}
|
|
29
|
+
export {};
|