@tstdl/base 0.93.140 → 0.93.142
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/application/application.d.ts +1 -1
- package/application/application.js +1 -1
- package/application/providers.d.ts +20 -2
- package/application/providers.js +34 -7
- package/audit/module.d.ts +5 -0
- package/audit/module.js +9 -1
- package/authentication/client/authentication.service.d.ts +1 -0
- package/authentication/client/authentication.service.js +3 -2
- package/authentication/server/module.d.ts +5 -0
- package/authentication/server/module.js +9 -1
- package/authentication/tests/authentication.api-controller.test.js +1 -1
- package/authentication/tests/authentication.api-request-token.provider.test.js +1 -1
- package/authentication/tests/authentication.client-service.test.js +1 -1
- package/circuit-breaker/circuit-breaker.d.ts +6 -4
- package/circuit-breaker/postgres/circuit-breaker.d.ts +1 -0
- package/circuit-breaker/postgres/circuit-breaker.js +8 -5
- package/circuit-breaker/postgres/module.d.ts +1 -0
- package/circuit-breaker/postgres/module.js +5 -1
- package/circuit-breaker/tests/circuit-breaker.test.js +20 -0
- package/document-management/server/configure.js +5 -1
- package/document-management/server/module.d.ts +1 -1
- package/document-management/server/module.js +1 -1
- package/document-management/server/services/document-management-ancillary.service.js +1 -1
- package/document-management/tests/ai-config-hierarchy.test.js +0 -5
- package/document-management/tests/document-management-ai-overrides.test.js +0 -1
- package/document-management/tests/document-validation-ai-overrides.test.js +0 -1
- package/examples/document-management/main.d.ts +1 -0
- package/examples/document-management/main.js +14 -11
- package/key-value-store/postgres/module.d.ts +1 -0
- package/key-value-store/postgres/module.js +5 -1
- package/lock/postgres/module.d.ts +1 -0
- package/lock/postgres/module.js +5 -1
- package/mail/module.d.ts +5 -1
- package/mail/module.js +11 -6
- package/module/modules/web-server.module.js +2 -3
- package/notification/server/module.d.ts +1 -0
- package/notification/server/module.js +5 -1
- package/notification/tests/notification-api.test.js +5 -1
- package/notification/tests/notification-flow.test.js +8 -5
- package/orm/decorators.d.ts +22 -5
- package/orm/decorators.js +10 -1
- package/orm/server/bootstrap.d.ts +11 -0
- package/orm/server/bootstrap.js +31 -0
- package/orm/server/drizzle/schema-converter.d.ts +3 -1
- package/orm/server/drizzle/schema-converter.js +85 -56
- package/orm/server/encryption.d.ts +0 -1
- package/orm/server/encryption.js +1 -4
- package/orm/server/extension.d.ts +14 -0
- package/orm/server/extension.js +27 -0
- package/orm/server/index.d.ts +3 -6
- package/orm/server/index.js +3 -6
- package/orm/server/migration.d.ts +18 -0
- package/orm/server/migration.js +58 -0
- package/orm/server/repository.d.ts +2 -1
- package/orm/server/repository.js +19 -9
- package/orm/server/transaction.d.ts +6 -10
- package/orm/server/transaction.js +25 -26
- package/orm/server/transactional.js +3 -3
- package/orm/tests/database-extension.test.js +63 -0
- package/orm/tests/database-migration.test.js +83 -0
- package/orm/tests/encryption.test.js +3 -4
- package/orm/tests/repository-compound-primary-key.test.d.ts +2 -0
- package/orm/tests/repository-compound-primary-key.test.js +234 -0
- package/orm/tests/schema-generation.test.d.ts +1 -0
- package/orm/tests/schema-generation.test.js +52 -5
- package/orm/utils.d.ts +17 -2
- package/orm/utils.js +49 -1
- package/package.json +5 -4
- package/rate-limit/postgres/module.d.ts +1 -0
- package/rate-limit/postgres/module.js +5 -1
- package/reflection/decorator-data.js +11 -12
- package/task-queue/README.md +2 -10
- package/task-queue/postgres/drizzle/0000_great_gwen_stacy.sql +84 -0
- package/task-queue/postgres/drizzle/meta/0000_snapshot.json +250 -89
- package/task-queue/postgres/drizzle/meta/_journal.json +2 -2
- package/task-queue/postgres/module.d.ts +1 -0
- package/task-queue/postgres/module.js +6 -1
- package/task-queue/postgres/schemas.d.ts +15 -6
- package/task-queue/postgres/schemas.js +4 -3
- package/task-queue/postgres/task-queue.d.ts +18 -15
- package/task-queue/postgres/task-queue.js +797 -499
- package/task-queue/postgres/task.model.d.ts +20 -9
- package/task-queue/postgres/task.model.js +65 -39
- package/task-queue/task-context.d.ts +12 -7
- package/task-queue/task-context.js +8 -6
- package/task-queue/task-queue.d.ts +364 -43
- package/task-queue/task-queue.js +153 -41
- package/task-queue/tests/coverage-branch.test.d.ts +1 -0
- package/task-queue/tests/coverage-branch.test.js +395 -0
- package/task-queue/tests/coverage-enhancement.test.d.ts +1 -0
- package/task-queue/tests/coverage-enhancement.test.js +150 -0
- package/task-queue/tests/dag.test.d.ts +1 -0
- package/task-queue/tests/dag.test.js +188 -0
- package/task-queue/tests/dependencies.test.js +165 -47
- package/task-queue/tests/enqueue-batch.test.d.ts +1 -0
- package/task-queue/tests/enqueue-batch.test.js +125 -0
- package/task-queue/tests/fan-out-spawning.test.d.ts +1 -0
- package/task-queue/tests/fan-out-spawning.test.js +94 -0
- package/task-queue/tests/idempotent-replacement.test.d.ts +1 -0
- package/task-queue/tests/idempotent-replacement.test.js +114 -0
- package/task-queue/tests/missing-idempotent-tasks.test.d.ts +1 -0
- package/task-queue/tests/missing-idempotent-tasks.test.js +39 -0
- package/task-queue/tests/queue.test.js +294 -49
- package/task-queue/tests/shutdown.test.d.ts +1 -0
- package/task-queue/tests/shutdown.test.js +41 -0
- package/task-queue/tests/transactions.test.d.ts +1 -0
- package/task-queue/tests/transactions.test.js +47 -0
- package/task-queue/tests/worker.test.js +63 -15
- package/task-queue/tests/zombie-parent.test.d.ts +1 -0
- package/task-queue/tests/zombie-parent.test.js +45 -0
- package/task-queue/tests/zombie-recovery.test.d.ts +1 -0
- package/task-queue/tests/zombie-recovery.test.js +51 -0
- package/test5.js +5 -5
- package/testing/integration-setup.d.ts +4 -4
- package/testing/integration-setup.js +56 -29
- package/text/localization.service.js +2 -2
- package/utils/file-reader.js +1 -2
- package/utils/timing.d.ts +2 -2
- package/task-queue/postgres/drizzle/0000_simple_invisible_woman.sql +0 -74
- package/task-queue/tests/complex.test.js +0 -306
- package/task-queue/tests/extensive-dependencies.test.js +0 -234
- /package/{task-queue/tests/complex.test.d.ts → orm/tests/database-extension.test.d.ts} +0 -0
- /package/{task-queue/tests/extensive-dependencies.test.d.ts → orm/tests/database-migration.test.d.ts} +0 -0
package/mail/module.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Injector } from '../injector/injector.js';
|
|
1
2
|
import { type DatabaseConfig } from '../orm/server/index.js';
|
|
2
3
|
import type { Type } from '../types/index.js';
|
|
3
4
|
import { MailClient, MailClientConfig } from './mail.client.js';
|
|
@@ -7,9 +8,12 @@ export declare class MailModuleConfig {
|
|
|
7
8
|
defaultClientConfig?: MailClientConfig;
|
|
8
9
|
client?: Type<MailClient>;
|
|
9
10
|
defaultData?: DefaultMailData;
|
|
11
|
+
autoMigrate?: boolean;
|
|
10
12
|
}
|
|
11
13
|
/**
|
|
12
14
|
* configure mail module
|
|
13
15
|
*/
|
|
14
|
-
export declare function configureMail(config: MailModuleConfig
|
|
16
|
+
export declare function configureMail({ injector, ...config }: MailModuleConfig & {
|
|
17
|
+
injector?: Injector;
|
|
18
|
+
}): void;
|
|
15
19
|
export declare function migrateMailSchema(): Promise<void>;
|
package/mail/module.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { inject } from '../injector/index.js';
|
|
2
2
|
import { Injector } from '../injector/injector.js';
|
|
3
|
-
import { Database, migrate } from '../orm/server/index.js';
|
|
3
|
+
import { Database, migrate, registerDatabaseMigration } from '../orm/server/index.js';
|
|
4
4
|
import { isDefined } from '../utils/type-guards.js';
|
|
5
5
|
import { MailClient, MailClientConfig } from './mail.client.js';
|
|
6
6
|
import { MAIL_DEFAULT_DATA } from './tokens.js';
|
|
@@ -9,20 +9,25 @@ export class MailModuleConfig {
|
|
|
9
9
|
defaultClientConfig;
|
|
10
10
|
client;
|
|
11
11
|
defaultData;
|
|
12
|
+
autoMigrate;
|
|
12
13
|
}
|
|
13
14
|
/**
|
|
14
15
|
* configure mail module
|
|
15
16
|
*/
|
|
16
|
-
export function configureMail(config) {
|
|
17
|
-
|
|
17
|
+
export function configureMail({ injector, ...config }) {
|
|
18
|
+
const targetInjector = injector ?? Injector;
|
|
19
|
+
targetInjector.register(MailModuleConfig, { useValue: config });
|
|
18
20
|
if (isDefined(config.defaultClientConfig)) {
|
|
19
|
-
|
|
21
|
+
targetInjector.registerSingleton(MailClientConfig, { useValue: config.defaultClientConfig });
|
|
20
22
|
}
|
|
21
23
|
if (isDefined(config.client)) {
|
|
22
|
-
|
|
24
|
+
targetInjector.registerSingleton(MailClient, { useToken: config.client });
|
|
23
25
|
}
|
|
24
26
|
if (isDefined(config.defaultData)) {
|
|
25
|
-
|
|
27
|
+
targetInjector.registerSingleton(MAIL_DEFAULT_DATA, { useValue: config.defaultData });
|
|
28
|
+
}
|
|
29
|
+
if (config.autoMigrate != false) {
|
|
30
|
+
registerDatabaseMigration('Mail', migrateMailSchema, { injector });
|
|
26
31
|
}
|
|
27
32
|
}
|
|
28
33
|
export async function migrateMailSchema() {
|
|
@@ -18,7 +18,7 @@ export class WebServerModuleConfiguration {
|
|
|
18
18
|
}
|
|
19
19
|
;
|
|
20
20
|
let WebServerModule = class WebServerModule extends Module {
|
|
21
|
-
config = inject(WebServerModuleConfiguration);
|
|
21
|
+
config = inject(WebServerModuleConfiguration, undefined, { optional: true });
|
|
22
22
|
httpServer = inject(HttpServer);
|
|
23
23
|
apiGateway = inject(ApiGateway);
|
|
24
24
|
apiControllers = inject(API_CONTROLLERS);
|
|
@@ -37,7 +37,7 @@ let WebServerModule = class WebServerModule extends Module {
|
|
|
37
37
|
}
|
|
38
38
|
async _run(cancellationSignal) {
|
|
39
39
|
this.initialize();
|
|
40
|
-
await this.httpServer.listen(this.config
|
|
40
|
+
await this.httpServer.listen(this.config?.port ?? 8000);
|
|
41
41
|
const closePromise = cancellationSignal.wait().then(async () => {
|
|
42
42
|
await this.httpServer[Symbol.asyncDispose]();
|
|
43
43
|
});
|
|
@@ -58,5 +58,4 @@ export { WebServerModule };
|
|
|
58
58
|
export function configureWebServerModule({ injector, ...config } = {}) {
|
|
59
59
|
const targetInjector = injector ?? Injector;
|
|
60
60
|
targetInjector.register(WebServerModuleConfiguration, { useValue: config });
|
|
61
|
-
targetInjector.registerSingleton(WebServerModule, { useClass: WebServerModule });
|
|
62
61
|
}
|
|
@@ -11,6 +11,7 @@ export declare class NotificationConfiguration {
|
|
|
11
11
|
* Defaults to 30 days.
|
|
12
12
|
*/
|
|
13
13
|
autoArchiveAfter?: number;
|
|
14
|
+
autoMigrate?: boolean;
|
|
14
15
|
}
|
|
15
16
|
export declare function configureNotification({ injector, ...config }: NotificationConfiguration & {
|
|
16
17
|
injector?: Injector;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { inject, Injector } from '../../injector/index.js';
|
|
2
|
-
import { Database, migrate } from '../../orm/server/index.js';
|
|
2
|
+
import { Database, migrate, registerDatabaseMigration } from '../../orm/server/index.js';
|
|
3
3
|
import { isDefined } from '../../utils/type-guards.js';
|
|
4
4
|
import { NotificationAncillaryService } from './services/notification-ancillary.service.js';
|
|
5
5
|
export class NotificationConfiguration {
|
|
@@ -11,6 +11,7 @@ export class NotificationConfiguration {
|
|
|
11
11
|
* Defaults to 30 days.
|
|
12
12
|
*/
|
|
13
13
|
autoArchiveAfter;
|
|
14
|
+
autoMigrate;
|
|
14
15
|
}
|
|
15
16
|
export function configureNotification({ injector, ...config }) {
|
|
16
17
|
const targetInjector = injector ?? Injector;
|
|
@@ -18,6 +19,9 @@ export function configureNotification({ injector, ...config }) {
|
|
|
18
19
|
if (isDefined(config.ancillaryService)) {
|
|
19
20
|
targetInjector.register(NotificationAncillaryService, { useToken: config.ancillaryService });
|
|
20
21
|
}
|
|
22
|
+
if (config.autoMigrate != false) {
|
|
23
|
+
registerDatabaseMigration('Notification', migrateNotificationSchema, { injector });
|
|
24
|
+
}
|
|
21
25
|
}
|
|
22
26
|
/**
|
|
23
27
|
* Migrates the notification schema.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Subject } from 'rxjs';
|
|
2
|
-
import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
|
|
2
|
+
import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
|
|
3
3
|
import { SubjectService } from '../../authentication/server/subject.service.js';
|
|
4
4
|
import { clearTenantData, setupIntegrationTest } from '../../testing/index.js';
|
|
5
5
|
import { NotificationChannel } from '../models/index.js';
|
|
@@ -44,6 +44,10 @@ describe('Notification API (Integration)', () => {
|
|
|
44
44
|
beforeEach(() => {
|
|
45
45
|
vi.clearAllMocks();
|
|
46
46
|
});
|
|
47
|
+
afterEach(async () => {
|
|
48
|
+
await clearTenantData(database, schema, ['in_app', 'in_app_archive', 'log', 'preference', 'web_push_subscription'], tenantId);
|
|
49
|
+
await clearTenantData(database, 'authentication', ['user', 'subject'], tenantId);
|
|
50
|
+
});
|
|
47
51
|
const createMockContext = (params = {}) => ({
|
|
48
52
|
parameters: params,
|
|
49
53
|
abortSignal: new AbortController().signal,
|
|
@@ -4,12 +4,12 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
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;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
|
|
7
|
+
import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
|
|
8
8
|
import { SubjectService } from '../../authentication/server/subject.service.js';
|
|
9
9
|
import { runInInjectionContext, Singleton } from '../../injector/index.js';
|
|
10
10
|
import { MailService } from '../../mail/mail.service.js';
|
|
11
11
|
import { injectRepository } from '../../orm/server/index.js';
|
|
12
|
-
import { clearTenantData, setupIntegrationTest
|
|
12
|
+
import { clearTenantData, setupIntegrationTest } from '../../testing/index.js';
|
|
13
13
|
import { InAppNotification, NotificationChannel, NotificationLogEntity, NotificationStatus, WebPushSubscription } from '../models/index.js';
|
|
14
14
|
import { configureNotification } from '../server/module.js';
|
|
15
15
|
import { EmailChannelProvider } from '../server/providers/email-channel-provider.js';
|
|
@@ -34,7 +34,7 @@ describe('Notification Flow (Integration)', () => {
|
|
|
34
34
|
let subjectService;
|
|
35
35
|
let mailServiceMock;
|
|
36
36
|
const schema = 'notification';
|
|
37
|
-
|
|
37
|
+
let tenantId;
|
|
38
38
|
beforeAll(async () => {
|
|
39
39
|
({ injector, database } = await setupIntegrationTest({
|
|
40
40
|
orm: { schema },
|
|
@@ -63,10 +63,13 @@ describe('Notification Flow (Integration)', () => {
|
|
|
63
63
|
worker.registerProvider(NotificationChannel.InApp, injector.resolve(InAppChannelProvider));
|
|
64
64
|
});
|
|
65
65
|
beforeEach(async () => {
|
|
66
|
-
|
|
67
|
-
await clearTenantData(database, 'authentication', ['user', 'subject'], tenantId);
|
|
66
|
+
tenantId = crypto.randomUUID();
|
|
68
67
|
vi.clearAllMocks();
|
|
69
68
|
});
|
|
69
|
+
afterEach(async () => {
|
|
70
|
+
await clearTenantData(database, schema, ['in_app', 'in_app_archive', 'log', 'preference', 'web_push_subscription'], tenantId);
|
|
71
|
+
await clearTenantData(database, 'authentication', ['user', 'subject'], tenantId);
|
|
72
|
+
});
|
|
70
73
|
test('should execute full notification flow with escalation', async () => {
|
|
71
74
|
await runInInjectionContext(injector, async () => {
|
|
72
75
|
const logRepo = injectRepository(NotificationLogEntity);
|
package/orm/decorators.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Defines decorators for ORM entities and columns, used to configure database schema mapping.
|
|
4
4
|
*/
|
|
5
5
|
import type { SQL } from 'drizzle-orm';
|
|
6
|
-
import type { ExtraConfigColumn } from 'drizzle-orm/pg-core';
|
|
6
|
+
import type { ExtraConfigColumn, UpdateDeleteAction } from 'drizzle-orm/pg-core';
|
|
7
7
|
import type { LiteralUnion, SetRequired } from 'type-fest';
|
|
8
8
|
import { type SpecificCreateDecoratorOptions } from '../reflection/index.js';
|
|
9
9
|
import type { AbstractConstructor, Record, TypedOmit } from '../types/index.js';
|
|
@@ -40,8 +40,7 @@ export type WhereBuilder<T extends BaseEntity = BaseEntity> = SqlBuilder<T, Quer
|
|
|
40
40
|
export type OrmTableReflectionData<T extends BaseEntity = BaseEntity> = {
|
|
41
41
|
name?: string;
|
|
42
42
|
schema?: string;
|
|
43
|
-
|
|
44
|
-
compoundPrimaryKeyNaming?: NamingStrategy;
|
|
43
|
+
primaryKey?: PrimaryKeyReflectionData<T>;
|
|
45
44
|
unique?: UniqueReflectionData[];
|
|
46
45
|
index?: IndexReflectionData[];
|
|
47
46
|
paradeIndex?: ParadeIndexReflectionData<T>;
|
|
@@ -87,12 +86,21 @@ type ReferenceReflectionData<T extends AnyEntity = AnyEntity> = {
|
|
|
87
86
|
target: () => EntityType<T>;
|
|
88
87
|
targetColumn?: TargetColumnPath<T>;
|
|
89
88
|
excludeTenant?: boolean;
|
|
89
|
+
onDelete?: UpdateDeleteAction;
|
|
90
|
+
onUpdate?: UpdateDeleteAction;
|
|
91
|
+
};
|
|
92
|
+
export type PrimaryKeyReflectionData<T extends BaseEntity = any> = {
|
|
93
|
+
columns?: ValueOrProvider<(TargetColumnPath<T> | SQL | ExtraConfigColumn)[], ExtraConfigColumnsFromType<EntityType<T>>>;
|
|
94
|
+
options?: {
|
|
95
|
+
name?: string;
|
|
96
|
+
naming?: NamingStrategy;
|
|
97
|
+
};
|
|
90
98
|
};
|
|
91
99
|
/**
|
|
92
100
|
* Reflection data for unique constraints.
|
|
93
101
|
*/
|
|
94
|
-
export type UniqueReflectionData = {
|
|
95
|
-
columns?:
|
|
102
|
+
export type UniqueReflectionData<T extends BaseEntity = any> = {
|
|
103
|
+
columns?: ValueOrProvider<(TargetColumnPath<T> | SQL | ExtraConfigColumn)[], ExtraConfigColumnsFromType<EntityType<T>>>;
|
|
96
104
|
options?: {
|
|
97
105
|
name?: string;
|
|
98
106
|
naming?: NamingStrategy;
|
|
@@ -122,6 +130,8 @@ export type ForeignKeyReflectionData = {
|
|
|
122
130
|
options?: {
|
|
123
131
|
name?: string;
|
|
124
132
|
naming?: NamingStrategy;
|
|
133
|
+
onDelete?: UpdateDeleteAction;
|
|
134
|
+
onUpdate?: UpdateDeleteAction;
|
|
125
135
|
};
|
|
126
136
|
};
|
|
127
137
|
export type IndexOptions<T extends BaseEntity> = {
|
|
@@ -290,6 +300,13 @@ export declare function Table(name?: string, options?: TableOptions): ClassDecor
|
|
|
290
300
|
* @param options Table options including name and schema.
|
|
291
301
|
*/
|
|
292
302
|
export declare function Table(options?: TableOptions): ClassDecorator;
|
|
303
|
+
/**
|
|
304
|
+
* Define a composite primary key on multiple columns.
|
|
305
|
+
* @template T The entity type.
|
|
306
|
+
* @param columns An array of property names included in the primary key.
|
|
307
|
+
* @param options Additional primary key options.
|
|
308
|
+
*/
|
|
309
|
+
export declare function PrimaryKey<T extends AnyEntity>(columns: Columns<T>, options?: PrimaryKeyReflectionData['options']): ClassDecorator;
|
|
293
310
|
/**
|
|
294
311
|
* Define a foreign key relationship.
|
|
295
312
|
* @param target A function returning the referenced entity type.
|
package/orm/decorators.js
CHANGED
|
@@ -71,7 +71,7 @@ export function PrimaryKeyProperty() {
|
|
|
71
71
|
export function Reference(target, targetColumnOrOptions) {
|
|
72
72
|
const targetColumn = (isString(targetColumnOrOptions) ? targetColumnOrOptions : targetColumnOrOptions?.targetColumn);
|
|
73
73
|
const options = isString(targetColumnOrOptions) ? undefined : targetColumnOrOptions;
|
|
74
|
-
return createColumnDecorator({ references: [{ target, targetColumn, excludeTenant: options?.excludeTenant }] });
|
|
74
|
+
return createColumnDecorator({ references: [{ target, targetColumn, excludeTenant: options?.excludeTenant, onDelete: options?.onDelete, onUpdate: options?.onUpdate }] });
|
|
75
75
|
}
|
|
76
76
|
export {
|
|
77
77
|
/** @deprecated use {@link Reference} instead. */
|
|
@@ -113,6 +113,15 @@ export function Table(nameOrOptions, optionsOrNothing) {
|
|
|
113
113
|
: filterUndefinedObjectProperties({ name, schema });
|
|
114
114
|
return createTableDecorator(data);
|
|
115
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Define a composite primary key on multiple columns.
|
|
118
|
+
* @template T The entity type.
|
|
119
|
+
* @param columns An array of property names included in the primary key.
|
|
120
|
+
* @param options Additional primary key options.
|
|
121
|
+
*/
|
|
122
|
+
export function PrimaryKey(columns, options) {
|
|
123
|
+
return createTableDecorator({ primaryKey: { columns, options } });
|
|
124
|
+
}
|
|
116
125
|
/**
|
|
117
126
|
* Define a foreign key relationship.
|
|
118
127
|
* @param target A function returning the referenced entity type.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type ProvidersItem } from '../../injector/injector.js';
|
|
2
|
+
/**
|
|
3
|
+
* Provides the ORM bootstrap functionality by returning an initializer provider.
|
|
4
|
+
* This will run database extensions and migrations during application startup.
|
|
5
|
+
* @returns A provider item.
|
|
6
|
+
*/
|
|
7
|
+
export declare function provideOrm(): ProvidersItem;
|
|
8
|
+
/**
|
|
9
|
+
* Bootstraps the ORM by running database extensions and migrations within an advisory lock.
|
|
10
|
+
*/
|
|
11
|
+
export declare function bootstrapOrm(): Promise<void>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { sql } from 'drizzle-orm';
|
|
2
|
+
import { provideInitializer } from '../../application/providers.js';
|
|
3
|
+
import { inject, runInInjectionContext } from '../../injector/inject.js';
|
|
4
|
+
import { Injector } from '../../injector/injector.js';
|
|
5
|
+
import { Database } from './database.js';
|
|
6
|
+
import { runDatabaseExtensions } from './extension.js';
|
|
7
|
+
import { runDatabaseMigrationsCore } from './migration.js';
|
|
8
|
+
/**
|
|
9
|
+
* Provides the ORM bootstrap functionality by returning an initializer provider.
|
|
10
|
+
* This will run database extensions and migrations during application startup.
|
|
11
|
+
* @returns A provider item.
|
|
12
|
+
*/
|
|
13
|
+
export function provideOrm() {
|
|
14
|
+
return provideInitializer(bootstrapOrm);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Bootstraps the ORM by running database extensions and migrations within an advisory lock.
|
|
18
|
+
*/
|
|
19
|
+
export async function bootstrapOrm() {
|
|
20
|
+
const injector = inject(Injector);
|
|
21
|
+
const database = inject(Database);
|
|
22
|
+
const lockId = 123456789; // Fixed lock ID for database setup
|
|
23
|
+
await database.execute(sql `SELECT pg_advisory_lock(${lockId})`);
|
|
24
|
+
try {
|
|
25
|
+
await runInInjectionContext(injector, async () => await runDatabaseExtensions());
|
|
26
|
+
await runInInjectionContext(injector, async () => await runDatabaseMigrationsCore());
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
await database.execute(sql `SELECT pg_advisory_unlock(${lockId})`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type PgEnum, type PgSchema, type PgTableWithColumns } from 'drizzle-orm/pg-core';
|
|
1
|
+
import { type PgColumn, type PgEnum, type PgSchema, type PgTableWithColumns } from 'drizzle-orm/pg-core';
|
|
2
2
|
import type { AbstractConstructor, Enumeration } from '../../../types/index.js';
|
|
3
3
|
import { type EntityType } from '../../entity.js';
|
|
4
4
|
import type { ColumnDefinition, ColumnDefinitionsMap, PgTableFromType } from '../types.js';
|
|
@@ -13,4 +13,6 @@ export declare function getColumnDefinitionsMap(table: PgTableWithColumns<any>):
|
|
|
13
13
|
export declare function _getDrizzleTableFromType<T extends EntityType, S extends string>(type: T, fallbackSchemaName?: S): PgTableFromType<T, S>;
|
|
14
14
|
export declare function isTableOwning(type: AbstractConstructor): boolean;
|
|
15
15
|
export declare function getPgEnum(schema: string | PgSchema, enumeration: Enumeration, context?: ConverterContext): PgEnum<[string, ...string[]]>;
|
|
16
|
+
export declare function getPrimaryKeyColumnDefinitions(type: EntityType, table: PgTableFromType, columnDefinitions?: ColumnDefinition[], columnDefinitionsMap?: ColumnDefinitionsMap): ColumnDefinition[];
|
|
17
|
+
export declare function getPrimaryKeyColumns(type: EntityType, table: PgTableFromType, columnDefinitions?: ColumnDefinition[], columnDefinitionsMap?: ColumnDefinitionsMap): PgColumn[];
|
|
16
18
|
export {};
|
|
@@ -15,13 +15,13 @@ import { typeExtends } from '../../../utils/index.js';
|
|
|
15
15
|
import { merge } from '../../../utils/merge.js';
|
|
16
16
|
import { compileDereferencer } from '../../../utils/object/dereference.js';
|
|
17
17
|
import { fromEntries, mapObjectKeysToSnakeCase, objectEntries } from '../../../utils/object/object.js';
|
|
18
|
-
import { assertDefined, assertDefinedPass, isArray, isDefined, isNotNull,
|
|
18
|
+
import { assertDefined, assertDefinedPass, isArray, isDefined, isNotNull, isNull, isString, isUndefined } from '../../../utils/type-guards.js';
|
|
19
19
|
import { resolveValueOrProvider } from '../../../utils/value-or-provider.js';
|
|
20
20
|
import { bytea, numericDate, timestamp, tsvector } from '../../data-types/index.js';
|
|
21
21
|
import { TenantBaseEntity, TenantEntity } from '../../entity.js';
|
|
22
22
|
import { getEnumName } from '../../enums.js';
|
|
23
23
|
import { JsonSchema, NumericDateSchema, NumericSchema, TimestampSchema, TsVectorSchema, UuidSchema } from '../../schemas/index.js';
|
|
24
|
-
import { getInheritanceMetadata, isChildEntity } from '../../utils.js';
|
|
24
|
+
import { getEntitySchema, getEntityTableName, getInheritanceMetadata, getTableReflectionDatas, isChildEntity } from '../../utils.js';
|
|
25
25
|
import { decryptBytes, encryptBytes } from '../encryption.js';
|
|
26
26
|
import { convertQuery, resolveTargetColumn, resolveTargetColumns } from '../query-converter.js';
|
|
27
27
|
const getDbSchema = memoizeSingle(pgSchema);
|
|
@@ -42,13 +42,18 @@ export function getColumnDefinitionsMap(table) {
|
|
|
42
42
|
export function _getDrizzleTableFromType(type, fallbackSchemaName) {
|
|
43
43
|
const tableReflectionDatas = getTableReflectionDatas(type);
|
|
44
44
|
const mergedTableReflectionData = tableReflectionDatas.reduceRight((merged, data) => ({ ...merged, ...data }), {});
|
|
45
|
-
const schema =
|
|
46
|
-
const tableName =
|
|
45
|
+
const schema = getEntitySchema(type, fallbackSchemaName);
|
|
46
|
+
const tableName = getEntityTableName(type);
|
|
47
47
|
const dbSchema = getDbSchema(schema);
|
|
48
48
|
const inheritanceMetadata = getInheritanceMetadata(type);
|
|
49
49
|
const allColumnDefinitions = getPostgresColumnEntries(type, dbSchema, tableName, undefined, '', { filterInherited: false }, type);
|
|
50
|
+
const primaryKeyPropertyNames = new Set(isDefined(mergedTableReflectionData.primaryKey?.columns)
|
|
51
|
+
? resolveValueOrProvider(mergedTableReflectionData.primaryKey.columns, {}).filter((c) => isString(c))
|
|
52
|
+
: []);
|
|
50
53
|
const columnDefinitions = allColumnDefinitions.filter((cd) => !isChildEntity(type)
|
|
51
54
|
|| !cd.inherited
|
|
55
|
+
|| (cd.reflectionData?.primaryKey == true)
|
|
56
|
+
|| primaryKeyPropertyNames.has(cd.objectPath.path)
|
|
52
57
|
|| (cd.objectPath.path == 'id')
|
|
53
58
|
|| (cd.objectPath.path == 'tenantId')
|
|
54
59
|
|| (cd.objectPath.path == inheritanceMetadata?.discriminatorColumn));
|
|
@@ -100,23 +105,43 @@ export function _getDrizzleTableFromType(type, fallbackSchemaName) {
|
|
|
100
105
|
}
|
|
101
106
|
return builder;
|
|
102
107
|
}
|
|
103
|
-
function
|
|
104
|
-
const inheritanceMetadata =
|
|
108
|
+
function getInheritanceColumns(inheritanceTable, inheritanceType) {
|
|
109
|
+
const inheritanceMetadata = getInheritanceMetadata(inheritanceType);
|
|
105
110
|
const discriminatorColumn = inheritanceMetadata.discriminatorColumn;
|
|
106
|
-
const
|
|
111
|
+
const pkColumnDefinitions = getPrimaryKeyColumnDefinitions(inheritanceType, inheritanceTable, columnDefinitions, columnDefinitionsMap);
|
|
112
|
+
const discriminatorColumnObject = inheritanceTable[discriminatorColumn];
|
|
113
|
+
const hasTenantId = pkColumnDefinitions.some((d) => d.objectPath.path == 'tenantId');
|
|
114
|
+
const tenantIdColumn = hasTenantId ? inheritanceTable['tenantId'] : undefined;
|
|
107
115
|
const columns = [
|
|
108
|
-
...(
|
|
109
|
-
|
|
110
|
-
|
|
116
|
+
...(isDefined(tenantIdColumn) ? [tenantIdColumn] : []),
|
|
117
|
+
discriminatorColumnObject,
|
|
118
|
+
...pkColumnDefinitions.filter((d) => d.objectPath.path != 'tenantId').map((d) => inheritanceTable[d.name]),
|
|
119
|
+
];
|
|
120
|
+
const identifierParts = [
|
|
121
|
+
...(hasTenantId ? ['tenantId'] : []),
|
|
122
|
+
discriminatorColumn,
|
|
123
|
+
...pkColumnDefinitions.filter((d) => d.objectPath.path != 'tenantId').map((d) => d.objectPath.path),
|
|
111
124
|
];
|
|
125
|
+
return { columns, identifierParts };
|
|
126
|
+
}
|
|
127
|
+
function buildInheritanceCompositeUniqueConstraint(table) {
|
|
128
|
+
const { columns } = getInheritanceColumns(table, type);
|
|
112
129
|
return unique(getUniqueName(tableName, columns)).on(...columns);
|
|
113
130
|
}
|
|
114
131
|
function buildPrimaryKey(table) {
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
132
|
+
const primaryKeyData = mergedTableReflectionData.primaryKey;
|
|
133
|
+
const resolvedColumns = isDefined(primaryKeyData?.columns) ? resolveValueOrProvider(primaryKeyData.columns, table) : undefined;
|
|
134
|
+
const columns = match(resolvedColumns)
|
|
135
|
+
.with(P.nonNullable, (primaryColumns) => primaryColumns.map((columnValue) => {
|
|
136
|
+
if (columnValue instanceof SQL) {
|
|
137
|
+
return columnValue;
|
|
138
|
+
}
|
|
139
|
+
return getColumn(table, columnValue);
|
|
140
|
+
}))
|
|
141
|
+
.with(undefined, () => getPrimaryKeyColumns(type, table, columnDefinitions, columnDefinitionsMap))
|
|
142
|
+
.exhaustive();
|
|
118
143
|
return primaryKey({
|
|
119
|
-
name:
|
|
144
|
+
name: primaryKeyData?.options?.name ?? getPrimaryKeyName(tableName, columns, { naming: primaryKeyData?.options?.naming }),
|
|
120
145
|
columns,
|
|
121
146
|
});
|
|
122
147
|
}
|
|
@@ -128,22 +153,14 @@ export function _getDrizzleTableFromType(type, fallbackSchemaName) {
|
|
|
128
153
|
constraints.push(buildInheritanceCompositeUniqueConstraint(table));
|
|
129
154
|
}
|
|
130
155
|
if (isDefined(inheritanceMetadata) && isDefined(childEntityMetadata)) {
|
|
131
|
-
const
|
|
156
|
+
const parentType = reflectionRegistry.getMetadata(type).parent;
|
|
157
|
+
const parentTable = getDrizzleTableFromType(parentType, schema);
|
|
158
|
+
const { columns: foreignKeyColumns, identifierParts: foreignKeyIdentifierParts } = getInheritanceColumns(table, type);
|
|
159
|
+
const { columns: parentForeignKeyColumns } = getInheritanceColumns(parentTable, parentType);
|
|
132
160
|
constraints.push(check(getIdentifier(tableName, discriminatorColumn, 'check'), eq(table[discriminatorColumn], sql.raw(`'${childEntityMetadata.discriminatorValue}'`))), foreignKey({
|
|
133
|
-
name: getForeignKeyName(tableName,
|
|
134
|
-
columns:
|
|
135
|
-
|
|
136
|
-
table[discriminatorColumn],
|
|
137
|
-
table['id'],
|
|
138
|
-
],
|
|
139
|
-
foreignColumns: (() => {
|
|
140
|
-
const parentTable = getDrizzleTableFromType(reflectionRegistry.getMetadata(type).parent, schema);
|
|
141
|
-
return [
|
|
142
|
-
...(hasTenantId ? [parentTable['tenantId']] : []),
|
|
143
|
-
parentTable[discriminatorColumn],
|
|
144
|
-
parentTable.id,
|
|
145
|
-
];
|
|
146
|
-
})(),
|
|
161
|
+
name: getForeignKeyName(tableName, getEntityTableName(parentType), foreignKeyIdentifierParts),
|
|
162
|
+
columns: foreignKeyColumns,
|
|
163
|
+
foreignColumns: parentForeignKeyColumns,
|
|
147
164
|
}).onDelete('cascade'));
|
|
148
165
|
}
|
|
149
166
|
return constraints;
|
|
@@ -222,7 +239,7 @@ export function _getDrizzleTableFromType(type, fallbackSchemaName) {
|
|
|
222
239
|
return builder;
|
|
223
240
|
}
|
|
224
241
|
const primaryKeyColumnDefinitions = columnDefinitions.filter((columnDefinition) => (columnDefinition.reflectionData?.primaryKey == true) || (columnDefinition.objectPath.path == 'id' && columnDefinition.reflectionData?.primaryKey != false));
|
|
225
|
-
const skipPrimaryKey = primaryKeyColumnDefinitions.length > 1;
|
|
242
|
+
const skipPrimaryKey = (primaryKeyColumnDefinitions.length > 1) || isDefined(mergedTableReflectionData.primaryKey?.columns);
|
|
226
243
|
const columnEntries = columnDefinitions.map((entry) => [entry.name, entry.buildType({ skipPrimaryKey })]);
|
|
227
244
|
const drizzleSchema = dbSchema.table(tableName, fromEntries(columnEntries), (drizzleTable) => {
|
|
228
245
|
const table = drizzleTable;
|
|
@@ -231,7 +248,7 @@ export function _getDrizzleTableFromType(type, fallbackSchemaName) {
|
|
|
231
248
|
const bm25Index = buildParadeIndex(table);
|
|
232
249
|
const checks = tableReflectionDatas.flatMap((tableReflectionData) => tableReflectionData.checks).filter(isDefined).map((data) => check(data.name, data.builder(table)));
|
|
233
250
|
return [
|
|
234
|
-
...(
|
|
251
|
+
...(skipPrimaryKey
|
|
235
252
|
? [buildPrimaryKey(table)]
|
|
236
253
|
: []),
|
|
237
254
|
...buildInheritanceConstraints(table),
|
|
@@ -247,7 +264,7 @@ export function _getDrizzleTableFromType(type, fallbackSchemaName) {
|
|
|
247
264
|
const foreignTable = getDrizzleTableFromType(tenantReferenceData.target(), dbSchema.schemaName);
|
|
248
265
|
const nonTenantColumn = tenantReferenceData.targetColumn ?? 'id';
|
|
249
266
|
return foreignKey({
|
|
250
|
-
name: getForeignKeyName(tableName,
|
|
267
|
+
name: getForeignKeyName(tableName, getEntityTableName(tenantReferenceData.target()), [nonTenantColumn]),
|
|
251
268
|
columns: [getColumn(table, 'tenantId'), getColumn(table, columnDefinition.name)],
|
|
252
269
|
foreignColumns: [getColumn(foreignTable, 'tenantId'), getColumn(foreignTable, nonTenantColumn)],
|
|
253
270
|
});
|
|
@@ -257,15 +274,23 @@ export function _getDrizzleTableFromType(type, fallbackSchemaName) {
|
|
|
257
274
|
return tableReflectionData.foreignKeys?.map((foreignKeyData) => {
|
|
258
275
|
const foreignKeyTarget = foreignKeyData.target();
|
|
259
276
|
const foreignTable = getDrizzleTableFromType(foreignKeyTarget, dbSchema.schemaName);
|
|
260
|
-
|
|
261
|
-
name: foreignKeyData.options?.name ?? getForeignKeyName(tableName,
|
|
277
|
+
let builder = foreignKey({
|
|
278
|
+
name: foreignKeyData.options?.name ?? getForeignKeyName(tableName, getEntityTableName(foreignKeyData.target()), foreignKeyData.columns, { naming: foreignKeyData.options?.naming }),
|
|
262
279
|
columns: foreignKeyData.columns.map((column) => getColumn(table, column)),
|
|
263
280
|
foreignColumns: foreignKeyData.foreignColumns.map((column) => getColumn(foreignTable, column)),
|
|
264
281
|
});
|
|
282
|
+
if (isDefined(foreignKeyData.options?.onDelete)) {
|
|
283
|
+
builder = builder.onDelete(foreignKeyData.options.onDelete);
|
|
284
|
+
}
|
|
285
|
+
if (isDefined(foreignKeyData.options?.onUpdate)) {
|
|
286
|
+
builder = builder.onUpdate(foreignKeyData.options.onUpdate);
|
|
287
|
+
}
|
|
288
|
+
return builder;
|
|
265
289
|
}) ?? [];
|
|
266
290
|
}),
|
|
267
291
|
...tableReflectionDatas.flatMap((tableReflectionData) => tableReflectionData.unique).filter(isDefined).map((data) => {
|
|
268
|
-
const
|
|
292
|
+
const resolvedColumns = resolveValueOrProvider(data.columns, table);
|
|
293
|
+
const columns = resolvedColumns.map((column) => getColumn(table, column));
|
|
269
294
|
let constraint = unique(data.options?.name ?? getUniqueName(tableName, columns, { naming: data.options?.naming })).on(...columns);
|
|
270
295
|
if (data.options?.nulls == 'not distinct') {
|
|
271
296
|
constraint = constraint.nullsNotDistinct();
|
|
@@ -398,7 +423,7 @@ function getPostgresColumn(tableName, columnName, dbSchema, propertySchema, refl
|
|
|
398
423
|
if (((reflectionData.primaryKey == true) || (context.property == 'id' && reflectionData.primaryKey != false)) && (options.skipPrimaryKey != true)) {
|
|
399
424
|
column = column.primaryKey();
|
|
400
425
|
}
|
|
401
|
-
for (const { target, targetColumn, excludeTenant } of reflectionData.references ?? []) {
|
|
426
|
+
for (const { target, targetColumn, excludeTenant, onDelete, onUpdate } of reflectionData.references ?? []) {
|
|
402
427
|
column = column.references(() => {
|
|
403
428
|
const targetType = target();
|
|
404
429
|
if ((excludeTenant != true) && (typeExtends(context.type, TenantBaseEntity) || typeExtends(context.type, TenantEntity)) && (typeExtends(targetType, TenantBaseEntity) || typeExtends(targetType, TenantEntity))) {
|
|
@@ -406,7 +431,7 @@ function getPostgresColumn(tableName, columnName, dbSchema, propertySchema, refl
|
|
|
406
431
|
}
|
|
407
432
|
const targetTable = getDrizzleTableFromType(targetType, dbSchema.schemaName);
|
|
408
433
|
return targetTable[(targetColumn ?? 'id')];
|
|
409
|
-
});
|
|
434
|
+
}, { onDelete, onUpdate });
|
|
410
435
|
}
|
|
411
436
|
return column;
|
|
412
437
|
}
|
|
@@ -462,8 +487,29 @@ export function getPgEnum(schema, enumeration, context) {
|
|
|
462
487
|
}
|
|
463
488
|
return dbEnum;
|
|
464
489
|
}
|
|
465
|
-
function
|
|
466
|
-
|
|
490
|
+
export function getPrimaryKeyColumnDefinitions(type, table, columnDefinitions, columnDefinitionsMap) {
|
|
491
|
+
const tableReflectionDatas = getTableReflectionDatas(type);
|
|
492
|
+
const mergedTableReflectionData = tableReflectionDatas.reduceRight((merged, data) => ({ ...merged, ...data }), {});
|
|
493
|
+
const resolvedColumnDefinitions = columnDefinitions ?? getColumnDefinitions(table);
|
|
494
|
+
const resolvedColumnDefinitionsMap = columnDefinitionsMap ?? getColumnDefinitionsMap(table);
|
|
495
|
+
const primaryKeyData = mergedTableReflectionData.primaryKey;
|
|
496
|
+
let definitions;
|
|
497
|
+
if (isDefined(primaryKeyData?.columns)) {
|
|
498
|
+
const resolvedColumns = resolveValueOrProvider(primaryKeyData.columns, table);
|
|
499
|
+
definitions = resolvedColumns.map((columnValue) => {
|
|
500
|
+
if (columnValue instanceof SQL) {
|
|
501
|
+
throw new NotSupportedError('SQL in primary key is not supported by Repository.');
|
|
502
|
+
}
|
|
503
|
+
return assertDefinedPass(resolvedColumnDefinitionsMap.get(columnValue), `Could not map primary key property ${columnValue} to column.`);
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
else {
|
|
507
|
+
definitions = resolvedColumnDefinitions.filter((columnDefinition) => (columnDefinition.reflectionData?.primaryKey == true) || (columnDefinition.objectPath.path == 'id' && columnDefinition.reflectionData?.primaryKey != false));
|
|
508
|
+
}
|
|
509
|
+
return definitions.toSorted(compareByValueSelectionToOrder(['tenantId', 'id', orderRest], (columnDefinition) => columnDefinition.objectPath.path));
|
|
510
|
+
}
|
|
511
|
+
export function getPrimaryKeyColumns(type, table, columnDefinitions, columnDefinitionsMap) {
|
|
512
|
+
return getPrimaryKeyColumnDefinitions(type, table, columnDefinitions, columnDefinitionsMap).map((def) => table[def.name]);
|
|
467
513
|
}
|
|
468
514
|
function getPrimaryKeyName(tableName, columnsOrBaseName, options) {
|
|
469
515
|
return getIdentifier(tableName, columnsOrBaseName, 'pk', options);
|
|
@@ -486,23 +532,6 @@ function getForeignKeyName(tableName, foreignTableName, columnsOrBaseName, optio
|
|
|
486
532
|
}
|
|
487
533
|
return identifier;
|
|
488
534
|
}
|
|
489
|
-
function getTableName(type) {
|
|
490
|
-
const tableReflectionDatas = getTableReflectionDatas(type);
|
|
491
|
-
const tableReflectionData = tableReflectionDatas[0];
|
|
492
|
-
return tableReflectionData?.name ?? getDefaultTableName(type);
|
|
493
|
-
}
|
|
494
|
-
function getTableReflectionDatas(type) {
|
|
495
|
-
const metadata = reflectionRegistry.getMetadata(type);
|
|
496
|
-
assertDefined(metadata, `Type ${type.name} does not have reflection metadata.`);
|
|
497
|
-
const tableReflectionDatas = [];
|
|
498
|
-
for (let currentMetadata = metadata; isNotNullOrUndefined(currentMetadata?.parent); currentMetadata = reflectionRegistry.getMetadata(currentMetadata.parent)) {
|
|
499
|
-
const tableReflectionData = currentMetadata.data.tryGet('orm');
|
|
500
|
-
if (isDefined(tableReflectionData)) {
|
|
501
|
-
tableReflectionDatas.push(tableReflectionData);
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
return tableReflectionDatas;
|
|
505
|
-
}
|
|
506
535
|
function getIdentifier(tableName, columnsOrBaseName, suffix, options) {
|
|
507
536
|
const middle = isString(columnsOrBaseName) ? columnsOrBaseName : getColumnNames(columnsOrBaseName).join('_');
|
|
508
537
|
const identifier = `${getTablePrefix(tableName, options?.naming)}_${middle}_${suffix}`;
|
|
@@ -12,7 +12,6 @@ export declare function encryptBytes(bytes: Uint8Array<ArrayBuffer>, key: Crypto
|
|
|
12
12
|
* @param bytes The byte array to decrypt (must include version and IV).
|
|
13
13
|
* @param key The CryptoKey to use for decryption.
|
|
14
14
|
* @returns A promise that resolves to the original decrypted byte array.
|
|
15
|
-
* @throws {DetailsError} If decryption fails (e.g., wrong key, corrupted data).
|
|
16
15
|
* @throws {Error} If the encryption version is invalid.
|
|
17
16
|
*/
|
|
18
17
|
export declare function decryptBytes(bytes: Uint8Array, key: CryptoKey): Promise<Uint8Array<ArrayBuffer>>;
|
package/orm/server/encryption.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* Provides utility functions for encrypting and decrypting byte arrays using AES-GCM.
|
|
4
4
|
* It includes versioning to handle potential future changes in the encryption format.
|
|
5
5
|
*/
|
|
6
|
-
import { DetailsError } from '../../errors/index.js';
|
|
7
6
|
import { decrypt, encrypt } from '../../utils/cryptography.js';
|
|
8
7
|
import { getRandomBytes } from '../../utils/random.js';
|
|
9
8
|
import { assert } from '../../utils/type-guards.js';
|
|
@@ -36,7 +35,6 @@ export async function encryptBytes(bytes, key) {
|
|
|
36
35
|
* @param bytes The byte array to decrypt (must include version and IV).
|
|
37
36
|
* @param key The CryptoKey to use for decryption.
|
|
38
37
|
* @returns A promise that resolves to the original decrypted byte array.
|
|
39
|
-
* @throws {DetailsError} If decryption fails (e.g., wrong key, corrupted data).
|
|
40
38
|
* @throws {Error} If the encryption version is invalid.
|
|
41
39
|
*/
|
|
42
40
|
export async function decryptBytes(bytes, key) {
|
|
@@ -49,7 +47,6 @@ export async function decryptBytes(bytes, key) {
|
|
|
49
47
|
return new Uint8Array(decrypted);
|
|
50
48
|
}
|
|
51
49
|
catch (error) {
|
|
52
|
-
|
|
53
|
-
throw new DetailsError('Decrypt error', error);
|
|
50
|
+
throw new Error('Decryption failed.', { cause: error });
|
|
54
51
|
}
|
|
55
52
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Injector } from '../../injector/index.js';
|
|
2
|
+
export type DatabaseExtension = {
|
|
3
|
+
name: string;
|
|
4
|
+
};
|
|
5
|
+
export declare const DATABASE_EXTENSION: import("../../injector/index.js").InjectionToken<DatabaseExtension, never>;
|
|
6
|
+
/**
|
|
7
|
+
* Registers a database extension in the provided injector.
|
|
8
|
+
* @param name - The name of the extension.
|
|
9
|
+
* @param options - Optional injector.
|
|
10
|
+
*/
|
|
11
|
+
export declare function registerDatabaseExtension(name: string, { injector }?: {
|
|
12
|
+
injector?: Injector;
|
|
13
|
+
}): void;
|
|
14
|
+
export declare function runDatabaseExtensions(): Promise<void>;
|