@pocket-architect/core 0.1.18 → 0.1.20

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 (49) hide show
  1. package/README.md +102 -0
  2. package/build/AggregateRoot.d.ts +0 -5
  3. package/build/AggregateRoot.js +1 -11
  4. package/build/AggregateRoot.js.map +1 -1
  5. package/build/DomainEvent.d.ts +4 -8
  6. package/build/DomainEvent.js +8 -4
  7. package/build/DomainEvent.js.map +1 -1
  8. package/build/Entity.d.ts +6 -1
  9. package/build/Entity.js +30 -0
  10. package/build/Entity.js.map +1 -1
  11. package/build/Entity.spec.js +33 -3
  12. package/build/Entity.spec.js.map +1 -1
  13. package/build/EntityId.d.ts +2 -2
  14. package/build/EntityId.js.map +1 -1
  15. package/build/EntityId.spec.js +6 -5
  16. package/build/EntityId.spec.js.map +1 -1
  17. package/build/EventBus.d.ts +2 -0
  18. package/build/EventBus.spec.d.ts +1 -0
  19. package/build/EventBus.spec.js +157 -0
  20. package/build/EventBus.spec.js.map +1 -0
  21. package/build/eventBus/InMemoryEventBus.d.ts +9 -2
  22. package/build/eventBus/InMemoryEventBus.js +43 -12
  23. package/build/eventBus/InMemoryEventBus.js.map +1 -1
  24. package/build/eventBus/InMemoryEventBus.spec.js +0 -3
  25. package/build/eventBus/InMemoryEventBus.spec.js.map +1 -1
  26. package/build/helpers.d.ts +1 -0
  27. package/build/helpers.js +30 -0
  28. package/build/helpers.js.map +1 -0
  29. package/build/helpers.spec.d.ts +1 -0
  30. package/build/helpers.spec.js +70 -0
  31. package/build/helpers.spec.js.map +1 -0
  32. package/build/index.d.ts +4 -1
  33. package/build/index.js +3 -1
  34. package/build/index.js.map +1 -1
  35. package/package.json +1 -1
  36. package/src/AggregateRoot.ts +0 -15
  37. package/src/DomainEvent.ts +10 -13
  38. package/src/Entity.spec.ts +28 -5
  39. package/src/Entity.ts +37 -2
  40. package/src/EntityId.spec.ts +5 -4
  41. package/src/EntityId.ts +3 -3
  42. package/src/EventBus.spec.ts +108 -0
  43. package/src/EventBus.ts +2 -0
  44. package/src/eventBus/InMemoryEventBus.spec.ts +1 -5
  45. package/src/eventBus/InMemoryEventBus.ts +30 -5
  46. package/src/helpers.spec.ts +62 -0
  47. package/src/helpers.ts +25 -0
  48. package/src/index.ts +7 -1
  49. package/src/AggregateRoot.spec.ts +0 -35
@@ -3,34 +3,65 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.InMemoryEventBus = void 0;
4
4
  var tslib_1 = require("tslib");
5
5
  var events_1 = require("events");
