@tstdl/base 0.93.140 → 0.93.141

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.
Files changed (98) hide show
  1. package/application/application.d.ts +1 -1
  2. package/application/application.js +1 -1
  3. package/application/providers.d.ts +20 -2
  4. package/application/providers.js +34 -7
  5. package/audit/module.d.ts +5 -0
  6. package/audit/module.js +9 -1
  7. package/authentication/server/module.d.ts +5 -0
  8. package/authentication/server/module.js +9 -1
  9. package/authentication/tests/authentication.api-controller.test.js +1 -1
  10. package/authentication/tests/authentication.api-request-token.provider.test.js +1 -1
  11. package/authentication/tests/authentication.client-service.test.js +1 -1
  12. package/circuit-breaker/postgres/module.d.ts +1 -0
  13. package/circuit-breaker/postgres/module.js +5 -1
  14. package/document-management/server/configure.js +5 -1
  15. package/document-management/server/module.d.ts +1 -1
  16. package/document-management/server/module.js +1 -1
  17. package/document-management/server/services/document-management-ancillary.service.js +1 -1
  18. package/document-management/tests/ai-config-hierarchy.test.js +0 -5
  19. package/document-management/tests/document-management-ai-overrides.test.js +0 -1
  20. package/document-management/tests/document-validation-ai-overrides.test.js +0 -1
  21. package/examples/document-management/main.d.ts +1 -0
  22. package/examples/document-management/main.js +14 -11
  23. package/key-value-store/postgres/module.d.ts +1 -0
  24. package/key-value-store/postgres/module.js +5 -1
  25. package/lock/postgres/module.d.ts +1 -0
  26. package/lock/postgres/module.js +5 -1
  27. package/mail/module.d.ts +5 -1
  28. package/mail/module.js +11 -6
  29. package/module/modules/web-server.module.js +2 -3
  30. package/notification/server/module.d.ts +1 -0
  31. package/notification/server/module.js +5 -1
  32. package/notification/tests/notification-flow.test.js +2 -2
  33. package/orm/decorators.d.ts +5 -1
  34. package/orm/decorators.js +1 -1
  35. package/orm/server/drizzle/schema-converter.js +17 -30
  36. package/orm/server/encryption.d.ts +0 -1
  37. package/orm/server/encryption.js +1 -4
  38. package/orm/server/index.d.ts +1 -6
  39. package/orm/server/index.js +1 -6
  40. package/orm/server/migration.d.ts +19 -0
  41. package/orm/server/migration.js +72 -0
  42. package/orm/server/repository.d.ts +1 -1
  43. package/orm/server/transaction.d.ts +5 -10
  44. package/orm/server/transaction.js +22 -26
  45. package/orm/server/transactional.js +3 -3
  46. package/orm/tests/database-migration.test.d.ts +1 -0
  47. package/orm/tests/database-migration.test.js +82 -0
  48. package/orm/tests/encryption.test.js +3 -4
  49. package/orm/utils.d.ts +17 -2
  50. package/orm/utils.js +49 -1
  51. package/package.json +4 -3
  52. package/rate-limit/postgres/module.d.ts +1 -0
  53. package/rate-limit/postgres/module.js +5 -1
  54. package/reflection/decorator-data.js +11 -12
  55. package/task-queue/README.md +2 -9
  56. package/task-queue/postgres/drizzle/{0000_simple_invisible_woman.sql → 0000_wakeful_sunspot.sql} +22 -14
  57. package/task-queue/postgres/drizzle/meta/0000_snapshot.json +160 -82
  58. package/task-queue/postgres/drizzle/meta/_journal.json +2 -2
  59. package/task-queue/postgres/module.d.ts +1 -0
  60. package/task-queue/postgres/module.js +5 -1
  61. package/task-queue/postgres/schemas.d.ts +9 -6
  62. package/task-queue/postgres/schemas.js +4 -3
  63. package/task-queue/postgres/task-queue.d.ts +2 -12
  64. package/task-queue/postgres/task-queue.js +431 -354
  65. package/task-queue/postgres/task.model.d.ts +12 -5
  66. package/task-queue/postgres/task.model.js +51 -25
  67. package/task-queue/task-context.d.ts +2 -2
  68. package/task-queue/task-context.js +7 -7
  69. package/task-queue/task-queue.d.ts +36 -19
  70. package/task-queue/task-queue.js +18 -10
  71. package/task-queue/tests/cascading-cancellations.test.d.ts +1 -0
  72. package/task-queue/tests/cascading-cancellations.test.js +38 -0
  73. package/task-queue/tests/complex.test.js +44 -228
  74. package/task-queue/tests/coverage-branch.test.d.ts +1 -0
  75. package/task-queue/tests/coverage-branch.test.js +407 -0
  76. package/task-queue/tests/coverage-enhancement.test.d.ts +1 -0
  77. package/task-queue/tests/coverage-enhancement.test.js +144 -0
  78. package/task-queue/tests/dag-dependencies.test.d.ts +1 -0
  79. package/task-queue/tests/dag-dependencies.test.js +41 -0
  80. package/task-queue/tests/dependencies.test.js +26 -26
  81. package/task-queue/tests/extensive-dependencies.test.js +64 -139
  82. package/task-queue/tests/fan-out-spawning.test.d.ts +1 -0
  83. package/task-queue/tests/fan-out-spawning.test.js +53 -0
  84. package/task-queue/tests/idempotent-replacement.test.d.ts +1 -0
  85. package/task-queue/tests/idempotent-replacement.test.js +61 -0
  86. package/task-queue/tests/missing-idempotent-tasks.test.d.ts +1 -0
  87. package/task-queue/tests/missing-idempotent-tasks.test.js +38 -0
  88. package/task-queue/tests/queue.test.js +33 -24
  89. package/task-queue/tests/worker.test.js +20 -5
  90. package/task-queue/tests/zombie-parent.test.d.ts +1 -0
  91. package/task-queue/tests/zombie-parent.test.js +45 -0
  92. package/task-queue/tests/zombie-recovery.test.d.ts +1 -0
  93. package/task-queue/tests/zombie-recovery.test.js +51 -0
  94. package/test5.js +5 -5
  95. package/testing/integration-setup.d.ts +4 -4
  96. package/testing/integration-setup.js +54 -29
  97. package/text/localization.service.js +2 -2
  98. package/utils/file-reader.js +1 -2
