@decaf-ts/for-typeorm 0.0.6

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 (109) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +93 -0
  3. package/dist/for-typeorm.cjs +2553 -0
  4. package/dist/for-typeorm.esm.cjs +2538 -0
  5. package/lib/TypeORMAdapter.cjs +1129 -0
  6. package/lib/TypeORMAdapter.d.ts +221 -0
  7. package/lib/TypeORMDispatch.cjs +134 -0
  8. package/lib/TypeORMDispatch.d.ts +87 -0
  9. package/lib/TypeORMEventSubscriber.cjs +96 -0
  10. package/lib/TypeORMEventSubscriber.d.ts +56 -0
  11. package/lib/TypeORMRepository.cjs +209 -0
  12. package/lib/TypeORMRepository.d.ts +125 -0
  13. package/lib/constants.cjs +43 -0
  14. package/lib/constants.d.ts +39 -0
  15. package/lib/errors.cjs +28 -0
  16. package/lib/errors.d.ts +21 -0
  17. package/lib/esm/TypeORMAdapter.d.ts +221 -0
  18. package/lib/esm/TypeORMAdapter.js +1124 -0
  19. package/lib/esm/TypeORMDispatch.d.ts +87 -0
  20. package/lib/esm/TypeORMDispatch.js +130 -0
  21. package/lib/esm/TypeORMEventSubscriber.d.ts +56 -0
  22. package/lib/esm/TypeORMEventSubscriber.js +93 -0
  23. package/lib/esm/TypeORMRepository.d.ts +125 -0
  24. package/lib/esm/TypeORMRepository.js +206 -0
  25. package/lib/esm/constants.d.ts +39 -0
  26. package/lib/esm/constants.js +40 -0
  27. package/lib/esm/errors.d.ts +21 -0
  28. package/lib/esm/errors.js +24 -0
  29. package/lib/esm/index.d.ts +22 -0
  30. package/lib/esm/index.js +25 -0
  31. package/lib/esm/indexes/generator.d.ts +50 -0
  32. package/lib/esm/indexes/generator.js +95 -0
  33. package/lib/esm/indexes/index.d.ts +1 -0
  34. package/lib/esm/indexes/index.js +2 -0
  35. package/lib/esm/overrides/Column.d.ts +74 -0
  36. package/lib/esm/overrides/Column.js +70 -0
  37. package/lib/esm/overrides/CreateDateColumn.d.ts +2 -0
  38. package/lib/esm/overrides/CreateDateColumn.js +9 -0
  39. package/lib/esm/overrides/Entity.d.ts +11 -0
  40. package/lib/esm/overrides/Entity.js +28 -0
  41. package/lib/esm/overrides/PrimaryColumn.d.ts +20 -0
  42. package/lib/esm/overrides/PrimaryColumn.js +53 -0
  43. package/lib/esm/overrides/PrimaryGeneratedColumn.d.ts +24 -0
  44. package/lib/esm/overrides/PrimaryGeneratedColumn.js +51 -0
  45. package/lib/esm/overrides/UpdateDateColumn.d.ts +2 -0
  46. package/lib/esm/overrides/UpdateDateColumn.js +9 -0
  47. package/lib/esm/overrides/utils.d.ts +2 -0
  48. package/lib/esm/overrides/utils.js +29 -0
  49. package/lib/esm/query/Paginator.d.ts +86 -0
  50. package/lib/esm/query/Paginator.js +124 -0
  51. package/lib/esm/query/Statement.d.ts +131 -0
  52. package/lib/esm/query/Statement.js +242 -0
  53. package/lib/esm/query/constants.d.ts +52 -0
  54. package/lib/esm/query/constants.js +74 -0
  55. package/lib/esm/query/index.d.ts +4 -0
  56. package/lib/esm/query/index.js +5 -0
  57. package/lib/esm/query/translate.d.ts +34 -0
  58. package/lib/esm/query/translate.js +42 -0
  59. package/lib/esm/raw/postgres.d.ts +36 -0
  60. package/lib/esm/raw/postgres.js +2 -0
  61. package/lib/esm/sequences/Sequence.d.ts +67 -0
  62. package/lib/esm/sequences/Sequence.js +117 -0
  63. package/lib/esm/sequences/index.d.ts +1 -0
  64. package/lib/esm/sequences/index.js +2 -0
  65. package/lib/esm/types.d.ts +67 -0
  66. package/lib/esm/types.js +28 -0
  67. package/lib/esm/utils.d.ts +16 -0
  68. package/lib/esm/utils.js +29 -0
  69. package/lib/index.cjs +42 -0
  70. package/lib/index.d.ts +22 -0
  71. package/lib/indexes/generator.cjs +98 -0
  72. package/lib/indexes/generator.d.ts +50 -0
  73. package/lib/indexes/index.cjs +18 -0
  74. package/lib/indexes/index.d.ts +1 -0
  75. package/lib/overrides/Column.cjs +73 -0
  76. package/lib/overrides/Column.d.ts +74 -0
  77. package/lib/overrides/CreateDateColumn.cjs +12 -0
  78. package/lib/overrides/CreateDateColumn.d.ts +2 -0
  79. package/lib/overrides/Entity.cjs +31 -0
  80. package/lib/overrides/Entity.d.ts +11 -0
  81. package/lib/overrides/PrimaryColumn.cjs +56 -0
  82. package/lib/overrides/PrimaryColumn.d.ts +20 -0
  83. package/lib/overrides/PrimaryGeneratedColumn.cjs +54 -0
  84. package/lib/overrides/PrimaryGeneratedColumn.d.ts +24 -0
  85. package/lib/overrides/UpdateDateColumn.cjs +12 -0
  86. package/lib/overrides/UpdateDateColumn.d.ts +2 -0
  87. package/lib/overrides/utils.cjs +32 -0
  88. package/lib/overrides/utils.d.ts +2 -0
  89. package/lib/query/Paginator.cjs +128 -0
  90. package/lib/query/Paginator.d.ts +86 -0
  91. package/lib/query/Statement.cjs +246 -0
  92. package/lib/query/Statement.d.ts +131 -0
  93. package/lib/query/constants.cjs +77 -0
  94. package/lib/query/constants.d.ts +52 -0
  95. package/lib/query/index.cjs +21 -0
  96. package/lib/query/index.d.ts +4 -0
  97. package/lib/query/translate.cjs +45 -0
  98. package/lib/query/translate.d.ts +34 -0
  99. package/lib/raw/postgres.cjs +3 -0
  100. package/lib/raw/postgres.d.ts +36 -0
  101. package/lib/sequences/Sequence.cjs +121 -0
  102. package/lib/sequences/Sequence.d.ts +67 -0
  103. package/lib/sequences/index.cjs +18 -0
  104. package/lib/sequences/index.d.ts +1 -0
  105. package/lib/types.cjs +31 -0
  106. package/lib/types.d.ts +67 -0
  107. package/lib/utils.cjs +32 -0
  108. package/lib/utils.d.ts +16 -0
  109. package/package.json +128 -0