6
- var InMemoryEventBus = /** @class */ (function (_super) {
7
- tslib_1.__extends(InMemoryEventBus, _super);
6
+ var InMemoryEventBus = /** @class */ (function () {
8
7
  function InMemoryEventBus() {
9
- return _super !== null && _super.apply(this, arguments) || this;
8
+ this._events = [];
9
+ this._emitter = new events_1.EventEmitter();
10
10
  }
11
+ InMemoryEventBus.prototype.push = function (event) {
12
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
13
+ return tslib_1.__generator(this, function (_a) {
14
+ this._events.push(event);
15
+ return [2 /*return*/];
16
+ });
17
+ });
18
+ };
19
+ InMemoryEventBus.prototype.clear = function () {
20
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
21
+ return tslib_1.__generator(this, function (_a) {
22
+ this._events = [];
23
+ return [2 /*return*/];
24
+ });
25
+ });
26
+ };
11
27
  InMemoryEventBus.prototype.publish = function (events) {
28
+ if (events === void 0) { events = []; }
12
29
  return tslib_1.__awaiter(this, void 0, void 0, function () {
13
- var _i, events_2, event;
30
+ var allEvents, _i, allEvents_1, event;
14
31
  return tslib_1.__generator(this, function (_a) {
15
- for (_i = 0, events_2 = events; _i < events_2.length; _i++) {
16
- event = events_2[_i];
17
- this.emit(event.eventName, event);
32
+ switch (_a.label) {
33
+ case 0:
34
+ allEvents = (this._events || []).concat(events !== null && events !== void 0 ? events : []);
35
+ for (_i = 0, allEvents_1 = allEvents; _i < allEvents_1.length; _i++) {
36
+ event = allEvents_1[_i];
37
+ this._emitter.emit(event.eventName, event);
38
+ }
39
+ return [4 /*yield*/, this.clear()];
40
+ case 1:
41
+ _a.sent();
42
+ return [2 /*return*/];
18
43
  }
19
- return [2 /*return*/];
20
44
  });
21
45
  });
22
46
  };
47
+ InMemoryEventBus.prototype.on = function (event, listener) {
48
+ this._emitter.on(event, listener);
49
+ };
50
+ InMemoryEventBus.prototype.listenerCount = function (event) {
51
+ return this._emitter.listenerCount(event);
52
+ };
23
53
  InMemoryEventBus.prototype.addSubscribers = function (subscribers) {
54
+ var _a;
24
55
  for (var _i = 0, subscribers_1 = subscribers; _i < subscribers_1.length; _i++) {
25
56
  var subscriber = subscribers_1[_i];
26
57
  var events = subscriber.subscribedTo();
27
- for (var _a = 0, events_3 = events; _a < events_3.length; _a++) {
28
- var event = events_3[_a];
29
- this.on(event.EVENT_NAME, subscriber.on.bind(subscriber));
58
+ for (var _b = 0, events_2 = events; _b < events_2.length; _b++) {
59
+ var event = events_2[_b];
60
+ this._emitter.on((_a = event.EVENT_NAME) !== null && _a !== void 0 ? _a : event.name, subscriber.on.bind(subscriber));
30
61
  }
31
62
  }
32
63
  };
33
64
  return InMemoryEventBus;
34
- }(events_1.EventEmitter));
65
+ }());
35
66
  exports.InMemoryEventBus = InMemoryEventBus;
36
67
  //# sourceMappingURL=InMemoryEventBus.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"InMemoryEventBus.js","sourceRoot":"","sources":["../../src/eventBus/InMemoryEventBus.ts"],"names":[],"mappings":";;;;AAAA,iCAAsC;AAKtC;IAAsC,4CAAY;IAAlD;;IAeA,CAAC;IAdO,kCAAO,GAAb,UAAc,MAAwB;;;;gBACpC,WAA0B,EAAN,iBAAM,EAAN,oBAAM,EAAN,IAAM,EAAE,CAAC;oBAAlB,KAAK;oBACd,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;gBACpC,CAAC;;;;KACF;IAED,yCAAc,GAAd,UAAe,WAAoC;QACjD,KAAyB,UAAW,EAAX,2BAAW,EAAX,yBAAW,EAAX,IAAW,EAAE,CAAC;YAAlC,IAAM,UAAU,oBAAA;YACnB,IAAM,MAAM,GAAG,UAAU,CAAC,YAAY,EAAE,CAAC;YACzC,KAAoB,UAAM,EAAN,iBAAM,EAAN,oBAAM,EAAN,IAAM,EAAE,CAAC;gBAAxB,IAAM,KAAK,eAAA;gBACd,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;IACH,CAAC;IACH,uBAAC;AAAD,CAAC,AAfD,CAAsC,qBAAY,GAejD;AAfY,4CAAgB"}