@@ -4,7 +4,7 @@ import { Module } from '../module/index.js';
4
4
  import type { OneOrMany, Type } from '../types/index.js';
5
5
  export type InitializerFn = () => void | Promise<void>;
6
6
  export type DestructorFn = () => void | Promise<void>;
7
- export declare const APPLICATION_MODULE: import("../injector/token.js").InjectionToken<Module, never>;
7
+ export declare const APPLICATION_MODULE: import("../injector/token.js").InjectionToken<Module | Type<Module>, never>;
8
8
  export declare const APPLICATION_INITIALIZER: import("../injector/token.js").InjectionToken<InitializerFn, never>;
9
9
  export declare const APPLICATION_DESTRUCTOR: import("../injector/token.js").InjectionToken<DestructorFn, never>;
10
10
  export declare const APPLICATION_INSTANCE_ID: import("../injector/token.js").InjectionToken<string, never>;
@@ -79,7 +79,7 @@ let Application = Application_1 = class Application {
79
79
  try {
80
80
  const initializers = await this.#injector.resolveAllAsync(APPLICATION_INITIALIZER, undefined, { optional: true });
81
81
  for (const initializer of initializers) {
82
- await runInInjectionContext(this.#injector, initializer);
82
+ await runInInjectionContext(this.#injector, async () => await initializer());
83
83
  }
84
84
  modules = await toArrayAsync(mapAsync(this.#moduleTypesAndInstances, async (instanceOrType) => (isFunction(instanceOrType) ? await this.#injector.resolveAsync(instanceOrType) : instanceOrType)));
85
85
  await Promise.race([
@@ -1,9 +1,27 @@
1
1
  import { CancellationSignal } from '../cancellation/index.js';
2
- import { type ProvidersItem } from '../injector/index.js';
2
+ import { Injector, type ProvidersItem } from '../injector/index.js';
3
3
  import { Module, type FunctionModuleFunction } from '../module/index.js';
4
4
  import type { OneOrMany, Type } from '../types/index.js';
5
5
  import { type DestructorFn, type InitializerFn } from './application.js';
6
- export declare function provideModule(...functionsAndModules: OneOrMany<FunctionModuleFunction | Type<Module>>[]): ProvidersItem[];
6
+ /**
7
+ * Registers an application initializer function that will be executed during application startup.
8
+ */
9
+ export declare function registerInitializer(fn: InitializerFn, options?: {
10
+ injector?: Injector;
11
+ }): void;
12
+ /**
13
+ * Registers an application destructor function that will be executed during application shutdown.
14
+ */
15
+ export declare function registerDestructor(fn: DestructorFn, options?: {
16
+ injector?: Injector;
17
+ }): void;
18
+ /**
19
+ * Registers a module or a function-based module in the application. If a class extending Module is provided, it will be registered directly. If a function is provided, it will be wrapped in a FunctionModule.
20
+ */
21
+ export declare function registerModule(fnOrModule: FunctionModuleFunction | Type<Module>, options?: {
22
+ injector?: Injector;
23
+ }): void;
24
+ export declare function provideModule(...functionsAndModules: OneOrMany<FunctionModuleFunction | Type<Module>>[]): ProvidersItem<Module | Type<Module>>[];
7
25
  export declare function provideInitializer(fn: InitializerFn): ProvidersItem;
8
26
  export declare function provideDestructor(fn: DestructorFn): ProvidersItem;
9
27
  export declare function provideShutdownSignal(signal: CancellationSignal): ProvidersItem;
@@ -1,5 +1,5 @@
1
1
  import { CancellationSignal } from '../cancellation/index.js';
2
- import { inject } from '../injector/index.js';
2
+ import { inject, Injector, provide } from '../injector/index.js';
3
3
  import { Logger } from '../logger/index.js';
4
4
  import { FunctionModule, Module } from '../module/index.js';
5
5
  import { isFunction } from '../utils/type-guards.js';
@@ -7,17 +7,44 @@ import { typeExtends } from '../utils/type/index.js';
7
7
  import { Application, APPLICATION_DESTRUCTOR, APPLICATION_INITIALIZER, APPLICATION_MODULE } from './application.js';
8
8
  const quitSignals = ['SIGTERM', 'SIGINT', 'SIGHUP', 'SIGBREAK'];
9
9
  const quitEvents = ['uncaughtException', 'unhandledRejection', 'rejectionHandled'];
10
+ /**
11
+ * Registers an application initializer function that will be executed during application startup.
12
+ */
13
+ export function registerInitializer(fn, options) {
14
+ const targetInjector = options?.injector ?? Injector;
15
+ targetInjector.register(APPLICATION_INITIALIZER, { useValue: fn }, { multi: true });
16
+ }
17
+ /**
18
+ * Registers an application destructor function that will be executed during application shutdown.
19
+ */
20
+ export function registerDestructor(fn, options) {
21
+ const targetInjector = options?.injector ?? Injector;
22
+ targetInjector.register(APPLICATION_DESTRUCTOR, { useValue: fn }, { multi: true });
23
+ }
24
+ /**
25
+ * Registers a module or a function-based module in the application. If a class extending Module is provided, it will be registered directly. If a function is provided, it will be wrapped in a FunctionModule.
26
+ */
27
+ export function registerModule(fnOrModule, options) {
28
+ const targetInjector = options?.injector ?? Injector;
29
+ if (typeExtends(fnOrModule, Module)) {
30
+ targetInjector.register(APPLICATION_MODULE, { useValue: fnOrModule }, { multi: true });
31
+ }
32
+ else if (isFunction(fnOrModule)) {
33
+ targetInjector.register(APPLICATION_MODULE, { useToken: FunctionModule, defaultArgument: fnOrModule }, { multi: true });
34
+ }
35
+ else {
36
+ throw new TypeError('Invalid module or function provided to registerModule');
37
+ }
38
+ }
10
39
  export function provideModule(...functionsAndModules) {
11
40
  return functionsAndModules.flat().map((fnOrModule) => {
12
41
  if (typeExtends(fnOrModule, Module)) {
13
- return { provide: APPLICATION_MODULE, useValue: fnOrModule, multi: true };
14
- }
15
- else if (isFunction(fnOrModule)) {
16
- return { provide: APPLICATION_MODULE, useToken: FunctionModule, defaultArgument: fnOrModule, multi: true };
42
+ return provide(APPLICATION_MODULE, { useValue: fnOrModule, multi: true });
17
43
  }
18
- else {
19
- throw new TypeError('Invalid module or function provided to provideModules');
44
+ if (isFunction(fnOrModule)) {
45
+ return provide(APPLICATION_MODULE, { useToken: FunctionModule, defaultArgument: fnOrModule, multi: true });
20
46
  }
47
+ throw new TypeError('Invalid module or function provided to provideModule');
21
48
  });
22
49
  }
23
50
  export function provideInitializer(fn) {
package/audit/module.d.ts CHANGED
@@ -9,6 +9,11 @@ export declare class AuditModuleConfig {
9
9
  * If not provided, the global database configuration is used.
10
10
  */
11
11
  database?: DatabaseConfig;
12
+ /**
13
+ * Whether to automatically run database migrations when the application starts.
14
+ * Defaults to `true`.
15
+ */
16
+ autoMigrate?: boolean;
12
17
  }
13
18
  /**
14
19
  * Configures audit server services.
package/audit/module.js CHANGED
@@ -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
  /**
4
4
  * Configuration for {@link configureAudit}.
5
5
  */
@@ -9,6 +9,11 @@ export class AuditModuleConfig {
9
9
  * If not provided, the global database configuration is used.
10
10
  */
11
11
  database;
12
+ /**
13
+ * Whether to automatically run database migrations when the application starts.
14
+ * Defaults to `true`.
15
+ */
16
+ autoMigrate;
12
17
  }
13
18
  /**
14
19
  * Configures audit server services.
@@ -17,6 +22,9 @@ export class AuditModuleConfig {
17
22
  export function configureAudit({ injector, ...config } = {}) {
18
23
  const targetInjector = injector ?? Injector;
19
24
  targetInjector.register(AuditModuleConfig, { useValue: config });
25
+ if (config.autoMigrate != false) {
26
+ registerDatabaseMigration('Audit', migrateAuditSchema, { injector });
27
+ }
20
28
  }
21
29
  /**
22
30
  * Migrates the audit database schema to the latest version.
@@ -25,6 +25,11 @@ export declare class AuthenticationModuleConfig {
25
25
  * Override default {@link AuthenticationAncillaryService}.
26
26
  */
27
27
  authenticationAncillaryService?: InjectionToken<AuthenticationAncillaryService<any, any, any>>;
28
+ /**
29
+ * Whether to automatically run database migrations when the application starts.
30
+ * Defaults to `true`.
31
+ */
32
+ autoMigrate?: boolean;
28
33
  }
29
34
  /**
30
35
  * Configures authentication server services.
@@ -2,7 +2,7 @@ import { ApiRequestTokenProvider } from '../../api/server/api-request-token.prov
2
2
  import { inject } from '../../injector/index.js';
3
3
  import { Injector } from '../../injector/injector.js';
4
4
  import { isProvider } from '../../injector/provider.js';
5
- import { Database, migrate } from '../../orm/server/index.js';
5
+ import { Database, migrate, registerDatabaseMigration } from '../../orm/server/index.js';
6
6
  import { isDefined } from '../../utils/type-guards.js';
7
7
  import { AuthenticationAncillaryService } from './authentication-ancillary.service.js';
8
8
  import { AuthenticationApiRequestTokenProvider } from './authentication-api-request-token.provider.js';
@@ -28,6 +28,11 @@ export class AuthenticationModuleConfig {
28
28
  * Override default {@link AuthenticationAncillaryService}.
29
29
  */
30
30
  authenticationAncillaryService;
31
+ /**
32
+ * Whether to automatically run database migrations when the application starts.
33
+ * Defaults to `true`.
34
+ */
35
+ autoMigrate;
31
36
  }
32
37
  /**
33
38
  * Configures authentication server services.
@@ -44,6 +49,9 @@ export function configureAuthenticationServer({ injector, ...config }) {
44
49
  if (isDefined(config.authenticationAncillaryService)) {
45
50
  targetInjector.registerSingleton(AuthenticationAncillaryService, { useToken: config.authenticationAncillaryService });
46
51
  }
52
+ if (config.autoMigrate != false) {
53
+ registerDatabaseMigration('Authentication', migrateAuthenticationSchema, { injector });
54
+ }
47
55
  }
48
56
  /**
49
57
  * Migrates the authentication schema.
@@ -25,7 +25,7 @@ describe('AuthenticationApiController Integration', () => {
25
25
  clear: vi.fn(() => storage.clear()),
26
26
  };
27
27
  ({ injector, database } = await setupIntegrationTest({
28
- modules: { authentication: true, audit: true, keyValueStore: true, test: true, api: true, webServer: true },
28
+ modules: { authentication: true, audit: true, keyValueStore: true, signals: true, api: true, webServer: true },
29
29
  authenticationAncillaryService: DefaultAuthenticationAncillaryService,
30
30
  }));
31
31
  await runInInjectionContext(injector, async () => {
@@ -11,7 +11,7 @@ describe('AuthenticationApiRequestTokenProvider', () => {
11
11
  let tokenProvider;
12
12
  const tenantId = crypto.randomUUID();
13
13
  beforeAll(async () => {
14
- ({ injector } = await setupIntegrationTest({ modules: { authentication: true, test: true } }));
14
+ ({ injector } = await setupIntegrationTest({ modules: { authentication: true, signals: true } }));
15
15
  authenticationService = await injector.resolveAsync(AuthenticationService);
16
16
  subjectService = await injector.resolveAsync(SubjectService);
17
17
  tokenProvider = injector.resolve(AuthenticationApiRequestTokenProvider);
@@ -25,7 +25,7 @@ describe('AuthenticationClientService Integration', () => {
25
25
  clear: vi.fn(() => storage.clear()),
26
26
  };
27
27
  ({ injector, database } = await setupIntegrationTest({
28
- modules: { authentication: true, audit: true, keyValueStore: true, test: true, api: true, webServer: true },
28
+ modules: { authentication: true, audit: true, keyValueStore: true, signals: true, api: true, webServer: true },
29
29
  authenticationAncillaryService: DefaultAuthenticationAncillaryService,
30
30
  }));
31
31
  await runInInjectionContext(injector, async () => {
@@ -2,6 +2,7 @@ import { Injector } from '../../injector/index.js';
2
2
  import { type DatabaseConfig } from '../../orm/server/index.js';
3
3
  export declare class PostgresCircuitBreakerModuleConfig {
4
4
  database?: DatabaseConfig;
5
+ autoMigrate?: boolean;
5
6
  }
6
7
  /**
7
8
  * configure circuit breaker module
@@ -1,11 +1,12 @@
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 { CircuitBreaker } from '../circuit-breaker.js';
4
4
  import { CircuitBreakerProvider } from '../provider.js';
5
5
  import { PostgresCircuitBreakerService } from './circuit-breaker.js';
6
6
  import { PostgresCircuitBreakerProvider } from './provider.js';
7
7
  export class PostgresCircuitBreakerModuleConfig {
8
8
  database;
9
+ autoMigrate;
9
10
  }
10
11
  /**
11
12
  * configure circuit breaker module
@@ -15,6 +16,9 @@ export function configurePostgresCircuitBreaker({ injector, ...config } = {}) {
15
16
  targetInjector.register(PostgresCircuitBreakerModuleConfig, { useValue: config });
16
17
  targetInjector.registerSingleton(CircuitBreakerProvider, { useToken: PostgresCircuitBreakerProvider });
17
18
  targetInjector.registerSingleton(CircuitBreaker, { useToken: PostgresCircuitBreakerService });
19
+ if (config.autoMigrate != false) {
20
+ registerDatabaseMigration('PostgresCircuitBreaker', migratePostgresCircuitBreaker, { injector });
21
+ }
18
22
  }
19
23
  export async function migratePostgresCircuitBreaker() {
20
24
  const connection = inject(PostgresCircuitBreakerModuleConfig, undefined, { optional: true })?.database?.connection;
@@ -1,7 +1,8 @@
1
1
  import { Injector } from '../../injector/injector.js';
2
+ import { registerDatabaseMigration } from '../../orm/server/index.js';
2
3
  import { isDefined } from '../../utils/type-guards.js';
3
4
  import { DocumentManagementAuthorizationService } from '../authorization/document-management-authorization.service.js';
4
- import { DocumentManagementConfiguration } from './module.js';
5
+ import { DocumentManagementConfiguration, migrateDocumentManagementSchema } from './module.js';
5
6
  import { DocumentManagementAiProviderService, DocumentManagementAncillaryService } from './services/index.js';
6
7
  export function configureDocumentManagement(configuration) {
7
8
  const targetInjector = configuration.injector ?? Injector;
@@ -11,4 +12,7 @@ export function configureDocumentManagement(configuration) {
11
12
  if (isDefined(configuration.aiProvider)) {
12
13
  targetInjector.register(DocumentManagementAiProviderService, { useToken: configuration.aiProvider });
13
14
  }
15
+ if (configuration.autoMigrate != false) {
16
+ registerDatabaseMigration('DocumentManagement', migrateDocumentManagementSchema, { injector: configuration.injector });
17
+ }
14
18
  }
@@ -1,4 +1,3 @@
1
- import './schemas.js';
2
1
  import { type InjectionToken } from '../../injector/index.js';
3
2
  import { type DatabaseConfig } from '../../orm/server/index.js';
4
3
  import type { DocumentManagementAuthorizationService } from '../authorization/document-management-authorization.service.js';
@@ -14,5 +13,6 @@ export declare class DocumentManagementConfiguration {
14
13
  database?: DatabaseConfig;
15
14
  maxFileSize?: number;
16
15
  skipAi?: boolean;
16
+ autoMigrate?: boolean;
17
17
  }
18
18
  export declare function migrateDocumentManagementSchema(): Promise<void>;
@@ -1,4 +1,3 @@
1
- import './schemas.js';
2
1
  import { inject } from '../../injector/index.js';
3
2
  import { Database, migrate } from '../../orm/server/index.js';
4
3
  export class DocumentManagementConfiguration {
@@ -11,6 +10,7 @@ export class DocumentManagementConfiguration {
11
10
  database;
12
11
  maxFileSize;
13
12
  skipAi;
13
+ autoMigrate;
14
14
  }
15
15
  ;
16
16
  export async function migrateDocumentManagementSchema() {
@@ -6,6 +6,6 @@ export class DocumentManagementAncillaryService {
6
6
  * @returns The resolved file name for the document, without the file extension.
7
7
  */
8
8
  getDocumentFilename(document) {
9
- return document.title ?? document.originalFileName ?? document.id;
9
+ return document.title ?? document.originalFileName?.slice(0, document.originalFileName.lastIndexOf('.')) ?? document.id;
10
10
  }
11
11
  }
@@ -8,7 +8,6 @@ import { TestDocumentManagementAncillaryService } from './helper.js';
8
8
  describe('DocumentManagementAiService Hierarchy', () => {
9
9
  let injector;
10
10
  let aiService;
11
- let flashModel;
12
11
  const tenantId = crypto.randomUUID();
13
12
  const mockAiProvider = {
14
13
  getGlobalConfiguration: vi.fn(),
@@ -20,12 +19,8 @@ describe('DocumentManagementAiService Hierarchy', () => {
20
19
  };
21
20
  beforeAll(async () => {
22
21
  ({ injector } = await setupIntegrationTest({
23
- orm: { schema: 'document_management' },
24
22
  modules: { messageBus: true, signals: true, objectStorage: true, documentManagement: true },
25
23
  }));
26
- runInInjectionContext(injector, () => {
27
- flashModel = injectModel('gemini-2.5-flash');
28
- });
29
24
  injector.register(DocumentManagementAiProviderService, { useValue: mockAiProvider });
30
25
  // Ancillary and configuration are already registered by setupIntegrationTest, but we can override if needed
31
26
  injector.register(DocumentManagementAncillaryService, { useToken: TestDocumentManagementAncillaryService });
@@ -22,7 +22,6 @@ describe('DocumentManagementAiService Overrides', () => {
22
22
  };
23
23
  beforeAll(async () => {
24
24
  ({ injector } = await setupIntegrationTest({
25
- orm: { schema: 'document_management' },
26
25
  modules: { messageBus: true, signals: true, objectStorage: true },
27
26
  }));
28
27
  runInInjectionContext(injector, () => {
@@ -32,7 +32,6 @@ describe('AiValidationExecutor Overrides', () => {
32
32
  };
33
33
  beforeAll(async () => {
34
34
  ({ injector } = await setupIntegrationTest({
35
- orm: { schema: 'document_management' },
36
35
  modules: { messageBus: true, signals: true, objectStorage: true },
37
36
  }));
38
37
  runInInjectionContext(injector, () => {
@@ -1,3 +1,4 @@
1
+ /** biome-ignore-all lint/nursery/noExcessiveClassesPerFile: <explanation> */
1
2
  import '../../polyfills.js';
2
3
  import { DocumentManagementAuthorizationService, type DocumentCollection, type DocumentCollectionMetadata } from '../../document-management/index.js';
3
4
  import { DocumentManagementAncillaryService } from '../../document-management/server/index.js';
@@ -1,3 +1,4 @@
1
+ /** biome-ignore-all lint/nursery/noExcessiveClassesPerFile: <explanation> */
1
2
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
3
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
4
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -10,22 +11,23 @@ import { MockApiRequestTokenProvider } from '../../api/server/api-request-token.
10
11
  import { configureApiServer } from '../../api/server/module.js';
11
12
  import { Application } from '../../application/application.js';
12
13
  import { provideInitializer, provideModule, provideSignalHandler } from '../../application/index.js';
13
- import { configurePostgresCircuitBreaker, migratePostgresCircuitBreaker } from '../../circuit-breaker/postgres/module.js';
14
+ import { configureAudit } from '../../audit/module.js';
15
+ import { configurePostgresCircuitBreaker } from '../../circuit-breaker/postgres/module.js';
14
16
  import { DocumentManagementAuthorizationService } from '../../document-management/index.js';
15
17
  import { configureDocumentManagement } from '../../document-management/server/configure.js';
16
18
  import { DocumentCategoryTypeService, DocumentCollectionService, DocumentManagementAncillaryService, DocumentManagementApiController, DocumentRequestService } from '../../document-management/server/index.js';
17
- import { migrateDocumentManagementSchema } from '../../document-management/server/module.js';
18
19
  import { DocumentManagementService } from '../../document-management/server/services/document-management.service.js';
19
20
  import { configureNodeHttpServer } from '../../http/server/node/module.js';
20
- import { Injector, Singleton } from '../../injector/index.js';
21
- import { inject, injectManyAsync, runInInjectionContext } from '../../injector/inject.js';
21
+ import { Singleton } from '../../injector/index.js';
22
+ import { injectManyAsync } from '../../injector/inject.js';
22
23
  import { PrettyPrintLogFormatter, provideConsoleLogTransport } from '../../logger/index.js';
23
24
  import { configureLocalMessageBus } from '../../message-bus/index.js';
24
25
  import { WebServerModule } from '../../module/index.js';
25
26
  import { configureS3ObjectStorage } from '../../object-storage/s3/index.js';
26
- import { configureOrm } from '../../orm/server/index.js';
27
+ import { configureOrm, provideDatabaseMigrator } from '../../orm/server/index.js';
28
+ import { configurePostgresRateLimiter } from '../../rate-limit/postgres/module.js';
27
29
  import { configureDefaultSignalsImplementation } from '../../signals/implementation/configure.js';
28
- import { configurePostgresTaskQueue, migratePostgresTaskQueueSchema } from '../../task-queue/postgres/index.js';
30
+ import { configurePostgresTaskQueue } from '../../task-queue/postgres/index.js';
29
31
  import { boolean, positiveInteger, string } from '../../utils/config-parser.js';
30
32
  import { ExampleAiProviderService } from './ai-provider.js';
31
33
  import { TstdlCategoryParents, TstdlDocumentCategoryLabels, TstdlDocumentPropertyConfiguration, TstdlDocumentTypeCategories, TstdlDocumentTypeLabels, TstdlDocumentTypeProperties } from './categories-and-types.js';
@@ -84,11 +86,13 @@ AllowAllDocumentManagementAuthorizationService = __decorate([
84
86
  Singleton()
85
87
  ], AllowAllDocumentManagementAuthorizationService);
86
88
  export { AllowAllDocumentManagementAuthorizationService };
87
- async function bootstrap() {
88
- const injector = inject(Injector);
89
+ function bootstrap() {
90
+ configureAudit();
89
91
  configureNodeHttpServer();
90
92
  configurePostgresTaskQueue();
91
93
  configurePostgresCircuitBreaker();
94
+ configurePostgresTaskQueue();
95
+ configurePostgresRateLimiter();
92
96
  configureLocalMessageBus();
93
97
  configureDefaultSignalsImplementation();
94
98
  configureGenkit({
@@ -119,6 +123,7 @@ async function bootstrap() {
119
123
  bucketPerModule: config.s3.bucketPerModule,
120
124
  accessKey: config.s3.accessKey,
121
125
  secretKey: config.s3.secretKey,
126
+ forcePathStyle: true,
122
127
  });
123
128
  configureApiServer({
124
129
  controllers: [DocumentManagementApiController],
@@ -139,9 +144,6 @@ async function bootstrap() {
139
144
  location: config.ai.vertex.location,
140
145
  },
141
146
  });
142
- await runInInjectionContext(injector, migrateDocumentManagementSchema);
143
- await runInInjectionContext(injector, migratePostgresCircuitBreaker);
144
- await runInInjectionContext(injector, migratePostgresTaskQueueSchema);
145
147
  }
146
148
  async function main() {
147
149
  const tenantId = '00000000-0000-0000-0000-000000000000';
@@ -171,4 +173,5 @@ Application.run('DocumentManagementTest', [
171
173
  provideModule(main, WebServerModule),
172
174
  provideSignalHandler(),
173
175
  provideConsoleLogTransport(PrettyPrintLogFormatter),
176
+ provideDatabaseMigrator(),
174
177
  ]);
@@ -2,6 +2,7 @@ import { Injector } from '../../injector/index.js';
2
2
  import { type DatabaseConfig } from '../../orm/server/index.js';
3
3
  export declare class PostgresKeyValueStoreModuleConfig {
4
4
  database?: DatabaseConfig;
5
+ autoMigrate?: boolean;
5
6
  }
6
7
  /**
7
8
  * configure key-value store module
@@ -1,10 +1,11 @@
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 { KeyValueStore } from '../key-value.store.js';
5
5
  import { PostgresKeyValueStore } from './key-value-store.service.js';
6
6
  export class PostgresKeyValueStoreModuleConfig {
7
7
  database;
8
+ autoMigrate;
8
9
  }
9
10
  /**
10
11
  * configure key-value store module
@@ -15,6 +16,9 @@ export function configurePostgresKeyValueStore({ injector, ...config } = {}) {
15
16
  targetInjector.register(PostgresKeyValueStoreModuleConfig, { useValue: config });
16
17
  }
17
18
  targetInjector.registerSingleton(KeyValueStore, { useToken: PostgresKeyValueStore });
19
+ if (config.autoMigrate != false) {
20
+ registerDatabaseMigration('PostgresKeyValueStore', migratePostgresKeyValueStoreSchema, { injector });
21
+ }
18
22
  }
19
23
  export async function migratePostgresKeyValueStoreSchema() {
20
24
  const connection = inject(PostgresKeyValueStoreModuleConfig, undefined, { optional: true })?.database?.connection;
@@ -2,6 +2,7 @@ import { Injector } from '../../injector/index.js';
2
2
  import { type DatabaseConfig } from '../../orm/server/index.js';
3
3
  export declare class PostgresLockModuleConfig {
4
4
  database?: DatabaseConfig;
5
+ autoMigrate?: boolean;
5
6
  }
6
7
  /**
7
8
  * configure lock module
@@ -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 { Lock } from '../lock.js';
5
5
  import { LockProvider } from '../provider.js';
@@ -7,6 +7,7 @@ import { PostgresLockAdapter } from './lock.js';
7
7
  import { PostgresLockProvider } from './provider.js';
8
8
  export class PostgresLockModuleConfig {
9
9
  database;
10
+ autoMigrate;
10
11
  }
11
12
  /**
12
13
  * configure lock module
@@ -18,6 +19,9 @@ export function configurePostgresLock({ injector, ...config } = {}) {
18
19
  }
19
20
  targetInjector.registerSingleton(LockProvider, { useToken: PostgresLockProvider });
20
21
  targetInjector.registerSingleton(Lock, { useToken: PostgresLockAdapter });
22
+ if (config.autoMigrate != false) {
23
+ registerDatabaseMigration('PostgresLock', migratePostgresLockSchema, { injector });
24
+ }
21
25
  }
22
26
  export async function migratePostgresLockSchema() {
23
27
  const connection = inject(PostgresLockModuleConfig, undefined, { optional: true })?.database?.connection;
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): void;
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
- Injector.register(MailModuleConfig, { useValue: config });
17
+ export function configureMail({ injector, ...config }) {
18
+ const targetInjector = injector ?? Injector;
19
+ targetInjector.register(MailModuleConfig, { useValue: config });
18
20
  if (isDefined(config.defaultClientConfig)) {
19
- Injector.registerSingleton(MailClientConfig, { useValue: config.defaultClientConfig });
21
+ targetInjector.registerSingleton(MailClientConfig, { useValue: config.defaultClientConfig });
20
22
  }
21
23
  if (isDefined(config.client)) {
22
- Injector.registerSingleton(MailClient, { useToken: config.client });
24
+ targetInjector.registerSingleton(MailClient, { useToken: config.client });
23
25
  }
24
26
  if (isDefined(config.defaultData)) {
25
- Injector.registerSingleton(MAIL_DEFAULT_DATA, { useValue: config.defaultData });
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.port ?? 8000);
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.