@tstdl/base 0.92.123 → 0.92.125
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/ai-file.service.js +23 -18
- package/ai/ai.service.d.ts +4 -12
- package/ai/ai.service.js +79 -147
- package/ai/functions.d.ts +1 -1
- package/ai/types.d.ts +3 -1
- package/api/server/gateway.js +6 -6
- package/authentication/authentication.api.js +24 -24
- package/authentication/server/authentication.service.js +20 -20
- package/browser/page-controller.js +1 -1
- package/context/context.js +5 -5
- package/document-management/api/document-management.api.d.ts +60 -215
- package/document-management/api/document-management.api.js +32 -68
- package/document-management/models/document-assignment-scope.model.d.ts +11 -0
- package/document-management/models/{document-request-assignment-task-collection.model.js → document-assignment-scope.model.js} +14 -10
- package/document-management/models/document-assignment-task.model.d.ts +13 -0
- package/document-management/models/document-assignment-task.model.js +38 -0
- package/document-management/models/document-category.model.d.ts +2 -0
- package/document-management/models/document-category.model.js +7 -1
- package/document-management/models/{document-collection-document.model.d.ts → document-collection-assignment.model.d.ts} +1 -1
- package/document-management/models/{document-collection-document.model.js → document-collection-assignment.model.js} +7 -7
- package/document-management/models/document-collection.model.d.ts +2 -0
- package/document-management/models/document-collection.model.js +10 -0
- package/document-management/models/document-property-value.model.d.ts +3 -11
- package/document-management/models/document-property-value.model.js +15 -46
- package/document-management/models/document-property.model.d.ts +2 -1
- package/document-management/models/document-property.model.js +2 -2
- package/document-management/models/document-request-submission.model.d.ts +7 -0
- package/document-management/models/document-request-submission.model.js +34 -0
- package/document-management/models/document-request-template.d.ts +2 -4
- package/document-management/models/document-request-template.js +3 -8
- package/document-management/models/document-request.model.d.ts +14 -6
- package/document-management/models/document-request.model.js +22 -12
- package/document-management/models/document-type-validation.model.d.ts +6 -0
- package/document-management/models/document-type-validation.model.js +34 -0
- package/document-management/models/document-type.model.d.ts +0 -1
- package/document-management/models/document-type.model.js +0 -5
- package/document-management/models/document-validation-definition.model.d.ts +10 -0
- package/document-management/models/document-validation-definition.model.js +39 -0
- package/document-management/models/document-validation-execution-related-document.model.d.ts +7 -0
- package/document-management/models/document-validation-execution-related-document.model.js +34 -0
- package/document-management/models/document-validation-execution.model.d.ts +26 -0
- package/document-management/models/document-validation-execution.model.js +72 -0
- package/document-management/models/document-workflow.model.d.ts +35 -0
- package/document-management/models/document-workflow.model.js +70 -0
- package/document-management/models/document.model.d.ts +12 -1
- package/document-management/models/document.model.js +21 -5
- package/document-management/models/index.d.ts +10 -5
- package/document-management/models/index.js +10 -5
- package/document-management/models/service-models/categories-and-types.view-model.d.ts +3 -3
- package/document-management/models/service-models/categories-and-types.view-model.js +2 -21
- package/document-management/models/service-models/document-folders.view-model.d.ts +7 -14
- package/document-management/models/service-models/document-folders.view-model.js +20 -44
- package/document-management/models/service-models/document-management.view-model.d.ts +41 -0
- package/document-management/models/service-models/{document.view-model.js → document-management.view-model.js} +43 -26
- package/document-management/models/service-models/document.service-model.d.ts +51 -81
- package/document-management/models/service-models/document.service-model.js +30 -28
- package/document-management/models/service-models/enriched/enriched-document-assignment.view.d.ts +11 -0
- package/document-management/models/service-models/enriched/enriched-document-assignment.view.js +12 -0
- package/document-management/models/service-models/enriched/enriched-document-category.view.d.ts +13 -0
- package/document-management/models/service-models/enriched/enriched-document-category.view.js +47 -0
- package/document-management/models/service-models/enriched/enriched-document-collection.view.d.ts +22 -0
- package/document-management/models/service-models/enriched/enriched-document-collection.view.js +89 -0
- package/document-management/models/service-models/enriched/enriched-document-file.view.d.ts +12 -0
- package/document-management/models/service-models/enriched/enriched-document-file.view.js +16 -0
- package/document-management/models/service-models/enriched/enriched-document-management-data.view.d.ts +41 -0
- package/document-management/models/service-models/enriched/enriched-document-management-data.view.js +130 -0
- package/document-management/models/service-models/enriched/enriched-document-request.view.d.ts +17 -0
- package/document-management/models/service-models/enriched/enriched-document-request.view.js +52 -0
- package/document-management/models/service-models/enriched/enriched-document-type.view.d.ts +9 -0
- package/document-management/models/service-models/enriched/enriched-document-type.view.js +10 -0
- package/document-management/models/service-models/enriched/enriched-document.view.d.ts +28 -0
- package/document-management/models/service-models/enriched/enriched-document.view.js +77 -0
- package/document-management/models/service-models/enriched/enriched.d.ts +18 -0
- package/document-management/models/service-models/enriched/enriched.js +39 -0
- package/document-management/models/service-models/enriched/index.d.ts +9 -0
- package/document-management/models/service-models/enriched/index.js +9 -0
- package/document-management/models/service-models/index.d.ts +2 -2
- package/document-management/models/service-models/index.js +2 -2
- package/document-management/models/service-models/normalized-requests-template-data.model.d.ts +12 -10
- package/document-management/models/service-models/normalized-requests-template-data.model.js +5 -4
- package/document-management/models/service-models/stats.view-model.d.ts +7 -5
- package/document-management/models/service-models/stats.view-model.js +19 -9
- package/document-management/server/module.d.ts +2 -2
- package/document-management/server/module.js +3 -7
- package/document-management/server/schemas.d.ts +18 -23
- package/document-management/server/schemas.js +18 -23
- package/document-management/server/services/document-category-type.service.d.ts +25 -0
- package/document-management/server/services/document-category-type.service.js +66 -0
- package/document-management/server/services/document-collection.service.d.ts +13 -0
- package/document-management/server/services/document-collection.service.js +41 -0
- package/document-management/server/services/document-file.service.d.ts +17 -0
- package/document-management/server/services/document-file.service.js +204 -0
- package/document-management/server/services/document-management-ai.service.d.ts +22 -0
- package/document-management/server/services/document-management-ai.service.js +340 -0
- package/document-management/server/services/document-management-ancillary.service.d.ts +127 -3
- package/document-management/server/services/document-management-ancillary.service.js +24 -0
- package/document-management/server/services/document-management.service.d.ts +10 -122
- package/document-management/server/services/document-management.service.js +106 -888
- package/document-management/server/services/document-property.service.d.ts +84 -0
- package/document-management/server/services/document-property.service.js +87 -0
- package/document-management/server/services/document-request.service.d.ts +30 -0
- package/document-management/server/services/document-request.service.js +138 -0
- package/document-management/server/services/document-validation.service.d.ts +20 -0
- package/document-management/server/services/document-validation.service.js +145 -0
- package/document-management/server/services/document-workflow.service.d.ts +20 -0
- package/document-management/server/services/document-workflow.service.js +132 -0
- package/document-management/server/services/document.service.d.ts +16 -0
- package/document-management/server/services/document.service.js +81 -0
- package/document-management/server/services/index.d.ts +9 -0
- package/document-management/server/services/index.js +9 -0
- package/document-management/server/validators/ai-validation-executor.d.ts +19 -0
- package/document-management/server/validators/ai-validation-executor.js +51 -0
- package/document-management/server/validators/index.d.ts +2 -0
- package/document-management/server/validators/index.js +2 -0
- package/document-management/server/validators/single-document-validation-executor.d.ts +16 -0
- package/document-management/server/validators/single-document-validation-executor.js +20 -0
- package/document-management/server/validators/validator.d.ts +21 -0
- package/document-management/server/validators/validator.js +2 -0
- package/eslint.config.js +31 -17
- package/examples/document-management/main.d.ts +18 -3
- package/examples/document-management/main.js +28 -12
- package/file/mime-type.js +2 -9
- package/formats.d.ts +5 -2
- package/formats.js +32 -23
- package/http/client/http-client.js +1 -1
- package/injector/injector.js +2 -2
- package/object-storage/s3/s3.object-storage.js +1 -1
- package/orm/data-types/bytea.d.ts +8 -0
- package/orm/data-types/bytea.js +8 -0
- package/orm/data-types/index.d.ts +4 -0
- package/orm/data-types/index.js +4 -0
- package/orm/data-types/numeric-date.d.ts +9 -0
- package/orm/data-types/numeric-date.js +9 -0
- package/orm/data-types/timestamp.d.ts +9 -0
- package/orm/data-types/timestamp.js +9 -0
- package/orm/decorators.d.ts +139 -5
- package/orm/decorators.js +50 -0
- package/orm/entity.d.ts +19 -0
- package/orm/entity.js +19 -0
- package/orm/index.d.ts +5 -0
- package/orm/index.js +5 -0
- package/orm/query.d.ts +51 -0
- package/orm/query.js +6 -0
- package/orm/repository.types.d.ts +54 -2
- package/orm/server/database-schema.d.ts +34 -0
- package/orm/server/database-schema.js +29 -0
- package/orm/server/database.d.ts +19 -1
- package/orm/server/database.js +17 -3
- package/orm/server/drizzle/schema-converter.d.ts +2 -1
- package/orm/server/drizzle/schema-converter.js +12 -1
- package/orm/server/encryption.d.ts +16 -0
- package/orm/server/encryption.js +29 -4
- package/orm/server/index.d.ts +7 -0
- package/orm/server/index.js +7 -0
- package/orm/server/module.d.ts +20 -0
- package/orm/server/module.js +9 -0
- package/orm/server/query-converter.d.ts +17 -0
- package/orm/server/query-converter.js +66 -11
- package/orm/server/repository.d.ts +324 -18
- package/orm/server/repository.js +344 -73
- package/orm/server/transaction.d.ts +5 -5
- package/orm/server/transaction.js +5 -5
- package/orm/server/transactional.d.ts +75 -0
- package/orm/server/transactional.js +134 -0
- package/orm/server/types.d.ts +1 -0
- package/orm/sqls.d.ts +55 -0
- package/orm/sqls.js +60 -0
- package/orm/types.d.ts +67 -4
- package/orm/utils.d.ts +19 -3
- package/orm/utils.js +12 -0
- package/package.json +32 -31
- package/password/password-check-result.model.d.ts +9 -7
- package/password/password-check-result.model.js +8 -8
- package/password/password-check.js +5 -7
- package/password/password-check.localization.js +12 -12
- package/pdf/pdf.service.js +1 -1
- package/pdf/utils.d.ts +9 -0
- package/pdf/utils.js +19 -2
- package/process/spawn.d.ts +11 -4
- package/process/spawn.js +42 -5
- package/queue/postgres/queue.js +5 -5
- package/queue/queue.d.ts +6 -4
- package/queue/queue.js +6 -6
- package/schema/schemas/one-or-many.d.ts +2 -1
- package/schema/schemas/one-or-many.js +1 -1
- package/search-index/elastic/model/index-mapping.d.ts +1 -1
- package/search-index/elastic/model/index-mapping.js +0 -1
- package/search-index/elastic/search-index.d.ts +1 -2
- package/search-index/elastic/search-index.js +3 -3
- package/types.d.ts +1 -0
- package/utils/async-hook/async-hook.d.ts +9 -0
- package/utils/async-hook/async-hook.js +21 -0
- package/utils/async-hook/index.d.ts +1 -0
- package/utils/async-hook/index.js +1 -0
- package/utils/compression.js +1 -1
- package/utils/function/class.d.ts +6 -0
- package/utils/function/class.js +9 -0
- package/utils/function/index.d.ts +1 -0
- package/utils/function/index.js +1 -0
- package/utils/function/memoize.d.ts +18 -0
- package/utils/function/memoize.js +41 -2
- package/utils/jwt.d.ts +1 -1
- package/utils/jwt.js +5 -5
- package/utils/object/forward-ref.d.ts +3 -2
- package/utils/object/forward-ref.js +12 -12
- package/utils/object/lazy-property.js +2 -2
- package/utils/proxy.js +1 -1
- package/utils/stream/{readable-stream-from-promise.d.ts → from-promise.d.ts} +1 -0
- package/utils/stream/from-promise.js +27 -0
- package/utils/stream/index.d.ts +1 -1
- package/utils/stream/index.js +1 -1
- package/utils/stream/stream-reader.js +71 -31
- package/document-management/models/document-request-assignment-task-collection.model.d.ts +0 -7
- package/document-management/models/document-request-assignment-task.model.d.ts +0 -14
- package/document-management/models/document-request-assignment-task.model.js +0 -77
- package/document-management/models/document-request-file.model.d.ts +0 -16
- package/document-management/models/document-request-file.model.js +0 -86
- package/document-management/models/service-models/document.view-model.d.ts +0 -41
- package/document-management/models/service-models/normalized-document-collection-view.model.d.ts +0 -73
- package/document-management/models/service-models/normalized-document-collection-view.model.js +0 -110
- package/utils/stream/readable-stream-from-promise.js +0 -8
package/orm/server/repository.js
CHANGED
|
@@ -5,16 +5,11 @@ 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
|
-
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
-
};
|
|
11
8
|
import { and, asc, count, desc, eq, inArray, isNull, isSQLWrapper, SQL, sql } from 'drizzle-orm';
|
|
12
|
-
import {
|
|
13
|
-
import { createContextProvider } from '../../context/context.js';
|
|
9
|
+
import { match } from 'ts-pattern';
|
|
14
10
|
import { NotFoundError } from '../../errors/not-found.error.js';
|
|
15
11
|
import { Singleton } from '../../injector/decorators.js';
|
|
16
|
-
import {
|
|
17
|
-
import { inject, injectArgument, runInInjectionContext } from '../../injector/inject.js';
|
|
12
|
+
import { inject, injectArgument } from '../../injector/inject.js';
|
|
18
13
|
import { resolveArgumentType } from '../../injector/interfaces.js';
|
|
19
14
|
import { Schema } from '../../schema/schema.js';
|
|
20
15
|
import { toArray } from '../../utils/array/array.js';
|
|
@@ -26,80 +21,55 @@ import { fromDeepObjectEntries, fromEntries, objectEntries } from '../../utils/o
|
|
|
26
21
|
import { assertDefinedPass, isArray, isDefined, isString, isUndefined } from '../../utils/type-guards.js';
|
|
27
22
|
import { Entity } from '../entity.js';
|
|
28
23
|
import { TRANSACTION_TIMESTAMP } from '../sqls.js';
|
|
29
|
-
import {
|
|
30
|
-
import { getColumnDefinitions, getDrizzleTableFromType } from './drizzle/schema-converter.js';
|
|
24
|
+
import { getColumnDefinitions, getColumnDefinitionsMap, getDrizzleTableFromType } from './drizzle/schema-converter.js';
|
|
31
25
|
import { convertQuery } from './query-converter.js';
|
|
32
26
|
import { ENCRYPTION_SECRET } from './tokens.js';
|
|
33
|
-
import {
|
|
27
|
+
import { getTransactionalContextData, isInTransactionalContext, Transactional } from './transactional.js';
|
|
34
28
|
export const repositoryType = Symbol('repositoryType');
|
|
29
|
+
/**
|
|
30
|
+
* Configuration class for EntityRepository.
|
|
31
|
+
* Specifies the database schema to be used.
|
|
32
|
+
*/
|
|
35
33
|
export class EntityRepositoryConfig {
|
|
34
|
+
/** The name of the database schema. */
|
|
36
35
|
schema;
|
|
37
36
|
}
|
|
38
37
|
const entityTypeToken = Symbol('EntityType');
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
#
|
|
42
|
-
#injector = inject(Injector);
|
|
43
|
-
#repositoryConstructor;
|
|
44
|
-
#withTransactionCache = new WeakMap();
|
|
45
|
-
#encryptionSecret = isInEntityRepositoryContext() ? this.#context.encryptionSecret : inject(ENCRYPTION_SECRET, undefined, { optional: true });
|
|
38
|
+
let EntityRepository = class EntityRepository extends Transactional {
|
|
39
|
+
#context = isInTransactionalContext() ? getTransactionalContextData(this) : {};
|
|
40
|
+
#encryptionSecret = isInTransactionalContext() ? this.#context.encryptionSecret : inject(ENCRYPTION_SECRET, undefined, { optional: true });
|
|
46
41
|
#transformContext = this.#context.transformContext;
|
|
47
42
|
type = this.#context.type ?? injectArgument(this, { optional: true }) ?? assertDefinedPass(this.constructor[entityTypeToken], 'Missing entity type.');
|
|
48
43
|
typeName = this.type.entityName ?? this.type.name;
|
|
49
44
|
#table = this.#context.table ?? getDrizzleTableFromType(this.type, inject(EntityRepositoryConfig, undefined, { optional: true })?.schema);
|
|
50
45
|
#tableWithMetadata = this.#table;
|
|
51
46
|
#columnDefinitions = this.#context.columnDefinitions ?? getColumnDefinitions(this.#table);
|
|
52
|
-
#columnDefinitionsMap = this.#context.columnDefinitionsMap ??
|
|
53
|
-
session = this.#context.session ?? inject(Database);
|
|
54
|
-
isInTransaction = this.session instanceof DrizzlePgTransaction;
|
|
47
|
+
#columnDefinitionsMap = this.#context.columnDefinitionsMap ?? getColumnDefinitionsMap(this.#table);
|
|
55
48
|
hasMetadata = typeExtends(this.type, Entity);
|
|
49
|
+
/**
|
|
50
|
+
* Gets the Drizzle table definition for the entity type.
|
|
51
|
+
*/
|
|
56
52
|
get table() {
|
|
57
53
|
return this.#table;
|
|
58
54
|
}
|
|
59
|
-
|
|
60
|
-
return this.isInTransaction;
|
|
61
|
-
}
|
|
62
|
-
constructor() {
|
|
63
|
-
this.#repositoryConstructor = new.target;
|
|
64
|
-
}
|
|
65
|
-
withOptionalTransaction(transaction) {
|
|
66
|
-
if (isUndefined(transaction)) {
|
|
67
|
-
return this;
|
|
68
|
-
}
|
|
69
|
-
return this.withTransaction(transaction);
|
|
70
|
-
}
|
|
71
|
-
withTransaction(transaction) {
|
|
72
|
-
if (this.#withTransactionCache.has(transaction)) {
|
|
73
|
-
return this.#withTransactionCache.get(transaction);
|
|
74
|
-
}
|
|
55
|
+
getTransactionalContextData() {
|
|
75
56
|
const context = {
|
|
76
57
|
type: this.type,
|
|
77
58
|
table: this.#table,
|
|
78
59
|
columnDefinitions: this.#columnDefinitions,
|
|
79
60
|
columnDefinitionsMap: this.#columnDefinitionsMap,
|
|
80
|
-
session: transaction.transaction,
|
|
81
61
|
encryptionSecret: this.#encryptionSecret,
|
|
82
|
-
transformContext: this.#transformContext
|
|
62
|
+
transformContext: this.#transformContext,
|
|
83
63
|
};
|
|
84
|
-
|
|
85
|
-
this.#withTransactionCache.set(transaction, repositoryWithTransaction);
|
|
86
|
-
return repositoryWithTransaction;
|
|
87
|
-
}
|
|
88
|
-
async startTransaction(config) {
|
|
89
|
-
return DrizzleTransaction.create(this.session, config);
|
|
90
|
-
}
|
|
91
|
-
async useTransaction(transaction, handler) {
|
|
92
|
-
if (isUndefined(transaction)) {
|
|
93
|
-
return this.transaction(handler);
|
|
94
|
-
}
|
|
95
|
-
const repository = this.withTransaction(transaction);
|
|
96
|
-
return transaction.use(async () => handler(repository, transaction));
|
|
97
|
-
}
|
|
98
|
-
async transaction(handler, config) {
|
|
99
|
-
const transaction = await DrizzleTransaction.create(this.session, config);
|
|
100
|
-
const repository = this.withTransaction(transaction);
|
|
101
|
-
return transaction.use(async () => handler(repository, transaction));
|
|
64
|
+
return context;
|
|
102
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Loads a single entity by its ID.
|
|
68
|
+
* Throws `NotFoundError` if the entity is not found.
|
|
69
|
+
* @param id The ID of the entity to load.
|
|
70
|
+
* @returns A promise that resolves to the loaded entity.
|
|
71
|
+
* @throws {NotFoundError} If the entity with the given ID is not found.
|
|
72
|
+
*/
|
|
103
73
|
async load(id) {
|
|
104
74
|
const entity = await this.tryLoad(id);
|
|
105
75
|
if (isUndefined(entity)) {
|
|
@@ -107,9 +77,23 @@ let EntityRepository = class EntityRepository {
|
|
|
107
77
|
}
|
|
108
78
|
return entity;
|
|
109
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Tries to load a single entity by its ID.
|
|
82
|
+
* Returns `undefined` if the entity is not found.
|
|
83
|
+
* @param id The ID of the entity to load.
|
|
84
|
+
* @returns A promise that resolves to the loaded entity or `undefined` if not found.
|
|
85
|
+
*/
|
|
110
86
|
async tryLoad(id) {
|
|
111
87
|
return this.tryLoadByQuery(eq(this.#table.id, id));
|
|
112
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Loads a single entity based on a query.
|
|
91
|
+
* Throws `NotFoundError` if no entity matches the query.
|
|
92
|
+
* @param query The query to filter entities.
|
|
93
|
+
* @param options Optional loading options (e.g., offset, order).
|
|
94
|
+
* @returns A promise that resolves to the loaded entity.
|
|
95
|
+
* @throws {NotFoundError} If no entity matches the query.
|
|
96
|
+
*/
|
|
113
97
|
async loadByQuery(query, options) {
|
|
114
98
|
const entity = await this.tryLoadByQuery(query, options);
|
|
115
99
|
if (isUndefined(entity)) {
|
|
@@ -117,6 +101,13 @@ let EntityRepository = class EntityRepository {
|
|
|
117
101
|
}
|
|
118
102
|
return entity;
|
|
119
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Tries to load a single entity based on a query.
|
|
106
|
+
* Returns `undefined` if no entity matches the query.
|
|
107
|
+
* @param query The query to filter entities.
|
|
108
|
+
* @param options Optional loading options (e.g., offset, order).
|
|
109
|
+
* @returns A promise that resolves to the loaded entity or `undefined` if not found.
|
|
110
|
+
*/
|
|
120
111
|
async tryLoadByQuery(query, options) {
|
|
121
112
|
const sqlQuery = this.convertQuery(query);
|
|
122
113
|
let dbQuery = this.session.select()
|
|
@@ -133,39 +124,83 @@ let EntityRepository = class EntityRepository {
|
|
|
133
124
|
}
|
|
134
125
|
return this.mapToEntity(row);
|
|
135
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Loads multiple entities by their IDs.
|
|
129
|
+
* @param ids An array of entity IDs to load.
|
|
130
|
+
* @param options Optional loading options (e.g., offset, limit, order).
|
|
131
|
+
* @returns A promise that resolves to an array of loaded entities.
|
|
132
|
+
*/
|
|
136
133
|
async loadMany(ids, options) {
|
|
137
134
|
return this.loadManyByQuery(inArray(this.#table.id, ids), options);
|
|
138
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Loads multiple entities by their IDs and returns them as an async iterable cursor.
|
|
138
|
+
* @param ids An array of entity IDs to load.
|
|
139
|
+
* @param options Optional loading options (e.g., offset, limit, order).
|
|
140
|
+
* @returns An async iterable iterator of loaded entities.
|
|
141
|
+
*/
|
|
139
142
|
async *loadManyCursor(ids, options) {
|
|
140
143
|
const entities = await this.loadMany(ids, options);
|
|
141
144
|
yield* entities;
|
|
142
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* Loads multiple entities based on a query.
|
|
148
|
+
* @param query The query to filter entities.
|
|
149
|
+
* @param options Optional loading options (e.g., offset, limit, order).
|
|
150
|
+
* @returns A promise that resolves to an array of loaded entities.
|
|
151
|
+
*/
|
|
143
152
|
async loadManyByQuery(query, options) {
|
|
144
153
|
const sqlQuery = this.convertQuery(query);
|
|
145
|
-
let dbQuery =
|
|
154
|
+
let dbQuery = match(options?.distinct ?? false)
|
|
155
|
+
.with(false, () => this.session.select())
|
|
156
|
+
.with(true, () => this.session.selectDistinct())
|
|
157
|
+
.otherwise((targets) => {
|
|
158
|
+
const ons = targets.map((target) => isString(target) ? this.getColumn(target) : target);
|
|
159
|
+
return this.session.selectDistinctOn(ons);
|
|
160
|
+
})
|
|
146
161
|
.from(this.#table)
|
|
162
|
+
.$dynamic();
|
|
163
|
+
dbQuery = dbQuery
|
|
147
164
|
.where(sqlQuery)
|
|
148
|
-
.orderBy()
|
|
149
165
|
.offset(options?.offset)
|
|
150
|
-
.limit(options?.limit)
|
|
151
|
-
.$dynamic();
|
|
166
|
+
.limit(options?.limit);
|
|
152
167
|
if (isDefined(options?.order)) {
|
|
153
168
|
dbQuery = dbQuery.orderBy(...this.convertOrderBy(options.order));
|
|
154
169
|
}
|
|
155
170
|
const rows = await dbQuery;
|
|
156
171
|
return this.mapManyToEntity(rows);
|
|
157
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* Loads multiple entities based on a query and returns them as an async iterable cursor.
|
|
175
|
+
* @param query The query to filter entities.
|
|
176
|
+
* @param options Optional loading options (e.g., offset, limit, order).
|
|
177
|
+
* @returns An async iterable iterator of loaded entities.
|
|
178
|
+
*/
|
|
158
179
|
async *loadManyByQueryCursor(query, options) {
|
|
159
180
|
const entities = await this.loadManyByQuery(query, options);
|
|
160
181
|
yield* entities;
|
|
161
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* Loads all entities of the repository's type.
|
|
185
|
+
* @param options Optional loading options (e.g., offset, limit, order).
|
|
186
|
+
* @returns A promise that resolves to an array of all entities.
|
|
187
|
+
*/
|
|
162
188
|
async loadAll(options) {
|
|
163
189
|
return this.loadManyByQuery({}, options);
|
|
164
190
|
}
|
|
191
|
+
/**
|
|
192
|
+
* Loads all entities of the repository's type and returns them as an async iterable cursor.
|
|
193
|
+
* @param options Optional loading options (e.g., offset, limit, order).
|
|
194
|
+
* @returns An async iterable iterator of all entities.
|
|
195
|
+
*/
|
|
165
196
|
async *loadAllCursor(options) {
|
|
166
197
|
const entities = await this.loadAll(options);
|
|
167
198
|
yield* entities;
|
|
168
199
|
}
|
|
200
|
+
/**
|
|
201
|
+
* Counts the total number of entities of the repository's type.
|
|
202
|
+
* @returns A promise that resolves to the total count.
|
|
203
|
+
*/
|
|
169
204
|
async count() {
|
|
170
205
|
const sqlQuery = this.convertQuery({});
|
|
171
206
|
const dbQuery = this.session
|
|
@@ -175,6 +210,11 @@ let EntityRepository = class EntityRepository {
|
|
|
175
210
|
const [result] = await dbQuery;
|
|
176
211
|
return assertDefinedPass(result).count;
|
|
177
212
|
}
|
|
213
|
+
/**
|
|
214
|
+
* Counts the number of entities matching a query.
|
|
215
|
+
* @param query The query to filter entities.
|
|
216
|
+
* @returns A promise that resolves to the count of matching entities.
|
|
217
|
+
*/
|
|
178
218
|
async countByQuery(query) {
|
|
179
219
|
const sqlQuery = this.convertQuery(query);
|
|
180
220
|
const dbQuery = this.session
|
|
@@ -184,9 +224,19 @@ let EntityRepository = class EntityRepository {
|
|
|
184
224
|
const [result] = await dbQuery;
|
|
185
225
|
return assertDefinedPass(result).count;
|
|
186
226
|
}
|
|
227
|
+
/**
|
|
228
|
+
* Checks if an entity with the given ID exists.
|
|
229
|
+
* @param id The ID of the entity to check.
|
|
230
|
+
* @returns A promise that resolves to `true` if the entity exists, `false` otherwise.
|
|
231
|
+
*/
|
|
187
232
|
async has(id) {
|
|
188
233
|
return this.hasByQuery(eq(this.#table.id, id));
|
|
189
234
|
}
|
|
235
|
+
/**
|
|
236
|
+
* Checks if any entity matches the given query.
|
|
237
|
+
* @param query The query to filter entities.
|
|
238
|
+
* @returns A promise that resolves to `true` if at least one entity matches the query, `false` otherwise.
|
|
239
|
+
*/
|
|
190
240
|
async hasByQuery(query) {
|
|
191
241
|
const sqlQuery = this.convertQuery(query);
|
|
192
242
|
const dbQuery = this.session
|
|
@@ -195,6 +245,11 @@ let EntityRepository = class EntityRepository {
|
|
|
195
245
|
const [result] = await dbQuery;
|
|
196
246
|
return assertDefinedPass(result).exists;
|
|
197
247
|
}
|
|
248
|
+
/**
|
|
249
|
+
* Checks if all entities with the given IDs exist.
|
|
250
|
+
* @param ids An array of entity IDs to check.
|
|
251
|
+
* @returns A promise that resolves to `true` if all entities exist, `false` otherwise.
|
|
252
|
+
*/
|
|
198
253
|
async hasAll(ids) {
|
|
199
254
|
const sqlQuery = this.convertQuery({});
|
|
200
255
|
const result = await this.session
|
|
@@ -220,6 +275,11 @@ let EntityRepository = class EntityRepository {
|
|
|
220
275
|
}
|
|
221
276
|
return this.mapToEntity(row);
|
|
222
277
|
}
|
|
278
|
+
/**
|
|
279
|
+
* Inserts a new entity into the database.
|
|
280
|
+
* @param entity The entity to insert.
|
|
281
|
+
* @returns A promise that resolves to the inserted entity.
|
|
282
|
+
*/
|
|
223
283
|
async insert(entity) {
|
|
224
284
|
const columns = await this.mapToInsertColumns(entity);
|
|
225
285
|
const [row] = await this.session
|
|
@@ -228,11 +288,23 @@ let EntityRepository = class EntityRepository {
|
|
|
228
288
|
.returning();
|
|
229
289
|
return this.mapToEntity(row);
|
|
230
290
|
}
|
|
291
|
+
/**
|
|
292
|
+
* Inserts multiple new entities into the database.
|
|
293
|
+
* @param entities An array of entities to insert.
|
|
294
|
+
* @returns A promise that resolves to an array of the inserted entities.
|
|
295
|
+
*/
|
|
231
296
|
async insertMany(entities) {
|
|
232
297
|
const columns = await this.mapManyToInsertColumns(entities);
|
|
233
298
|
const rows = await this.session.insert(this.#table).values(columns).returning();
|
|
234
299
|
return this.mapManyToEntity(rows);
|
|
235
300
|
}
|
|
301
|
+
/**
|
|
302
|
+
* Inserts an entity or updates it if a conflict occurs based on the target columns.
|
|
303
|
+
* @param target The column(s) to use for conflict detection.
|
|
304
|
+
* @param entity The entity to insert.
|
|
305
|
+
* @param update Optional update to apply if a conflict occurs. Defaults to the inserted entity's values.
|
|
306
|
+
* @returns A promise that resolves to the inserted or updated entity.
|
|
307
|
+
*/
|
|
236
308
|
async upsert(target, entity, update) {
|
|
237
309
|
const targetColumns = toArray(target).map((path) => this.getColumn(path));
|
|
238
310
|
const columns = await this.mapToInsertColumns(entity);
|
|
@@ -242,11 +314,18 @@ let EntityRepository = class EntityRepository {
|
|
|
242
314
|
.values(columns)
|
|
243
315
|
.onConflictDoUpdate({
|
|
244
316
|
target: targetColumns,
|
|
245
|
-
set: mappedUpdate
|
|
317
|
+
set: mappedUpdate,
|
|
246
318
|
})
|
|
247
319
|
.returning();
|
|
248
320
|
return this.mapToEntity(row);
|
|
249
321
|
}
|
|
322
|
+
/**
|
|
323
|
+
* Inserts multiple entities or updates them if a conflict occurs based on the target columns.
|
|
324
|
+
* @param target The column(s) to use for conflict detection.
|
|
325
|
+
* @param entities An array of entities to insert.
|
|
326
|
+
* @param update Optional update to apply if a conflict occurs. Defaults to the inserted entity's values.
|
|
327
|
+
* @returns A promise that resolves to an array of the inserted or updated entities.
|
|
328
|
+
*/
|
|
250
329
|
async upsertMany(target, entities, update) {
|
|
251
330
|
const targetColumns = toArray(target).map((path) => this.getColumn(path));
|
|
252
331
|
const columns = await this.mapManyToInsertColumns(entities);
|
|
@@ -254,18 +333,26 @@ let EntityRepository = class EntityRepository {
|
|
|
254
333
|
? await this.mapUpdate(update)
|
|
255
334
|
: {
|
|
256
335
|
...fromEntries(this.#columnDefinitions.map((column) => [column.name, sql `excluded.${sql.identifier(this.getColumn(column).name)}`])),
|
|
257
|
-
...this._getMetadataUpdate(update)
|
|
336
|
+
...this._getMetadataUpdate(update),
|
|
258
337
|
};
|
|
259
338
|
const rows = await this.session
|
|
260
339
|
.insert(this.#table)
|
|
261
340
|
.values(columns)
|
|
262
341
|
.onConflictDoUpdate({
|
|
263
342
|
target: targetColumns,
|
|
264
|
-
set: mappedUpdate
|
|
343
|
+
set: mappedUpdate,
|
|
265
344
|
})
|
|
266
345
|
.returning();
|
|
267
346
|
return this.mapManyToEntity(rows);
|
|
268
347
|
}
|
|
348
|
+
/**
|
|
349
|
+
* Updates an entity by its ID.
|
|
350
|
+
* Throws `NotFoundError` if the entity is not found.
|
|
351
|
+
* @param id The ID of the entity to update.
|
|
352
|
+
* @param update The update to apply to the entity.
|
|
353
|
+
* @returns A promise that resolves to the updated entity.
|
|
354
|
+
* @throws {NotFoundError} If the entity with the given ID is not found.
|
|
355
|
+
*/
|
|
269
356
|
async update(id, update) {
|
|
270
357
|
const entity = await this.tryUpdate(id, update);
|
|
271
358
|
if (isUndefined(entity)) {
|
|
@@ -273,6 +360,13 @@ let EntityRepository = class EntityRepository {
|
|
|
273
360
|
}
|
|
274
361
|
return entity;
|
|
275
362
|
}
|
|
363
|
+
/**
|
|
364
|
+
* Tries to update an entity by its ID.
|
|
365
|
+
* Returns `undefined` if the entity is not found.
|
|
366
|
+
* @param id The ID of the entity to update.
|
|
367
|
+
* @param update The update to apply to the entity.
|
|
368
|
+
* @returns A promise that resolves to the updated entity or `undefined` if not found.
|
|
369
|
+
*/
|
|
276
370
|
async tryUpdate(id, update) {
|
|
277
371
|
const sqlQuery = this.convertQuery(eq(this.#table.id, id));
|
|
278
372
|
const mappedUpdate = await this.mapUpdate(update);
|
|
@@ -286,6 +380,14 @@ let EntityRepository = class EntityRepository {
|
|
|
286
380
|
}
|
|
287
381
|
return this.mapToEntity(row);
|
|
288
382
|
}
|
|
383
|
+
/**
|
|
384
|
+
* Updates a single entity matching a query.
|
|
385
|
+
* Throws `NotFoundError` if no entity matches the query.
|
|
386
|
+
* @param query The query to filter entities.
|
|
387
|
+
* @param update The update to apply to the entity.
|
|
388
|
+
* @returns A promise that resolves to the updated entity.
|
|
389
|
+
* @throws {NotFoundError} If no entity matches the query.
|
|
390
|
+
*/
|
|
289
391
|
async updateByQuery(query, update) {
|
|
290
392
|
const entity = await this.tryUpdateByQuery(query, update);
|
|
291
393
|
if (isUndefined(entity)) {
|
|
@@ -293,6 +395,13 @@ let EntityRepository = class EntityRepository {
|
|
|
293
395
|
}
|
|
294
396
|
return entity;
|
|
295
397
|
}
|
|
398
|
+
/**
|
|
399
|
+
* Tries to update a single entity matching a query.
|
|
400
|
+
* Returns `undefined` if no entity matches the query.
|
|
401
|
+
* @param query The query to filter entities.
|
|
402
|
+
* @param update The update to apply to the entity.
|
|
403
|
+
* @returns A promise that resolves to the updated entity or `undefined` if not found.
|
|
404
|
+
*/
|
|
296
405
|
async tryUpdateByQuery(query, update) {
|
|
297
406
|
const mappedUpdate = await this.mapUpdate(update);
|
|
298
407
|
const idQuery = this.getIdLimitSelect(query);
|
|
@@ -306,9 +415,21 @@ let EntityRepository = class EntityRepository {
|
|
|
306
415
|
}
|
|
307
416
|
return this.mapToEntity(row);
|
|
308
417
|
}
|
|
418
|
+
/**
|
|
419
|
+
* Updates multiple entities by their IDs.
|
|
420
|
+
* @param ids An array of entity IDs to update.
|
|
421
|
+
* @param update The update to apply to the entities.
|
|
422
|
+
* @returns A promise that resolves to an array of the updated entities.
|
|
423
|
+
*/
|
|
309
424
|
async updateMany(ids, update) {
|
|
310
425
|
return this.updateManyByQuery(inArray(this.#table.id, ids), update);
|
|
311
426
|
}
|
|
427
|
+
/**
|
|
428
|
+
* Updates multiple entities matching a query.
|
|
429
|
+
* @param query The query to filter entities.
|
|
430
|
+
* @param update The update to apply to the entities.
|
|
431
|
+
* @returns A promise that resolves to an array of the updated entities.
|
|
432
|
+
*/
|
|
312
433
|
async updateManyByQuery(query, update) {
|
|
313
434
|
const sqlQuery = this.convertQuery(query);
|
|
314
435
|
const mappedUpdate = await this.mapUpdate(update);
|
|
@@ -319,6 +440,14 @@ let EntityRepository = class EntityRepository {
|
|
|
319
440
|
.returning();
|
|
320
441
|
return this.mapManyToEntity(rows);
|
|
321
442
|
}
|
|
443
|
+
/**
|
|
444
|
+
* Deletes an entity by its ID (soft delete if metadata is available).
|
|
445
|
+
* Throws `NotFoundError` if the entity is not found.
|
|
446
|
+
* @param id The ID of the entity to delete.
|
|
447
|
+
* @param metadataUpdate Optional metadata update to apply during soft delete.
|
|
448
|
+
* @returns A promise that resolves to the deleted entity.
|
|
449
|
+
* @throws {NotFoundError} If the entity with the given ID is not found.
|
|
450
|
+
*/
|
|
322
451
|
async delete(id, metadataUpdate) {
|
|
323
452
|
const entity = await this.tryDelete(id, metadataUpdate);
|
|
324
453
|
if (isUndefined(entity)) {
|
|
@@ -326,6 +455,13 @@ let EntityRepository = class EntityRepository {
|
|
|
326
455
|
}
|
|
327
456
|
return entity;
|
|
328
457
|
}
|
|
458
|
+
/**
|
|
459
|
+
* Tries to delete an entity by its ID (soft delete if metadata is available).
|
|
460
|
+
* Returns `undefined` if the entity is not found.
|
|
461
|
+
* @param id The ID of the entity to delete.
|
|
462
|
+
* @param metadataUpdate Optional metadata update to apply during soft delete.
|
|
463
|
+
* @returns A promise that resolves to the deleted entity or `undefined` if not found.
|
|
464
|
+
*/
|
|
329
465
|
async tryDelete(id, metadataUpdate) {
|
|
330
466
|
if (!this.hasMetadata) {
|
|
331
467
|
return this.tryHardDelete(id);
|
|
@@ -335,7 +471,7 @@ let EntityRepository = class EntityRepository {
|
|
|
335
471
|
.update(this.#tableWithMetadata)
|
|
336
472
|
.set({
|
|
337
473
|
deleteTimestamp: TRANSACTION_TIMESTAMP,
|
|
338
|
-
attributes: this.getAttributesUpdate(metadataUpdate?.attributes)
|
|
474
|
+
attributes: this.getAttributesUpdate(metadataUpdate?.attributes),
|
|
339
475
|
})
|
|
340
476
|
.where(sqlQuery)
|
|
341
477
|
.returning();
|
|
@@ -344,6 +480,14 @@ let EntityRepository = class EntityRepository {
|
|
|
344
480
|
}
|
|
345
481
|
return this.mapToEntity(row);
|
|
346
482
|
}
|
|
483
|
+
/**
|
|
484
|
+
* Deletes a single entity matching a query (soft delete if metadata is available).
|
|
485
|
+
* Throws `NotFoundError` if no entity matches the query.
|
|
486
|
+
* @param query The query to filter entities.
|
|
487
|
+
* @param metadataUpdate Optional metadata update to apply during soft delete.
|
|
488
|
+
* @returns A promise that resolves to the deleted entity.
|
|
489
|
+
* @throws {NotFoundError} If no entity matches the query.
|
|
490
|
+
*/
|
|
347
491
|
async deleteByQuery(query, metadataUpdate) {
|
|
348
492
|
const entity = await this.tryDeleteByQuery(query, metadataUpdate);
|
|
349
493
|
if (isUndefined(entity)) {
|
|
@@ -351,6 +495,13 @@ let EntityRepository = class EntityRepository {
|
|
|
351
495
|
}
|
|
352
496
|
return entity;
|
|
353
497
|
}
|
|
498
|
+
/**
|
|
499
|
+
* Tries to delete a single entity matching a query (soft delete if metadata is available).
|
|
500
|
+
* Returns `undefined` if no entity matches the query.
|
|
501
|
+
* @param query The query to filter entities.
|
|
502
|
+
* @param metadataUpdate Optional metadata update to apply during soft delete.
|
|
503
|
+
* @returns A promise that resolves to the deleted entity or `undefined` if not found.
|
|
504
|
+
*/
|
|
354
505
|
async tryDeleteByQuery(query, metadataUpdate) {
|
|
355
506
|
if (!this.hasMetadata) {
|
|
356
507
|
return this.tryHardDeleteByQuery(query);
|
|
@@ -360,7 +511,7 @@ let EntityRepository = class EntityRepository {
|
|
|
360
511
|
.update(this.#tableWithMetadata)
|
|
361
512
|
.set({
|
|
362
513
|
deleteTimestamp: TRANSACTION_TIMESTAMP,
|
|
363
|
-
attributes: this.getAttributesUpdate(metadataUpdate?.attributes)
|
|
514
|
+
attributes: this.getAttributesUpdate(metadataUpdate?.attributes),
|
|
364
515
|
})
|
|
365
516
|
.where(inArray(this.#table.id, idQuery.for('update')))
|
|
366
517
|
.returning();
|
|
@@ -369,9 +520,21 @@ let EntityRepository = class EntityRepository {
|
|
|
369
520
|
}
|
|
370
521
|
return this.mapToEntity(row);
|
|
371
522
|
}
|
|
523
|
+
/**
|
|
524
|
+
* Deletes multiple entities by their IDs (soft delete if metadata is available).
|
|
525
|
+
* @param ids An array of entity IDs to delete.
|
|
526
|
+
* @param metadataUpdate Optional metadata update to apply during soft delete.
|
|
527
|
+
* @returns A promise that resolves to an array of the deleted entities.
|
|
528
|
+
*/
|
|
372
529
|
async deleteMany(ids, metadataUpdate) {
|
|
373
530
|
return this.deleteManyByQuery(inArray(this.#table.id, ids), metadataUpdate);
|
|
374
531
|
}
|
|
532
|
+
/**
|
|
533
|
+
* Deletes multiple entities matching a query (soft delete if metadata is available).
|
|
534
|
+
* @param query The query to filter entities.
|
|
535
|
+
* @param metadataUpdate Optional metadata update to apply during soft delete.
|
|
536
|
+
* @returns A promise that resolves to an array of the deleted entities.
|
|
537
|
+
*/
|
|
375
538
|
async deleteManyByQuery(query, metadataUpdate) {
|
|
376
539
|
if (!this.hasMetadata) {
|
|
377
540
|
return this.hardDeleteManyByQuery(query);
|
|
@@ -381,12 +544,19 @@ let EntityRepository = class EntityRepository {
|
|
|
381
544
|
.update(this.#tableWithMetadata)
|
|
382
545
|
.set({
|
|
383
546
|
deleteTimestamp: TRANSACTION_TIMESTAMP,
|
|
384
|
-
attributes: this.getAttributesUpdate(metadataUpdate?.attributes)
|
|
547
|
+
attributes: this.getAttributesUpdate(metadataUpdate?.attributes),
|
|
385
548
|
})
|
|
386
549
|
.where(sqlQuery)
|
|
387
550
|
.returning();
|
|
388
551
|
return this.mapManyToEntity(rows);
|
|
389
552
|
}
|
|
553
|
+
/**
|
|
554
|
+
* Hard deletes an entity by its ID (removes from the database).
|
|
555
|
+
* Throws `NotFoundError` if the entity is not found.
|
|
556
|
+
* @param id The ID of the entity to hard delete.
|
|
557
|
+
* @returns A promise that resolves to the hard deleted entity.
|
|
558
|
+
* @throws {NotFoundError} If the entity with the given ID is not found.
|
|
559
|
+
*/
|
|
390
560
|
async hardDelete(id) {
|
|
391
561
|
const result = await this.tryHardDelete(id);
|
|
392
562
|
if (!result) {
|
|
@@ -394,6 +564,12 @@ let EntityRepository = class EntityRepository {
|
|
|
394
564
|
}
|
|
395
565
|
return result;
|
|
396
566
|
}
|
|
567
|
+
/**
|
|
568
|
+
* Tries to hard delete an entity by its ID (removes from the database).
|
|
569
|
+
* Returns `undefined` if the entity is not found.
|
|
570
|
+
* @param id The ID of the entity to hard delete.
|
|
571
|
+
* @returns A promise that resolves to the hard deleted entity or `undefined` if not found.
|
|
572
|
+
*/
|
|
397
573
|
async tryHardDelete(id) {
|
|
398
574
|
const sqlQuery = this.convertQuery(eq(this.#table.id, id));
|
|
399
575
|
const [row] = await this.session
|
|
@@ -405,6 +581,13 @@ let EntityRepository = class EntityRepository {
|
|
|
405
581
|
}
|
|
406
582
|
return this.mapToEntity(row);
|
|
407
583
|
}
|
|
584
|
+
/**
|
|
585
|
+
* Hard deletes a single entity matching a query (removes from the database).
|
|
586
|
+
* Throws `NotFoundError` if no entity matches the query.
|
|
587
|
+
* @param query The query to filter entities.
|
|
588
|
+
* @returns A promise that resolves to the hard deleted entity.
|
|
589
|
+
* @throws {NotFoundError} If no entity matches the query.
|
|
590
|
+
*/
|
|
408
591
|
async hardDeleteByQuery(query) {
|
|
409
592
|
const result = await this.tryHardDeleteByQuery(query);
|
|
410
593
|
if (!result) {
|
|
@@ -412,6 +595,12 @@ let EntityRepository = class EntityRepository {
|
|
|
412
595
|
}
|
|
413
596
|
return result;
|
|
414
597
|
}
|
|
598
|
+
/**
|
|
599
|
+
* Tries to hard delete a single entity matching a query (removes from the database).
|
|
600
|
+
* Returns `undefined` if no entity matches the query.
|
|
601
|
+
* @param query The query to filter entities.
|
|
602
|
+
* @returns A promise that resolves to the hard deleted entity or `undefined` if not found.
|
|
603
|
+
*/
|
|
415
604
|
async tryHardDeleteByQuery(query) {
|
|
416
605
|
const idQuery = this.getIdLimitSelect(query);
|
|
417
606
|
const [row] = await this.session
|
|
@@ -423,9 +612,19 @@ let EntityRepository = class EntityRepository {
|
|
|
423
612
|
}
|
|
424
613
|
return this.mapToEntity(row);
|
|
425
614
|
}
|
|
615
|
+
/**
|
|
616
|
+
* Hard deletes multiple entities by their IDs (removes from the database).
|
|
617
|
+
* @param ids An array of entity IDs to hard delete.
|
|
618
|
+
* @returns A promise that resolves to an array of the hard deleted entities.
|
|
619
|
+
*/
|
|
426
620
|
async hardDeleteMany(ids) {
|
|
427
621
|
return this.hardDeleteManyByQuery(inArray(this.#table.id, ids));
|
|
428
622
|
}
|
|
623
|
+
/**
|
|
624
|
+
* Hard deletes multiple entities matching a query (removes from the database).
|
|
625
|
+
* @param query The query to filter entities.
|
|
626
|
+
* @returns A promise that resolves to an array of the hard deleted entities.
|
|
627
|
+
*/
|
|
429
628
|
async hardDeleteManyByQuery(query) {
|
|
430
629
|
const sqlQuery = this.convertQuery(query);
|
|
431
630
|
const rows = await this.session
|
|
@@ -434,6 +633,11 @@ let EntityRepository = class EntityRepository {
|
|
|
434
633
|
.returning();
|
|
435
634
|
return this.mapManyToEntity(rows);
|
|
436
635
|
}
|
|
636
|
+
/**
|
|
637
|
+
* Retrieves the Drizzle PgColumn for a given object path or column definition.
|
|
638
|
+
* @param pathOrColumn The object path or column definition.
|
|
639
|
+
* @returns The corresponding PgColumn.
|
|
640
|
+
*/
|
|
437
641
|
getColumn(pathOrColumn) {
|
|
438
642
|
if (isString(pathOrColumn)) {
|
|
439
643
|
const columnName = assertDefinedPass(this.#columnDefinitionsMap.get(pathOrColumn), `Could not map ${pathOrColumn} to column.`).name;
|
|
@@ -441,6 +645,14 @@ let EntityRepository = class EntityRepository {
|
|
|
441
645
|
}
|
|
442
646
|
return this.#table[pathOrColumn.name];
|
|
443
647
|
}
|
|
648
|
+
getColumns(pathOrColumns) {
|
|
649
|
+
return pathOrColumns.map((column) => this.getColumn(column));
|
|
650
|
+
}
|
|
651
|
+
/**
|
|
652
|
+
* Converts an Order object to an array of Drizzle SQL order expressions.
|
|
653
|
+
* @param order The order object.
|
|
654
|
+
* @returns An array of SQL order expressions.
|
|
655
|
+
*/
|
|
444
656
|
convertOrderBy(order) {
|
|
445
657
|
if (isArray(order)) {
|
|
446
658
|
return order.map((item) => {
|
|
@@ -460,6 +672,13 @@ let EntityRepository = class EntityRepository {
|
|
|
460
672
|
return direction == 'asc' ? asc(column) : desc(column);
|
|
461
673
|
});
|
|
462
674
|
}
|
|
675
|
+
/**
|
|
676
|
+
* Converts a Query object to a Drizzle SQL where clause.
|
|
677
|
+
* Automatically filters out soft-deleted entities unless `withDeleted` is true.
|
|
678
|
+
* @param query The query object.
|
|
679
|
+
* @param options Optional options, including `withDeleted` to include soft-deleted entities.
|
|
680
|
+
* @returns A Drizzle SQL condition.
|
|
681
|
+
*/
|
|
463
682
|
convertQuery(query, options) {
|
|
464
683
|
let sql = convertQuery(query, this.#table, this.#columnDefinitionsMap);
|
|
465
684
|
if (!this.hasMetadata || (options?.withDeleted == true)) {
|
|
@@ -467,34 +686,75 @@ let EntityRepository = class EntityRepository {
|
|
|
467
686
|
}
|
|
468
687
|
return and(isNull(this.#tableWithMetadata.deleteTimestamp), sql);
|
|
469
688
|
}
|
|
689
|
+
/**
|
|
690
|
+
* Maps multiple database rows to an array of entities.
|
|
691
|
+
* @param columns An array of database rows.
|
|
692
|
+
* @returns A promise that resolves to an array of entities.
|
|
693
|
+
*/
|
|
470
694
|
async mapManyToEntity(columns) {
|
|
471
695
|
const transformContext = await this.getTransformContext();
|
|
472
696
|
return this._mapManyToEntity(columns, transformContext);
|
|
473
697
|
}
|
|
698
|
+
/**
|
|
699
|
+
* Maps a single database row to an entity.
|
|
700
|
+
* @param columns A database row.
|
|
701
|
+
* @returns A promise that resolves to an entity.
|
|
702
|
+
*/
|
|
474
703
|
async mapToEntity(columns) {
|
|
475
704
|
const transformContext = await this.getTransformContext();
|
|
476
705
|
return this._mapToEntity(columns, transformContext);
|
|
477
706
|
}
|
|
707
|
+
/**
|
|
708
|
+
* Maps multiple entity-like objects to database column values for insertion or update.
|
|
709
|
+
* @param objects An array of entity-like objects.
|
|
710
|
+
* @returns A promise that resolves to an array of database column values.
|
|
711
|
+
*/
|
|
478
712
|
async mapManyToColumns(objects) {
|
|
479
713
|
const transformContext = await this.getTransformContext();
|
|
480
714
|
return this._mapManyToColumns(objects, transformContext);
|
|
481
715
|
}
|
|
716
|
+
/**
|
|
717
|
+
* Maps a single entity-like object to database column values for insertion or update.
|
|
718
|
+
* @param obj An entity-like object.
|
|
719
|
+
* @returns A promise that resolves to database column values.
|
|
720
|
+
*/
|
|
482
721
|
async mapToColumns(obj) {
|
|
483
722
|
const transformContext = await this.getTransformContext();
|
|
484
723
|
return this._mapToColumns(obj, transformContext);
|
|
485
724
|
}
|
|
725
|
+
/**
|
|
726
|
+
* Maps multiple new entity objects to database column values for insertion.
|
|
727
|
+
* @param objects An array of new entity objects.
|
|
728
|
+
* @returns A promise that resolves to an array of database column values for insertion.
|
|
729
|
+
*/
|
|
486
730
|
async mapManyToInsertColumns(objects) {
|
|
487
731
|
const transformContext = await this.getTransformContext();
|
|
488
732
|
return this._mapManyToInsertColumns(objects, transformContext);
|
|
489
733
|
}
|
|
734
|
+
/**
|
|
735
|
+
* Maps a new entity object to database column values for insertion.
|
|
736
|
+
* @param obj A new entity object.
|
|
737
|
+
* @returns A promise that resolves to database column values for insertion.
|
|
738
|
+
*/
|
|
490
739
|
async mapToInsertColumns(obj) {
|
|
491
740
|
const transformContext = await this.getTransformContext();
|
|
492
741
|
return this._mapToInsertColumns(obj, transformContext);
|
|
493
742
|
}
|
|
743
|
+
/**
|
|
744
|
+
* Maps an entity update object to database column values for updating.
|
|
745
|
+
* @param update The entity update object.
|
|
746
|
+
* @returns A promise that resolves to database column values for updating.
|
|
747
|
+
*/
|
|
494
748
|
async mapUpdate(update) {
|
|
495
749
|
const transformContext = await this.getTransformContext();
|
|
496
750
|
return this._mapUpdate(update, transformContext);
|
|
497
751
|
}
|
|
752
|
+
/**
|
|
753
|
+
* Gets a Drizzle select query for the ID of a single entity matching the provided query, limited to 1 result.
|
|
754
|
+
* Useful for subqueries in update/delete operations targeting a single entity.
|
|
755
|
+
* @param query The query to filter entities.
|
|
756
|
+
* @returns A Drizzle select query for the entity ID.
|
|
757
|
+
*/
|
|
498
758
|
getIdLimitQuery(query) {
|
|
499
759
|
return this.getIdLimitSelect(query);
|
|
500
760
|
}
|
|
@@ -542,9 +802,9 @@ let EntityRepository = class EntityRepository {
|
|
|
542
802
|
? {
|
|
543
803
|
revision: 1,
|
|
544
804
|
revisionTimestamp: TRANSACTION_TIMESTAMP,
|
|
545
|
-
createTimestamp: TRANSACTION_TIMESTAMP
|
|
805
|
+
createTimestamp: TRANSACTION_TIMESTAMP,
|
|
546
806
|
}
|
|
547
|
-
: undefined)
|
|
807
|
+
: undefined),
|
|
548
808
|
};
|
|
549
809
|
}
|
|
550
810
|
async _mapUpdate(update, transformContext) {
|
|
@@ -558,7 +818,7 @@ let EntityRepository = class EntityRepository {
|
|
|
558
818
|
}
|
|
559
819
|
return {
|
|
560
820
|
...mappedUpdate,
|
|
561
|
-
...this._getMetadataUpdate(update)
|
|
821
|
+
...this._getMetadataUpdate(update),
|
|
562
822
|
};
|
|
563
823
|
}
|
|
564
824
|
_getMetadataUpdate(update) {
|
|
@@ -566,7 +826,7 @@ let EntityRepository = class EntityRepository {
|
|
|
566
826
|
? {
|
|
567
827
|
attributes: this.getAttributesUpdate(update?.metadata?.attributes),
|
|
568
828
|
revision: sql `${this.#tableWithMetadata.revision} + 1`,
|
|
569
|
-
revisionTimestamp: TRANSACTION_TIMESTAMP
|
|
829
|
+
revisionTimestamp: TRANSACTION_TIMESTAMP,
|
|
570
830
|
}
|
|
571
831
|
: undefined;
|
|
572
832
|
}
|
|
@@ -591,19 +851,30 @@ let EntityRepository = class EntityRepository {
|
|
|
591
851
|
}
|
|
592
852
|
};
|
|
593
853
|
EntityRepository = __decorate([
|
|
594
|
-
Singleton()
|
|
595
|
-
__metadata("design:paramtypes", [])
|
|
854
|
+
Singleton()
|
|
596
855
|
], EntityRepository);
|
|
597
856
|
export { EntityRepository };
|
|
857
|
+
/**
|
|
858
|
+
* Injects an EntityRepository instance for the specified entity type.
|
|
859
|
+
* @template T The entity type.
|
|
860
|
+
* @param type The entity type.
|
|
861
|
+
* @returns An EntityRepository instance for the specified type.
|
|
862
|
+
*/
|
|
598
863
|
export function injectRepository(type) {
|
|
599
864
|
return inject((EntityRepository), type);
|
|
600
865
|
}
|
|
866
|
+
/**
|
|
867
|
+
* Gets or creates a singleton EntityRepository class for the specified entity type.
|
|
868
|
+
* @template T The entity type.
|
|
869
|
+
* @param type The entity type.
|
|
870
|
+
* @returns A singleton EntityRepository class for the specified type.
|
|
871
|
+
*/
|
|
601
872
|
export function getRepository(type) {
|
|
602
873
|
const className = `${type.name}Service`;
|
|
603
874
|
const entityRepositoryClass = {
|
|
604
875
|
[className]: class extends EntityRepository {
|
|
605
876
|
static [entityTypeToken] = type;
|
|
606
|
-
}
|
|
877
|
+
},
|
|
607
878
|
}[className];
|
|
608
879
|
Singleton()(entityRepositoryClass);
|
|
609
880
|
return entityRepositoryClass;
|