1
+ {"version":3,"file":"InMemoryEventBus.js","sourceRoot":"","sources":["../../src/eventBus/InMemoryEventBus.ts"],"names":[],"mappings":";;;;AAAA,iCAAsC;AAKtC;IAIE;QAHU,YAAO,GAAqB,EAAE,CAAC;QAIvC,IAAI,CAAC,QAAQ,GAAG,IAAI,qBAAY,EAAE,CAAC;IACrC,CAAC;IAEK,+BAAI,GAAV,UAAW,KAAqB;;;gBAC9B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;;;;KAC1B;IAEK,gCAAK,GAAX;;;gBACE,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;;;;KACnB;IAEK,kCAAO,GAAb,UAAc,MAA6B;QAA7B,uBAAA,EAAA,WAA6B;;;;;;wBACnC,SAAS,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,aAAN,MAAM,cAAN,MAAM,GAAI,EAAE,CAAC,CAAC;wBAC5D,WAA6B,EAAT,uBAAS,EAAT,uBAAS,EAAT,IAAS,EAAE,CAAC;4BAArB,KAAK;4BACd,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;wBAC7C,CAAC;wBACD,qBAAM,IAAI,CAAC,KAAK,EAAE,EAAA;;wBAAlB,SAAkB,CAAC;;;;;KACpB;IAED,6BAAE,GAAF,UAAG,KAAa,EAAE,QAAoC;QACpD,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED,wCAAa,GAAb,UAAc,KAAa;QACzB,OAAO,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC;IAED,yCAAc,GAAd,UAAe,WAAoC;;QACjD,KAAyB,UAAW,EAAX,2BAAW,EAAX,yBAAW,EAAX,IAAW,EAAE,CAAC;YAAlC,IAAM,UAAU,oBAAA;YACnB,IAAM,MAAM,GAAG,UAAU,CAAC,YAAY,EAAE,CAAC;YACzC,KAAoB,UAAM,EAAN,iBAAM,EAAN,oBAAM,EAAN,IAAM,EAAE,CAAC;gBAAxB,IAAM,KAAK,eAAA;gBACd,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAA,KAAK,CAAC,UAAU,mCAAI,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;YACnF,CAAC;QACH,CAAC;IACH,CAAC;IACH,uBAAC;AAAD,CAAC,AAxCD,IAwCC;AAxCY,4CAAgB"}
@@ -20,9 +20,6 @@ var TestEvent = /** @class */ (function (_super) {
20
20
  function TestEvent() {
21
21
  return _super !== null && _super.apply(this, arguments) || this;
22
22
  }
23
- TestEvent.prototype.toPrimitives = function () {
24
- return {};
25
- };
26
23
  TestEvent.EVENT_NAME = 'TestEvent';
27
24
  return TestEvent;
28
25
  }(DomainEvent_1.DomainEvent));
