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,147 @@
1
+ import { assertNonNegativeInteger, assertString, Deferred } from "../utils/index.js";
2
+ import { promisify } from 'util';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { AbstractPostgresqlAccessor } from "./AbstractPostgresqlAccessor.js";
5
+ import { quoteIdentifier } from "./utils/index.js";
6
+ const delay = promisify(setTimeout);
7
+ /**
8
+ * PostgreSQL-backed implementation of IViewLocker.
9
+ *
10
+ * Uses a row with token + locked_till semantics to acquire a distributed view lock.
11
+ * The lock is automatically prolonged at half the TTL interval to prevent expiration
12
+ * while processing is in progress.
13
+ */
14
+ export class PostgresqlViewLocker extends AbstractPostgresqlAccessor {
15
+ static DEFAULT_VIEW_LOCK_TTL = 120_000;
16
+ static DEFAULT_TABLE = 'ncqrs_view_locks';
17
+ #projectionName;
18
+ #schemaVersion;
19
+ #viewLockTableName;
20
+ #viewLockTtl;
21
+ #logger;
22
+ #lockToken;
23
+ #lockMarker;
24
+ #lockProlongationTimeout;
25
+ constructor(o) {
26
+ super(o);
27
+ assertString(o.projectionName, 'o.projectionName');
28
+ assertString(o.schemaVersion, 'o.schemaVersion');
29
+ if (o.viewLockTableName !== undefined)
30
+ assertString(o.viewLockTableName, 'o.viewLockTableName');
31
+ if (o.viewLockTtl !== undefined)
32
+ assertNonNegativeInteger(o.viewLockTtl, 'o.viewLockTtl');
33
+ this.#projectionName = o.projectionName;
34
+ this.#schemaVersion = o.schemaVersion;
35
+ this.#viewLockTableName = quoteIdentifier(o.viewLockTableName ?? PostgresqlViewLocker.DEFAULT_TABLE);
36
+ this.#viewLockTtl = o.viewLockTtl ?? PostgresqlViewLocker.DEFAULT_VIEW_LOCK_TTL;
37
+ this.#logger = o.logger && 'child' in o.logger ?
38
+ o.logger.child({ service: this.constructor.name }) :
39
+ o.logger;
40
+ }
41
+ async initialize(db) {
42
+ await db.query(`
43
+ CREATE TABLE IF NOT EXISTS ${this.#viewLockTableName} (
44
+ projection_name text NOT NULL,
45
+ schema_version text NOT NULL,
46
+ locked_till timestamptz NULL,
47
+ lock_token text NULL,
48
+ last_event text NULL,
49
+ PRIMARY KEY (projection_name, schema_version)
50
+ )
51
+ `);
52
+ await db.query(`
53
+ CREATE INDEX IF NOT EXISTS ${quoteIdentifier(`${this.#tableNameForIndex()}_locked_till_idx`)}
54
+ ON ${this.#viewLockTableName} (locked_till)
55
+ `);
56
+ }
57
+ get ready() {
58
+ return !this.#lockMarker;
59
+ }
60
+ async lock() {
61
+ this.#lockMarker = new Deferred();
62
+ this.#lockToken = randomUUID();
63
+ await this.assertConnection();
64
+ let lockAcquired = false;
65
+ while (!lockAcquired) {
66
+ const lockedTill = new Date(Date.now() + this.#viewLockTtl);
67
+ const upsertResult = await this.connection.query(`
68
+ INSERT INTO ${this.#viewLockTableName} AS view_lock
69
+ (projection_name, schema_version, locked_till, lock_token)
70
+ VALUES ($1, $2, $3, $4)
71
+ ON CONFLICT (projection_name, schema_version)
72
+ DO UPDATE SET
73
+ locked_till = excluded.locked_till,
74
+ lock_token = excluded.lock_token
75
+ WHERE
76
+ view_lock.locked_till IS NULL
77
+ OR view_lock.locked_till < NOW()
78
+ `, [this.#projectionName, this.#schemaVersion, lockedTill, this.#lockToken]);
79
+ lockAcquired = upsertResult.rowCount === 1;
80
+ if (!lockAcquired) {
81
+ this.#logger?.debug(`"${this.#projectionName}" is locked by another process`);
82
+ await delay(this.#viewLockTtl / 2);
83
+ }
84
+ }
85
+ this.#logger?.debug(`"${this.#projectionName}" lock obtained for ${this.#viewLockTtl}ms`);
86
+ this.scheduleLockProlongation();
87
+ return true;
88
+ }
89
+ scheduleLockProlongation() {
90
+ const ms = this.#viewLockTtl / 2;
91
+ this.#lockProlongationTimeout = setTimeout(() => this.prolongLock(), ms);
92
+ this.#lockProlongationTimeout.unref();
93
+ this.#logger?.debug(`"${this.#projectionName}" lock refresh scheduled in ${ms}ms`);
94
+ }
95
+ cancelLockProlongation() {
96
+ clearTimeout(this.#lockProlongationTimeout);
97
+ this.#logger?.debug(`"${this.#projectionName}" lock refresh canceled`);
98
+ }
99
+ async prolongLock() {
100
+ await this.assertConnection();
101
+ const lockedTill = new Date(Date.now() + this.#viewLockTtl);
102
+ const result = await this.connection.query(`
103
+ UPDATE ${this.#viewLockTableName}
104
+ SET
105
+ locked_till = $1
106
+ WHERE
107
+ projection_name = $2
108
+ AND schema_version = $3
109
+ AND lock_token = $4
110
+ AND locked_till IS NOT NULL
111
+ `, [lockedTill, this.#projectionName, this.#schemaVersion, this.#lockToken]);
112
+ if (result.rowCount !== 1)
113
+ throw new Error(`"${this.#projectionName}" lock could not be prolonged`);
114
+ this.#logger?.debug(`"${this.#projectionName}" lock prolonged for ${this.#viewLockTtl}ms`);
115
+ this.scheduleLockProlongation();
116
+ }
117
+ async unlock() {
118
+ this.#lockMarker?.resolve();
119
+ this.#lockMarker = undefined;
120
+ this.cancelLockProlongation();
121
+ await this.assertConnection();
122
+ const result = await this.connection.query(`
123
+ UPDATE ${this.#viewLockTableName}
124
+ SET
125
+ locked_till = NULL,
126
+ lock_token = NULL
127
+ WHERE
128
+ projection_name = $1
129
+ AND schema_version = $2
130
+ AND lock_token = $3
131
+ `, [this.#projectionName, this.#schemaVersion, this.#lockToken]);
132
+ this.#lockToken = undefined;
133
+ if (result.rowCount === 1)
134
+ this.#logger?.debug(`"${this.#projectionName}" lock released`);
135
+ else
136
+ this.#logger?.warn(`"${this.#projectionName}" lock didn't exist`);
137
+ }
138
+ once(event) {
139
+ if (event !== 'ready')
140
+ throw new TypeError(`Unexpected event: ${event}`);
141
+ return this.#lockMarker?.promise ?? Promise.resolve();
142
+ }
143
+ #tableNameForIndex() {
144
+ return this.#viewLockTableName.replaceAll('"', '').replaceAll('.', '_');
145
+ }
146
+ }
147
+ //# sourceMappingURL=PostgresqlViewLocker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostgresqlViewLocker.js","sourceRoot":"","sources":["../../../src/postgresql/PostgresqlViewLocker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import "./IContainer.js";
2
+ export * from "./AbstractPostgresqlAccessor.js";
3
+ export * from "./AbstractPostgresqlObjectProjection.js";
4
+ export * from "./AbstractPostgresqlView.js";
5
+ export * from "./PostgresqlConnection.js";
6
+ export * from "./PostgresqlEventStorage.js";
7
+ export * from "./PostgresqlEventLocker.js";
8
+ export * from "./PostgresqlObjectStorage.js";
9
+ export * from "./PostgresqlObjectView.js";
10
+ export * from "./PostgresqlProjectionDataParams.js";
11
+ export * from "./PostgresqlViewLocker.js";
12
+ export * from "./utils/index.js";
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/postgresql/index.ts"],"names":[],"mappings":"AAAA,OAAO,iBAAiB,CAAC;AAEzB,cAAc,iCAAiC,CAAC;AAChD,cAAc,yCAAyC,CAAC;AACxD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qCAAqC,CAAC;AACpD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { createHash } from 'node:crypto';
2
+ /**
3
+ * Get assigned or generate a deterministic event ID as a hex string.
4
+ */
5
+ export const getEventId = (event) => {
6
+ if (typeof event.id === 'string')
7
+ return event.id;
8
+ return createHash('md5').update(JSON.stringify(event)).digest('hex');
9
+ };
10
+ //# sourceMappingURL=getEventId.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getEventId.js","sourceRoot":"","sources":["../../../../src/postgresql/utils/getEventId.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAa,EAAU,EAAE;IACnD,IAAI,OAAO,KAAK,CAAC,EAAE,KAAK,QAAQ;QAC/B,OAAO,KAAK,CAAC,EAAE,CAAC;IAEjB,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACtE,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from "./getEventId.js";
2
+ export * from "./quoteIdentifier.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/postgresql/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { assertString } from "../../utils/assert.js";
2
+ const IDENTIFIER_PART_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
3
+ export function quoteIdentifier(identifier) {
4
+ assertString(identifier, 'identifier');
5
+ return identifier.split('.').map(part => {
6
+ if (!IDENTIFIER_PART_PATTERN.test(part))
7
+ throw new TypeError(`Invalid PostgreSQL identifier: ${identifier}`);
8
+ return `"${part}"`;
9
+ }).join('.');
10
+ }
11
+ //# sourceMappingURL=quoteIdentifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quoteIdentifier.js","sourceRoot":"","sources":["../../../../src/postgresql/utils/quoteIdentifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD,MAAM,uBAAuB,GAAG,0BAA0B,CAAC;AAE3D,MAAM,UAAU,eAAe,CAAC,UAAkB;IACjD,YAAY,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IAEvC,OAAO,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QACvC,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC;YACtC,MAAM,IAAI,SAAS,CAAC,kCAAkC,UAAU,EAAE,CAAC,CAAC;QAErE,OAAO,IAAI,IAAI,GAAG,CAAC;IACpB,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACd,CAAC"}
@@ -9,6 +9,16 @@ function extractMeta(envelope) {
9
9
  return null;
10
10
  return rest;
11
11
  }
12
+ function reconstructEvent(row) {
13
+ const data = JSON.parse(row.data);
14
+ const event = {
15
+ id: bufferToGuid(row.id),
16
+ ...data
17
+ };
18
+ if (row.saga_origins)
19
+ event.sagaOrigins = JSON.parse(row.saga_origins);
20
+ return event;
21
+ }
12
22
  export class SqliteEventStorage extends AbstractSqliteAccessor {
13
23
  #insertEventQuery;
14
24
  #insertSagaRefQuery;
@@ -16,7 +26,6 @@ export class SqliteEventStorage extends AbstractSqliteAccessor {
16
26
  #getRowidQuery;
17
27
  #getAggregateEventsQuery;
18
28
  #getSagaEventsQuery;
19
- #getSagaRefsQuery;
20
29
  #getEventsByTypesQuery;
21
30
  initialize(db) {
22
31
  db.pragma('foreign_keys = ON');
@@ -62,8 +71,23 @@ export class SqliteEventStorage extends AbstractSqliteAccessor {
62
71
  ORDER BY rowid DESC
63
72
  LIMIT 1
64
73
  )
65
- SELECT e.id, e.aggregate_id, e.aggregate_version, e.type, e.data, e.meta, e.rowid
66
- FROM tbl_events e, tail
74
+ SELECT
75
+ e.id,
76
+ e.aggregate_id,
77
+ e.aggregate_version,
78
+ e.type,
79
+ e.data,
80
+ e.meta,
81
+ e.rowid,
82
+ NULLIF(
83
+ json_group_object(sr.saga_descriptor, lower(hex(sr.origin_id)))
84
+ FILTER (WHERE sr.saga_descriptor IS NOT NULL),
85
+ '{}'
86
+ ) AS saga_origins
87
+ FROM tbl_events e
88
+ CROSS JOIN tail
89
+ LEFT JOIN tbl_event_sagas sr
90
+ ON sr.event_id = e.id
67
91
  WHERE e.aggregate_id = @aggregateId
68
92
  AND (@afterVersion IS NULL OR e.aggregate_version > @afterVersion)
69
93
  AND (
@@ -71,29 +95,55 @@ export class SqliteEventStorage extends AbstractSqliteAccessor {
71
95
  OR e.type IN (SELECT value FROM json_each(@eventTypes))
72
96
  OR (@tail = 'last' AND e.id = tail.tail_id)
73
97
  )
98
+ GROUP BY e.id, e.aggregate_id, e.aggregate_version, e.type, e.data, e.meta, e.rowid
74
99
  ORDER BY e.rowid
75
100
  `);
76
101
  this.#getSagaEventsQuery = db.prepare(`
77
- SELECT e.id, e.aggregate_id, e.aggregate_version, e.type, e.data, e.meta, e.rowid
102
+ SELECT
103
+ e.id,
104
+ e.aggregate_id,
105
+ e.aggregate_version,
106
+ e.type,
107
+ e.data,
108
+ e.meta,
109
+ e.rowid,
110
+ NULLIF(
111
+ json_group_object(all_sr.saga_descriptor, lower(hex(all_sr.origin_id)))
112
+ FILTER (WHERE all_sr.saga_descriptor IS NOT NULL),
113
+ '{}'
114
+ ) AS saga_origins
78
115
  FROM tbl_events e
79
116
  LEFT JOIN tbl_event_sagas sr
80
117
  ON sr.event_id = e.id
81
118
  AND sr.saga_descriptor = @sagaDescriptor
82
119
  AND sr.origin_id = @originId
120
+ LEFT JOIN tbl_event_sagas all_sr
121
+ ON all_sr.event_id = e.id
83
122
  WHERE e.rowid >= @originRowid AND e.rowid < @beforeRowid
84
123
  AND (e.id = @originId OR sr.event_id IS NOT NULL)
124
+ GROUP BY e.id, e.aggregate_id, e.aggregate_version, e.type, e.data, e.meta, e.rowid
85
125
  ORDER BY e.rowid
86
126
  `);
87
- this.#getSagaRefsQuery = db.prepare(`
88
- SELECT saga_descriptor, origin_id
89
- FROM tbl_event_sagas
90
- WHERE event_id = ?
91
- `);
92
127
  this.#getEventsByTypesQuery = db.prepare(`
93
- SELECT id, aggregate_id, aggregate_version, type, data, meta, rowid
94
- FROM tbl_events
95
- WHERE rowid > ?
96
- ORDER BY rowid
128
+ SELECT
129
+ e.id,
130
+ e.aggregate_id,
131
+ e.aggregate_version,
132
+ e.type,
133
+ e.data,
134
+ e.meta,
135
+ e.rowid,
136
+ NULLIF(
137
+ json_group_object(sr.saga_descriptor, lower(hex(sr.origin_id)))
138
+ FILTER (WHERE sr.saga_descriptor IS NOT NULL),
139
+ '{}'
140
+ ) AS saga_origins
141
+ FROM tbl_events e
142
+ LEFT JOIN tbl_event_sagas sr
143
+ ON sr.event_id = e.id
144
+ WHERE e.rowid > ?
145
+ GROUP BY e.id, e.aggregate_id, e.aggregate_version, e.type, e.data, e.meta, e.rowid
146
+ ORDER BY e.rowid
97
147
  `);
98
148
  }
99
149
  // eslint-disable-next-line class-methods-use-this
@@ -134,7 +184,7 @@ export class SqliteEventStorage extends AbstractSqliteAccessor {
134
184
  tail: options?.tail ?? null
135
185
  });
136
186
  for (const row of rows)
137
- yield this.#reconstructEvent(row);
187
+ yield reconstructEvent(row);
138
188
  }
139
189
  async *getSagaEvents(sagaId, { beforeEvent }) {
140
190
  await this.assertConnection();
@@ -155,7 +205,7 @@ export class SqliteEventStorage extends AbstractSqliteAccessor {
155
205
  beforeRowid: beforeRowid.rowid
156
206
  });
157
207
  for (const row of rows)
158
- yield this.#reconstructEvent(row);
208
+ yield reconstructEvent(row);
159
209
  }
160
210
  async *getEventsByTypes(eventTypes, options) {
161
211
  await this.assertConnection();
@@ -172,7 +222,7 @@ export class SqliteEventStorage extends AbstractSqliteAccessor {
172
222
  const rows = this.#getEventsByTypesQuery.all(afterRowid);
173
223
  for (const row of rows) {
174
224
  if (eventTypes.includes(row.type))
175
- yield this.#reconstructEvent(row);
225
+ yield reconstructEvent(row);
176
226
  }
177
227
  }
178
228
  async process(batch) {
@@ -187,25 +237,5 @@ export class SqliteEventStorage extends AbstractSqliteAccessor {
187
237
  await this.commitEvents(events, { ignoreConcurrencyError, meta });
188
238
  return batch;
189
239
  }
190
- #getSagaOriginsForEvent(eventIdBuf) {
191
- const refs = this.#getSagaRefsQuery.all(eventIdBuf);
192
- if (refs.length === 0)
193
- return {};
194
- const sagaOrigins = {};
195
- for (const ref of refs)
196
- sagaOrigins[ref.saga_descriptor] = bufferToGuid(ref.origin_id);
197
- return sagaOrigins;
198
- }
199
- #reconstructEvent(row) {
200
- const data = JSON.parse(row.data);
201
- const sagaOrigins = this.#getSagaOriginsForEvent(row.id);
202
- const event = {
203
- id: bufferToGuid(row.id),
204
- ...data
205
- };
206
- if (Object.keys(sagaOrigins).length > 0)
207
- event.sagaOrigins = sagaOrigins;
208
- return event;
209
- }
210
240
  }
211
241
  //# sourceMappingURL=SqliteEventStorage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SqliteEventStorage.js","sourceRoot":"","sources":["../../../src/sqlite/SqliteEventStorage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAezC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAqBtD,SAAS,WAAW,CAAC,QAAkC;IACtD,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,sBAAsB,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,QAAQ,CAAC;IAC7E,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;QACjC,OAAO,IAAI,CAAC;IAEb,OAAO,IAAI,CAAC;AACb,CAAC;AAED,MAAM,OAAO,kBAAmB,SAAQ,sBAAsB;IAK7D,iBAAiB,CAAoF;IACrG,mBAAmB,CAAuC;IAC1D,sBAAsB,CAAyC;IAC/D,cAAc,CAAiC;IAC/C,wBAAwB,CAKV;IACd,mBAAmB,CAKL;IACd,iBAAiB,CAAmC;IACpD,sBAAsB,CAAiC;IAE7C,UAAU,CAAC,EAAY;QAChC,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;QAE/B,EAAE,CAAC,IAAI,CAAC;;;;;;;IAON,CAAC,CAAC;QAEJ,EAAE,CAAC,IAAI,CAAC;;;;;;IAMN,CAAC,CAAC;QAEJ,EAAE,CAAC,IAAI,CAAC,iFAAiF,CAAC,CAAC;QAC3F,EAAE,CAAC,IAAI,CAAC,mFAAmF,CAAC,CAAC;QAE7F,IAAI,CAAC,iBAAiB,GAAG,EAAE,CAAC,OAAO,CAAC;;;GAGnC,CAAC,CAAC;QAEH,IAAI,CAAC,mBAAmB,GAAG,EAAE,CAAC,OAAO,CAAC;;;GAGrC,CAAC,CAAC;QAEH,IAAI,CAAC,sBAAsB,GAAG,EAAE,CAAC,OAAO,CAAC;;;;GAIxC,CAAC,CAAC;QAEH,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC,OAAO,CAAC;;GAEhC,CAAC,CAAC;QAEH,IAAI,CAAC,wBAAwB,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;GAmB1C,CAAC,CAAC;QAEH,IAAI,CAAC,mBAAmB,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;;;;;;GAUrC,CAAC,CAAC;QAEH,IAAI,CAAC,iBAAiB,GAAG,EAAE,CAAC,OAAO,CAAC;;;;GAInC,CAAC,CAAC;QAEH,IAAI,CAAC,sBAAsB,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;GAKxC,CAAC,CAAC;IAEJ,CAAC;IAED,kDAAkD;IAClD,QAAQ;QACP,OAAO,UAAU,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,MAAiB,EAAE,OAGrC;QACA,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAE9B,MAAM,QAAQ,GAAG,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAErE,IAAI,CAAC,EAAG,CAAC,WAAW,CAAC,GAAG,EAAE;YACzB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC5B,IAAI,CAAC,OAAO,EAAE,sBAAsB,IAAI,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;oBACnG,MAAM,QAAQ,GAAG,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC;oBAClG,IAAI,QAAQ;wBACX,MAAM,IAAI,gBAAgB,CAAC,8BAA8B,KAAK,CAAC,gBAAgB,kBAAkB,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;gBACxH,CAAC;gBAED,MAAM,EAAE,WAAW,EAAE,EAAE,EAAE,GAAG,SAAS,EAAE,GAAG,KAAK,CAAC;gBAChD,YAAY,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;gBAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;gBAEzB,IAAI,CAAC,iBAAiB,CAAC,GAAG,CACzB,OAAO,EACP,KAAK,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,EAChE,KAAK,CAAC,gBAAgB,IAAI,IAAI,EAC9B,KAAK,CAAC,IAAI,EACV,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EACzB,QAAQ,CACR,CAAC;gBAEF,IAAI,WAAW,EAAE,CAAC;oBACjB,KAAK,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;wBAClE,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAC3B,UAAU,EACV,IAAI,CAAC,QAAQ,CAAC,EACd,OAAO,CACP,CAAC;oBACH,CAAC;gBACF,CAAC;YACF,CAAC;QACF,CAAC,CAAC,EAAE,CAAC;QAEL,OAAO,MAAM,CAAC;IACf,CAAC;IAED,KAAK,CAAA,CAAE,kBAAkB,CAAC,WAAuB,EAAE,OAAoC;QACtF,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAE9B,MAAM,IAAI,GAAG,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC;YAC9C,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC;YAC9B,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,gBAAgB,IAAI,IAAI;YACzD,UAAU,EAAE,OAAO,EAAE,UAAU;gBAC9B,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC;gBACpC,CAAC,CAAC,IAAI;YACP,IAAI,EAAE,OAAO,EAAE,IAAI,IAAI,IAAI;SAC3B,CAAC,CAAC;QAEH,KAAK,MAAM,GAAG,IAAI,IAAI;YACrB,MAAM,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAA,CAAE,aAAa,CAAC,MAAkB,EAAE,EAAE,WAAW,EAA2B;QAChF,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAE9B,YAAY,CAAC,WAAW,EAAE,EAAE,EAAE,gBAAgB,CAAC,CAAC;QAEhD,MAAM,EAAE,cAAc,EAAE,aAAa,EAAE,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;QAC9D,IAAI,WAAW,CAAC,WAAW,EAAE,CAAC,cAAc,CAAC,KAAK,aAAa;YAC9D,MAAM,IAAI,SAAS,CAAC,+CAA+C,CAAC,CAAC;QAEtE,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;QACjE,IAAI,CAAC,WAAW;YACf,MAAM,IAAI,KAAK,CAAC,gBAAgB,aAAa,YAAY,CAAC,CAAC;QAE5D,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;QAClE,IAAI,CAAC,WAAW;YACf,MAAM,IAAI,KAAK,CAAC,eAAe,WAAW,CAAC,EAAE,YAAY,CAAC,CAAC;QAE5D,MAAM,IAAI,GAAG,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC;YACzC,cAAc;YACd,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC;YAC7B,WAAW,EAAE,WAAW,CAAC,KAAK;YAC9B,WAAW,EAAE,WAAW,CAAC,KAAK;SAC9B,CAAC,CAAC;QAEH,KAAK,MAAM,GAAG,IAAI,IAAI;YACrB,MAAM,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAA,CAAE,gBAAgB,CAAC,UAA8B,EAAE,OAAyB;QAChF,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAE9B,MAAM,WAAW,GAAG,OAAO,EAAE,UAAU,EAAE,EAAE,CAAC;QAC5C,IAAI,OAAO,EAAE,UAAU;YACtB,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,uBAAuB,CAAC,CAAC;QAE9D,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,IAAI,WAAW,EAAE,CAAC;YACjB,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;YACvD,IAAI,CAAC,GAAG;gBACP,OAAO;YAER,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC;QACxB,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAEzD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACxB,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;gBAChC,MAAM,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;QACpC,CAAC;IACF,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,KAA4B;QACzC,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC1B,IAAI,CAAC,IAAI,CAAC,KAAK;gBACd,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;YAEzD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;QAED,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,MAAM,sBAAsB,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,sBAAsB,CAAC;QAEhE,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,sBAAsB,EAAE,IAAI,EAAE,CAAC,CAAC;QAElE,OAAO,KAAK,CAAC;IACd,CAAC;IAED,uBAAuB,CAAC,UAAkB;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACpD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YACpB,OAAO,EAAE,CAAC;QAEX,MAAM,WAAW,GAA2B,EAAE,CAAC;QAC/C,KAAK,MAAM,GAAG,IAAI,IAAI;YACrB,WAAW,CAAC,GAAG,CAAC,eAAe,CAAC,GAAG,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAEhE,OAAO,WAAW,CAAC;IACpB,CAAC;IAED,iBAAiB,CAAC,GAAa;QAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,WAAW,GAAG,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEzD,MAAM,KAAK,GAAW;YACrB,EAAE,EAAE,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,GAAG,IAAI;SACP,CAAC;QAEF,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,CAAC;YACtC,KAAK,CAAC,WAAW,GAAG,WAAW,CAAC;QAEjC,OAAO,KAAK,CAAC;IACd,CAAC;CACD"}
1
+ {"version":3,"file":"SqliteEventStorage.js","sourceRoot":"","sources":["../../../src/sqlite/SqliteEventStorage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { IContainer } from 'node-cqrs';
2
+ import type { PostgresqlConnection } from './PostgresqlConnection.ts';
3
+ /**
4
+ * Abstract base class for accessing a PostgreSQL connection.
5
+ *
6
+ * Manages the connection lifecycle, ensuring initialization via `assertConnection`.
7
+ * Supports providing a query-capable connection directly or a factory function for lazy initialization.
8
+ *
9
+ * Subclasses must implement the `initialize` method for specific setup tasks.
10
+ */
11
+ export declare abstract class AbstractPostgresqlAccessor {
12
+ #private;
13
+ protected db: PostgresqlConnection | undefined;
14
+ constructor(c: Partial<Pick<IContainer, 'viewModelPostgresqlDb' | 'viewModelPostgresqlDbFactory'>>);
15
+ protected abstract initialize(db: PostgresqlConnection): Promise<void> | void;
16
+ protected get connection(): PostgresqlConnection;
17
+ /**
18
+ * Ensures that the PostgreSQL connection is initialized.
19
+ * Uses a lock to prevent race conditions during concurrent initialization attempts.
20
+ * If the connection is not already set, it creates one using the provided factory
21
+ * and then calls the `initialize` method.
22
+ *
23
+ * This method is idempotent and safe to call multiple times.
24
+ */
25
+ assertConnection(): Promise<void>;
26
+ runInTransaction<T>(callback: () => Promise<T> | T): Promise<T>;
27
+ private getTransactionConnection;
28
+ private static isConnectionPool;
29
+ }
@@ -0,0 +1,12 @@
1
+ import type { IContainer } from 'node-cqrs';
2
+ import { AbstractProjection } from '../AbstractProjection.ts';
3
+ import type { IEvent } from '../interfaces/index.ts';
4
+ import { PostgresqlObjectView } from './PostgresqlObjectView.ts';
5
+ type PostgresqlObjectProjectionParams = Partial<Pick<IContainer, 'viewModelPostgresqlDb' | 'viewModelPostgresqlDbFactory' | 'logger' | 'postgresqlObjectStorageMaxRetries'>> & Partial<Pick<ConstructorParameters<typeof PostgresqlObjectView>[0], 'eventLockTableName' | 'eventLockTtl' | 'viewLockTableName' | 'viewLockTtl'>>;
6
+ export declare abstract class AbstractPostgresqlObjectProjection<T> extends AbstractProjection<PostgresqlObjectView<T>> {
7
+ static get tableName(): string;
8
+ static get schemaVersion(): string;
9
+ constructor({ eventLockTableName, eventLockTtl, logger, postgresqlObjectStorageMaxRetries, viewLockTableName, viewLockTtl, viewModelPostgresqlDb, viewModelPostgresqlDbFactory }: PostgresqlObjectProjectionParams);
10
+ project(event: IEvent, meta?: Record<string, any>): Promise<void>;
11
+ }
12
+ export {};
@@ -0,0 +1,23 @@
1
+ import type { IContainer } from 'node-cqrs';
2
+ import type { IEvent, IEventLocker, ILogger, IViewLocker } from '../interfaces/index.ts';
3
+ import { AbstractPostgresqlAccessor } from './AbstractPostgresqlAccessor.ts';
4
+ import { PostgresqlEventLocker, type PostgresqlEventLockerParams } from './PostgresqlEventLocker.ts';
5
+ import { PostgresqlViewLocker, type PostgresqlViewLockerParams } from './PostgresqlViewLocker.ts';
6
+ /**
7
+ * Base class for PostgreSQL-backed projection views with restore locking and last-processed-event tracking.
8
+ */
9
+ export declare abstract class AbstractPostgresqlView extends AbstractPostgresqlAccessor implements IViewLocker, IEventLocker {
10
+ protected readonly schemaVersion: string;
11
+ protected readonly viewLocker: PostgresqlViewLocker;
12
+ protected readonly eventLocker: PostgresqlEventLocker;
13
+ protected logger: ILogger | undefined;
14
+ get ready(): boolean;
15
+ constructor(options: Partial<Pick<IContainer, 'viewModelPostgresqlDb' | 'viewModelPostgresqlDbFactory' | 'logger'>> & PostgresqlEventLockerParams & PostgresqlViewLockerParams);
16
+ lock(): Promise<boolean>;
17
+ unlock(): Promise<void>;
18
+ once(event: 'ready'): Promise<void>;
19
+ getLastEvent(): Promise<IEvent | undefined>;
20
+ tryMarkAsProjecting(event: IEvent): Promise<boolean>;
21
+ markAsProjected(event: IEvent): Promise<void>;
22
+ markAsLastEvent(event: IEvent): Promise<void>;
23
+ }
@@ -0,0 +1,12 @@
1
+ import type { PostgresqlConnection } from './PostgresqlConnection.ts';
2
+ declare module 'node-cqrs' {
3
+ interface IContainer {
4
+ viewModelPostgresqlDb?: PostgresqlConnection;
5
+ viewModelPostgresqlDbFactory?: () => Promise<PostgresqlConnection> | PostgresqlConnection;
6
+ postgresqlEventStorageConfig?: {
7
+ eventsTableName?: string;
8
+ eventSagasTableName?: string;
9
+ };
10
+ postgresqlObjectStorageMaxRetries?: number;
11
+ }
12
+ }
@@ -0,0 +1,7 @@
1
+ export type PostgresqlQueryResult<TRow extends Record<string, unknown> = Record<string, unknown>> = {
2
+ rows: TRow[];
3
+ rowCount: number | null;
4
+ };
5
+ export type PostgresqlConnection = {
6
+ query<TRow extends Record<string, unknown> = Record<string, unknown>>(text: string, values?: readonly unknown[]): Promise<PostgresqlQueryResult<TRow>>;
7
+ };
@@ -0,0 +1,39 @@
1
+ import type { IContainer } from 'node-cqrs';
2
+ import type { IEvent, IEventLocker } from '../interfaces/index.ts';
3
+ import type { PostgresqlConnection } from './PostgresqlConnection.ts';
4
+ import type { PostgresqlProjectionDataParams } from './PostgresqlProjectionDataParams.ts';
5
+ import type { PostgresqlViewLockerParams } from './PostgresqlViewLocker.ts';
6
+ import { AbstractPostgresqlAccessor } from './AbstractPostgresqlAccessor.ts';
7
+ export type PostgresqlEventLockerParams = PostgresqlProjectionDataParams & Pick<PostgresqlViewLockerParams, 'viewLockTableName'> & {
8
+ /**
9
+ * (Optional) PostgreSQL table name where event locks are stored.
10
+ *
11
+ * @default PostgresqlEventLocker.DEFAULT_EVENT_LOCK_TABLE
12
+ */
13
+ eventLockTableName?: string;
14
+ /**
15
+ * (Optional) Time-to-live (TTL) duration in milliseconds
16
+ * for which an event remains in the "processing" state until released.
17
+ *
18
+ * @default PostgresqlEventLocker.DEFAULT_EVENT_LOCK_TTL
19
+ */
20
+ eventLockTtl?: number;
21
+ };
22
+ /**
23
+ * PostgreSQL-backed implementation of IEventLocker.
24
+ *
25
+ * Uses one table for per-event processing locks and the view lock table for the
26
+ * last processed event checkpoint.
27
+ */
28
+ export declare class PostgresqlEventLocker extends AbstractPostgresqlAccessor implements IEventLocker {
29
+ #private;
30
+ static DEFAULT_EVENT_LOCK_TTL: number;
31
+ static DEFAULT_EVENT_LOCK_TABLE: string;
32
+ static DEFAULT_VIEW_LOCK_TABLE: string;
33
+ constructor(o: Partial<Pick<IContainer, 'viewModelPostgresqlDb' | 'viewModelPostgresqlDbFactory'>> & PostgresqlEventLockerParams);
34
+ protected initialize(db: PostgresqlConnection): Promise<void>;
35
+ tryMarkAsProjecting(event: IEvent): Promise<boolean>;
36
+ markAsProjected(event: IEvent): Promise<void>;
37
+ markAsLastEvent(event: IEvent): Promise<void>;
38
+ getLastEvent(): Promise<IEvent | undefined>;
39
+ }
@@ -0,0 +1,23 @@
1
+ import type { IContainer } from 'node-cqrs';
2
+ import type { AggregateEventsQueryParams, DispatchPipelineBatch, EventQueryAfter, IDispatchPipelineProcessor, IEvent, IEventSet, IEventStorageReader, IEventStream, IIdentifierProvider, Identifier } from '../interfaces/index.ts';
3
+ import { AbstractPostgresqlAccessor } from './AbstractPostgresqlAccessor.ts';
4
+ import type { PostgresqlConnection } from './PostgresqlConnection.ts';
5
+ export declare class PostgresqlEventStorage extends AbstractPostgresqlAccessor implements IEventStorageReader, IIdentifierProvider, IDispatchPipelineProcessor {
6
+ #private;
7
+ static readonly EVENTS_TABLE = "tbl_events";
8
+ static readonly EVENT_SAGAS_TABLE = "tbl_event_sagas";
9
+ constructor({ postgresqlEventStorageConfig, viewModelPostgresqlDb, viewModelPostgresqlDbFactory }: Partial<Pick<IContainer, 'postgresqlEventStorageConfig' | 'viewModelPostgresqlDb' | 'viewModelPostgresqlDbFactory'>>);
10
+ protected initialize(db: PostgresqlConnection): Promise<void>;
11
+ getNewId(): string;
12
+ commitEvents(events: IEventSet, options?: {
13
+ ignoreConcurrencyError?: boolean;
14
+ meta?: Record<string, unknown> | null;
15
+ }): Promise<IEventSet>;
16
+ getAggregateEvents(aggregateId: Identifier, options?: AggregateEventsQueryParams): IEventStream;
17
+ getSagaEvents(sagaId: Identifier, { beforeEvent }: {
18
+ beforeEvent: IEvent;
19
+ }): IEventStream;
20
+ getEventsByTypes(eventTypes: Readonly<string[]>, options?: EventQueryAfter): IEventStream;
21
+ process(batch: DispatchPipelineBatch): Promise<DispatchPipelineBatch>;
22
+ private isAggregateVersionUniqueViolation;
23
+ }
@@ -0,0 +1,29 @@
1
+ import type { IContainer } from 'node-cqrs';
2
+ import type { Identifier, IObjectStorage } from '../interfaces/index.ts';
3
+ import { AbstractPostgresqlAccessor } from './AbstractPostgresqlAccessor.ts';
4
+ import type { PostgresqlConnection } from './PostgresqlConnection.ts';
5
+ /**
6
+ * PostgreSQL-backed implementation of IObjectStorage.
7
+ *
8
+ * Each record is stored as a row `{ id, data, version }`.
9
+ * The version field enables optimistic concurrency control: `update` and
10
+ * `updateEnforcingNew` re-read the record after the user callback runs and
11
+ * atomically commit only when the version still matches.
12
+ * On mismatch the operation retries up to `maxRetries` times.
13
+ */
14
+ export declare class PostgresqlObjectStorage<TRecord> extends AbstractPostgresqlAccessor implements IObjectStorage<TRecord> {
15
+ #private;
16
+ constructor(o: Partial<Pick<IContainer, 'viewModelPostgresqlDb' | 'viewModelPostgresqlDbFactory'>> & {
17
+ tableName: string;
18
+ maxRetries?: number;
19
+ });
20
+ protected initialize(db: PostgresqlConnection): Promise<void>;
21
+ get(id: Identifier): Promise<TRecord | undefined>;
22
+ create(id: Identifier, data: TRecord): Promise<void>;
23
+ update(id: Identifier, update: (r: TRecord) => TRecord): Promise<void>;
24
+ updateEnforcingNew(id: Identifier, update: (r?: TRecord) => TRecord): Promise<void>;
25
+ delete(id: Identifier): Promise<boolean>;
26
+ private getRow;
27
+ private updateByVersion;
28
+ private static parseData;
29
+ }
@@ -0,0 +1,19 @@
1
+ import type { IEventLocker, Identifier, IObjectStorage } from '../interfaces/index.ts';
2
+ import { AbstractPostgresqlView } from './AbstractPostgresqlView.ts';
3
+ import type { PostgresqlConnection } from './PostgresqlConnection.ts';
4
+ /**
5
+ * PostgreSQL-backed object view with restore locking and last-processed-event tracking.
6
+ */
7
+ export declare class PostgresqlObjectView<TRecord> extends AbstractPostgresqlView implements IObjectStorage<TRecord>, IEventLocker {
8
+ #private;
9
+ constructor(options: ConstructorParameters<typeof AbstractPostgresqlView>[0] & {
10
+ tableNamePrefix: string;
11
+ postgresqlObjectStorageMaxRetries?: number;
12
+ });
13
+ protected initialize(_db: PostgresqlConnection): Promise<void> | void;
14
+ get(id: Identifier): Promise<TRecord | undefined>;
15
+ create(id: Identifier, data: TRecord): Promise<void>;
16
+ update(id: Identifier, update: (r: TRecord) => TRecord): Promise<void>;
17
+ updateEnforcingNew(id: Identifier, update: (r?: TRecord) => TRecord): Promise<void>;
18
+ delete(id: Identifier): Promise<boolean>;
19
+ }
@@ -0,0 +1,14 @@
1
+ export type PostgresqlProjectionDataParams = {
2
+ /**
3
+ * Unique identifier for the projection, used with the schema version to distinguish data ownership.
4
+ */
5
+ projectionName: string;
6
+ /**
7
+ * The version of the schema used for data produced by the projection.
8
+ * When the projection's output format changes, this version should be incremented.
9
+ * A version change indicates that previously stored data is obsolete and must be rebuilt.
10
+ *
11
+ * @example "20250519", "1.0.0"
12
+ */
13
+ schemaVersion: string;
14
+ };