node-cqrs 1.2.0-beta.0 → 1.3.0-alpha.0

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 (82) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +29 -9
  3. package/dist/cjs/postgresql/AbstractPostgresqlAccessor.js +83 -0
  4. package/dist/cjs/postgresql/AbstractPostgresqlAccessor.js.map +1 -0
  5. package/dist/cjs/postgresql/AbstractPostgresqlObjectProjection.js +36 -0
  6. package/dist/cjs/postgresql/AbstractPostgresqlObjectProjection.js.map +1 -0
  7. package/dist/cjs/postgresql/AbstractPostgresqlView.js +53 -0
  8. package/dist/cjs/postgresql/AbstractPostgresqlView.js.map +1 -0
  9. package/dist/cjs/postgresql/IContainer.js +3 -0
  10. package/dist/cjs/postgresql/IContainer.js.map +1 -0
  11. package/dist/cjs/postgresql/PostgresqlConnection.js +3 -0
  12. package/dist/cjs/postgresql/PostgresqlConnection.js.map +1 -0
  13. package/dist/cjs/postgresql/PostgresqlEventLocker.js +127 -0
  14. package/dist/cjs/postgresql/PostgresqlEventLocker.js.map +1 -0
  15. package/dist/cjs/postgresql/PostgresqlEventStorage.js +315 -0
  16. package/dist/cjs/postgresql/PostgresqlEventStorage.js.map +1 -0
  17. package/dist/cjs/postgresql/PostgresqlObjectStorage.js +137 -0
  18. package/dist/cjs/postgresql/PostgresqlObjectStorage.js.map +1 -0
  19. package/dist/cjs/postgresql/PostgresqlObjectView.js +46 -0
  20. package/dist/cjs/postgresql/PostgresqlObjectView.js.map +1 -0
  21. package/dist/cjs/postgresql/PostgresqlProjectionDataParams.js +3 -0
  22. package/dist/cjs/postgresql/PostgresqlProjectionDataParams.js.map +1 -0
  23. package/dist/cjs/postgresql/PostgresqlViewLocker.js +151 -0
  24. package/dist/cjs/postgresql/PostgresqlViewLocker.js.map +1 -0
  25. package/dist/cjs/postgresql/index.js +29 -0
  26. package/dist/cjs/postgresql/index.js.map +1 -0
  27. package/dist/cjs/postgresql/utils/getEventId.js +14 -0
  28. package/dist/cjs/postgresql/utils/getEventId.js.map +1 -0
  29. package/dist/cjs/postgresql/utils/index.js +19 -0
  30. package/dist/cjs/postgresql/utils/index.js.map +1 -0
  31. package/dist/cjs/postgresql/utils/quoteIdentifier.js +14 -0
  32. package/dist/cjs/postgresql/utils/quoteIdentifier.js.map +1 -0
  33. package/dist/cjs/sqlite/SqliteEventStorage.js +66 -36
  34. package/dist/cjs/sqlite/SqliteEventStorage.js.map +1 -1
  35. package/dist/esm/postgresql/AbstractPostgresqlAccessor.js +79 -0
  36. package/dist/esm/postgresql/AbstractPostgresqlAccessor.js.map +1 -0
  37. package/dist/esm/postgresql/AbstractPostgresqlObjectProjection.js +32 -0
  38. package/dist/esm/postgresql/AbstractPostgresqlObjectProjection.js.map +1 -0
  39. package/dist/esm/postgresql/AbstractPostgresqlView.js +49 -0
  40. package/dist/esm/postgresql/AbstractPostgresqlView.js.map +1 -0
  41. package/dist/esm/postgresql/IContainer.js +2 -0
  42. package/dist/esm/postgresql/IContainer.js.map +1 -0
  43. package/dist/esm/postgresql/PostgresqlConnection.js +2 -0
  44. package/dist/esm/postgresql/PostgresqlConnection.js.map +1 -0
  45. package/dist/esm/postgresql/PostgresqlEventLocker.js +123 -0
  46. package/dist/esm/postgresql/PostgresqlEventLocker.js.map +1 -0
  47. package/dist/esm/postgresql/PostgresqlEventStorage.js +311 -0
  48. package/dist/esm/postgresql/PostgresqlEventStorage.js.map +1 -0
  49. package/dist/esm/postgresql/PostgresqlObjectStorage.js +133 -0
  50. package/dist/esm/postgresql/PostgresqlObjectStorage.js.map +1 -0
  51. package/dist/esm/postgresql/PostgresqlObjectView.js +42 -0
  52. package/dist/esm/postgresql/PostgresqlObjectView.js.map +1 -0
  53. package/dist/esm/postgresql/PostgresqlProjectionDataParams.js +2 -0
  54. package/dist/esm/postgresql/PostgresqlProjectionDataParams.js.map +1 -0
  55. package/dist/esm/postgresql/PostgresqlViewLocker.js +147 -0
  56. package/dist/esm/postgresql/PostgresqlViewLocker.js.map +1 -0
  57. package/dist/esm/postgresql/index.js +13 -0
  58. package/dist/esm/postgresql/index.js.map +1 -0
  59. package/dist/esm/postgresql/utils/getEventId.js +10 -0
  60. package/dist/esm/postgresql/utils/getEventId.js.map +1 -0
  61. package/dist/esm/postgresql/utils/index.js +3 -0
  62. package/dist/esm/postgresql/utils/index.js.map +1 -0
  63. package/dist/esm/postgresql/utils/quoteIdentifier.js +11 -0
  64. package/dist/esm/postgresql/utils/quoteIdentifier.js.map +1 -0
  65. package/dist/esm/sqlite/SqliteEventStorage.js +66 -36
  66. package/dist/esm/sqlite/SqliteEventStorage.js.map +1 -1
  67. package/dist/types/postgresql/AbstractPostgresqlAccessor.d.ts +29 -0
  68. package/dist/types/postgresql/AbstractPostgresqlObjectProjection.d.ts +12 -0
  69. package/dist/types/postgresql/AbstractPostgresqlView.d.ts +23 -0
  70. package/dist/types/postgresql/IContainer.d.ts +12 -0
  71. package/dist/types/postgresql/PostgresqlConnection.d.ts +7 -0
  72. package/dist/types/postgresql/PostgresqlEventLocker.d.ts +39 -0
  73. package/dist/types/postgresql/PostgresqlEventStorage.d.ts +23 -0
  74. package/dist/types/postgresql/PostgresqlObjectStorage.d.ts +29 -0
  75. package/dist/types/postgresql/PostgresqlObjectView.d.ts +19 -0
  76. package/dist/types/postgresql/PostgresqlProjectionDataParams.d.ts +14 -0
  77. package/dist/types/postgresql/PostgresqlViewLocker.d.ts +41 -0
  78. package/dist/types/postgresql/index.d.ts +12 -0
  79. package/dist/types/postgresql/utils/getEventId.d.ts +5 -0
  80. package/dist/types/postgresql/utils/index.d.ts +2 -0
  81. package/dist/types/postgresql/utils/quoteIdentifier.d.ts +1 -0
  82. package/package.json +20 -5