@@ -1 +1 @@
1
- {"version":3,"file":"InMemoryEventBus.spec.js","sourceRoot":"","sources":["../../src/eventBus/InMemoryEventBus.spec.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"InMemoryEventBus.spec.js","sourceRoot":"","sources":["../../src/eventBus/InMemoryEventBus.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function createSnapshot<T>(obj: T): T;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createSnapshot = void 0;
4
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
+ function createSnapshot(obj) {
6
+ if (!obj) {
7
+ return obj;
8
+ }
9
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
10
+ // @ts-ignore
11
+ if (typeof obj.toSnapshot === 'function') {
12
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
13
+ // @ts-ignore
14
+ return obj.toSnapshot();
15
+ }
16
+ var copy = {};
17
+ for (var key in obj) {
18
+ if (!Object.prototype.hasOwnProperty.call(obj, key)) {
19
+ continue;
20
+ }
21
+ if (typeof obj[key] !== 'object') {
22
+ copy[key] = obj[key];
23
+ continue;
24
+ }
25
+ copy[key] = createSnapshot(obj[key]);
26
+ }
27
+ return copy;
28
+ }
29
+ exports.createSnapshot = createSnapshot;
30
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":";;;AAAA,8DAA8D;AAC9D,SAAgB,cAAc,CAAI,GAAM;IACtC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,GAAG,CAAC;IACb,CAAC;IACD,6DAA6D;IAC7D,aAAa;IACb,IAAI,OAAO,GAAG,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;QACzC,6DAA6D;QAC7D,aAAa;QACb,OAAO,GAAG,CAAC,UAAU,EAAO,CAAC;IAC/B,CAAC;IACD,IAAM,IAAI,GAAK,EAAO,CAAC;IACvB,KAAK,IAAM,GAAG,IAAI,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;YACpD,SAAS;QACX,CAAC;QACD,IAAI,OAAO,GAAG,CAAC,GAAG,CAAC,KAAK,QAAQ,EAAE,CAAC;YACjC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;YACrB,SAAS;QACX,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAvBD,wCAuBC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var tslib_1 = require("tslib");
4
+ var helpers_1 = require("./helpers");
5
+ var EntityId_1 = require("./EntityId");
6
+ var Entity_1 = require("./Entity");
7
+ var TestEntity = /** @class */ (function (_super) {
8
+ tslib_1.__extends(TestEntity, _super);
9
+ function TestEntity() {
10
+ return _super !== null && _super.apply(this, arguments) || this;
11
+ }
12
+ TestEntity.create = function (props, id) {
13
+ return new TestEntity(props, id);
14
+ };
15
+ Object.defineProperty(TestEntity.prototype, "name", {
16
+ set: function (name) {
17
+ this.props.name = name;
18
+ },
19
+ enumerable: false,
20
+ configurable: true
21
+ });
22
+ Object.defineProperty(TestEntity.prototype, "testId", {
23
+ set: function (val) {
24
+ this.props.testId = val;
25
+ },
26
+ enumerable: false,
27
+ configurable: true
28
+ });
29
+ TestEntity.prototype.toSnapshot = function () {
30
+ return tslib_1.__assign(tslib_1.__assign({}, this.props), { testId: undefined });
31
+ };
32
+ return TestEntity;
33
+ }(Entity_1.Entity));
34
+ describe('helpers', function () {
35
+ test('createSnapshot', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
36
+ var original, snapshot, item, itemSnapshot;
37
+ return tslib_1.__generator(this, function (_a) {
38
+ original = {
39
+ a: 1,
40
+ b: 'test',
41
+ c: {
42
+ d: 2,
43
+ e: 'nested',
44
+ f: {
45
+ g: 3
46
+ }
47
+ },
48
+ id: new EntityId_1.EntityId('1'),
49
+ };
50
+ snapshot = (0, helpers_1.createSnapshot)(original);
51
+ expect(snapshot).toEqual(original);
52
+ expect(snapshot).not.toBe(original);
53
+ expect(snapshot.c).not.toBe(original.c);
54
+ expect(snapshot.c.f).not.toBe(original.c.f);
55
+ expect(snapshot.id).not.toBe(original.id);
56
+ expect(snapshot.id).toEqual(new EntityId_1.EntityId('1'));
57
+ item = TestEntity.create({
58
+ name: 'test',
59
+ testId: new EntityId_1.EntityId('2')
60
+ }, '2');
61
+ itemSnapshot = (0, helpers_1.createSnapshot)(item);
62
+ expect(itemSnapshot).toEqual({
63
+ name: 'test',
64
+ testId: undefined
65
+ });
66
+ return [2 /*return*/];
67
+ });
68
+ }); });
69
+ });
70
+ //# sourceMappingURL=helpers.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.spec.js","sourceRoot":"","sources":["../src/helpers.spec.ts"],"names":[],"mappings":";;;AAAA,qCAAyC;AACzC,uCAAoC;AACpC,mCAAgC;AAMhC;IAAyB,sCAA2C;IAApE;;IAmBA,CAAC;IAlBQ,iBAAM,GAAb,UAAc,KAAgB,EAAE,EAA2B;QACzD,OAAO,IAAI,UAAU,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACnC,CAAC;IAED,sBAAI,4BAAI;aAAR,UAAS,IAAY;YACnB,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;QACzB,CAAC;;;OAAA;IAED,sBAAI,8BAAM;aAAV,UAAW,GAAqB;YAC9B,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC;QAC1B,CAAC;;;OAAA;IAED,+BAAU,GAAV;QACE,OAAO,sCACF,IAAI,CAAC,KAAK,KACb,MAAM,EAAE,SAAS,GACT,CAAC;IACb,CAAC;IACH,iBAAC;AAAD,CAAC,AAnBD,CAAyB,eAAM,GAmB9B;AAED,QAAQ,CAAC,SAAS,EAAE;IAClB,IAAI,CAAC,gBAAgB,EAAE;;;YACf,QAAQ,GAAG;gBACf,CAAC,EAAE,CAAC;gBACJ,CAAC,EAAE,MAAM;gBACT,CAAC,EAAE;oBACD,CAAC,EAAE,CAAC;oBACJ,CAAC,EAAE,QAAQ;oBACX,CAAC,EAAE;wBACD,CAAC,EAAE,CAAC;qBACL;iBACF;gBACD,EAAE,EAAE,IAAI,mBAAQ,CAAS,GAAG,CAAC;aAC9B,CAAC;YACI,QAAQ,GAAG,IAAA,wBAAc,EAAC,QAAQ,CAAC,CAAC;YAC1C,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YACnC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACpC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YACxC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5C,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YAC1C,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,mBAAQ,CAAS,GAAG,CAAC,CAAC,CAAC;YAEjD,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC;gBAC7B,IAAI,EAAE,MAAM;gBACZ,MAAM,EAAE,IAAI,mBAAQ,CAAC,GAAG,CAAC;aAC1B,EAAE,GAAG,CAAC,CAAC;YACF,YAAY,GAAG,IAAA,wBAAc,EAAC,IAAI,CAAC,CAAC;YAC1C,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC;gBAC3B,IAAI,EAAE,MAAM;gBACZ,MAAM,EAAE,SAAS;aAClB,CAAC,CAAC;;;SACJ,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/build/index.d.ts CHANGED
@@ -3,4 +3,7 @@ import { EntityId } from './EntityId';
3
3
  import { ValueObject } from './ValueObject';
4
4
  import { AggregateRoot } from './AggregateRoot';