@@ -0,0 +1,221 @@
1
+ import { Adapter, RelationsMetadata, Sequence, type SequenceOptions } from "@decaf-ts/core";
2
+ import { BaseError, Context, OperationKeys } from "@decaf-ts/db-decorators";
3
+ import "reflect-metadata";
4
+ import { type Constructor, Model } from "@decaf-ts/decorator-validation";
5
+ import { TypeORMStatement } from "./query";
6
+ import { TypeORMFlags, TypeORMQuery, TypeORMTableSpec } from "./types";
7
+ import { TypeORMRepository } from "./TypeORMRepository";
8
+ import { TypeORMDispatch } from "./TypeORMDispatch";
9
+ import { DataSource } from "typeorm";
10
+ import { DataSourceOptions } from "typeorm/data-source/DataSourceOptions";
11
+ export declare function createdByOnPostgresCreateUpdate<M extends Model, R extends TypeORMRepository<M>, V extends RelationsMetadata>(this: R, context: Context<TypeORMFlags>, data: V, key: keyof M, model: M): Promise<void>;
12
+ /**
13
+ * @description Adapter for TypeORM-backed persistence operations.
14
+ * @summary Implements the Decaf.ts Adapter over a TypeORM DataSource, providing CRUD operations, query/statement factories, sequence management, error parsing, and decoration helpers.
15
+ * @template Y The native configuration type (TypeORM DataSourceOptions).
16
+ * @template F The repository flags type.
17
+ * @template C The context type.
18
+ * @param {DataSourceOptions} scope The DataSource options for the adapter.
19
+ * @param {string} flavour The flavour of the adapter.
20
+ * @param {string} [alias] Optional alias for the adapter.
21
+ * @class TypeORMAdapter
22
+ * @example
23
+ * const adapter = new TypeORMAdapter({ type: 'postgres', /* ... *\/ });
24
+ * await adapter.initialize();
25
+ * const repo = new (adapter.repository<User>())(adapter, User);
26
+ * const created = await repo.create(new User({ name: 'Alice' }));
27
+ *
28
+ * @mermaid
29
+ * sequenceDiagram
30
+ * participant App
31
+ * participant Adapter as TypeORMAdapter
32
+ * participant Repo as TypeORMRepository
33
+ * participant DS as TypeORM DataSource
34
+ *
35
+ * App->>Adapter: new TypeORMAdapter(opts)
36
+ * Adapter->>DS: initialize()
37
+ * App->>Adapter: repository()
38
+ * Adapter-->>App: TypeORMRepository
39
+ * App->>Repo: create(model)
40
+ * Repo->>Adapter: prepare/create/revert
41
+ * Adapter-->>Repo: Model
42
+ * Repo-->>App: Model
43
+ */
44
+ export declare class TypeORMAdapter extends Adapter<DataSourceOptions, TypeORMQuery, TypeORMFlags, Context<TypeORMFlags>> {
45
+ private _dataSource?;
46
+ get dataSource(): DataSource;
47
+ constructor(options: DataSourceOptions, alias?: string);
48
+ protected flags<M extends Model>(operation: OperationKeys, model: Constructor<M>, flags: Partial<TypeORMFlags>): Promise<TypeORMFlags>;
49
+ protected Dispatch(): TypeORMDispatch;
50
+ repository<M extends Model>(): Constructor<TypeORMRepository<M>>;
51
+ /**
52
+ * @description Creates a new Postgres statement for querying
53
+ * @summary Factory method that creates a new PostgresStatement instance for building queries
54
+ * @template M - The model type
55
+ * @return {TypeORMStatement<M, any>} A new PostgresStatement instance
56
+ */
57
+ Statement<M extends Model>(): TypeORMStatement<M, any>;
58
+ /**
59
+ * @description Creates a new PostgreSQL sequence
60
+ * @summary Factory method that creates a new PostgreSQLSequence instance for managing sequences
61
+ * @param {SequenceOptions} options - The options for the sequence
62
+ * @return {Promise<Sequence>} A promise that resolves to a new Sequence instance
63
+ */
64
+ Sequence(options: SequenceOptions): Promise<Sequence>;
65
+ /**
66
+ * @description Initializes the adapter by creating indexes for all managed models
67
+ * @summary Sets up the necessary database indexes for all models managed by this adapter
68
+ * @return {Promise<void>} A promise that resolves when initialization is complete
69
+ */
70
+ initialize(): Promise<void>;
71
+ /**
72
+ * @description Creates indexes for the given models
73
+ * @summary Abstract method that must be implemented to create database indexes for the specified models
74
+ * @template M - The model type
75
+ * @param {...Constructor<M>} models - The model constructors to create indexes for
76
+ * @return {Promise<void>} A promise that resolves when all indexes are created
77
+ */
78
+ protected index<M extends Model>(...models: Constructor<M>[]): Promise<void>;
79
+ /**
80
+ * @description Executes a raw SQL query against the database
81
+ * @summary Abstract method that must be implemented to execute raw SQL queries
82
+ * @template R - The result type
83
+ * @param {TypeORMQuery} q - The query to execute
84
+ * @return {Promise<R>} A promise that resolves to the query result
85
+ */
86
+ raw<R>(q: TypeORMQuery): Promise<R>;
87
+ prepare<M extends Model>(model: M, pk: keyof M, child?: boolean): {
88
+ record: Record<string, any>;
89
+ id: string;
90
+ transient?: Record<string, any>;
91
+ };
92
+ revert<M extends Model>(obj: Record<string, any>, clazz: string | Constructor<M>, pk: keyof M, id: string | number | bigint, transient?: Record<string, any>): M;
93
+ /**
94
+ * @description Creates a new record in the database
95
+ * @summary Abstract method that must be implemented to create a new record
96
+ * @param {string} tableName - The name of the table
97
+ * @param {string|number} id - The ID of the record
98
+ * @param {Record<string, any>} model - The model to create
99
+ * @param {...any[]} args - Additional arguments
100
+ * @return {Promise<Record<string, any>>} A promise that resolves to the created record
101
+ */
102
+ create(tableName: string, id: string | number, model: Record<string, any>, ...args: any[]): Promise<Record<string, any>>;
103
+ /**
104
+ * @description Reads a record from the database
105
+ * @summary Abstract method that must be implemented to read a record
106
+ * @param {string} tableName - The name of the table
107
+ * @param {string|number} id - The ID of the record
108
+ * @param {string} pk - primary key colum
109
+ * @return {Promise<Record<string, any>>} A promise that resolves to the read record
110
+ */
111
+ read(tableName: string, id: string | number, pk: string): Promise<Record<string, any>>;
112
+ /**
113
+ * @description Updates a record in the database
114
+ * @summary Abstract method that must be implemented to update a record
115
+ * @param {string} tableName - The name of the table
116
+ * @param {string|number} id - The ID of the record
117
+ * @param {Record<string, any>} model - The model to update
118
+ * @param {string} pk - Additional arguments
119
+ * @return A promise that resolves to the updated record
120
+ */
121
+ update(tableName: string, id: string | number, model: Record<string, any>, ...args: any[]): Promise<Record<string, any>>;
122
+ /**
123
+ * @description Deletes a record from the database
124
+ * @summary Abstract method that must be implemented to delete a record
125
+ * @param {string} tableName - The name of the table
126
+ * @param {string|number} id - The ID of the record
127
+ * @param {string} pk - Additional arguments
128
+ * @return A promise that resolves to the deleted record
129
+ */
130
+ delete(tableName: string, id: string | number, pk: string, ...args: any[]): Promise<Record<string, any>>;
131
+ createAll(tableName: string, id: (string | number)[], model: Record<string, any>[], ...args: any[]): Promise<Record<string, any>[]>;
132
+ readAll(tableName: string, id: (string | number | bigint)[], pk: string, ...args: any[]): Promise<Record<string, any>[]>;
133
+ updateAll(tableName: string, ids: string[] | number[], model: Record<string, any>[], pk: string, ...args: any[]): Promise<Record<string, any>[]>;
134
+ deleteAll(tableName: string, ids: (string | number | bigint)[], pk: string, ...args: any[]): Promise<Record<string, any>[]>;
135
+ /**
136
+ * @description Parses an error and converts it to a BaseError
137
+ * @summary Converts various error types to appropriate BaseError subtypes
138
+ * @param {Error|string} err - The error to parse
139
+ * @param {string} [reason] - Optional reason for the error
140
+ * @return {BaseError} The parsed error as a BaseError
141
+ */
142
+ parseError(err: Error | string, reason?: string): BaseError;
143
+ /**
144
+ * @description Checks if an attribute is reserved
145
+ * @summary Determines if an attribute name is reserved in PostgreSQL
146
+ * @param {string} attr - The attribute name to check
147
+ * @return {boolean} True if the attribute is reserved, false otherwise
148
+ */
149
+ protected isReserved(attr: string): boolean;
150
+ /**
151
+ * @description Static method to parse an error and convert it to a BaseError
152
+ * @summary Converts various error types to appropriate BaseError subtypes based on PostgreSQL error codes and messages
153
+ * @param {Error|string} err - The error to parse
154
+ * @param {string} [reason] - Optional reason for the error
155
+ * @return {BaseError} The parsed error as a BaseError
156
+ * @mermaid
157
+ * sequenceDiagram
158
+ * participant Caller
159
+ * participant parseError
160
+ * participant ErrorTypes
161
+ *
162
+ * Caller->>parseError: err, reason
163
+ * Note over parseError: Check if err is already a BaseError
164
+ * alt err is BaseError
165
+ * parseError-->>Caller: return err
166
+ * else err is string
167
+ * Note over parseError: Extract code from string
168
+ * alt code matches "duplicate key|already exists"
169
+ * parseError->>ErrorTypes: new ConflictError(code)
170
+ * ErrorTypes-->>Caller: ConflictError
171
+ * else code matches "does not exist|not found"
172
+ * parseError->>ErrorTypes: new NotFoundError(code)
173
+ * ErrorTypes-->>Caller: NotFoundError
174
+ * end
175
+ * else err has code property
176
+ * Note over parseError: Extract code and reason
177
+ * else
178
+ * Note over parseError: Use err.message as code
179
+ * end
180
+ *
181
+ * Note over parseError: Switch on PostgreSQL error code
182
+ * alt code is 23505 (unique_violation)
183
+ * parseError->>ErrorTypes: new ConflictError(reason)
184
+ * ErrorTypes-->>Caller: ConflictError
185
+ * else code is 23503 (foreign_key_violation)
186
+ * parseError->>ErrorTypes: new ConflictError(reason)
187
+ * ErrorTypes-->>Caller: ConflictError
188
+ * else code is 42P01 (undefined_table)
189
+ * parseError->>ErrorTypes: new NotFoundError(reason)
190
+ * ErrorTypes-->>Caller: NotFoundError
191
+ * else code is 42703 (undefined_column)
192
+ * parseError->>ErrorTypes: new NotFoundError(reason)
193
+ * ErrorTypes-->>Caller: NotFoundError
194
+ * else code is 42P07 (duplicate_table)
195
+ * parseError->>ErrorTypes: new ConflictError(reason)
196
+ * ErrorTypes-->>Caller: ConflictError
197
+ * else code is 42P16 (invalid_table_definition)
198
+ * parseError->>ErrorTypes: new IndexError(err)
199
+ * ErrorTypes-->>Caller: IndexError
200
+ * else code matches "ECONNREFUSED"
201
+ * parseError->>ErrorTypes: new ConnectionError(err)
202
+ * ErrorTypes-->>Caller: ConnectionError
203
+ * else
204
+ * parseError->>ErrorTypes: new InternalError(err)
205
+ * ErrorTypes-->>Caller: InternalError
206
+ * end
207
+ */
208
+ protected static parseError(err: Error | string, reason?: string): BaseError;
209
+ static connect(config: DataSourceOptions): Promise<DataSource>;
210
+ static createDatabase(dataSource: DataSource, dbName: string): Promise<void>;
211
+ static createNotifyFunction(dataSource: DataSource, user: string): Promise<void>;
212
+ static deleteDatabase(dataSource: DataSource, dbName: string, user?: string): Promise<void>;
213
+ static createUser(dataSource: DataSource, dbName: string, user: string, password: string): Promise<void>;
214
+ static deleteUser(client: DataSource, user: string, admin: string): Promise<void>;
215
+ private static parseTypeToPostgres;
216
+ private static parseValidationToPostgres;
217
+ private static parseRelationsToPostgres;
218
+ static createTable<M extends Model>(client: DataSource, model: Constructor<M>): Promise<Record<string, TypeORMTableSpec>>;
219
+ static getCurrentUser(client: DataSource): Promise<string>;
220
+ static decoration(): void;
221
+ }
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TypeORMDispatch = void 0;
4
+ const core_1 = require("@decaf-ts/core");
5
+ const db_decorators_1 = require("@decaf-ts/db-decorators");
6
+ const TypeORMEventSubscriber_1 = require("./TypeORMEventSubscriber.cjs");
7
+ /**
8
+ * @description Dispatcher for TypeORM-driven change events.
9
+ * @summary Subscribes a TypeORM DataSource with a custom EntitySubscriber to notify observers when records are created, updated, or deleted.
10
+ * @param {number} [timeout=5000] Timeout in milliseconds for initialization retries.
11
+ * @class TypeORMDispatch
12
+ * @example
13
+ * // Create a dispatcher for a TypeORM DataSource
14
+ * const dispatch = new TypeORMDispatch();
15
+ * await dispatch.observe(adapter, adapter.dataSource.options);
16
+ *
17
+ * // The dispatcher registers a TypeORMEventSubscriber and notifies observers when entities change.
18
+ * @mermaid
19
+ * classDiagram
20
+ * class Dispatch {
21
+ * +initialize()
22
+ * +updateObservers()
23
+ * }
24
+ * class TypeORMDispatch {
25
+ * -observerLastUpdate?: string
26
+ * -attemptCounter: number
27
+ * -timeout: number
28
+ * +constructor(timeout)
29
+ * #notificationHandler()
30
+ * #initialize()
31
+ * }
32
+ * Dispatch <|-- TypeORMDispatch
33
+ */
34
+ class TypeORMDispatch extends core_1.Dispatch {
35
+ constructor(timeout = 5000) {
36
+ super();
37
+ this.timeout = timeout;
38
+ this.attemptCounter = 0;
39
+ }
40
+ /**
41
+ * @description Processes TypeORM notification events.
42
+ * @summary Handles change notifications (translated from TypeORM events) and notifies observers about record changes.
43
+ * @param {string} table The notification payload.
44
+ * @param {OperationKeys} operation The notification payload.
45
+ * @param {EventIds} ids The notification payload.
46
+ * @return {Promise<void>} A promise that resolves when all notifications have been processed.
47
+ * @mermaid
48
+ * sequenceDiagram
49
+ * participant D as PostgreSQLDispatch
50
+ * participant L as Logger
51
+ * participant O as Observers
52
+ * Note over D: Receive notification from PostgreSQL
53
+ * D->>D: Parse notification payload
54
+ * D->>D: Extract table, operation, and ids
55
+ * D->>O: updateObservers(table, operation, ids)
56
+ * D->>D: Update observerLastUpdate
57
+ * D->>L: Log successful dispatch
58
+ */
59
+ async notificationHandler(table, operation, ids) {
60
+ const log = this.log.for(this.notificationHandler);
61
+ try {
62
+ // Notify observers
63
+ await this.updateObservers(table, operation, ids);
64
+ this.observerLastUpdate = new Date().toISOString();
65
+ log.verbose(`Observer refresh dispatched by ${operation} for ${table}`);
66
+ log.debug(`pks: ${ids}`);
67
+ }
68
+ catch (e) {
69
+ log.error(`Failed to process notification: ${e}`);
70
+ }
71
+ }
72
+ /**
73
+ * @description Initializes the dispatcher and subscribes to TypeORM notifications.
74
+ * @summary Registers the TypeORMEventSubscriber on the DataSource and logs the subscription lifecycle.
75
+ * @return {Promise<void>} A promise that resolves when the subscription is established.
76
+ * @mermaid
77
+ * sequenceDiagram
78
+ * participant D as TypeORMDispatch
79
+ * participant S as subscribeToTypeORM
80
+ * participant DS as TypeORM DataSource
81
+ * participant L as Logger
82
+ * D->>S: Call subscribeToTypeORM
83
+ * S->>S: Check adapter and native
84
+ * alt No adapter or native
85
+ * S-->>S: throw InternalError
86
+ * end
87
+ * S->>DS: initialize()
88
+ * S->>DS: subscribers.push(TypeORMEventSubscriber)
89
+ * alt Success
90
+ * DS-->>S: Subscription established
91
+ * S-->>D: Promise resolves
92
+ * D->>L: Log successful subscription
93
+ * else Error
94
+ * DS-->>S: Error
95
+ * S-->>D: Promise rejects
96
+ * end
97
+ */
98
+ async initialize() {
99
+ async function subscribeToTypeORM() {
100
+ if (!this.adapter || !this.native) {
101
+ throw new db_decorators_1.InternalError(`No adapter/native observed for dispatch`);
102
+ }
103
+ const adapter = this.adapter;
104
+ try {
105
+ if (!adapter.dataSource.isInitialized)
106
+ await adapter.dataSource.initialize();
107
+ adapter.dataSource.subscribers.push(new TypeORMEventSubscriber_1.TypeORMEventSubscriber(this.notificationHandler.bind(this)));
108
+ }
109
+ catch (e) {
110
+ throw new db_decorators_1.InternalError(e);
111
+ }
112
+ }
113
+ subscribeToTypeORM
114
+ .call(this)
115
+ .then(() => {
116
+ this.log.info(`Subscribed to TypeORM notifications`);
117
+ })
118
+ .catch((e) => {
119
+ throw new db_decorators_1.InternalError(`Failed to subscribe to TypeORM notifications: ${e}`);
120
+ });
121
+ }
122
+ /**
123
+ * Cleanup method to release resources when the dispatcher is no longer needed
124
+ */
125
+ cleanup() {
126
+ // if (this.adapter) {
127
+ //
128
+ // const adapter = this.adapter as TypeORMAdapter;
129
+ // await adapter.dataSource.destroy();
130
+ // }
131
+ }
132
+ }
133
+ exports.TypeORMDispatch = TypeORMDispatch;
134
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVHlwZU9STURpc3BhdGNoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL1R5cGVPUk1EaXNwYXRjaC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSx5Q0FBb0Q7QUFDcEQsMkRBQXVFO0FBR3ZFLHlFQUFrRTtBQUVsRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0EwQkc7QUFDSCxNQUFhLGVBQWdCLFNBQVEsZUFBMkI7SUFJOUQsWUFBb0IsVUFBVSxJQUFJO1FBQ2hDLEtBQUssRUFBRSxDQUFDO1FBRFUsWUFBTyxHQUFQLE9BQU8sQ0FBTztRQUYxQixtQkFBYyxHQUFXLENBQUMsQ0FBQztJQUluQyxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7OztPQWtCRztJQUNPLEtBQUssQ0FBQyxtQkFBbUIsQ0FDakMsS0FBYSxFQUNiLFNBQXdCLEVBQ3hCLEdBQWE7UUFFYixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUNuRCxJQUFJLENBQUM7WUFDSCxtQkFBbUI7WUFDbkIsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLEtBQUssRUFBRSxTQUFTLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDbEQsSUFBSSxDQUFDLGtCQUFrQixHQUFHLElBQUksSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDbkQsR0FBRyxDQUFDLE9BQU8sQ0FBQyxrQ0FBa0MsU0FBUyxRQUFRLEtBQUssRUFBRSxDQUFDLENBQUM7WUFDeEUsR0FBRyxDQUFDLEtBQUssQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDM0IsQ0FBQztRQUFDLE9BQU8sQ0FBVSxFQUFFLENBQUM7WUFDcEIsR0FBRyxDQUFDLEtBQUssQ0FBQyxtQ0FBbUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNwRCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O09BeUJHO0lBQ2dCLEtBQUssQ0FBQyxVQUFVO1FBQ2pDLEtBQUssVUFBVSxrQkFBa0I7WUFDL0IsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQ2xDLE1BQU0sSUFBSSw2QkFBYSxDQUFDLHlDQUF5QyxDQUFDLENBQUM7WUFDckUsQ0FBQztZQUVELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxPQUF5QixDQUFDO1lBRS9DLElBQUksQ0FBQztnQkFDSCxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxhQUFhO29CQUNuQyxNQUFNLE9BQU8sQ0FBQyxVQUFVLENBQUMsVUFBVSxFQUFFLENBQUM7Z0JBRXhDLE9BQU8sQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLElBQUksQ0FDakMsSUFBSSwrQ0FBc0IsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQ2hFLENBQUM7WUFDSixDQUFDO1lBQUMsT0FBTyxDQUFVLEVBQUUsQ0FBQztnQkFDcEIsTUFBTSxJQUFJLDZCQUFhLENBQUMsQ0FBVSxDQUFDLENBQUM7WUFDdEMsQ0FBQztRQUNILENBQUM7UUFFRCxrQkFBa0I7YUFDZixJQUFJLENBQUMsSUFBSSxDQUFDO2FBQ1YsSUFBSSxDQUFDLEdBQUcsRUFBRTtZQUNULElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLHFDQUFxQyxDQUFDLENBQUM7UUFDdkQsQ0FBQyxDQUFDO2FBQ0QsS0FBSyxDQUFDLENBQUMsQ0FBVSxFQUFFLEVBQUU7WUFDcEIsTUFBTSxJQUFJLDZCQUFhLENBQ3JCLGlEQUFpRCxDQUFDLEVBQUUsQ0FDckQsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVEOztPQUVHO0lBQ0ksT0FBTztRQUNaLHNCQUFzQjtRQUN0QixFQUFFO1FBQ0Ysb0RBQW9EO1FBQ3BELHdDQUF3QztRQUN4QyxJQUFJO0lBQ04sQ0FBQztDQUNGO0FBaEhELDBDQWdIQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERpc3BhdGNoLCBFdmVudElkcyB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgSW50ZXJuYWxFcnJvciwgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgRGF0YVNvdXJjZU9wdGlvbnMgfSBmcm9tIFwidHlwZW9ybS9kYXRhLXNvdXJjZS9EYXRhU291cmNlT3B0aW9uc1wiO1xuaW1wb3J0IHsgVHlwZU9STUFkYXB0ZXIgfSBmcm9tIFwiLi9UeXBlT1JNQWRhcHRlclwiO1xuaW1wb3J0IHsgVHlwZU9STUV2ZW50U3Vic2NyaWJlciB9IGZyb20gXCIuL1R5cGVPUk1FdmVudFN1YnNjcmliZXJcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGlzcGF0Y2hlciBmb3IgVHlwZU9STS1kcml2ZW4gY2hhbmdlIGV2ZW50cy5cbiAqIEBzdW1tYXJ5IFN1YnNjcmliZXMgYSBUeXBlT1JNIERhdGFTb3VyY2Ugd2l0aCBhIGN1c3RvbSBFbnRpdHlTdWJzY3JpYmVyIHRvIG5vdGlmeSBvYnNlcnZlcnMgd2hlbiByZWNvcmRzIGFyZSBjcmVhdGVkLCB1cGRhdGVkLCBvciBkZWxldGVkLlxuICogQHBhcmFtIHtudW1iZXJ9IFt0aW1lb3V0PTUwMDBdIFRpbWVvdXQgaW4gbWlsbGlzZWNvbmRzIGZvciBpbml0aWFsaXphdGlvbiByZXRyaWVzLlxuICogQGNsYXNzIFR5cGVPUk1EaXNwYXRjaFxuICogQGV4YW1wbGVcbiAqIC8vIENyZWF0ZSBhIGRpc3BhdGNoZXIgZm9yIGEgVHlwZU9STSBEYXRhU291cmNlXG4gKiBjb25zdCBkaXNwYXRjaCA9IG5ldyBUeXBlT1JNRGlzcGF0Y2goKTtcbiAqIGF3YWl0IGRpc3BhdGNoLm9ic2VydmUoYWRhcHRlciwgYWRhcHRlci5kYXRhU291cmNlLm9wdGlvbnMpO1xuICpcbiAqIC8vIFRoZSBkaXNwYXRjaGVyIHJlZ2lzdGVycyBhIFR5cGVPUk1FdmVudFN1YnNjcmliZXIgYW5kIG5vdGlmaWVzIG9ic2VydmVycyB3aGVuIGVudGl0aWVzIGNoYW5nZS5cbiAqIEBtZXJtYWlkXG4gKiBjbGFzc0RpYWdyYW1cbiAqICAgY2xhc3MgRGlzcGF0Y2gge1xuICogICAgICtpbml0aWFsaXplKClcbiAqICAgICArdXBkYXRlT2JzZXJ2ZXJzKClcbiAqICAgfVxuICogICBjbGFzcyBUeXBlT1JNRGlzcGF0Y2gge1xuICogICAgIC1vYnNlcnZlckxhc3RVcGRhdGU/OiBzdHJpbmdcbiAqICAgICAtYXR0ZW1wdENvdW50ZXI6IG51bWJlclxuICogICAgIC10aW1lb3V0OiBudW1iZXJcbiAqICAgICArY29uc3RydWN0b3IodGltZW91dClcbiAqICAgICAjbm90aWZpY2F0aW9uSGFuZGxlcigpXG4gKiAgICAgI2luaXRpYWxpemUoKVxuICogICB9XG4gKiAgIERpc3BhdGNoIDx8LS0gVHlwZU9STURpc3BhdGNoXG4gKi9cbmV4cG9ydCBjbGFzcyBUeXBlT1JNRGlzcGF0Y2ggZXh0ZW5kcyBEaXNwYXRjaDxEYXRhU291cmNlT3B0aW9ucz4ge1xuICBwcml2YXRlIG9ic2VydmVyTGFzdFVwZGF0ZT86IHN0cmluZztcbiAgcHJpdmF0ZSBhdHRlbXB0Q291bnRlcjogbnVtYmVyID0gMDtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHRpbWVvdXQgPSA1MDAwKSB7XG4gICAgc3VwZXIoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJvY2Vzc2VzIFR5cGVPUk0gbm90aWZpY2F0aW9uIGV2ZW50cy5cbiAgICogQHN1bW1hcnkgSGFuZGxlcyBjaGFuZ2Ugbm90aWZpY2F0aW9ucyAodHJhbnNsYXRlZCBmcm9tIFR5cGVPUk0gZXZlbnRzKSBhbmQgbm90aWZpZXMgb2JzZXJ2ZXJzIGFib3V0IHJlY29yZCBjaGFuZ2VzLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFibGUgVGhlIG5vdGlmaWNhdGlvbiBwYXlsb2FkLlxuICAgKiBAcGFyYW0ge09wZXJhdGlvbktleXN9IG9wZXJhdGlvbiBUaGUgbm90aWZpY2F0aW9uIHBheWxvYWQuXG4gICAqIEBwYXJhbSB7RXZlbnRJZHN9IGlkcyBUaGUgbm90aWZpY2F0aW9uIHBheWxvYWQuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gYWxsIG5vdGlmaWNhdGlvbnMgaGF2ZSBiZWVuIHByb2Nlc3NlZC5cbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgRCBhcyBQb3N0Z3JlU1FMRGlzcGF0Y2hcbiAgICogICBwYXJ0aWNpcGFudCBMIGFzIExvZ2dlclxuICAgKiAgIHBhcnRpY2lwYW50IE8gYXMgT2JzZXJ2ZXJzXG4gICAqICAgTm90ZSBvdmVyIEQ6IFJlY2VpdmUgbm90aWZpY2F0aW9uIGZyb20gUG9zdGdyZVNRTFxuICAgKiAgIEQtPj5EOiBQYXJzZSBub3RpZmljYXRpb24gcGF5bG9hZFxuICAgKiAgIEQtPj5EOiBFeHRyYWN0IHRhYmxlLCBvcGVyYXRpb24sIGFuZCBpZHNcbiAgICogICBELT4+TzogdXBkYXRlT2JzZXJ2ZXJzKHRhYmxlLCBvcGVyYXRpb24sIGlkcylcbiAgICogICBELT4+RDogVXBkYXRlIG9ic2VydmVyTGFzdFVwZGF0ZVxuICAgKiAgIEQtPj5MOiBMb2cgc3VjY2Vzc2Z1bCBkaXNwYXRjaFxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIG5vdGlmaWNhdGlvbkhhbmRsZXIoXG4gICAgdGFibGU6IHN0cmluZyxcbiAgICBvcGVyYXRpb246IE9wZXJhdGlvbktleXMsXG4gICAgaWRzOiBFdmVudElkc1xuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5ub3RpZmljYXRpb25IYW5kbGVyKTtcbiAgICB0cnkge1xuICAgICAgLy8gTm90aWZ5IG9ic2VydmVyc1xuICAgICAgYXdhaXQgdGhpcy51cGRhdGVPYnNlcnZlcnModGFibGUsIG9wZXJhdGlvbiwgaWRzKTtcbiAgICAgIHRoaXMub2JzZXJ2ZXJMYXN0VXBkYXRlID0gbmV3IERhdGUoKS50b0lTT1N0cmluZygpO1xuICAgICAgbG9nLnZlcmJvc2UoYE9ic2VydmVyIHJlZnJlc2ggZGlzcGF0Y2hlZCBieSAke29wZXJhdGlvbn0gZm9yICR7dGFibGV9YCk7XG4gICAgICBsb2cuZGVidWcoYHBrczogJHtpZHN9YCk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgbG9nLmVycm9yKGBGYWlsZWQgdG8gcHJvY2VzcyBub3RpZmljYXRpb246ICR7ZX1gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEluaXRpYWxpemVzIHRoZSBkaXNwYXRjaGVyIGFuZCBzdWJzY3JpYmVzIHRvIFR5cGVPUk0gbm90aWZpY2F0aW9ucy5cbiAgICogQHN1bW1hcnkgUmVnaXN0ZXJzIHRoZSBUeXBlT1JNRXZlbnRTdWJzY3JpYmVyIG9uIHRoZSBEYXRhU291cmNlIGFuZCBsb2dzIHRoZSBzdWJzY3JpcHRpb24gbGlmZWN5Y2xlLlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBzdWJzY3JpcHRpb24gaXMgZXN0YWJsaXNoZWQuXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IEQgYXMgVHlwZU9STURpc3BhdGNoXG4gICAqICAgcGFydGljaXBhbnQgUyBhcyBzdWJzY3JpYmVUb1R5cGVPUk1cbiAgICogICBwYXJ0aWNpcGFudCBEUyBhcyBUeXBlT1JNIERhdGFTb3VyY2VcbiAgICogICBwYXJ0aWNpcGFudCBMIGFzIExvZ2dlclxuICAgKiAgIEQtPj5TOiBDYWxsIHN1YnNjcmliZVRvVHlwZU9STVxuICAgKiAgIFMtPj5TOiBDaGVjayBhZGFwdGVyIGFuZCBuYXRpdmVcbiAgICogICBhbHQgTm8gYWRhcHRlciBvciBuYXRpdmVcbiAgICogICAgIFMtLT4+UzogdGhyb3cgSW50ZXJuYWxFcnJvclxuICAgKiAgIGVuZFxuICAgKiAgIFMtPj5EUzogaW5pdGlhbGl6ZSgpXG4gICAqICAgUy0+PkRTOiBzdWJzY3JpYmVycy5wdXNoKFR5cGVPUk1FdmVudFN1YnNjcmliZXIpXG4gICAqICAgYWx0IFN1Y2Nlc3NcbiAgICogICAgIERTLS0+PlM6IFN1YnNjcmlwdGlvbiBlc3RhYmxpc2hlZFxuICAgKiAgICAgUy0tPj5EOiBQcm9taXNlIHJlc29sdmVzXG4gICAqICAgICBELT4+TDogTG9nIHN1Y2Nlc3NmdWwgc3Vic2NyaXB0aW9uXG4gICAqICAgZWxzZSBFcnJvclxuICAgKiAgICAgRFMtLT4+UzogRXJyb3JcbiAgICogICAgIFMtLT4+RDogUHJvbWlzZSByZWplY3RzXG4gICAqICAgZW5kXG4gICAqL1xuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgYXN5bmMgaW5pdGlhbGl6ZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhc3luYyBmdW5jdGlvbiBzdWJzY3JpYmVUb1R5cGVPUk0odGhpczogVHlwZU9STURpc3BhdGNoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICBpZiAoIXRoaXMuYWRhcHRlciB8fCAhdGhpcy5uYXRpdmUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoYE5vIGFkYXB0ZXIvbmF0aXZlIG9ic2VydmVkIGZvciBkaXNwYXRjaGApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBhZGFwdGVyID0gdGhpcy5hZGFwdGVyIGFzIFR5cGVPUk1BZGFwdGVyO1xuXG4gICAgICB0cnkge1xuICAgICAgICBpZiAoIWFkYXB0ZXIuZGF0YVNvdXJjZS5pc0luaXRpYWxpemVkKVxuICAgICAgICAgIGF3YWl0IGFkYXB0ZXIuZGF0YVNvdXJjZS5pbml0aWFsaXplKCk7XG5cbiAgICAgICAgYWRhcHRlci5kYXRhU291cmNlLnN1YnNjcmliZXJzLnB1c2goXG4gICAgICAgICAgbmV3IFR5cGVPUk1FdmVudFN1YnNjcmliZXIodGhpcy5ub3RpZmljYXRpb25IYW5kbGVyLmJpbmQodGhpcykpXG4gICAgICAgICk7XG4gICAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGUgYXMgRXJyb3IpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHN1YnNjcmliZVRvVHlwZU9STVxuICAgICAgLmNhbGwodGhpcylcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgdGhpcy5sb2cuaW5mbyhgU3Vic2NyaWJlZCB0byBUeXBlT1JNIG5vdGlmaWNhdGlvbnNgKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goKGU6IHVua25vd24pID0+IHtcbiAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgICAgYEZhaWxlZCB0byBzdWJzY3JpYmUgdG8gVHlwZU9STSBub3RpZmljYXRpb25zOiAke2V9YFxuICAgICAgICApO1xuICAgICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ2xlYW51cCBtZXRob2QgdG8gcmVsZWFzZSByZXNvdXJjZXMgd2hlbiB0aGUgZGlzcGF0Y2hlciBpcyBubyBsb25nZXIgbmVlZGVkXG4gICAqL1xuICBwdWJsaWMgY2xlYW51cCgpOiB2b2lkIHtcbiAgICAvLyBpZiAodGhpcy5hZGFwdGVyKSB7XG4gICAgLy9cbiAgICAvLyAgIGNvbnN0IGFkYXB0ZXIgPSB0aGlzLmFkYXB0ZXIgYXMgVHlwZU9STUFkYXB0ZXI7XG4gICAgLy8gICBhd2FpdCBhZGFwdGVyLmRhdGFTb3VyY2UuZGVzdHJveSgpO1xuICAgIC8vIH1cbiAgfVxufVxuIl19
@@ -0,0 +1,87 @@
1
+ import { Dispatch, EventIds } from "@decaf-ts/core";
2
+ import { OperationKeys } from "@decaf-ts/db-decorators";
3
+ import { DataSourceOptions } from "typeorm/data-source/DataSourceOptions";
4
+ /**
5
+ * @description Dispatcher for TypeORM-driven change events.
6
+ * @summary Subscribes a TypeORM DataSource with a custom EntitySubscriber to notify observers when records are created, updated, or deleted.
7
+ * @param {number} [timeout=5000] Timeout in milliseconds for initialization retries.
8
+ * @class TypeORMDispatch
9
+ * @example
10
+ * // Create a dispatcher for a TypeORM DataSource
11
+ * const dispatch = new TypeORMDispatch();
12
+ * await dispatch.observe(adapter, adapter.dataSource.options);
13
+ *
14
+ * // The dispatcher registers a TypeORMEventSubscriber and notifies observers when entities change.
15
+ * @mermaid
16
+ * classDiagram
17
+ * class Dispatch {
18
+ * +initialize()
19
+ * +updateObservers()
20
+ * }
21
+ * class TypeORMDispatch {
22
+ * -observerLastUpdate?: string
23
+ * -attemptCounter: number
24
+ * -timeout: number
25
+ * +constructor(timeout)
26
+ * #notificationHandler()
27
+ * #initialize()
28
+ * }
29
+ * Dispatch <|-- TypeORMDispatch
30
+ */
31
+ export declare class TypeORMDispatch extends Dispatch<DataSourceOptions> {
32
+ private timeout;
33
+ private observerLastUpdate?;
34
+ private attemptCounter;
35
+ constructor(timeout?: number);
36
+ /**
37
+ * @description Processes TypeORM notification events.
38
+ * @summary Handles change notifications (translated from TypeORM events) and notifies observers about record changes.
39
+ * @param {string} table The notification payload.
40
+ * @param {OperationKeys} operation The notification payload.
41
+ * @param {EventIds} ids The notification payload.
42
+ * @return {Promise<void>} A promise that resolves when all notifications have been processed.
43
+ * @mermaid
44
+ * sequenceDiagram
45
+ * participant D as PostgreSQLDispatch
46
+ * participant L as Logger
47
+ * participant O as Observers
48
+ * Note over D: Receive notification from PostgreSQL
49
+ * D->>D: Parse notification payload
50
+ * D->>D: Extract table, operation, and ids
51
+ * D->>O: updateObservers(table, operation, ids)
52
+ * D->>D: Update observerLastUpdate
53
+ * D->>L: Log successful dispatch
54
+ */
55
+ protected notificationHandler(table: string, operation: OperationKeys, ids: EventIds): Promise<void>;
56
+ /**
57
+ * @description Initializes the dispatcher and subscribes to TypeORM notifications.
58
+ * @summary Registers the TypeORMEventSubscriber on the DataSource and logs the subscription lifecycle.
59
+ * @return {Promise<void>} A promise that resolves when the subscription is established.
60
+ * @mermaid
61
+ * sequenceDiagram
62
+ * participant D as TypeORMDispatch
63
+ * participant S as subscribeToTypeORM
64
+ * participant DS as TypeORM DataSource
65
+ * participant L as Logger
66
+ * D->>S: Call subscribeToTypeORM
67
+ * S->>S: Check adapter and native
68
+ * alt No adapter or native
69
+ * S-->>S: throw InternalError
70
+ * end
71
+ * S->>DS: initialize()
72
+ * S->>DS: subscribers.push(TypeORMEventSubscriber)
73
+ * alt Success
74
+ * DS-->>S: Subscription established
75
+ * S-->>D: Promise resolves
76
+ * D->>L: Log successful subscription
77
+ * else Error
78
+ * DS-->>S: Error
79
+ * S-->>D: Promise rejects
80
+ * end
81
+ */
82
+ protected initialize(): Promise<void>;
83
+ /**
84
+ * Cleanup method to release resources when the dispatcher is no longer needed
85
+ */
86
+ cleanup(): void;
87
+ }
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
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
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.TypeORMEventSubscriber = void 0;
13
+ const typeorm_1 = require("typeorm");
14
+ const core_1 = require("@decaf-ts/core");
15
+ const db_decorators_1 = require("@decaf-ts/db-decorators");
16
+ const decorator_validation_1 = require("@decaf-ts/decorator-validation");
17
+ /**
18
+ * @description TypeORM event subscriber that forwards entity lifecycle events to the adapter.
19
+ * @summary Listens for insert, update, and remove events emitted by TypeORM and notifies the Decaf.ts adapter so that observers can be updated accordingly.
20
+ * @param {TypeORMAdapter} adapter The TypeORM adapter used to propagate events and look up metadata.
21
+ * @class
22
+ * @example
23
+ * // Registering the subscriber when creating a DataSource
24
+ * // dataSourceOptions.subscribers = [new TypeORMEventSubscriber(adapter)];
25
+ *
26
+ * @mermaid
27
+ * sequenceDiagram
28
+ * participant TypeORM
29
+ * participant Subscriber as TypeORMEventSubscriber
30
+ * participant Adapter as TypeORMAdapter
31
+ * participant Observers
32
+ *
33
+ * TypeORM->>Subscriber: afterInsert(entity)
34
+ * Subscriber->>Adapter: updateObservers(table, CREATE, [id])
35
+ * Adapter->>Observers: notify(table, CREATE, [id])
36
+ *
37
+ * TypeORM->>Subscriber: afterUpdate(event)
38
+ * Subscriber->>Adapter: updateObservers(table, UPDATE, [id])
39
+ * Adapter->>Observers: notify(table, UPDATE, [id])
40
+ *
41
+ * TypeORM->>Subscriber: afterRemove(event)
42
+ * Subscriber->>Adapter: updateObservers(table, DELETE, [id])
43
+ * Adapter->>Observers: notify(table, DELETE, [id])
44
+ */
45
+ let TypeORMEventSubscriber = class TypeORMEventSubscriber {
46
+ constructor(handler) {
47
+ this.handler = handler;
48
+ }
49
+ /**
50
+ * @description Handles post-insert events.
51
+ * @summary Notifies observers about a create operation for the inserted entity.
52
+ * @param {InsertEvent<any>} event The TypeORM insert event.
53
+ * @return {Promise<any>|void} A promise when async or void otherwise.
54
+ */
55
+ afterInsert(event) {
56
+ const constructor = decorator_validation_1.Model.get(event.entity.constructor.name);
57
+ if (!constructor)
58
+ throw new db_decorators_1.InternalError(`No registered model found for ${event.entity.constructor.name}`);
59
+ const tableName = core_1.Repository.table(constructor);
60
+ this.handler(tableName, db_decorators_1.OperationKeys.CREATE, [event.entityId]);
61
+ }
62
+ /**
63
+ * @description Handles post-remove events.
64
+ * @summary Notifies observers about a delete operation for the removed entity.
65
+ * @param {RemoveEvent<any>} event The TypeORM remove event.
66
+ * @return {Promise<any>|void} A promise when async or void otherwise.
67
+ */
68
+ afterRemove(event) {
69
+ const constructor = decorator_validation_1.Model.get(event.entity.constructor.name);
70
+ if (!constructor)
71
+ throw new db_decorators_1.InternalError(`No registered model found for ${event.entity.constructor.name}`);
72
+ const tableName = core_1.Repository.table(constructor);
73
+ this.handler(tableName, db_decorators_1.OperationKeys.DELETE, [event.entityId]);
74
+ }
75
+ /**
76
+ * @description Handles post-update events.
77
+ * @summary Notifies observers about an update operation for the modified entity.
78
+ * @param {UpdateEvent<any>} event The TypeORM update event.
79
+ * @return {Promise<any>|void} A promise when async or void otherwise.
80
+ */
81
+ afterUpdate(event) {
82
+ const constructor = decorator_validation_1.Model.get(event.databaseEntity.constructor.name);
83
+ if (!constructor)
84
+ throw new db_decorators_1.InternalError(`No registered model found for ${event.databaseEntity.constructor.name}`);
85
+ const tableName = core_1.Repository.table(constructor);
86
+ return this.handler(tableName, db_decorators_1.OperationKeys.UPDATE, [
87
+ event.entity["id"],
88
+ ]);
89
+ }
90
+ };
91
+ exports.TypeORMEventSubscriber = TypeORMEventSubscriber;
92
+ exports.TypeORMEventSubscriber = TypeORMEventSubscriber = __decorate([
93
+ (0, typeorm_1.EventSubscriber)(),
94
+ __metadata("design:paramtypes", [Function])
95
+ ], TypeORMEventSubscriber);
96
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVHlwZU9STUV2ZW50U3Vic2NyaWJlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9UeXBlT1JNRXZlbnRTdWJzY3JpYmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztBQUFBLHFDQU1pQjtBQUNqQix5Q0FBc0Q7QUFDdEQsMkRBQXVFO0FBQ3ZFLHlFQUF1RDtBQUV2RDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBMkJHO0FBRUksSUFBTSxzQkFBc0IsR0FBNUIsTUFBTSxzQkFBc0I7SUFDakMsWUFDcUIsT0FJVjtRQUpVLFlBQU8sR0FBUCxPQUFPLENBSWpCO0lBQ1IsQ0FBQztJQUVKOzs7OztPQUtHO0lBQ0gsV0FBVyxDQUFDLEtBQXVCO1FBQ2pDLE1BQU0sV0FBVyxHQUFHLDRCQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzdELElBQUksQ0FBQyxXQUFXO1lBQ2QsTUFBTSxJQUFJLDZCQUFhLENBQ3JCLGlDQUFpQyxLQUFLLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsQ0FDakUsQ0FBQztRQUNKLE1BQU0sU0FBUyxHQUFHLGlCQUFVLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBRWhELElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLDZCQUFhLENBQUMsTUFBTSxFQUFFLENBQUMsS0FBSyxDQUFDLFFBQWUsQ0FBQyxDQUFDLENBQUM7SUFDekUsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsV0FBVyxDQUFDLEtBQXVCO1FBQ2pDLE1BQU0sV0FBVyxHQUFHLDRCQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzdELElBQUksQ0FBQyxXQUFXO1lBQ2QsTUFBTSxJQUFJLDZCQUFhLENBQ3JCLGlDQUFpQyxLQUFLLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsQ0FDakUsQ0FBQztRQUNKLE1BQU0sU0FBUyxHQUFHLGlCQUFVLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBRWhELElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLDZCQUFhLENBQUMsTUFBTSxFQUFFLENBQUMsS0FBSyxDQUFDLFFBQWUsQ0FBQyxDQUFDLENBQUM7SUFDekUsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsV0FBVyxDQUFDLEtBQXVCO1FBQ2pDLE1BQU0sV0FBVyxHQUFHLDRCQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3JFLElBQUksQ0FBQyxXQUFXO1lBQ2QsTUFBTSxJQUFJLDZCQUFhLENBQ3JCLGlDQUFpQyxLQUFLLENBQUMsY0FBYyxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsQ0FDekUsQ0FBQztRQUNKLE1BQU0sU0FBUyxHQUFHLGlCQUFVLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBRWhELE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsNkJBQWEsQ0FBQyxNQUFNLEVBQUU7WUFDbEQsS0FBSyxDQUFDLE1BQWMsQ0FBQyxJQUFJLENBQVE7U0FDbkMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztDQUNGLENBQUE7QUE3RFksd0RBQXNCO2lDQUF0QixzQkFBc0I7SUFEbEMsSUFBQSx5QkFBZSxHQUFFOztHQUNMLHNCQUFzQixDQTZEbEMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBFbnRpdHlTdWJzY3JpYmVySW50ZXJmYWNlLFxuICBFdmVudFN1YnNjcmliZXIsXG4gIEluc2VydEV2ZW50LFxuICBSZW1vdmVFdmVudCxcbiAgVXBkYXRlRXZlbnQsXG59IGZyb20gXCJ0eXBlb3JtXCI7XG5pbXBvcnQgeyBFdmVudElkcywgUmVwb3NpdG9yeSB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgSW50ZXJuYWxFcnJvciwgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFR5cGVPUk0gZXZlbnQgc3Vic2NyaWJlciB0aGF0IGZvcndhcmRzIGVudGl0eSBsaWZlY3ljbGUgZXZlbnRzIHRvIHRoZSBhZGFwdGVyLlxuICogQHN1bW1hcnkgTGlzdGVucyBmb3IgaW5zZXJ0LCB1cGRhdGUsIGFuZCByZW1vdmUgZXZlbnRzIGVtaXR0ZWQgYnkgVHlwZU9STSBhbmQgbm90aWZpZXMgdGhlIERlY2FmLnRzIGFkYXB0ZXIgc28gdGhhdCBvYnNlcnZlcnMgY2FuIGJlIHVwZGF0ZWQgYWNjb3JkaW5nbHkuXG4gKiBAcGFyYW0ge1R5cGVPUk1BZGFwdGVyfSBhZGFwdGVyIFRoZSBUeXBlT1JNIGFkYXB0ZXIgdXNlZCB0byBwcm9wYWdhdGUgZXZlbnRzIGFuZCBsb29rIHVwIG1ldGFkYXRhLlxuICogQGNsYXNzXG4gKiBAZXhhbXBsZVxuICogLy8gUmVnaXN0ZXJpbmcgdGhlIHN1YnNjcmliZXIgd2hlbiBjcmVhdGluZyBhIERhdGFTb3VyY2VcbiAqIC8vIGRhdGFTb3VyY2VPcHRpb25zLnN1YnNjcmliZXJzID0gW25ldyBUeXBlT1JNRXZlbnRTdWJzY3JpYmVyKGFkYXB0ZXIpXTtcbiAqXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IFR5cGVPUk1cbiAqICAgcGFydGljaXBhbnQgU3Vic2NyaWJlciBhcyBUeXBlT1JNRXZlbnRTdWJzY3JpYmVyXG4gKiAgIHBhcnRpY2lwYW50IEFkYXB0ZXIgYXMgVHlwZU9STUFkYXB0ZXJcbiAqICAgcGFydGljaXBhbnQgT2JzZXJ2ZXJzXG4gKlxuICogICBUeXBlT1JNLT4+U3Vic2NyaWJlcjogYWZ0ZXJJbnNlcnQoZW50aXR5KVxuICogICBTdWJzY3JpYmVyLT4+QWRhcHRlcjogdXBkYXRlT2JzZXJ2ZXJzKHRhYmxlLCBDUkVBVEUsIFtpZF0pXG4gKiAgIEFkYXB0ZXItPj5PYnNlcnZlcnM6IG5vdGlmeSh0YWJsZSwgQ1JFQVRFLCBbaWRdKVxuICpcbiAqICAgVHlwZU9STS0+PlN1YnNjcmliZXI6IGFmdGVyVXBkYXRlKGV2ZW50KVxuICogICBTdWJzY3JpYmVyLT4+QWRhcHRlcjogdXBkYXRlT2JzZXJ2ZXJzKHRhYmxlLCBVUERBVEUsIFtpZF0pXG4gKiAgIEFkYXB0ZXItPj5PYnNlcnZlcnM6IG5vdGlmeSh0YWJsZSwgVVBEQVRFLCBbaWRdKVxuICpcbiAqICAgVHlwZU9STS0+PlN1YnNjcmliZXI6IGFmdGVyUmVtb3ZlKGV2ZW50KVxuICogICBTdWJzY3JpYmVyLT4+QWRhcHRlcjogdXBkYXRlT2JzZXJ2ZXJzKHRhYmxlLCBERUxFVEUsIFtpZF0pXG4gKiAgIEFkYXB0ZXItPj5PYnNlcnZlcnM6IG5vdGlmeSh0YWJsZSwgREVMRVRFLCBbaWRdKVxuICovXG5ARXZlbnRTdWJzY3JpYmVyKClcbmV4cG9ydCBjbGFzcyBUeXBlT1JNRXZlbnRTdWJzY3JpYmVyIGltcGxlbWVudHMgRW50aXR5U3Vic2NyaWJlckludGVyZmFjZSB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByb3RlY3RlZCByZWFkb25seSBoYW5kbGVyOiAoXG4gICAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICAgIG9wZXJhdGlvbjogT3BlcmF0aW9uS2V5cyxcbiAgICAgIGlkczogRXZlbnRJZHNcbiAgICApID0+IHZvaWRcbiAgKSB7fVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSGFuZGxlcyBwb3N0LWluc2VydCBldmVudHMuXG4gICAqIEBzdW1tYXJ5IE5vdGlmaWVzIG9ic2VydmVycyBhYm91dCBhIGNyZWF0ZSBvcGVyYXRpb24gZm9yIHRoZSBpbnNlcnRlZCBlbnRpdHkuXG4gICAqIEBwYXJhbSB7SW5zZXJ0RXZlbnQ8YW55Pn0gZXZlbnQgVGhlIFR5cGVPUk0gaW5zZXJ0IGV2ZW50LlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPGFueT58dm9pZH0gQSBwcm9taXNlIHdoZW4gYXN5bmMgb3Igdm9pZCBvdGhlcndpc2UuXG4gICAqL1xuICBhZnRlckluc2VydChldmVudDogSW5zZXJ0RXZlbnQ8YW55Pik6IFByb21pc2U8YW55PiB8IHZvaWQge1xuICAgIGNvbnN0IGNvbnN0cnVjdG9yID0gTW9kZWwuZ2V0KGV2ZW50LmVudGl0eS5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICBpZiAoIWNvbnN0cnVjdG9yKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgIGBObyByZWdpc3RlcmVkIG1vZGVsIGZvdW5kIGZvciAke2V2ZW50LmVudGl0eS5jb25zdHJ1Y3Rvci5uYW1lfWBcbiAgICAgICk7XG4gICAgY29uc3QgdGFibGVOYW1lID0gUmVwb3NpdG9yeS50YWJsZShjb25zdHJ1Y3Rvcik7XG5cbiAgICB0aGlzLmhhbmRsZXIodGFibGVOYW1lLCBPcGVyYXRpb25LZXlzLkNSRUFURSwgW2V2ZW50LmVudGl0eUlkIGFzIGFueV0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBIYW5kbGVzIHBvc3QtcmVtb3ZlIGV2ZW50cy5cbiAgICogQHN1bW1hcnkgTm90aWZpZXMgb2JzZXJ2ZXJzIGFib3V0IGEgZGVsZXRlIG9wZXJhdGlvbiBmb3IgdGhlIHJlbW92ZWQgZW50aXR5LlxuICAgKiBAcGFyYW0ge1JlbW92ZUV2ZW50PGFueT59IGV2ZW50IFRoZSBUeXBlT1JNIHJlbW92ZSBldmVudC5cbiAgICogQHJldHVybiB7UHJvbWlzZTxhbnk+fHZvaWR9IEEgcHJvbWlzZSB3aGVuIGFzeW5jIG9yIHZvaWQgb3RoZXJ3aXNlLlxuICAgKi9cbiAgYWZ0ZXJSZW1vdmUoZXZlbnQ6IFJlbW92ZUV2ZW50PGFueT4pOiBQcm9taXNlPGFueT4gfCB2b2lkIHtcbiAgICBjb25zdCBjb25zdHJ1Y3RvciA9IE1vZGVsLmdldChldmVudC5lbnRpdHkuY29uc3RydWN0b3IubmFtZSk7XG4gICAgaWYgKCFjb25zdHJ1Y3RvcilcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICBgTm8gcmVnaXN0ZXJlZCBtb2RlbCBmb3VuZCBmb3IgJHtldmVudC5lbnRpdHkuY29uc3RydWN0b3IubmFtZX1gXG4gICAgICApO1xuICAgIGNvbnN0IHRhYmxlTmFtZSA9IFJlcG9zaXRvcnkudGFibGUoY29uc3RydWN0b3IpO1xuXG4gICAgdGhpcy5oYW5kbGVyKHRhYmxlTmFtZSwgT3BlcmF0aW9uS2V5cy5ERUxFVEUsIFtldmVudC5lbnRpdHlJZCBhcyBhbnldKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSGFuZGxlcyBwb3N0LXVwZGF0ZSBldmVudHMuXG4gICAqIEBzdW1tYXJ5IE5vdGlmaWVzIG9ic2VydmVycyBhYm91dCBhbiB1cGRhdGUgb3BlcmF0aW9uIGZvciB0aGUgbW9kaWZpZWQgZW50aXR5LlxuICAgKiBAcGFyYW0ge1VwZGF0ZUV2ZW50PGFueT59IGV2ZW50IFRoZSBUeXBlT1JNIHVwZGF0ZSBldmVudC5cbiAgICogQHJldHVybiB7UHJvbWlzZTxhbnk+fHZvaWR9IEEgcHJvbWlzZSB3aGVuIGFzeW5jIG9yIHZvaWQgb3RoZXJ3aXNlLlxuICAgKi9cbiAgYWZ0ZXJVcGRhdGUoZXZlbnQ6IFVwZGF0ZUV2ZW50PGFueT4pOiBQcm9taXNlPGFueT4gfCB2b2lkIHtcbiAgICBjb25zdCBjb25zdHJ1Y3RvciA9IE1vZGVsLmdldChldmVudC5kYXRhYmFzZUVudGl0eS5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICBpZiAoIWNvbnN0cnVjdG9yKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgIGBObyByZWdpc3RlcmVkIG1vZGVsIGZvdW5kIGZvciAke2V2ZW50LmRhdGFiYXNlRW50aXR5LmNvbnN0cnVjdG9yLm5hbWV9YFxuICAgICAgKTtcbiAgICBjb25zdCB0YWJsZU5hbWUgPSBSZXBvc2l0b3J5LnRhYmxlKGNvbnN0cnVjdG9yKTtcblxuICAgIHJldHVybiB0aGlzLmhhbmRsZXIodGFibGVOYW1lLCBPcGVyYXRpb25LZXlzLlVQREFURSwgW1xuICAgICAgKGV2ZW50LmVudGl0eSBhcyBhbnkpW1wiaWRcIl0gYXMgYW55LFxuICAgIF0pO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,56 @@
1
+ import { EntitySubscriberInterface, InsertEvent, RemoveEvent, UpdateEvent } from "typeorm";
2
+ import { EventIds } from "@decaf-ts/core";
3
+ import { OperationKeys } from "@decaf-ts/db-decorators";
4
+ /**
5
+ * @description TypeORM event subscriber that forwards entity lifecycle events to the adapter.
6
+ * @summary Listens for insert, update, and remove events emitted by TypeORM and notifies the Decaf.ts adapter so that observers can be updated accordingly.
7
+ * @param {TypeORMAdapter} adapter The TypeORM adapter used to propagate events and look up metadata.
8
+ * @class
9
+ * @example
10
+ * // Registering the subscriber when creating a DataSource
11
+ * // dataSourceOptions.subscribers = [new TypeORMEventSubscriber(adapter)];
12
+ *
13
+ * @mermaid
14
+ * sequenceDiagram
15
+ * participant TypeORM
16
+ * participant Subscriber as TypeORMEventSubscriber
17
+ * participant Adapter as TypeORMAdapter
18
+ * participant Observers
19
+ *
20
+ * TypeORM->>Subscriber: afterInsert(entity)
21
+ * Subscriber->>Adapter: updateObservers(table, CREATE, [id])
22
+ * Adapter->>Observers: notify(table, CREATE, [id])
23
+ *
24
+ * TypeORM->>Subscriber: afterUpdate(event)
25
+ * Subscriber->>Adapter: updateObservers(table, UPDATE, [id])
26
+ * Adapter->>Observers: notify(table, UPDATE, [id])
27
+ *
28
+ * TypeORM->>Subscriber: afterRemove(event)
29
+ * Subscriber->>Adapter: updateObservers(table, DELETE, [id])
30
+ * Adapter->>Observers: notify(table, DELETE, [id])
31
+ */
32
+ export declare class TypeORMEventSubscriber implements EntitySubscriberInterface {
33
+ protected readonly handler: (tableName: string, operation: OperationKeys, ids: EventIds) => void;
34
+ constructor(handler: (tableName: string, operation: OperationKeys, ids: EventIds) => void);
35
+ /**
36
+ * @description Handles post-insert events.
37
+ * @summary Notifies observers about a create operation for the inserted entity.
38
+ * @param {InsertEvent<any>} event The TypeORM insert event.
39
+ * @return {Promise<any>|void} A promise when async or void otherwise.
40
+ */
41
+ afterInsert(event: InsertEvent<any>): Promise<any> | void;
42
+ /**
43
+ * @description Handles post-remove events.
44
+ * @summary Notifies observers about a delete operation for the removed entity.
45
+ * @param {RemoveEvent<any>} event The TypeORM remove event.
46
+ * @return {Promise<any>|void} A promise when async or void otherwise.
47
+ */
48
+ afterRemove(event: RemoveEvent<any>): Promise<any> | void;
49
+ /**
50
+ * @description Handles post-update events.
51
+ * @summary Notifies observers about an update operation for the modified entity.
52
+ * @param {UpdateEvent<any>} event The TypeORM update event.
53
+ * @return {Promise<any>|void} A promise when async or void otherwise.
54
+ */
55
+ afterUpdate(event: UpdateEvent<any>): Promise<any> | void;
56
+ }