@@ -0,0 +1,315 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PostgresqlEventStorage = void 0;
4
+ const node_crypto_1 = require("node:crypto");
5
+ const index_ts_1 = require("../errors/index.js");
6
+ const index_ts_2 = require("../utils/index.js");
7
+ const AbstractPostgresqlAccessor_ts_1 = require("./AbstractPostgresqlAccessor.js");
8
+ const index_ts_3 = require("./utils/index.js");
9
+ function extractMeta(envelope) {
10
+ const { event: _event, ignoreConcurrencyError: _ignore, ...rest } = envelope;
11
+ if (Object.keys(rest).length === 0)
12
+ return null;
13
+ return rest;
14
+ }
15
+ function parseJson(value) {
16
+ if (typeof value !== 'string')
17
+ return value;
18
+ return JSON.parse(value);
19
+ }
20
+ function indexPrefix(tableName) {
21
+ return tableName.replaceAll('"', '').replaceAll('.', '_');
22
+ }
23
+ function reconstructEvent(row) {
24
+ const data = parseJson(row.data);
25
+ const event = {
26
+ id: row.id,
27
+ ...data
28
+ };
29
+ if (row.saga_origins)
30
+ event.sagaOrigins = parseJson(row.saga_origins);
31
+ return event;
32
+ }
33
+ class PostgresqlEventStorage extends AbstractPostgresqlAccessor_ts_1.AbstractPostgresqlAccessor {
34
+ static EVENTS_TABLE = 'tbl_events';
35
+ static EVENT_SAGAS_TABLE = 'tbl_event_sagas';
36
+ #eventsTableName;
37
+ #eventSagasTableName;
38
+ #aggregateVersionIndexName;
39
+ constructor({ postgresqlEventStorageConfig, viewModelPostgresqlDb, viewModelPostgresqlDbFactory }) {
40
+ super({ viewModelPostgresqlDb, viewModelPostgresqlDbFactory });
41
+ const eventsTableName = postgresqlEventStorageConfig?.eventsTableName ?? PostgresqlEventStorage.EVENTS_TABLE;
42
+ const eventSagasTableName = postgresqlEventStorageConfig?.eventSagasTableName ??
43
+ PostgresqlEventStorage.EVENT_SAGAS_TABLE;
44
+ (0, index_ts_2.assertString)(eventsTableName, 'postgresqlEventStorageConfig.eventsTableName');
45
+ (0, index_ts_2.assertString)(eventSagasTableName, 'postgresqlEventStorageConfig.eventSagasTableName');
46
+ this.#eventsTableName = (0, index_ts_3.quoteIdentifier)(eventsTableName);
47
+ this.#eventSagasTableName = (0, index_ts_3.quoteIdentifier)(eventSagasTableName);
48
+ this.#aggregateVersionIndexName = `${indexPrefix(this.#eventsTableName)}_aggregate_version_unique_idx`;
49
+ }
50
+ async initialize(db) {
51
+ await db.query(`
52
+ CREATE TABLE IF NOT EXISTS ${this.#eventsTableName} (
53
+ position BIGSERIAL PRIMARY KEY,
54
+ id TEXT NOT NULL UNIQUE,
55
+ aggregate_id TEXT,
56
+ aggregate_version INTEGER,
57
+ type TEXT NOT NULL,
58
+ data JSONB NOT NULL,
59
+ meta JSONB,
60
+ check_concurrency BOOLEAN NOT NULL DEFAULT TRUE
61
+ )
62
+ `);
63
+ await db.query(`
64
+ CREATE TABLE IF NOT EXISTS ${this.#eventSagasTableName} (
65
+ saga_descriptor TEXT NOT NULL,
66
+ origin_id TEXT NOT NULL,
67
+ event_id TEXT NOT NULL,
68
+ PRIMARY KEY (saga_descriptor, origin_id, event_id),
69
+ FOREIGN KEY (event_id) REFERENCES ${this.#eventsTableName}(id) ON DELETE CASCADE
70
+ )
71
+ `);
72
+ const eventsIndexPrefix = indexPrefix(this.#eventsTableName);
73
+ const sagasIndexPrefix = indexPrefix(this.#eventSagasTableName);
74
+ await db.query(`
75
+ CREATE INDEX IF NOT EXISTS "${eventsIndexPrefix}_aggregate_id_idx"
76
+ ON ${this.#eventsTableName} (aggregate_id, aggregate_version)
77
+ `);
78
+ // Only checked rows participate in aggregate-version uniqueness, so ignoreConcurrencyError can opt out.
79
+ await db.query(`
80
+ CREATE UNIQUE INDEX IF NOT EXISTS "${this.#aggregateVersionIndexName}"
81
+ ON ${this.#eventsTableName} (aggregate_id, aggregate_version)
82
+ WHERE check_concurrency
83
+ AND aggregate_id IS NOT NULL
84
+ AND aggregate_version IS NOT NULL
85
+ `);
86
+ await db.query(`
87
+ CREATE INDEX IF NOT EXISTS "${eventsIndexPrefix}_type_position_idx"
88
+ ON ${this.#eventsTableName} (type, position)
89
+ `);
90
+ await db.query(`
91
+ CREATE INDEX IF NOT EXISTS "${sagasIndexPrefix}_event_id_idx"
92
+ ON ${this.#eventSagasTableName} (event_id)
93
+ `);
94
+ }
95
+ // eslint-disable-next-line class-methods-use-this
96
+ getNewId() {
97
+ return (0, node_crypto_1.randomUUID)().replaceAll('-', '');
98
+ }
99
+ async commitEvents(events, options) {
100
+ try {
101
+ await this.runInTransaction(async () => {
102
+ const metaJson = options?.meta ? JSON.stringify(options.meta) : null;
103
+ for (const event of events) {
104
+ const { sagaOrigins, id, ...eventData } = event;
105
+ const eventId = id ?? this.getNewId();
106
+ (0, index_ts_2.assertString)(eventId, 'event.id');
107
+ event.id = eventId;
108
+ await this.connection.query(`
109
+ INSERT INTO ${this.#eventsTableName} (
110
+ id,
111
+ aggregate_id,
112
+ aggregate_version,
113
+ type,
114
+ data,
115
+ meta,
116
+ check_concurrency
117
+ )
118
+ VALUES ($1, $2, $3, $4, $5::jsonb, $6::jsonb, $7)
119
+ `, [
120
+ eventId,
121
+ event.aggregateId !== undefined ? String(event.aggregateId) : null,
122
+ event.aggregateVersion ?? null,
123
+ event.type,
124
+ JSON.stringify(eventData),
125
+ metaJson,
126
+ !options?.ignoreConcurrencyError
127
+ ]);
128
+ if (sagaOrigins) {
129
+ for (const [descriptor, originId] of Object.entries(sagaOrigins)) {
130
+ await this.connection.query(`
131
+ INSERT INTO ${this.#eventSagasTableName} (
132
+ saga_descriptor,
133
+ origin_id,
134
+ event_id
135
+ )
136
+ VALUES ($1, $2, $3)
137
+ `, [descriptor, String(originId), eventId]);
138
+ }
139
+ }
140
+ }
141
+ });
142
+ }
143
+ catch (error) {
144
+ if (this.isAggregateVersionUniqueViolation(error))
145
+ throw new index_ts_1.ConcurrencyError('Concurrency conflict: duplicate event version', { cause: error });
146
+ throw error;
147
+ }
148
+ return events;
149
+ }
150
+ async *getAggregateEvents(aggregateId, options) {
151
+ await this.assertConnection();
152
+ const rows = await this.connection.query(`
153
+ WITH tail AS (
154
+ SELECT id AS tail_id
155
+ FROM ${this.#eventsTableName}
156
+ WHERE aggregate_id = $1
157
+ AND ($2::integer IS NULL OR aggregate_version > $2)
158
+ ORDER BY position DESC
159
+ LIMIT 1
160
+ )
161
+ SELECT
162
+ e.id,
163
+ e.aggregate_id,
164
+ e.aggregate_version,
165
+ e.type,
166
+ e.data,
167
+ e.meta,
168
+ e.position,
169
+ jsonb_object_agg(sr.saga_descriptor, sr.origin_id)
170
+ FILTER (WHERE sr.saga_descriptor IS NOT NULL) AS saga_origins
171
+ FROM ${this.#eventsTableName} e
172
+ LEFT JOIN tail ON TRUE
173
+ LEFT JOIN ${this.#eventSagasTableName} sr
174
+ ON sr.event_id = e.id
175
+ WHERE e.aggregate_id = $1
176
+ AND ($2::integer IS NULL OR e.aggregate_version > $2)
177
+ AND (
178
+ $3::text[] IS NULL
179
+ OR e.type = ANY($3::text[])
180
+ OR ($4 = 'last' AND e.id = tail.tail_id)
181
+ )
182
+ GROUP BY e.id, e.aggregate_id, e.aggregate_version, e.type, e.data, e.meta, e.position
183
+ ORDER BY e.position
184
+ `, [
185
+ String(aggregateId),
186
+ options?.snapshot?.aggregateVersion ?? null,
187
+ options?.eventTypes ?? null,
188
+ options?.tail ?? null
189
+ ]);
190
+ for (const row of rows.rows)
191
+ yield reconstructEvent(row);
192
+ }
193
+ async *getSagaEvents(sagaId, { beforeEvent }) {
194
+ await this.assertConnection();
195
+ (0, index_ts_2.assertString)(beforeEvent?.id, 'beforeEvent.id');
196
+ const { sagaDescriptor, originEventId } = (0, index_ts_2.parseSagaId)(sagaId);
197
+ if (beforeEvent.sagaOrigins?.[sagaDescriptor] !== originEventId)
198
+ throw new TypeError('beforeEvent.sagaOrigins does not match sagaId');
199
+ const rows = await this.connection.query(`
200
+ WITH bounds AS (
201
+ SELECT
202
+ (SELECT position FROM ${this.#eventsTableName} WHERE id = $2) AS origin_position,
203
+ (SELECT position FROM ${this.#eventsTableName} WHERE id = $3) AS before_position
204
+ )
205
+ SELECT
206
+ b.origin_position,
207
+ b.before_position,
208
+ e.id,
209
+ e.aggregate_id,
210
+ e.aggregate_version,
211
+ e.type,
212
+ e.data,
213
+ e.meta,
214
+ e.position,
215
+ e.saga_origins
216
+ FROM bounds b
217
+ LEFT JOIN LATERAL (
218
+ SELECT
219
+ e.id,
220
+ e.aggregate_id,
221
+ e.aggregate_version,
222
+ e.type,
223
+ e.data,
224
+ e.meta,
225
+ e.position,
226
+ jsonb_object_agg(sr.saga_descriptor, sr.origin_id)
227
+ FILTER (WHERE sr.saga_descriptor IS NOT NULL) AS saga_origins
228
+ FROM ${this.#eventsTableName} e
229
+ LEFT JOIN ${this.#eventSagasTableName} filter_sr
230
+ ON filter_sr.event_id = e.id
231
+ AND filter_sr.saga_descriptor = $1
232
+ AND filter_sr.origin_id = $2
233
+ LEFT JOIN ${this.#eventSagasTableName} sr
234
+ ON sr.event_id = e.id
235
+ WHERE b.origin_position IS NOT NULL
236
+ AND b.before_position IS NOT NULL
237
+ AND e.position >= b.origin_position
238
+ AND e.position < b.before_position
239
+ AND (e.id = $2 OR filter_sr.event_id IS NOT NULL)
240
+ GROUP BY e.id, e.aggregate_id, e.aggregate_version, e.type, e.data, e.meta, e.position
241
+ ORDER BY e.position
242
+ ) e ON TRUE
243
+ ORDER BY e.position
244
+ `, [sagaDescriptor, originEventId, beforeEvent.id]);
245
+ const bounds = rows.rows[0];
246
+ if (!bounds?.origin_position)
247
+ throw new Error(`origin event ${originEventId} not found`);
248
+ if (!bounds.before_position)
249
+ throw new Error(`beforeEvent ${beforeEvent.id} not found`);
250
+ for (const row of rows.rows) {
251
+ if (row.id)
252
+ yield reconstructEvent(row);
253
+ }
254
+ }
255
+ async *getEventsByTypes(eventTypes, options) {
256
+ await this.assertConnection();
257
+ const lastEventId = options?.afterEvent?.id;
258
+ if (options?.afterEvent)
259
+ (0, index_ts_2.assertString)(options.afterEvent.id, 'options.afterEvent.id');
260
+ let afterPosition = 0;
261
+ if (lastEventId) {
262
+ const row = await this.connection.query(`
263
+ SELECT position
264
+ FROM ${this.#eventsTableName}
265
+ WHERE id = $1
266
+ `, [lastEventId]);
267
+ if (!row.rows.length)
268
+ return;
269
+ afterPosition = row.rows[0].position;
270
+ }
271
+ const rows = await this.connection.query(`
272
+ SELECT
273
+ e.id,
274
+ e.aggregate_id,
275
+ e.aggregate_version,
276
+ e.type,
277
+ e.data,
278
+ e.meta,
279
+ e.position,
280
+ jsonb_object_agg(sr.saga_descriptor, sr.origin_id)
281
+ FILTER (WHERE sr.saga_descriptor IS NOT NULL) AS saga_origins
282
+ FROM ${this.#eventsTableName} e
283
+ LEFT JOIN ${this.#eventSagasTableName} sr
284
+ ON sr.event_id = e.id
285
+ WHERE e.position > $1
286
+ AND e.type = ANY($2::text[])
287
+ GROUP BY e.id, e.aggregate_id, e.aggregate_version, e.type, e.data, e.meta, e.position
288
+ ORDER BY e.position
289
+ `, [afterPosition, eventTypes]);
290
+ for (const row of rows.rows)
291
+ yield reconstructEvent(row);
292
+ }
293
+ async process(batch) {
294
+ const events = [];
295
+ for (const item of batch) {
296
+ if (!item.event)
297
+ throw new Error('Event batch does not contain `event`');
298
+ events.push(item.event);
299
+ }
300
+ await this.commitEvents(events, {
301
+ ignoreConcurrencyError: batch[0]?.ignoreConcurrencyError,
302
+ meta: extractMeta(batch[0])
303
+ });
304
+ return batch;
305
+ }
306
+ isAggregateVersionUniqueViolation(error) {
307
+ return typeof error === 'object' &&
308
+ error !== null &&
309
+ 'code' in error &&
310
+ error.code === '23505' &&
311
+ error.constraint === this.#aggregateVersionIndexName;
312
+ }
313
+ }
314
+ exports.PostgresqlEventStorage = PostgresqlEventStorage;
315
+ //# sourceMappingURL=PostgresqlEventStorage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostgresqlEventStorage.js","sourceRoot":"","sources":["../../../src/postgresql/PostgresqlEventStorage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PostgresqlObjectStorage = void 0;
4
+ const assert_ts_1 = require("../utils/assert.js");
5
+ const AbstractPostgresqlAccessor_ts_1 = require("./AbstractPostgresqlAccessor.js");
6
+ const index_ts_1 = require("./utils/index.js");
7
+ /**
8
+ * PostgreSQL-backed implementation of IObjectStorage.
9
+ *
10
+ * Each record is stored as a row `{ id, data, version }`.
11
+ * The version field enables optimistic concurrency control: `update` and
12
+ * `updateEnforcingNew` re-read the record after the user callback runs and
13
+ * atomically commit only when the version still matches.
14
+ * On mismatch the operation retries up to `maxRetries` times.
15
+ */
16
+ class PostgresqlObjectStorage extends AbstractPostgresqlAccessor_ts_1.AbstractPostgresqlAccessor {
17
+ #tableName;
18
+ #maxRetries;
19
+ constructor(o) {
20
+ super(o);
21
+ (0, assert_ts_1.assertString)(o.tableName, 'tableName');
22
+ if (o.maxRetries !== undefined)
23
+ (0, assert_ts_1.assertNonNegativeInteger)(o.maxRetries, 'maxRetries');
24
+ this.#tableName = (0, index_ts_1.quoteIdentifier)(o.tableName);
25
+ this.#maxRetries = o.maxRetries ?? 100;
26
+ }
27
+ async initialize(db) {
28
+ await db.query(`
29
+ CREATE TABLE IF NOT EXISTS ${this.#tableName} (
30
+ id text PRIMARY KEY,
31
+ version integer NOT NULL DEFAULT 1,
32
+ data jsonb NOT NULL
33
+ )
34
+ `);
35
+ }
36
+ async get(id) {
37
+ (0, assert_ts_1.assertDefined)(id, 'id');
38
+ await this.assertConnection();
39
+ const result = await this.connection.query(`
40
+ SELECT data, version
41
+ FROM ${this.#tableName}
42
+ WHERE id = $1
43
+ `, [String(id)]);
44
+ const row = result.rows[0];
45
+ if (!row)
46
+ return undefined;
47
+ return PostgresqlObjectStorage.parseData(row.data);
48
+ }
49
+ async create(id, data) {
50
+ (0, assert_ts_1.assertDefined)(id, 'id');
51
+ await this.assertConnection();
52
+ const result = await this.connection.query(`
53
+ INSERT INTO ${this.#tableName} (id, data)
54
+ VALUES ($1, $2::jsonb)
55
+ ON CONFLICT (id) DO NOTHING
56
+ `, [String(id), JSON.stringify(data)]);
57
+ if (result.rowCount !== 1)
58
+ throw new Error(`Record '${id}' could not be created`);
59
+ }
60
+ async update(id, update) {
61
+ (0, assert_ts_1.assertDefined)(id, 'id');
62
+ (0, assert_ts_1.assertFunction)(update, 'update');
63
+ await this.assertConnection();
64
+ for (let attempt = 0; attempt <= this.#maxRetries; attempt++) {
65
+ const row = await this.getRow(id);
66
+ if (!row)
67
+ throw new Error(`Record '${id}' does not exist`);
68
+ const updatedData = update(PostgresqlObjectStorage.parseData(row.data));
69
+ const result = await this.updateByVersion(id, row.version, updatedData);
70
+ if (result.rowCount === 1)
71
+ return;
72
+ // version mismatch - retry
73
+ }
74
+ throw new Error(`Record '${id}' could not be updated after ${this.#maxRetries} retries`);
75
+ }
76
+ async updateEnforcingNew(id, update) {
77
+ (0, assert_ts_1.assertDefined)(id, 'id');
78
+ (0, assert_ts_1.assertFunction)(update, 'update');
79
+ await this.assertConnection();
80
+ for (let attempt = 0; attempt <= this.#maxRetries; attempt++) {
81
+ const row = await this.getRow(id);
82
+ if (row) {
83
+ const updatedData = update(PostgresqlObjectStorage.parseData(row.data));
84
+ const result = await this.updateByVersion(id, row.version, updatedData);
85
+ if (result.rowCount === 1)
86
+ return;
87
+ // version mismatch - retry
88
+ }
89
+ else {
90
+ const result = await this.connection.query(`
91
+ INSERT INTO ${this.#tableName} (id, data)
92
+ VALUES ($1, $2::jsonb)
93
+ ON CONFLICT (id) DO NOTHING
94
+ `, [String(id), JSON.stringify(update(undefined))]);
95
+ if (result.rowCount === 1)
96
+ return;
97
+ // Another process inserted first - retry
98
+ }
99
+ }
100
+ throw new Error(`Record '${id}' could not be upserted after ${this.#maxRetries} retries`);
101
+ }
102
+ async delete(id) {
103
+ (0, assert_ts_1.assertDefined)(id, 'id');
104
+ await this.assertConnection();
105
+ const result = await this.connection.query(`
106
+ DELETE FROM ${this.#tableName}
107
+ WHERE id = $1
108
+ `, [String(id)]);
109
+ return result.rowCount === 1;
110
+ }
111
+ async getRow(id) {
112
+ const result = await this.connection.query(`
113
+ SELECT data, version
114
+ FROM ${this.#tableName}
115
+ WHERE id = $1
116
+ `, [String(id)]);
117
+ return result.rows[0];
118
+ }
119
+ updateByVersion(id, version, data) {
120
+ return this.connection.query(`
121
+ UPDATE ${this.#tableName}
122
+ SET
123
+ data = $1::jsonb,
124
+ version = version + 1
125
+ WHERE
126
+ id = $2
127
+ AND version = $3
128
+ `, [JSON.stringify(data), String(id), version]);
129
+ }
130
+ static parseData(data) {
131
+ if (typeof data === 'string')
132
+ return JSON.parse(data);
133
+ return data;
134
+ }
135
+ }
136
+ exports.PostgresqlObjectStorage = PostgresqlObjectStorage;
137
+ //# sourceMappingURL=PostgresqlObjectStorage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostgresqlObjectStorage.js","sourceRoot":"","sources":["../../../src/postgresql/PostgresqlObjectStorage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PostgresqlObjectView = void 0;
4
+ const assert_ts_1 = require("../utils/assert.js");
5
+ const AbstractPostgresqlView_ts_1 = require("./AbstractPostgresqlView.js");
6
+ const PostgresqlObjectStorage_ts_1 = require("./PostgresqlObjectStorage.js");
7
+ /**
8
+ * PostgreSQL-backed object view with restore locking and last-processed-event tracking.
9
+ */
10
+ class PostgresqlObjectView extends AbstractPostgresqlView_ts_1.AbstractPostgresqlView {
11
+ #postgresqlObjectStorage;
12
+ constructor(options) {
13
+ (0, assert_ts_1.assertString)(options?.tableNamePrefix, 'tableNamePrefix');
14
+ (0, assert_ts_1.assertString)(options?.schemaVersion, 'schemaVersion');
15
+ super(options);
16
+ this.#postgresqlObjectStorage = new PostgresqlObjectStorage_ts_1.PostgresqlObjectStorage({
17
+ viewModelPostgresqlDb: options.viewModelPostgresqlDb,
18
+ viewModelPostgresqlDbFactory: options.viewModelPostgresqlDbFactory,
19
+ tableName: `${options.tableNamePrefix}_${options.schemaVersion}`,
20
+ maxRetries: options.postgresqlObjectStorageMaxRetries
21
+ });
22
+ }
23
+ // eslint-disable-next-line class-methods-use-this
24
+ initialize(_db) {
25
+ // No need to initialize the table here, it's done in PostgresqlObjectStorage
26
+ }
27
+ async get(id) {
28
+ if (!this.ready)
29
+ await this.once('ready');
30
+ return this.#postgresqlObjectStorage.get(id);
31
+ }
32
+ async create(id, data) {
33
+ await this.#postgresqlObjectStorage.create(id, data);
34
+ }
35
+ async update(id, update) {
36
+ await this.#postgresqlObjectStorage.update(id, update);
37
+ }
38
+ async updateEnforcingNew(id, update) {
39
+ await this.#postgresqlObjectStorage.updateEnforcingNew(id, update);
40
+ }
41
+ async delete(id) {
42
+ return this.#postgresqlObjectStorage.delete(id);
43
+ }
44
+ }
45
+ exports.PostgresqlObjectView = PostgresqlObjectView;
46
+ //# sourceMappingURL=PostgresqlObjectView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostgresqlObjectView.js","sourceRoot":"","sources":["../../../src/postgresql/PostgresqlObjectView.ts"],"names":[],"mappings":";;;AACA,kDAAkD;AAClD,2EAAqE;AACrE,6EAAuE;AAGvE;;GAEG;AACH,MAAa,oBACZ,SAAQ,kDAAsB;IAGrB,wBAAwB,CAAmC;IAEpE,YAAY,OAGX;QACA,IAAA,wBAAY,EAAC,OAAO,EAAE,eAAe,EAAE,iBAAiB,CAAC,CAAC;QAC1D,IAAA,wBAAY,EAAC,OAAO,EAAE,aAAa,EAAE,eAAe,CAAC,CAAC;QAEtD,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,wBAAwB,GAAG,IAAI,oDAAuB,CAAU;YACpE,qBAAqB,EAAE,OAAO,CAAC,qBAAqB;YACpD,4BAA4B,EAAE,OAAO,CAAC,4BAA4B;YAClE,SAAS,EAAE,GAAG,OAAO,CAAC,eAAe,IAAI,OAAO,CAAC,aAAa,EAAE;YAChE,UAAU,EAAE,OAAO,CAAC,iCAAiC;SACrD,CAAC,CAAC;IACJ,CAAC;IAED,kDAAkD;IACxC,UAAU,CAAC,GAAyB;QAC7C,6EAA6E;IAC9E,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,EAAc;QACvB,IAAI,CAAC,IAAI,CAAC,KAAK;YACd,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAE1B,OAAO,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAc,EAAE,IAAa;QACzC,MAAM,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAc,EAAE,MAA+B;QAC3D,MAAM,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,EAAc,EAAE,MAAgC;QACxE,MAAM,IAAI,CAAC,wBAAwB,CAAC,kBAAkB,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACpE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAc;QAC1B,OAAO,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC;CACD;AAlDD,oDAkDC"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=PostgresqlProjectionDataParams.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostgresqlProjectionDataParams.js","sourceRoot":"","sources":["../../../src/postgresql/PostgresqlProjectionDataParams.ts"],"names":[],"mappings":""}