5
5
  import { HashError } from './error/HashError';
6
- export { Entity, EntityId, ValueObject, AggregateRoot, HashError };
6
+ import { DomainEvent } from './DomainEvent';
7
+ import { DomainEventSubscriber } from './DomainEventSubscriber';
8
+ import { EventBus } from './EventBus';
9
+ export { Entity, EntityId, ValueObject, AggregateRoot, HashError, DomainEvent, DomainEventSubscriber, EventBus };
package/build/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.HashError = exports.AggregateRoot = exports.ValueObject = exports.EntityId = exports.Entity = void 0;
3
+ exports.DomainEvent = exports.HashError = exports.AggregateRoot = exports.ValueObject = exports.EntityId = exports.Entity = void 0;
4
4
  var Entity_1 = require("./Entity");
5
5
  Object.defineProperty(exports, "Entity", { enumerable: true, get: function () { return Entity_1.Entity; } });
6
6
  var EntityId_1 = require("./EntityId");
@@ -11,4 +11,6 @@ var AggregateRoot_1 = require("./AggregateRoot");
11
11
  Object.defineProperty(exports, "AggregateRoot", { enumerable: true, get: function () { return AggregateRoot_1.AggregateRoot; } });
12
12
  var HashError_1 = require("./error/HashError");
13
13
  Object.defineProperty(exports, "HashError", { enumerable: true, get: function () { return HashError_1.HashError; } });
14
+ var DomainEvent_1 = require("./DomainEvent");
15
+ Object.defineProperty(exports, "DomainEvent", { enumerable: true, get: function () { return DomainEvent_1.DomainEvent; } });
14
16
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,mCAAkC;AAOhC,uFAPO,eAAM,OAOP;AANR,uCAAsC;AAOpC,yFAPO,mBAAQ,OAOP;AANV,6CAA4C;AAO1C,4FAPO,yBAAW,OAOP;AANb,iDAAgD;AAO9C,8FAPO,6BAAa,OAOP;AANf,+CAA8C;AAO5C,0FAPO,qBAAS,OAOP"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,mCAAkC;AAUhC,uFAVO,eAAM,OAUP;AATR,uCAAsC;AAUpC,yFAVO,mBAAQ,OAUP;AATV,6CAA4C;AAU1C,4FAVO,yBAAW,OAUP;AATb,iDAAgD;AAU9C,8FAVO,6BAAa,OAUP;AATf,+CAA8C;AAU5C,0FAVO,qBAAS,OAUP;AATX,6CAA4C;AAU1C,4FAVO,yBAAW,OAUP"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pocket-architect/core",
3
- "version": "0.1.18",
3
+ "version": "0.1.20",
4
4
  "description": "",
5
5
  "main": "build/index.js",
