@rkrkdldkd/example-event-sourcing 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.module.js +2 -3
- package/dist/app.module.js.map +1 -1
- package/dist/event-sourcing.module.d.ts +4 -2
- package/dist/event-sourcing.module.js +32 -22
- package/dist/event-sourcing.module.js.map +1 -1
- package/dist/helper/logger/default.logger.d.ts +13 -0
- package/dist/helper/logger/default.logger.js +31 -0
- package/dist/helper/logger/default.logger.js.map +1 -0
- package/dist/model/db/db.client.d.ts +7 -6
- package/dist/model/db/db.client.js +7 -20
- package/dist/model/db/db.client.js.map +1 -1
- package/dist/model/db/db.connection.d.ts +11 -0
- package/dist/model/db/db.connection.js +52 -0
- package/dist/model/db/db.connection.js.map +1 -0
- package/dist/model/db/event-sourcing.repository.d.ts +19 -0
- package/dist/model/db/event-sourcing.repository.js +80 -0
- package/dist/model/db/event-sourcing.repository.js.map +1 -0
- package/dist/model/db/event-store.repository.d.ts +21 -0
- package/dist/model/db/event-store.repository.js +101 -0
- package/dist/model/db/event-store.repository.js.map +1 -0
- package/dist/model/db/index.d.ts +4 -0
- package/dist/model/db/index.js +21 -0
- package/dist/model/db/index.js.map +1 -0
- package/dist/model/db/snapshot.repository.d.ts +17 -0
- package/dist/model/db/snapshot.repository.js +60 -0
- package/dist/model/db/snapshot.repository.js.map +1 -0
- package/dist/model/index.d.ts +1 -2
- package/dist/model/index.js +1 -2
- package/dist/model/index.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/dist/model/abstract.repository.d.ts +0 -13
- package/dist/model/abstract.repository.js +0 -119
- package/dist/model/abstract.repository.js.map +0 -1
- package/dist/model/temp.repository.d.ts +0 -3
- package/dist/model/temp.repository.js +0 -18
- package/dist/model/temp.repository.js.map +0 -1
package/dist/app.module.js
CHANGED
|
@@ -8,8 +8,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.AppModule = void 0;
|
|
10
10
|
const common_1 = require("@nestjs/common");
|
|
11
|
-
const event_sourcing_module_1 = require("
|
|
12
|
-
const temp_repository_1 = require("src/model/temp.repository");
|
|
11
|
+
const event_sourcing_module_1 = require("./event-sourcing.module");
|
|
13
12
|
const app_controller_1 = require("./app.controller");
|
|
14
13
|
const app_service_1 = require("./app.service");
|
|
15
14
|
let AppModule = class AppModule {
|
|
@@ -27,7 +26,7 @@ exports.AppModule = AppModule = __decorate([
|
|
|
27
26
|
}),
|
|
28
27
|
],
|
|
29
28
|
controllers: [app_controller_1.AppController],
|
|
30
|
-
providers: [app_service_1.AppService
|
|
29
|
+
providers: [app_service_1.AppService],
|
|
31
30
|
})
|
|
32
31
|
], AppModule);
|
|
33
32
|
//# sourceMappingURL=app.module.js.map
|
package/dist/app.module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.module.js","sourceRoot":"","sources":["../src/app.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,
|
|
1
|
+
{"version":3,"file":"app.module.js","sourceRoot":"","sources":["../src/app.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,mEAAgE;AAChE,qDAAiD;AACjD,+CAA2C;AAepC,IAAM,SAAS,GAAf,MAAM,SAAS;CAAG,CAAA;AAAZ,8BAAS;oBAAT,SAAS;IAbrB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,2CAAmB,CAAC,YAAY,CAAC;gBAC/B,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,IAAI;gBACV,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE,UAAU;gBACpB,QAAQ,EAAE,UAAU;aACrB,CAAC;SACH;QACD,WAAW,EAAE,CAAC,8BAAa,CAAC;QAC5B,SAAS,EAAE,CAAC,wBAAU,CAAC;KACxB,CAAC;GACW,SAAS,CAAG"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { DynamicModule, OnModuleInit } from '@nestjs/common';
|
|
2
2
|
import { PoolConfig } from 'pg';
|
|
3
|
-
import { DbClient } from './model
|
|
3
|
+
import { DbClient, EventStoreRepository, SnapshotRepository } from './model';
|
|
4
4
|
export declare class EventSourcingModule implements OnModuleInit {
|
|
5
5
|
private readonly dbClient;
|
|
6
|
+
private readonly eventStoreRepository;
|
|
7
|
+
private readonly snapshotRepository;
|
|
6
8
|
static forRootAsync(config: PoolConfig): DynamicModule;
|
|
7
|
-
constructor(dbClient: DbClient);
|
|
9
|
+
constructor(dbClient: DbClient, eventStoreRepository: EventStoreRepository, snapshotRepository: SnapshotRepository);
|
|
8
10
|
onModuleInit(): Promise<void>;
|
|
9
11
|
}
|
|
@@ -13,10 +13,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
13
13
|
exports.EventSourcingModule = void 0;
|
|
14
14
|
const common_1 = require("@nestjs/common");
|
|
15
15
|
const core_1 = require("@nestjs/core");
|
|
16
|
-
const constants_1 = require("
|
|
17
|
-
const
|
|
16
|
+
const constants_1 = require("./common/constants");
|
|
17
|
+
const model_1 = require("./model");
|
|
18
18
|
let EventSourcingModule = EventSourcingModule_1 = class EventSourcingModule {
|
|
19
19
|
dbClient;
|
|
20
|
+
eventStoreRepository;
|
|
21
|
+
snapshotRepository;
|
|
20
22
|
static forRootAsync(config) {
|
|
21
23
|
const providers = [
|
|
22
24
|
{
|
|
@@ -24,13 +26,27 @@ let EventSourcingModule = EventSourcingModule_1 = class EventSourcingModule {
|
|
|
24
26
|
useValue: config,
|
|
25
27
|
},
|
|
26
28
|
{
|
|
27
|
-
provide:
|
|
29
|
+
provide: model_1.DbClient,
|
|
28
30
|
useFactory: (options) => {
|
|
29
|
-
const client = new
|
|
31
|
+
const client = new model_1.DbClient(options);
|
|
30
32
|
return client;
|
|
31
33
|
},
|
|
32
34
|
inject: [constants_1.EVENT_SOURCING_OPTIONS],
|
|
33
35
|
},
|
|
36
|
+
{
|
|
37
|
+
provide: model_1.EventStoreRepository,
|
|
38
|
+
useFactory: (dbClient) => {
|
|
39
|
+
return new model_1.EventStoreRepository(dbClient);
|
|
40
|
+
},
|
|
41
|
+
inject: [model_1.DbClient],
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
provide: model_1.SnapshotRepository,
|
|
45
|
+
useFactory: (dbClient) => {
|
|
46
|
+
return new model_1.SnapshotRepository(dbClient);
|
|
47
|
+
},
|
|
48
|
+
inject: [model_1.DbClient],
|
|
49
|
+
},
|
|
34
50
|
];
|
|
35
51
|
return {
|
|
36
52
|
module: EventSourcingModule_1,
|
|
@@ -40,30 +56,22 @@ let EventSourcingModule = EventSourcingModule_1 = class EventSourcingModule {
|
|
|
40
56
|
global: true,
|
|
41
57
|
};
|
|
42
58
|
}
|
|
43
|
-
constructor(dbClient) {
|
|
59
|
+
constructor(dbClient, eventStoreRepository, snapshotRepository) {
|
|
44
60
|
this.dbClient = dbClient;
|
|
61
|
+
this.eventStoreRepository = eventStoreRepository;
|
|
62
|
+
this.snapshotRepository = snapshotRepository;
|
|
45
63
|
}
|
|
46
64
|
async onModuleInit() {
|
|
47
65
|
const connection = await this.dbClient.getConnection();
|
|
48
66
|
try {
|
|
49
|
-
await connection.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
payload JSONB NOT NULL,
|
|
55
|
-
event_date VARCHAR(7) NOT NULL,
|
|
56
|
-
event_id VARCHAR(40) NOT NULL,
|
|
57
|
-
aggregate_id VARCHAR(40) NOT NULL,
|
|
58
|
-
occurred_on TIMESTAMPTZ NOT NULL,
|
|
59
|
-
correlation_id VARCHAR(255),
|
|
60
|
-
causation_id VARCHAR(255),
|
|
61
|
-
PRIMARY KEY (stream_id, version)
|
|
62
|
-
)`);
|
|
63
|
-
await connection.query('COMMIT');
|
|
67
|
+
await connection.begin();
|
|
68
|
+
const aggregateName = 'BookAggregate';
|
|
69
|
+
await this.eventStoreRepository.createEventTable(aggregateName, connection);
|
|
70
|
+
await this.snapshotRepository.createSnapshotTable(aggregateName, connection);
|
|
71
|
+
await connection.commit();
|
|
64
72
|
}
|
|
65
73
|
catch (error) {
|
|
66
|
-
await connection.
|
|
74
|
+
await connection.rollback();
|
|
67
75
|
throw error;
|
|
68
76
|
}
|
|
69
77
|
finally {
|
|
@@ -76,6 +84,8 @@ exports.EventSourcingModule = EventSourcingModule = EventSourcingModule_1 = __de
|
|
|
76
84
|
(0, common_1.Module)({
|
|
77
85
|
imports: [],
|
|
78
86
|
}),
|
|
79
|
-
__metadata("design:paramtypes", [
|
|
87
|
+
__metadata("design:paramtypes", [model_1.DbClient,
|
|
88
|
+
model_1.EventStoreRepository,
|
|
89
|
+
model_1.SnapshotRepository])
|
|
80
90
|
], EventSourcingModule);
|
|
81
91
|
//# sourceMappingURL=event-sourcing.module.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-sourcing.module.js","sourceRoot":"","sources":["../src/event-sourcing.module.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAA+E;AAC/E,uCAA+C;AAE/C,
|
|
1
|
+
{"version":3,"file":"event-sourcing.module.js","sourceRoot":"","sources":["../src/event-sourcing.module.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAA+E;AAC/E,uCAA+C;AAE/C,kDAA8D;AAC9D,mCAA6E;AAKtE,IAAM,mBAAmB,2BAAzB,MAAM,mBAAmB;IAyCX;IACA;IACA;IA1CnB,MAAM,CAAC,YAAY,CAAC,MAAkB;QACpC,MAAM,SAAS,GAAe;YAC5B;gBACE,OAAO,EAAE,kCAAsB;gBAC/B,QAAQ,EAAE,MAAM;aACjB;YACD;gBACE,OAAO,EAAE,gBAAQ;gBACjB,UAAU,EAAE,CAAC,OAAmB,EAAE,EAAE;oBAClC,MAAM,MAAM,GAAG,IAAI,gBAAQ,CAAC,OAAO,CAAC,CAAC;oBACrC,OAAO,MAAM,CAAC;gBAChB,CAAC;gBACD,MAAM,EAAE,CAAC,kCAAsB,CAAC;aACjC;YACD;gBACE,OAAO,EAAE,4BAAoB;gBAC7B,UAAU,EAAE,CAAC,QAAkB,EAAE,EAAE;oBACjC,OAAO,IAAI,4BAAoB,CAAC,QAAQ,CAAC,CAAC;gBAC5C,CAAC;gBACD,MAAM,EAAE,CAAC,gBAAQ,CAAC;aACnB;YACD;gBACE,OAAO,EAAE,0BAAkB;gBAC3B,UAAU,EAAE,CAAC,QAAkB,EAAE,EAAE;oBACjC,OAAO,IAAI,0BAAkB,CAAC,QAAQ,CAAC,CAAC;gBAC1C,CAAC;gBACD,MAAM,EAAE,CAAC,gBAAQ,CAAC;aACnB;SACF,CAAC;QAEF,OAAO;YACL,MAAM,EAAE,qBAAmB;YAC3B,OAAO,EAAE,CAAC,sBAAe,CAAC;YAC1B,SAAS;YACT,OAAO,EAAE,SAAS;YAClB,MAAM,EAAE,IAAI;SACb,CAAC;IACJ,CAAC;IAED,YACmB,QAAkB,EAClB,oBAA0C,EAC1C,kBAAsC;QAFtC,aAAQ,GAAR,QAAQ,CAAU;QAClB,yBAAoB,GAApB,oBAAoB,CAAsB;QAC1C,uBAAkB,GAAlB,kBAAkB,CAAoB;IACtD,CAAC;IAEJ,KAAK,CAAC,YAAY;QAChB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QAEvD,IAAI,CAAC;YACH,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC;YAEzB,MAAM,aAAa,GAAG,eAAe,CAAC;YAEtC,MAAM,IAAI,CAAC,oBAAoB,CAAC,gBAAgB,CAC9C,aAAa,EACb,UAAU,CACX,CAAC;YAEF,MAAM,IAAI,CAAC,kBAAkB,CAAC,mBAAmB,CAC/C,aAAa,EACb,UAAU,CACX,CAAC;YAEF,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,UAAU,CAAC,QAAQ,EAAE,CAAC;YAC5B,MAAM,KAAK,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,UAAU,CAAC,OAAO,EAAE,CAAC;QACvB,CAAC;IACH,CAAC;CACF,CAAA;AAxEY,kDAAmB;8BAAnB,mBAAmB;IAH/B,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,EAAE;KACZ,CAAC;qCA0C6B,gBAAQ;QACI,4BAAoB;QACtB,0BAAkB;GA3C9C,mBAAmB,CAwE/B"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ConsoleLogger, LogLevel } from '@nestjs/common';
|
|
2
|
+
export declare class DefaultLogger extends ConsoleLogger {
|
|
3
|
+
colors: {
|
|
4
|
+
red: (text: string) => string;
|
|
5
|
+
green: (text: string) => string;
|
|
6
|
+
yellow: (text: string) => string;
|
|
7
|
+
grey: (text: string) => string;
|
|
8
|
+
cyan: (text: string) => string;
|
|
9
|
+
magenta: (text: string) => string;
|
|
10
|
+
blue: (text: string) => string;
|
|
11
|
+
};
|
|
12
|
+
protected colorize(message: string, logLevel: LogLevel): string;
|
|
13
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DefaultLogger = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
class DefaultLogger extends common_1.ConsoleLogger {
|
|
6
|
+
colors = {
|
|
7
|
+
red: (text) => `\x1B[31m${text}\x1B[39m`,
|
|
8
|
+
green: (text) => `\x1B[32m${text}\x1B[39m`,
|
|
9
|
+
yellow: (text) => `\x1B[33m${text}\x1B[39m`,
|
|
10
|
+
grey: (text) => `\x1B[90m${text}\x1B[39m`,
|
|
11
|
+
cyan: (text) => `\x1B[36m${text}\x1B[39m`,
|
|
12
|
+
magenta: (text) => `\x1B[35m${text}\x1B[39m`,
|
|
13
|
+
blue: (text) => `\x1B[34m${text}\x1B[39m`,
|
|
14
|
+
};
|
|
15
|
+
colorize(message, logLevel) {
|
|
16
|
+
switch (logLevel) {
|
|
17
|
+
case 'error':
|
|
18
|
+
return this.colors.red(message);
|
|
19
|
+
case 'warn':
|
|
20
|
+
return this.colors.yellow(message);
|
|
21
|
+
case 'debug':
|
|
22
|
+
return this.colors.magenta(message);
|
|
23
|
+
case 'verbose':
|
|
24
|
+
return this.colors.cyan(message);
|
|
25
|
+
default:
|
|
26
|
+
return this.colors.blue(message);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.DefaultLogger = DefaultLogger;
|
|
31
|
+
//# sourceMappingURL=default.logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default.logger.js","sourceRoot":"","sources":["../../../src/helper/logger/default.logger.ts"],"names":[],"mappings":";;;AAAA,2CAAyD;AAEzD,MAAa,aAAc,SAAQ,sBAAa;IAC9C,MAAM,GAAG;QACP,GAAG,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,WAAW,IAAI,UAAU;QAChD,KAAK,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,WAAW,IAAI,UAAU;QAClD,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,WAAW,IAAI,UAAU;QACnD,IAAI,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,WAAW,IAAI,UAAU;QACjD,IAAI,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,WAAW,IAAI,UAAU;QACjD,OAAO,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,WAAW,IAAI,UAAU;QACpD,IAAI,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,WAAW,IAAI,UAAU;KAClD,CAAC;IAEQ,QAAQ,CAAC,OAAe,EAAE,QAAkB;QACpD,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,OAAO;gBACV,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAClC,KAAK,MAAM;gBACT,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACrC,KAAK,OAAO;gBACV,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACtC,KAAK,SAAS;gBACZ,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACnC;gBACE,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;CACF;AAzBD,sCAyBC"}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { PoolClient, PoolConfig, QueryConfig, QueryConfigValues, QueryResult, QueryResultRow } from 'pg';
|
|
2
|
+
import { DbConnection } from './db.connection';
|
|
2
3
|
export declare class DbClient {
|
|
3
4
|
private readonly options;
|
|
4
5
|
private pool;
|
|
5
6
|
private readonly logger;
|
|
6
7
|
constructor(options: PoolConfig);
|
|
7
|
-
getConnection(): Promise<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
getConnection(): Promise<DbConnection>;
|
|
9
|
+
query<R extends QueryResultRow = any, I = any[]>({ queryTextOrConfig, values, connection, }: {
|
|
10
|
+
queryTextOrConfig: string | QueryConfig<I>;
|
|
11
|
+
values?: QueryConfigValues<I>;
|
|
12
|
+
connection: PoolClient;
|
|
13
|
+
}): Promise<QueryResult<R>>;
|
|
13
14
|
}
|
|
@@ -13,34 +13,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
13
13
|
exports.DbClient = void 0;
|
|
14
14
|
const common_1 = require("@nestjs/common");
|
|
15
15
|
const pg_1 = require("pg");
|
|
16
|
+
const default_logger_1 = require("../../helper/logger/default.logger");
|
|
17
|
+
const db_connection_1 = require("./db.connection");
|
|
16
18
|
let DbClient = DbClient_1 = class DbClient {
|
|
17
19
|
options;
|
|
18
20
|
pool;
|
|
19
|
-
logger = new
|
|
21
|
+
logger = new default_logger_1.DefaultLogger(DbClient_1.name);
|
|
20
22
|
constructor(options) {
|
|
21
23
|
this.options = options;
|
|
22
24
|
this.pool = new pg_1.Pool(options);
|
|
23
25
|
}
|
|
24
26
|
async getConnection() {
|
|
25
|
-
|
|
27
|
+
const connection = await this.pool.connect();
|
|
28
|
+
return new db_connection_1.DbConnection(connection);
|
|
26
29
|
}
|
|
27
|
-
async
|
|
28
|
-
await connection.query('BEGIN');
|
|
29
|
-
this.logger.log('BEGIN');
|
|
30
|
-
}
|
|
31
|
-
async commit(connection) {
|
|
32
|
-
await connection.query('COMMIT');
|
|
33
|
-
this.logger.log('COMMIT');
|
|
34
|
-
}
|
|
35
|
-
async rollback(connection) {
|
|
36
|
-
await connection.query('ROLLBACK');
|
|
37
|
-
this.logger.log('ROLLBACK');
|
|
38
|
-
}
|
|
39
|
-
releaseConnection(connection) {
|
|
40
|
-
connection.release();
|
|
41
|
-
this.logger.log('RELEASE');
|
|
42
|
-
}
|
|
43
|
-
async query(queryTextOrConfig, values) {
|
|
30
|
+
async query({ queryTextOrConfig, values, connection, }) {
|
|
44
31
|
const start = Date.now();
|
|
45
32
|
const text = typeof queryTextOrConfig === 'string'
|
|
46
33
|
? queryTextOrConfig
|
|
@@ -51,7 +38,7 @@ let DbClient = DbClient_1 = class DbClient {
|
|
|
51
38
|
: queryTextOrConfig.values);
|
|
52
39
|
const paramsText = params === undefined ? '' : ` [params: ${JSON.stringify(params)}]`;
|
|
53
40
|
try {
|
|
54
|
-
const result = await
|
|
41
|
+
const result = await connection.query(queryTextOrConfig, values);
|
|
55
42
|
const ms = Date.now() - start;
|
|
56
43
|
this.logger.log(`[query] ${text ?? '[unknown]'}${paramsText} [took ${ms} ms]`);
|
|
57
44
|
return result;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.client.js","sourceRoot":"","sources":["../../../src/model/db/db.client.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"db.client.js","sourceRoot":"","sources":["../../../src/model/db/db.client.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAA4C;AAC5C,2BAQY;AACZ,uEAAiE;AACjE,mDAA+C;AAGxC,IAAM,QAAQ,gBAAd,MAAM,QAAQ;IAIU;IAHrB,IAAI,CAAO;IACF,MAAM,GAAG,IAAI,8BAAa,CAAC,UAAQ,CAAC,IAAI,CAAC,CAAC;IAE3D,YAA6B,OAAmB;QAAnB,YAAO,GAAP,OAAO,CAAY;QAC9C,IAAI,CAAC,IAAI,GAAG,IAAI,SAAI,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAE7C,OAAO,IAAI,4BAAY,CAAC,UAAU,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,KAAK,CAA4C,EACrD,iBAAiB,EACjB,MAAM,EACN,UAAU,GAKX;QACC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,MAAM,IAAI,GACR,OAAO,iBAAiB,KAAK,QAAQ;YACnC,CAAC,CAAC,iBAAiB;YACnB,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC;QAE7B,MAAM,MAAM,GACV,MAAM;YACN,CAAC,OAAO,iBAAiB,KAAK,QAAQ;gBACpC,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAEhC,MAAM,UAAU,GACd,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC;QAErE,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,KAAK,CAAO,iBAAiB,EAAE,MAAM,CAAC,CAAC;YACvE,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;YAC9B,IAAI,CAAC,MAAM,CAAC,GAAG,CACb,WAAW,IAAI,IAAI,WAAW,GAAG,UAAU,UAAU,EAAE,MAAM,CAC9D,CAAC;YACF,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;YAC9B,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACzE,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,WAAW,IAAI,IAAI,WAAW,GAAG,UAAU,UAAU,EAAE,cAAc,OAAO,EAAE,CAC/E,CAAC;YACF,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CACF,CAAA;AAtDY,4BAAQ;mBAAR,QAAQ;IADpB,IAAA,mBAAU,GAAE;;GACA,QAAQ,CAsDpB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { PoolClient, QueryConfig, QueryConfigValues, QueryResult, QueryResultRow } from 'pg';
|
|
2
|
+
export declare class DbConnection {
|
|
3
|
+
private connection;
|
|
4
|
+
private readonly logger;
|
|
5
|
+
constructor(connection: PoolClient);
|
|
6
|
+
begin(): Promise<void>;
|
|
7
|
+
commit(): Promise<void>;
|
|
8
|
+
rollback(): Promise<void>;
|
|
9
|
+
release(): void;
|
|
10
|
+
query<R extends QueryResultRow = any, I = any[]>(queryTextOrConfig: string | QueryConfig<I>, values?: QueryConfigValues<I>): Promise<QueryResult<R>>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DbConnection = void 0;
|
|
4
|
+
const default_logger_1 = require("../../helper/logger/default.logger");
|
|
5
|
+
class DbConnection {
|
|
6
|
+
connection;
|
|
7
|
+
logger = new default_logger_1.DefaultLogger(DbConnection.name);
|
|
8
|
+
constructor(connection) {
|
|
9
|
+
this.connection = connection;
|
|
10
|
+
}
|
|
11
|
+
async begin() {
|
|
12
|
+
await this.connection.query('BEGIN');
|
|
13
|
+
this.logger.log('BEGIN');
|
|
14
|
+
}
|
|
15
|
+
async commit() {
|
|
16
|
+
await this.connection.query('COMMIT');
|
|
17
|
+
this.logger.log('COMMIT');
|
|
18
|
+
}
|
|
19
|
+
async rollback() {
|
|
20
|
+
await this.connection.query('ROLLBACK');
|
|
21
|
+
this.logger.log('ROLLBACK');
|
|
22
|
+
}
|
|
23
|
+
release() {
|
|
24
|
+
this.connection.release();
|
|
25
|
+
this.logger.log('RELEASE');
|
|
26
|
+
}
|
|
27
|
+
async query(queryTextOrConfig, values) {
|
|
28
|
+
const start = Date.now();
|
|
29
|
+
const text = typeof queryTextOrConfig === 'string'
|
|
30
|
+
? queryTextOrConfig
|
|
31
|
+
: queryTextOrConfig.text;
|
|
32
|
+
const params = values ??
|
|
33
|
+
(typeof queryTextOrConfig === 'string'
|
|
34
|
+
? undefined
|
|
35
|
+
: queryTextOrConfig.values);
|
|
36
|
+
const paramsText = params === undefined ? '' : ` [params: ${JSON.stringify(params)}]`;
|
|
37
|
+
try {
|
|
38
|
+
const result = await this.connection.query(queryTextOrConfig, values);
|
|
39
|
+
const ms = Date.now() - start;
|
|
40
|
+
this.logger.log(`[query] ${text ?? '[unknown]'}${paramsText} [took ${ms} ms]`);
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
const ms = Date.now() - start;
|
|
45
|
+
const message = error instanceof Error ? error.message : 'unknown error';
|
|
46
|
+
this.logger.error(`[query] ${text ?? '[unknown]'}${paramsText} [took ${ms} ms] error=${message}`);
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.DbConnection = DbConnection;
|
|
52
|
+
//# sourceMappingURL=db.connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.connection.js","sourceRoot":"","sources":["../../../src/model/db/db.connection.ts"],"names":[],"mappings":";;;AAQA,uEAAiE;AAEjE,MAAa,YAAY;IACf,UAAU,CAAa;IACd,MAAM,GAAkB,IAAI,8BAAa,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAE9E,YAAY,UAAsB;QAChC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,MAAM;QACV,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC9B,CAAC;IAED,OAAO;QACL,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;QAC1B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,KAAK,CACT,iBAA0C,EAC1C,MAA6B;QAE7B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,MAAM,IAAI,GACR,OAAO,iBAAiB,KAAK,QAAQ;YACnC,CAAC,CAAC,iBAAiB;YACnB,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC;QAE7B,MAAM,MAAM,GACV,MAAM;YACN,CAAC,OAAO,iBAAiB,KAAK,QAAQ;gBACpC,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAEhC,MAAM,UAAU,GACd,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC;QAErE,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CACxC,iBAAiB,EACjB,MAAM,CACP,CAAC;YACF,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;YAC9B,IAAI,CAAC,MAAM,CAAC,GAAG,CACb,WAAW,IAAI,IAAI,WAAW,GAAG,UAAU,UAAU,EAAE,MAAM,CAC9D,CAAC;YACF,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;YAC9B,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACzE,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,WAAW,IAAI,IAAI,WAAW,GAAG,UAAU,UAAU,EAAE,cAAc,OAAO,EAAE,CAC/E,CAAC;YACF,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CACF;AAlED,oCAkEC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { AggregateRoot } from '../aggregate.root';
|
|
2
|
+
import { EventEnvelope } from '../event-envelope';
|
|
3
|
+
import { DbClient } from './db.client';
|
|
4
|
+
import { DbConnection } from './db.connection';
|
|
5
|
+
import { EventStoreRepository } from './event-store.repository';
|
|
6
|
+
import { SnapshotRepository } from './snapshot.repository';
|
|
7
|
+
export declare class EventSourcingRepository {
|
|
8
|
+
private readonly dbClient;
|
|
9
|
+
private readonly eventStoreRepository;
|
|
10
|
+
private readonly snapshotRepository;
|
|
11
|
+
constructor(dbClient: DbClient, eventStoreRepository: EventStoreRepository, snapshotRepository: SnapshotRepository);
|
|
12
|
+
getById(): Promise<void>;
|
|
13
|
+
getEnvelope({ aggregate, version, connection, }: {
|
|
14
|
+
aggregate: string;
|
|
15
|
+
version: number;
|
|
16
|
+
connection: DbConnection;
|
|
17
|
+
}): Promise<EventEnvelope>;
|
|
18
|
+
save(aggregate: AggregateRoot): Promise<void>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
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
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.EventSourcingRepository = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const time_uuid_1 = require("@smiledragon-corp/time-uuid");
|
|
18
|
+
const event_envelope_1 = require("../event-envelope");
|
|
19
|
+
const db_client_1 = require("./db.client");
|
|
20
|
+
const event_store_repository_1 = require("./event-store.repository");
|
|
21
|
+
const snapshot_repository_1 = require("./snapshot.repository");
|
|
22
|
+
let EventSourcingRepository = class EventSourcingRepository {
|
|
23
|
+
dbClient;
|
|
24
|
+
eventStoreRepository;
|
|
25
|
+
snapshotRepository;
|
|
26
|
+
constructor(dbClient, eventStoreRepository, snapshotRepository) {
|
|
27
|
+
this.dbClient = dbClient;
|
|
28
|
+
this.eventStoreRepository = eventStoreRepository;
|
|
29
|
+
this.snapshotRepository = snapshotRepository;
|
|
30
|
+
}
|
|
31
|
+
async getById() { }
|
|
32
|
+
async getEnvelope({ aggregate, version, connection, }) {
|
|
33
|
+
const { rows: entities } = await connection.query(`SELECT event, payload, event_id, aggregate_id, version, occurred_on, correlation_id, causation_id
|
|
34
|
+
FROM "${aggregate}_event"
|
|
35
|
+
WHERE version = $1`, [version]);
|
|
36
|
+
const entity = entities[0];
|
|
37
|
+
if (!entity) {
|
|
38
|
+
throw new Error(`Event with version ${version} not found`);
|
|
39
|
+
}
|
|
40
|
+
return event_envelope_1.EventEnvelope.from(entity.event, entity.payload, {
|
|
41
|
+
eventId: time_uuid_1.TimeUUID.parse(entity.event_id),
|
|
42
|
+
aggregateId: entity.aggregate_id,
|
|
43
|
+
version: entity.version,
|
|
44
|
+
occurredOn: entity.occurred_on,
|
|
45
|
+
correlationId: entity.correlation_id ?? undefined,
|
|
46
|
+
causationId: entity.causation_id ?? undefined,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
async save(aggregate) {
|
|
50
|
+
const events = aggregate.commit();
|
|
51
|
+
const connection = await this.dbClient.getConnection();
|
|
52
|
+
try {
|
|
53
|
+
await connection.begin();
|
|
54
|
+
await this.eventStoreRepository.save({
|
|
55
|
+
aggregate,
|
|
56
|
+
events,
|
|
57
|
+
connection,
|
|
58
|
+
});
|
|
59
|
+
await this.snapshotRepository.save({
|
|
60
|
+
aggregate,
|
|
61
|
+
connection,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
await connection.rollback();
|
|
66
|
+
throw new Error('Failed to save aggregate');
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
connection.release();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
exports.EventSourcingRepository = EventSourcingRepository;
|
|
74
|
+
exports.EventSourcingRepository = EventSourcingRepository = __decorate([
|
|
75
|
+
__param(0, (0, common_1.Inject)(db_client_1.DbClient)),
|
|
76
|
+
__metadata("design:paramtypes", [db_client_1.DbClient,
|
|
77
|
+
event_store_repository_1.EventStoreRepository,
|
|
78
|
+
snapshot_repository_1.SnapshotRepository])
|
|
79
|
+
], EventSourcingRepository);
|
|
80
|
+
//# sourceMappingURL=event-sourcing.repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-sourcing.repository.js","sourceRoot":"","sources":["../../../src/model/db/event-sourcing.repository.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAwC;AACxC,2DAAuD;AAGvD,sDAAkD;AAClD,2CAAuC;AAEvC,qEAAgE;AAChE,+DAA2D;AAE3D,IAAa,uBAAuB,GAApC,MAAa,uBAAuB;IAGf;IACA;IACA;IAJnB,YAEmB,QAAkB,EAClB,oBAA0C,EAC1C,kBAAsC;QAFtC,aAAQ,GAAR,QAAQ,CAAU;QAClB,yBAAoB,GAApB,oBAAoB,CAAsB;QAC1C,uBAAkB,GAAlB,kBAAkB,CAAoB;IACtD,CAAC;IAEJ,KAAK,CAAC,OAAO,KAAI,CAAC;IAElB,KAAK,CAAC,WAAW,CAAC,EAChB,SAAS,EACT,OAAO,EACP,UAAU,GAKX;QACC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,MAAM,UAAU,CAAC,KAAK,CAa/C;gBACU,SAAS;2BACE,EACrB,CAAC,OAAO,CAAC,CACV,CAAC;QAEF,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAE3B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,sBAAsB,OAAO,YAAY,CAAC,CAAC;QAC7D,CAAC;QAED,OAAO,8BAAa,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE;YACtD,OAAO,EAAE,oBAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC;YACxC,WAAW,EAAE,MAAM,CAAC,YAAY;YAChC,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,UAAU,EAAE,MAAM,CAAC,WAAW;YAC9B,aAAa,EAAE,MAAM,CAAC,cAAc,IAAI,SAAS;YACjD,WAAW,EAAE,MAAM,CAAC,YAAY,IAAI,SAAS;SAC9C,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,SAAwB;QACjC,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC;QAElC,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QAEvD,IAAI,CAAC;YACH,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC;YAEzB,MAAM,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC;gBACnC,SAAS;gBACT,MAAM;gBACN,UAAU;aACX,CAAC,CAAC;YAEH,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC;gBACjC,SAAS;gBACT,UAAU;aACX,CAAC,CAAC;QAEL,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,MAAM,UAAU,CAAC,QAAQ,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC9C,CAAC;gBAAS,CAAC;YACT,UAAU,CAAC,OAAO,EAAE,CAAC;QACvB,CAAC;IACH,CAAC;CACF,CAAA;AAhFY,0DAAuB;kCAAvB,uBAAuB;IAE/B,WAAA,IAAA,eAAM,EAAC,oBAAQ,CAAC,CAAA;qCACU,oBAAQ;QACI,6CAAoB;QACtB,wCAAkB;GAL9C,uBAAuB,CAgFnC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { IEvent } from 'src/interface';
|
|
2
|
+
import { AggregateRoot } from '../aggregate.root';
|
|
3
|
+
import { EventEnvelope } from '../event-envelope';
|
|
4
|
+
import { DbClient } from './db.client';
|
|
5
|
+
import { DbConnection } from './db.connection';
|
|
6
|
+
export declare class EventStoreRepository {
|
|
7
|
+
private readonly dbClient;
|
|
8
|
+
private readonly columns;
|
|
9
|
+
constructor(dbClient: DbClient);
|
|
10
|
+
createEventTable(aggregateName: string, connection: DbConnection): Promise<void>;
|
|
11
|
+
appendEvents({ aggregate, events, connection, }: {
|
|
12
|
+
aggregate: AggregateRoot;
|
|
13
|
+
events: IEvent[];
|
|
14
|
+
connection: DbConnection;
|
|
15
|
+
}): Promise<EventEnvelope[]>;
|
|
16
|
+
save({ aggregate, events, connection, }: {
|
|
17
|
+
aggregate: AggregateRoot;
|
|
18
|
+
events: IEvent[];
|
|
19
|
+
connection: DbConnection;
|
|
20
|
+
}): Promise<void>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
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
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.EventStoreRepository = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const time_uuid_1 = require("@smiledragon-corp/time-uuid");
|
|
18
|
+
const helper_1 = require("../../helper");
|
|
19
|
+
const event_envelope_1 = require("../event-envelope");
|
|
20
|
+
const db_client_1 = require("./db.client");
|
|
21
|
+
let EventStoreRepository = class EventStoreRepository {
|
|
22
|
+
dbClient;
|
|
23
|
+
columns = [
|
|
24
|
+
'stream_id',
|
|
25
|
+
'version',
|
|
26
|
+
'event',
|
|
27
|
+
'payload',
|
|
28
|
+
'event_date',
|
|
29
|
+
'event_id',
|
|
30
|
+
'aggregate_id',
|
|
31
|
+
'occurred_on',
|
|
32
|
+
'correlation_id',
|
|
33
|
+
'causation_id',
|
|
34
|
+
];
|
|
35
|
+
constructor(dbClient) {
|
|
36
|
+
this.dbClient = dbClient;
|
|
37
|
+
}
|
|
38
|
+
async createEventTable(aggregateName, connection) {
|
|
39
|
+
await connection.query(`CREATE TABLE IF NOT EXISTS "${aggregateName}_event" (
|
|
40
|
+
stream_id VARCHAR(120) NOT NULL,
|
|
41
|
+
version INT NOT NULL,
|
|
42
|
+
event VARCHAR(80) NOT NULL,
|
|
43
|
+
payload JSONB NOT NULL,
|
|
44
|
+
event_date VARCHAR(7) NOT NULL,
|
|
45
|
+
event_id VARCHAR(40) NOT NULL,
|
|
46
|
+
aggregate_id VARCHAR(40) NOT NULL,
|
|
47
|
+
occurred_on TIMESTAMPTZ NOT NULL,
|
|
48
|
+
correlation_id VARCHAR(255),
|
|
49
|
+
causation_id VARCHAR(255),
|
|
50
|
+
PRIMARY KEY (stream_id, version)
|
|
51
|
+
)`);
|
|
52
|
+
}
|
|
53
|
+
async appendEvents({ aggregate, events, connection, }) {
|
|
54
|
+
const streamId = `${aggregate.name}:${aggregate.getRawId()}`;
|
|
55
|
+
const aggregateVersion = aggregate.version;
|
|
56
|
+
const { rows: currentVersionRows } = await connection.query(`SELECT version FROM "${aggregate.name}_event" WHERE stream_id = $1 ORDER BY version DESC LIMIT 1`, [streamId]);
|
|
57
|
+
const currentVersion = currentVersionRows[0]?.version || 0;
|
|
58
|
+
if (aggregateVersion <= currentVersion) {
|
|
59
|
+
throw new Error('Version conflict');
|
|
60
|
+
}
|
|
61
|
+
let version = aggregateVersion - events.length + 1;
|
|
62
|
+
const envelopes = [];
|
|
63
|
+
for (const event of events) {
|
|
64
|
+
if (event instanceof event_envelope_1.EventEnvelope) {
|
|
65
|
+
envelopes.push(event);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const name = event.constructor.name;
|
|
69
|
+
const payload = JSON.stringify(event);
|
|
70
|
+
const envelope = event_envelope_1.EventEnvelope.create(name, payload, {
|
|
71
|
+
aggregateId: aggregate.getRawId(),
|
|
72
|
+
eventId: new time_uuid_1.TimeUUID(),
|
|
73
|
+
version: version++,
|
|
74
|
+
});
|
|
75
|
+
envelopes.push(envelope);
|
|
76
|
+
}
|
|
77
|
+
const values = [];
|
|
78
|
+
const params = [];
|
|
79
|
+
let paramIndex = 1;
|
|
80
|
+
for (const envelope of envelopes) {
|
|
81
|
+
values.push(`(${this.columns.map(() => `$${paramIndex++}`).join(', ')})`);
|
|
82
|
+
params.push(streamId, envelope.metadata.version, envelope.event, envelope.payload, new helper_1.TzDate('Asia/Seoul', envelope.metadata.eventId.timestamp).format('YYYY-MM-DD'), envelope.metadata.eventId.toString(), envelope.metadata.aggregateId, envelope.metadata.occurredOn.toISOString(), envelope.metadata.correlationId ?? null, envelope.metadata.causationId ?? null);
|
|
83
|
+
}
|
|
84
|
+
await connection.query(`INSERT INTO "${aggregate.name}_event" (${this.columns.join(', ')}) VALUES ${values.join(', ')}`, params);
|
|
85
|
+
return envelopes;
|
|
86
|
+
}
|
|
87
|
+
async save({ aggregate, events, connection, }) {
|
|
88
|
+
await this.appendEvents({
|
|
89
|
+
aggregate,
|
|
90
|
+
events,
|
|
91
|
+
connection,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
exports.EventStoreRepository = EventStoreRepository;
|
|
96
|
+
exports.EventStoreRepository = EventStoreRepository = __decorate([
|
|
97
|
+
(0, common_1.Injectable)(),
|
|
98
|
+
__param(0, (0, common_1.Inject)(db_client_1.DbClient)),
|
|
99
|
+
__metadata("design:paramtypes", [db_client_1.DbClient])
|
|
100
|
+
], EventStoreRepository);
|
|
101
|
+
//# sourceMappingURL=event-store.repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-store.repository.js","sourceRoot":"","sources":["../../../src/model/db/event-store.repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./db.client"), exports);
|
|
18
|
+
__exportStar(require("./event-sourcing.repository"), exports);
|
|
19
|
+
__exportStar(require("./event-store.repository"), exports);
|
|
20
|
+
__exportStar(require("./snapshot.repository"), exports);
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/model/db/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B;AAC5B,8DAA4C;AAC5C,2DAAyC;AACzC,wDAAsC"}
|