6
6
  "scripts": {
@@ -1,20 +1,5 @@
1
1
  import { Entity } from './Entity';
2
2
  import { EntityId } from './EntityId';
3
- import {DomainEvent} from "./DomainEvent";
4
3
 
5
4
  export abstract class AggregateRoot<T, E, H extends EntityId<E>> extends Entity<T, E, H> {
6
- private _domainEvents: DomainEvent<E>[] = [];
7
-
8
- pullDomainEvents(): DomainEvent<E>[] {
9
- const domainEvents = this._domainEvents.slice();
10
- this._domainEvents = [];
11
- return domainEvents;
12
- }
13
-
14
- pushDomainEvent(event: DomainEvent<E>): void {
15
- this._domainEvents.push(event);
16
- }
17
5
  }
18
-
19
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
- export type AnyAggregateRoot<T> = AggregateRoot<any, T, any>;
@@ -1,25 +1,25 @@
1
1
  import {EntityId} from "./EntityId";
2
- import {AnyAggregateRoot} from "./AggregateRoot";
3
2
 
4
3
  export abstract class DomainEvent<H> {
5
4
  static EVENT_NAME: string;
6
5
 
7
- readonly aggregate: AnyAggregateRoot<H>;
8
- readonly aggregateId: H;
9
- readonly eventId: EntityId<H>;
6
+ readonly props: H;
7
+ readonly eventId: EntityId<never>;
10
8
  readonly occurredOn: Date;
11
9
  readonly eventName: string;
12
10
 
13
- constructor(aggregate: AnyAggregateRoot<H>, eventId?: EntityId<H>, occurredOn?: Date) {
11
+ constructor(props: H, eventId?: EntityId<never>, occurredOn?: Date) {
12
+ this.props = props;
13
+
14
14
  const event = <typeof DomainEvent>this.constructor;
15
- this.eventName = event.EVENT_NAME;
16
- this.eventId = eventId || new EntityId<H>();
17
- this.aggregate = aggregate;
18
- this.aggregateId = aggregate.id;
15
+ this.eventName = event.EVENT_NAME ?? this.constructor.name;
16
+ this.eventId = eventId || new EntityId<never>();
19
17
  this.occurredOn = occurredOn || new Date();
20
18
  }
21
19
 
22
- abstract toPrimitives(): DomainEventAttributes;
20
+ toPrimitives(): H {
21
+ return this.props;
22
+ };
23
23
  }
24
24
 
25
25
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -27,6 +27,3 @@ export type AnyDomainEvent = DomainEvent<any>;
27
27
 
28
28
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
29
  export type DomainEventClass = typeof DomainEvent<any>;
30
-
31
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
32
- type DomainEventAttributes = any;
@@ -3,29 +3,38 @@ import { EntityId } from './EntityId';
3
3
 
4
4
  interface TestProps {
5
5
  name: string;
6
+ testId?: EntityId<string>;
6
7
  }
7
- class TestEntity extends Entity<TestProps, number, EntityId<number>> {
8
- static create(props: TestProps, id?:EntityId<number>|number): TestEntity {
8
+ class TestEntity extends Entity<TestProps, string, EntityId<string>> {
9
+ static create(props: TestProps, id?:EntityId<string>|string): TestEntity {
9
10
  return new TestEntity(props, id);
10
11
  }
12
+
13
+ set name(name: string) {
14
+ this.props.name = name;
15
+ }
16
+
17
+ set testId(val: EntityId<string>) {
18
+ this.props.testId = val;
19
+ }
11
20
  }
12
21
 
13
22
  describe('Entity', () => {
14
23
  let entity: TestEntity;
15
24
 
16
25
  beforeAll(() => {
17
- entity = TestEntity.create({ name: 'test' }, 1);
26
+ entity = TestEntity.create({ name: 'test', testId: new EntityId('1') }, '1');
18
27
  });
19
28
 
20
29
  test('base', async () => {
21
30
  const entityNew = TestEntity.create({ name: 'test2' });
22
31
  expect(entityNew.id.toString().length).toEqual(36); // random id
23
32
 
24
- const entity2 = TestEntity.create({ name: 'test2' }, 1);
33
+ const entity2 = TestEntity.create({ name: 'test2' }, '1');
25
34
  expect(entity.equals(entity2)).toBeTruthy(); // same id
26
35
  expect(entity.equals(entity)).toBeTruthy(); // same instance
27
36
  expect(entity.equals(null)).toBeFalsy(); // null
28
- expect(entity.equals(<TestEntity>{ id: new EntityId(1) })).toBeFalsy(); // not Entity
37
+ expect(entity.equals(<TestEntity>{ id: new EntityId('1') })).toBeFalsy(); // not Entity
29
38
  expect(entity.id.toPrimitive()).toEqual('1');
30
39
  expect(entity.id.toString()).toEqual('6061cf31-edcb-5d22-9adc-927af7c186fa');
31
40
 
@@ -34,4 +43,18 @@ describe('Entity', () => {
34
43
  expect(entity3.id.toPrimitive()).toEqual('1');
35
44
  expect(entity3.id.toString()).toEqual('6061cf31-edcb-5d22-9adc-927af7c186fa');
36
45
  });
46
+
47
+ test('snapshot', async () => {
48
+ const snapshot = entity.snapshot();
49
+ expect(snapshot).toEqual({ name: 'test', testId: new EntityId('1') });
50
+
51
+ expect(() => {
52
+ snapshot.name = 'changed';
53
+ }).toThrow()
54
+ expect(entity.isDirty()).toEqual(false);
55
+ expect(entity.snapshotDiff()).toEqual(null);
56
+ entity.name = 'test changed';
57
+ expect(entity.isDirty()).toEqual(true);
58
+ expect(entity.snapshotDiff()).toEqual({"name": "test changed"});
59
+ });
37
60
  });
package/src/Entity.ts CHANGED
@@ -7,6 +7,35 @@ const isEntity = <T, E, M extends EntityId<E>>(v: Entity<T, E, M>): v is Entity<
7
7
  export abstract class Entity<T, E, H extends EntityId<E>> {
8
8
  protected readonly _id: H;
9
9
  protected props: T;
10
+ protected _snapshot: string;
11
+
12
+ snapshot(): T {
13
+ this._snapshot = JSON.stringify(this.props);
14
+ const copy = JSON.parse(this._snapshot) as T;
15
+ Object.freeze(copy);
16
+ return copy;
17
+ }
18
+
19
+ snapshotDiff(): Partial<T> | null {
20
+ if (!this._snapshot) {
21
+ return null;
22
+ }
23
+ const diffs: Partial<T> = {};
24
+ const copy = JSON.parse(this._snapshot);
25
+ for (const key in this.props) {
26
+ if (JSON.stringify(this.props[key]) !== JSON.stringify(copy[key])) {
27
+ diffs[key] = this.props[key];
28
+ }
29
+ }
30
+ return Object.keys(diffs).length > 0 ? diffs : null;
31
+ }
32
+
33
+ isDirty(): boolean {
34
+ if (!this._snapshot) {
35
+ return false;
36
+ }
37
+ return this._snapshot !== JSON.stringify(this.props);
38
+ }
10
39
 
11
40
  protected constructor(props: T, id?: H|E) {
12
41
  if (id) {
@@ -41,7 +70,13 @@ export abstract class Entity<T, E, H extends EntityId<E>> {
41
70
  return this.props
42
71
  }
43
72
 
44
- toJSON(): T {
45
- return this.toPrimitive()
73
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
74
+ toJSON(): any {
75
+ return this.toPrimitive();
76
+ }
77
+
78
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
79
+ toSnapshot(): any {
80
+ return this.toPrimitive();
46
81
  }
47
82
  }
@@ -36,13 +36,14 @@ describe('ValueObject', () => {
36
36
  test('toHash', async () => {
37
37
  const id = new Test2Id('123');
38
38
  expect(id.toHash()).toEqual('9KdMR');
39
- expect(id.fromHash('VLoxm').toPrimitive()).toEqual('1');
40
- expect(id.toPrimitive()).toEqual('1');
41
- expect(id.toString()).toEqual('090bb5d1-267b-5967-84c8-95bc1bda380f');
39
+ const idFromHash = new Test2Id('VLoxm', true);
40
+ expect(idFromHash.toPrimitive()).toEqual('1');
41
+ expect(idFromHash.toPrimitive()).toEqual('1');
42
+ expect(idFromHash.toString()).toEqual('090bb5d1-267b-5967-84c8-95bc1bda380f');
42
43
 
43
44
  const id2 = new TestId(123);
44
45
  expect(id2.toHash()).toEqual('BJejP');
45
- expect(id2.fromHash('BJejP').toPrimitive()).toEqual(123);
46
+ expect(new TestId('BJejP', true).toPrimitive()).toEqual('123');
46
47
 
47
48
  const id3 = new Test2Id();
48
49
  expect(() => id3.toHash()).toThrow('Cannot hash an empty recordId');
package/src/EntityId.ts CHANGED
@@ -7,8 +7,8 @@ export class EntityId<T> {
7
7
  protected _recordId: T|null = null;
8
8
  protected _uuid: string = null;
9
9
 
10
- constructor(recordId: T = null, isHash:boolean = false, uuid: string = null) {
11
- this._recordId = recordId ? recordId : null;
10
+ constructor(recordId: T|string = null, isHash:boolean = false, uuid: string = null) {
11
+ this._recordId = recordId ? recordId as T : null;
12
12
  if (isHash) {
13
13
  this.fromHash(recordId as string);
14
14
  }
@@ -33,7 +33,7 @@ export class EntityId<T> {
33
33
  return hashids.encode(this.toPrimitive().toString());
34
34
  }
35
35
 
36
- fromHash(hash: string) : EntityId<T> {
36
+ protected fromHash(hash: string) : EntityId<T> {
37
37
  if (!hash) {
38
38
  return this;
39
39
  }
@@ -0,0 +1,108 @@
1
+ import {InMemoryEventBus} from "./eventBus/InMemoryEventBus";
2
+ import {DomainEventSubscriber} from "./DomainEventSubscriber";
3
+ import {DomainEvent, DomainEventClass} from "./DomainEvent";
4
+ import {EntityId} from "./EntityId";
5
+ import {Entity} from "./Entity";
6
+
7
+ describe('EventBus', () => {
8
+ class NewUserCreated extends DomainEvent<{ username: string }> {
9
+ }
10
+ class NewUserCreated2 extends DomainEvent<{ username: string }> {
11
+ static EVENT_NAME = 'Event2';
12
+ }
13
+
14
+ class NewUserSubscriber implements DomainEventSubscriber {
15
+ subscribedTo(): DomainEventClass[] {
16
+ return [NewUserCreated, NewUserCreated2];
17
+ }
18
+ async on(domainEvent: NewUserCreated|NewUserCreated2): Promise<void> {
19
+ console.log('Event received:', domainEvent);
20
+ }
21
+ }
22
+
23
+ test('lifecycle', async () => {
24
+ const newUserSubscriber = new NewUserSubscriber();
25
+ newUserSubscriber.on = jest.fn();
26
+ const hub = new InMemoryEventBus();
27
+ hub.addSubscribers([newUserSubscriber]);
28
+
29
+ const event = new NewUserCreated({ username: 'test' });
30
+ const event2 = new NewUserCreated2({ username: 'test2' });
31
+
32
+ expect(event.eventName).toEqual('NewUserCreated');
33
+ expect(event2.eventName).toEqual('Event2');
34
+
35
+ await hub.publish([event, event2]);
36
+
37
+ expect(newUserSubscriber.on).toHaveBeenCalledTimes(2);
38
+ });
39
+
40
+ test('user example', async () => {
41
+ class UserId extends EntityId<string> {}
42
+
43
+ interface IUser {
44
+ id: UserId;
45
+ username: string;
46
+ }
47
+
48
+ class User extends Entity<IUser, string, UserId> {
49
+ static create(props: IUser): User {
50
+ return new User(props, props.id);
51
+ }
52
+
53
+ set username(username: string) {
54
+ this.props.username = username;
55
+ }
56
+
57
+ get username(): string {
58
+ return this.props.username;
59
+ }
60
+ }
61
+
62
+ class UserCreatedEvent extends DomainEvent<Partial<IUser>> {
63
+ readonly eventName = 'UserCreatedEvent'; // без цього не буде працювати статична типізація
64
+
65
+ get username() {
66
+ return this.props.username;
67
+ }
68
+ }
69
+
70
+ class ChangeLoggerSubscriber implements DomainEventSubscriber {
71
+ // Підписуємося на події, які нас цікавлять
72
+ subscribedTo() {
73
+ return [UserCreatedEvent];
74
+ }
75
+
76
+ // Реалізуємо логіку обробки подій
77
+ async on(domainEvent: UserCreatedEvent) {
78
+ console.log('Username changed:', domainEvent.username);
79
+ }
80
+ }
81
+
82
+ // Далі створюємо EventBus і реєструємо підписника
83
+ const eventBus = new InMemoryEventBus();
84
+ const subscriber = new ChangeLoggerSubscriber();
85
+ const mockOn = jest.spyOn(subscriber, 'on');
86
+ eventBus.addSubscribers([subscriber]);
87
+
88
+ const user = User.create({ id: new UserId('1'), username: 'john_doe' });
89
+ // Створюємо знімок початкового стану
90
+ user.snapshot();
91
+ // Змінюємо ім'я користувача
92
+ user.username = 'john_doe_updated';
93
+ let event;
94
+ // Перевіряємо, чи є зміни
95
+ if (user.isDirty()) {
96
+ const diff = user.snapshotDiff();
97
+ if (diff) {
98
+ event = new UserCreatedEvent(diff);
99
+ // записуємо подію в чергу (не publish). Бо якщо в циклі може бути багато подій і їх треба назбирати, а потім виконати, тому збираємо через push
100
+ eventBus.push(event);
101
+ }
102
+ }
103
+ expect(mockOn).not.toHaveBeenCalled();
104
+ // Публікуємо всі події в черзі
105
+ await eventBus.publish();
106
+ expect(mockOn).toHaveBeenCalledWith(event);
107
+ });
108
+ });
package/src/EventBus.ts CHANGED
@@ -2,6 +2,8 @@ import {AnyDomainEvent} from './DomainEvent';
2
2
  import {DomainEventSubscriber} from "./DomainEventSubscriber";
3
3
 
4
4
  export interface EventBus {
5
+ push(event: AnyDomainEvent): Promise<void>;
6
+ clear(): Promise<void>;
5
7
  publish(events: AnyDomainEvent[]): Promise<void>;
6
8
  addSubscribers(subscribers: DomainEventSubscriber[]): void;
7
9
  }
@@ -12,12 +12,8 @@ class TestAggregate extends AggregateRoot<ITestAggregate, number, EntityId<numbe
12
12
  }
13
13
  }
14
14
 
15
- class TestEvent extends DomainEvent<number> {
15
+ class TestEvent extends DomainEvent<TestAggregate> {
16
16
  static EVENT_NAME = 'TestEvent';
17
-
18
- toPrimitives() {
19
- return {};
20
- }
21
17
  }
22
18
 
23
19
  class TestSubscriber implements DomainEventSubscriber {