@pocket-architect/core 0.1.23 → 0.1.27

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/build/Entity.d.ts CHANGED
@@ -4,7 +4,6 @@ export declare abstract class Entity<T, E, H extends EntityId<E>> {
4
4
  protected props: T;
5
5
  protected _snapshot: string;
6
6
  snapshot(): T;
7
- snapshotDiff(): Partial<T> | null;
8
7
  isDirty(): boolean;
9
8
  protected constructor(props: T, id?: H | E);
10
9
  equals(object?: Entity<T, E, H>): boolean;
package/build/Entity.js CHANGED
@@ -17,25 +17,13 @@ var Entity = /** @class */ (function () {
17
17
  this.props = props;
18
18
  }
19
19
  Entity.prototype.snapshot = function () {
20
- this._snapshot = JSON.stringify(this.props);
20
+ // важливо: snapshot має бути стабільним (createSnapshot)
21
+ var snapObj = (0, helpers_1.createSnapshot)(this.props);
22
+ this._snapshot = JSON.stringify(snapObj);
21
23
  var copy = JSON.parse(this._snapshot);
22
24
  Object.freeze(copy);
23
25
  return copy;
24
26
  };
25
- Entity.prototype.snapshotDiff = function () {
26
- if (!this._snapshot) {
27
- return null;
28
- }
29
- var diffs = {};
30
- var copy = JSON.parse(this._snapshot);
31
- var snapshotObj = (0, helpers_1.createSnapshot)(this.props);
32
- for (var key in this.props) {
33
- if (JSON.stringify(snapshotObj[key]) !== JSON.stringify(copy[key])) {
34
- diffs[key] = this.props[key];
35
- }
36
- }
37
- return Object.keys(diffs).length > 0 ? diffs : null;
38
- };
39
27
  Entity.prototype.isDirty = function () {
40
28
  if (!this._snapshot) {
41
29
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"Entity.js","sourceRoot":"","sources":["../src/Entity.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Entity.js","sourceRoot":"","sources":["../src/Entity.ts"],"names":[],"mappings":";;;AAAA,uCAAsC;AACtC,qCAAyC;AAEzC,IAAM,QAAQ,GAAG,UAA8B,CAAkB;IAC/D,OAAO,CAAC,YAAY,MAAM,CAAA;AAC5B,CAAC,CAAA;AAED;IAsBE,gBAAsB,KAAQ,EAAE,EAAQ;QACtC,IAAI,EAAE,EAAE,CAAC;YACP,IAAI,CAAC,GAAG,GAAM,CAAC,OAAO,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,mBAAQ,CAAI,EAAE,CAAC,CAAC,CAAC;QACpE,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,GAAG,GAAM,CAAC,IAAI,mBAAQ,EAAE,CAAC,CAAC;QACjC,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;IACpB,CAAC;IAxBD,yBAAQ,GAAR;QACE,yDAAyD;QACzD,IAAM,OAAO,GAAG,IAAA,wBAAc,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAEzC,IAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAM,CAAC;QAC7C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,wBAAO,GAAP;QACE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,CAAC,IAAA,wBAAc,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACvE,CAAC;IAWM,uBAAM,GAAb,UAAc,MAAwB;QACpC,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAC5C,OAAO,KAAK,CAAA;QACd,CAAC;QAED,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,OAAO,IAAI,CAAA;QACb,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACtB,OAAO,KAAK,CAAA;QACd,CAAC;QAED,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;IAED,sBAAI,sBAAE;aAAN;YACE,OAAO,IAAI,CAAC,GAAG,CAAA;QACjB,CAAC;;;OAAA;IAED,4BAAW,GAAX;QACE,OAAO,IAAI,CAAC,KAAK,CAAA;IACnB,CAAC;IAED,8DAA8D;IAC9D,uBAAM,GAAN;QACE,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;IAC5B,CAAC;IAED,8DAA8D;IAC9D,2BAAU,GAAV;QACE,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;IAC5B,CAAC;IACH,aAAC;AAAD,CAAC,AAhED,IAgEC;AAhEqB,wBAAM"}
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  var tslib_1 = require("tslib");
4
4
  var Entity_1 = require("./Entity");
5
5
  var EntityId_1 = require("./EntityId");
6
+ var diff_1 = require("./helpers/diff");
6
7
  var TestEntity = /** @class */ (function (_super) {
7
8
  tslib_1.__extends(TestEntity, _super);
8
9
  function TestEntity() {
@@ -25,26 +26,58 @@ var TestEntity = /** @class */ (function (_super) {
25
26
  enumerable: false,
26
27
  configurable: true
27
28
  });
29
+ TestEntity.prototype.setFirstAmount = function (amount) {
30
+ this.props.parts[0].amount = amount;
31
+ };
28
32
  return TestEntity;
29
33
  }(Entity_1.Entity));
34
+ var TestEntity2 = /** @class */ (function (_super) {
35
+ tslib_1.__extends(TestEntity2, _super);
36
+ function TestEntity2() {
37
+ return _super !== null && _super.apply(this, arguments) || this;
38
+ }
39
+ TestEntity2.create = function (props, id) {
40
+ return new TestEntity2(props, id);
41
+ };
42
+ return TestEntity2;
43
+ }(Entity_1.Entity));
30
44
  describe('Entity', function () {
31
45
  var entity;
32
46
  beforeAll(function () {
33
- entity = TestEntity.create({ name: 'test', testId: new EntityId_1.EntityId('1') }, '1');
47
+ entity = TestEntity.create({
48
+ name: 'test', testId: new EntityId_1.EntityId('1'),
49
+ test2: TestEntity2.create({ name: 'test', testId: new EntityId_1.EntityId('1') }),
50
+ parts: [{
51
+ amount: 1000,
52
+ entity: TestEntity2.create({ name: 'part entity', testId: new EntityId_1.EntityId('2') })
53
+ }]
54
+ }, '1');
34
55
  });
35
56
  test('base', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
36
57
  var entityNew, entity2, entity3;
37
58
  return tslib_1.__generator(this, function (_a) {
38
- entityNew = TestEntity.create({ name: 'test2' });
59
+ entityNew = TestEntity.create({
60
+ name: 'test2',
61
+ test2: TestEntity2.create({ name: 'test', testId: new EntityId_1.EntityId('1') }),
62
+ parts: []
63
+ });
39
64
  expect(entityNew.id.toString().length).toEqual(36); // random id
40
- entity2 = TestEntity.create({ name: 'test2' }, '1');
65
+ entity2 = TestEntity.create({
66
+ name: 'test2',
67
+ test2: TestEntity2.create({ name: 'test', testId: new EntityId_1.EntityId('1') }),
68
+ parts: []
69
+ }, '1');
41
70
  expect(entity.equals(entity2)).toBeTruthy(); // same id
42
71
  expect(entity.equals(entity)).toBeTruthy(); // same instance
43
72
  expect(entity.equals(null)).toBeFalsy(); // null
44
73
  expect(entity.equals({ id: new EntityId_1.EntityId('1') })).toBeFalsy(); // not Entity
45
74
  expect(entity.id.toPrimitive()).toEqual('1');
46
75
  expect(entity.id.toString()).toEqual('6061cf31-edcb-5d22-9adc-927af7c186fa');
47
- entity3 = TestEntity.create({ name: 'test2' }, entity.id);
76
+ entity3 = TestEntity.create({
77
+ name: 'test2',
78
+ test2: TestEntity2.create({ name: 'test', testId: new EntityId_1.EntityId('1') }),
79
+ parts: []
80
+ }, entity.id);
48
81
  expect(entity.equals(entity3)).toBeTruthy(); // same id
49
82
  expect(entity3.id.toPrimitive()).toEqual('1');
50
83
  expect(entity3.id.toString()).toEqual('6061cf31-edcb-5d22-9adc-927af7c186fa');
@@ -52,18 +85,78 @@ describe('Entity', function () {
52
85
  });
53
86
  }); });
54
87
  test('snapshot', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
55
- var snapshot;
88
+ var snapshot, beforeSnapshot, formatter;
56
89
  return tslib_1.__generator(this, function (_a) {
57
90
  snapshot = entity.snapshot();
58
- expect(snapshot).toEqual({ name: 'test', testId: '3D4WX' });
91
+ expect(snapshot).toEqual({
92
+ "name": "test",
93
+ "parts": [
94
+ {
95
+ "amount": 1000,
96
+ "entity": {
97
+ "name": "part entity",
98
+ "testId": "QbPvX"
99
+ }
100
+ }
101
+ ],
102
+ "test2": {
103
+ "name": "test",
104
+ "testId": "3D4WX"
105
+ },
106
+ "testId": "3D4WX"
107
+ });
59
108
  expect(function () {
60
109
  snapshot.name = 'changed';
61
110
  }).toThrow();
111
+ beforeSnapshot = entity.snapshot();
112
+ formatter = {
113
+ resolveLabel: function (_a) {
114
+ var key = _a.key, index = _a.index, path = _a.path;
115
+ if (key === 'createdAt')
116
+ return null; // ignore
117
+ if (key === 'amount' && index !== null)
118
+ return "\u0426\u0456\u043D\u0430 (\u043F\u043E\u0437\u0438\u0446\u0456\u044F ".concat(index + 1, ")");
119
+ if (path === 'name')
120
+ return 'Імʼя';
121
+ return undefined;
122
+ },
123
+ formatValue: function (value, _a) {
124
+ var key = _a.key;
125
+ if (value instanceof EntityId_1.EntityId) {
126
+ return value.toHash();
127
+ }
128
+ if (key === 'amount' && typeof value === 'number')
129
+ return "".concat(value.toFixed(2), " \u0433\u0440\u043D");
130
+ return String(value);
131
+ },
132
+ };
62
133
  expect(entity.isDirty()).toEqual(false);
63
- expect(entity.snapshotDiff()).toEqual(null);
134
+ expect((0, diff_1.getDiff)(beforeSnapshot, entity.snapshot(), formatter)).toEqual(null);
64
135
  entity.name = 'test changed';
136
+ entity.setFirstAmount(200);
65
137
  expect(entity.isDirty()).toEqual(true);
66
- expect(entity.snapshotDiff()).toEqual({ "name": "test changed" });
138
+ expect((0, diff_1.getDiff)(beforeSnapshot, entity.snapshot(), formatter)).toEqual([
139
+ {
140
+ "after": "test changed",
141
+ "afterRaw": "test changed",
142
+ "before": "test",
143
+ "beforeRaw": "test",
144
+ "index": null,
145
+ "kind": "changed",
146
+ "label": "Імʼя",
147
+ "path": "name"
148
+ },
149
+ {
150
+ "after": "200.00 грн",
151
+ "afterRaw": 200,
152
+ "before": "1000.00 грн",
153
+ "beforeRaw": 1000,
154
+ "index": 0,
155
+ "kind": "changed",
156
+ "label": "Ціна (позиція 1)",
157
+ "path": "parts[0].amount"
158
+ }
159
+ ]);
67
160
  return [2 /*return*/];
68
161
  });
69
162
  }); });
@@ -1 +1 @@
1
- {"version":3,"file":"Entity.spec.js","sourceRoot":"","sources":["../src/Entity.spec.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Entity.spec.js","sourceRoot":"","sources":["../src/Entity.spec.ts"],"names":[],"mappings":"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"}
package/build/EntityId.js CHANGED
@@ -58,7 +58,7 @@ var EntityId = /** @class */ (function () {
58
58
  return this._uuid;
59
59
  };
60
60
  EntityId.prototype.toJSON = function () {
61
- return this.toHash();
61
+ return this._recordId ? this.toHash() : null;
62
62
  };
63
63
  EntityId.prototype.equals = function (id) {
64
64
  return this._uuid === id._uuid;
@@ -1 +1 @@
1
- {"version":3,"file":"EntityId.js","sourceRoot":"","sources":["../src/EntityId.ts"],"names":[],"mappings":";;;;AAAA,0EAAuC;AACvC,8CAA+C;AAC/C,4DAA8B;AAC9B,+CAA4C;AAE5C;IAIE,kBAAY,QAAyB,EAAE,MAAsB,EAAE,IAAmB;QAAtE,yBAAA,EAAA,eAAyB;QAAE,uBAAA,EAAA,cAAsB;QAAE,qBAAA,EAAA,WAAmB;QAHxE,cAAS,GAAW,IAAI,CAAC;QACzB,UAAK,GAAW,IAAI,CAAC;QAG7B,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAa,CAAC,CAAC,CAAC,IAAI,CAAC;QACjD,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,QAAQ,CAAC,QAAkB,CAAC,CAAC;QACpC,CAAC;QACD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;IAEO,6BAAU,GAAlB;QACE,IAAI,CAAC,KAAK,GAAG,IAAA,wBAAU,EAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAA,gBAAQ,GAAE,EAAE,IAAA,wBAAU,EAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;IACtH,CAAC;IAED,sBAAI,iCAAW;aAAf;YACE,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACpC,CAAC;;;OAAA;IAED,yBAAM,GAAN;QACE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,CAAC;QACD,IAAM,OAAO,QAAO,iBAAO,YAAP,iBAAO,kCAAI,IAAI,CAAC,WAAW,YAAC,CAAC;QACjD,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;IACvD,CAAC;IAES,2BAAQ,GAAlB,UAAmB,IAAY;QAC7B,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAM,OAAO,QAAO,iBAAO,YAAP,iBAAO,kCAAI,IAAI,CAAC,WAAW,YAAC,CAAC;QACjD,IAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,qBAAS,CAAC,uBAAgB,IAAI,CAAE,CAAC,CAAC;QAC9C,CAAC;QACD,IAAI,CAAC,SAAS,GAAM,CAAC,OAAO,IAAI,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAChF,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,8BAAW,GAAX;QACE,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,2BAAQ,GAAR;QACE,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,yBAAM,GAAN;QACE,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;IACvB,CAAC;IAED,yBAAM,GAAN,UAAO,EAAe;QACpB,OAAO,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC,KAAK,CAAC;IACjC,CAAC;IACH,eAAC;AAAD,CAAC,AA3DD,IA2DC;AA3DY,4BAAQ"}
1
+ {"version":3,"file":"EntityId.js","sourceRoot":"","sources":["../src/EntityId.ts"],"names":[],"mappings":";;;;AAAA,0EAAuC;AACvC,8CAA+C;AAC/C,4DAA8B;AAC9B,+CAA4C;AAE5C;IAIE,kBAAY,QAAyB,EAAE,MAAsB,EAAE,IAAmB;QAAtE,yBAAA,EAAA,eAAyB;QAAE,uBAAA,EAAA,cAAsB;QAAE,qBAAA,EAAA,WAAmB;QAHxE,cAAS,GAAW,IAAI,CAAC;QACzB,UAAK,GAAW,IAAI,CAAC;QAG7B,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAa,CAAC,CAAC,CAAC,IAAI,CAAC;QACjD,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,QAAQ,CAAC,QAAkB,CAAC,CAAC;QACpC,CAAC;QACD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;IAEO,6BAAU,GAAlB;QACE,IAAI,CAAC,KAAK,GAAG,IAAA,wBAAU,EAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAA,gBAAQ,GAAE,EAAE,IAAA,wBAAU,EAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;IACtH,CAAC;IAED,sBAAI,iCAAW;aAAf;YACE,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACpC,CAAC;;;OAAA;IAED,yBAAM,GAAN;QACE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,CAAC;QACD,IAAM,OAAO,QAAO,iBAAO,YAAP,iBAAO,kCAAI,IAAI,CAAC,WAAW,YAAC,CAAC;QACjD,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;IACvD,CAAC;IAES,2BAAQ,GAAlB,UAAmB,IAAY;QAC7B,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAM,OAAO,QAAO,iBAAO,YAAP,iBAAO,kCAAI,IAAI,CAAC,WAAW,YAAC,CAAC;QACjD,IAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,qBAAS,CAAC,uBAAgB,IAAI,CAAE,CAAC,CAAC;QAC9C,CAAC;QACD,IAAI,CAAC,SAAS,GAAM,CAAC,OAAO,IAAI,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAChF,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,8BAAW,GAAX;QACE,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,2BAAQ,GAAR;QACE,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,yBAAM,GAAN;QACE,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/C,CAAC;IAED,yBAAM,GAAN,UAAO,EAAe;QACpB,OAAO,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC,KAAK,CAAC;IACjC,CAAC;IACH,eAAC;AAAD,CAAC,AA3DD,IA2DC;AA3DY,4BAAQ"}
@@ -88,18 +88,30 @@ describe('EventBus', function () {
88
88
  enumerable: false,
89
89
  configurable: true
90
90
  });
91
+ User.prototype.toDiff = function () {
92
+ return {
93
+ resolveLabel: function (_a) {
94
+ var key = _a.key;
95
+ return key;
96
+ },
97
+ formatValue: function (value) {
98
+ return value === null || value === void 0 ? void 0 : value.toString();
99
+ },
100
+ };
101
+ };
91
102
  return User;
92
103
  }(Entity_1.Entity));
93
104
  UserCreatedEvent = /** @class */ (function (_super) {
94
105
  tslib_1.__extends(UserCreatedEvent, _super);
106
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
95
107
  function UserCreatedEvent() {
96
108
  var _this = _super !== null && _super.apply(this, arguments) || this;
97
109
  _this.eventName = 'UserCreatedEvent'; // без цього не буде працювати статична типізація
98
110
  return _this;
99
111
  }
100
- Object.defineProperty(UserCreatedEvent.prototype, "username", {
112
+ Object.defineProperty(UserCreatedEvent.prototype, "diff", {
101
113
  get: function () {
102
- return this.props.username;
114
+ return this.props.diff;
103
115
  },
104
116
  enumerable: false,
105
117
  configurable: true
@@ -117,7 +129,9 @@ describe('EventBus', function () {
117
129
  ChangeLoggerSubscriber.prototype.on = function (domainEvent) {
118
130
  return tslib_1.__awaiter(this, void 0, void 0, function () {
119
131
  return tslib_1.__generator(this, function (_a) {
120
- console.log('Username changed:', domainEvent.username);
132
+ expect(domainEvent.diff).toEqual([
133
+ { test: 1 }
134
+ ]);
121
135
  return [2 /*return*/];
122
136
  });
123
137
  });
@@ -133,11 +147,12 @@ describe('EventBus', function () {
133
147
  user.snapshot();
134
148
  // Змінюємо ім'я користувача
135
149
  user.username = 'john_doe_updated';
150
+ expect(user.isDirty()).toBeTruthy();
136
151
  // Перевіряємо, чи є зміни
137
152
  if (user.isDirty()) {
138
- diff = user.snapshotDiff();
153
+ diff = [{ test: 1 }];
139
154
  if (diff) {
140
- event = new UserCreatedEvent(diff);
155
+ event = new UserCreatedEvent({ diff: diff });
141
156
  // записуємо подію в чергу (не publish). Бо якщо в циклі може бути багато подій і їх треба назбирати, а потім виконати, тому збираємо через push
142
157
  eventBus.push(event);
143
158
  }
@@ -1 +1 @@
1
- {"version":3,"file":"EventBus.spec.js","sourceRoot":"","sources":["../src/EventBus.spec.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EventBus.spec.js","sourceRoot":"","sources":["../src/EventBus.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ export type DiffKind = 'added' | 'removed' | 'changed';
2
+ export type PathSegment = {
3
+ type: 'key';
4
+ key: string;
5
+ } | {
6
+ type: 'index';
7
+ index: number;
8
+ };
9
+ export interface DiffEntry {
10
+ path: string;
11
+ segments: PathSegment[];
12
+ kind: DiffKind;
13
+ before?: unknown;
14
+ after?: unknown;
15
+ }
16
+ export interface LabelContext {
17
+ key: string | null;
18
+ index: number | null;
19
+ path: string;
20
+ segments: PathSegment[];
21
+ entry: DiffEntry;
22
+ }
23
+ export interface DiffFormatterOptions {
24
+ /**
25
+ * - string → label (людська назва поля)
26
+ * - null → ignore
27
+ * - undefined → fallback на path
28
+ */
29
+ resolveLabel?: (ctx: LabelContext) => string | null | undefined;
30
+ formatValue?: (value: unknown, ctx: LabelContext) => string;
31
+ }
32
+ export interface DiffViewModel {
33
+ kind: DiffKind;
34
+ label: string;
35
+ path: string;
36
+ index: number | null;
37
+ beforeRaw?: unknown;
38
+ afterRaw?: unknown;
39
+ before?: string;
40
+ after?: string;
41
+ }
42
+ export declare function diffObjects(before: unknown, after: unknown): DiffEntry[];
43
+ export declare function buildDiffViewModel(diffs: DiffEntry[], options: DiffFormatterOptions): DiffViewModel[];
44
+ /**
45
+ * Повертає diff у вигляді масиву обʼєктів (DiffViewModel),
46
+ */
47
+ export declare function getDiff(beforeObj: any, afterObj: any, diffOptions: DiffFormatterOptions): DiffViewModel[] | null;
@@ -0,0 +1,165 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getDiff = exports.buildDiffViewModel = exports.diffObjects = void 0;
4
+ var tslib_1 = require("tslib");
5
+ function diffObjects(before, after) {
6
+ var diffs = [];
7
+ walk(before, after, [], diffs);
8
+ return diffs;
9
+ }
10
+ exports.diffObjects = diffObjects;
11
+ function walk(before, after, segments, out) {
12
+ if (Object.is(before, after))
13
+ return;
14
+ var isPlainObject = function (v) {
15
+ return typeof v === 'object' && v !== null && !Array.isArray(v);
16
+ };
17
+ // arrays
18
+ if (Array.isArray(before) || Array.isArray(after)) {
19
+ var bArr = Array.isArray(before) ? before : [];
20
+ var aArr = Array.isArray(after) ? after : [];
21
+ var max = Math.max(bArr.length, aArr.length);
22
+ for (var i = 0; i < max; i++) {
23
+ walk(bArr[i], aArr[i], tslib_1.__spreadArray(tslib_1.__spreadArray([], segments, true), [{ type: 'index', index: i }], false), out);
24
+ }
25
+ return;
26
+ }
27
+ // primitives or mismatched types
28
+ if (!isPlainObject(before) || !isPlainObject(after)) {
29
+ out.push({
30
+ path: segmentsToPath(segments),
31
+ segments: segments,
32
+ kind: 'changed',
33
+ before: before,
34
+ after: after,
35
+ });
36
+ return;
37
+ }
38
+ // objects
39
+ var bObj = before;
40
+ var aObj = after;
41
+ var keys = tslib_1.__spreadArray(tslib_1.__spreadArray([], Object.keys(bObj), true), Object.keys(aObj), true);
42
+ for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
43
+ var key = keys_1[_i];
44
+ var b = bObj[key];
45
+ var a = aObj[key];
46
+ var nextSeg = tslib_1.__spreadArray(tslib_1.__spreadArray([], segments, true), [{ type: 'key', key: key }], false);
47
+ if (b === undefined && a !== undefined) {
48
+ out.push({
49
+ path: segmentsToPath(nextSeg),
50
+ segments: nextSeg,
51
+ kind: 'added',
52
+ after: a,
53
+ });
54
+ continue;
55
+ }
56
+ if (b !== undefined && a === undefined) {
57
+ out.push({
58
+ path: segmentsToPath(nextSeg),
59
+ segments: nextSeg,
60
+ kind: 'removed',
61
+ before: b,
62
+ });
63
+ continue;
64
+ }
65
+ walk(b, a, nextSeg, out);
66
+ }
67
+ }
68
+ function segmentsToPath(segments) {
69
+ var path = '';
70
+ for (var _i = 0, segments_1 = segments; _i < segments_1.length; _i++) {
71
+ var s = segments_1[_i];
72
+ if (s.type === 'key') {
73
+ path += path ? ".".concat(s.key) : s.key;
74
+ }
75
+ else {
76
+ path += "[".concat(s.index, "]");
77
+ }
78
+ }
79
+ return path || '';
80
+ }
81
+ function buildLabelContext(entry) {
82
+ var key = null;
83
+ var index = null;
84
+ for (var i = entry.segments.length - 1; i >= 0; i--) {
85
+ var s = entry.segments[i];
86
+ if (s.type === 'key') {
87
+ key = s.key;
88
+ break;
89
+ }
90
+ }
91
+ for (var i = entry.segments.length - 1; i >= 0; i--) {
92
+ var s = entry.segments[i];
93
+ if (s.type === 'index') {
94
+ index = s.index;
95
+ break;
96
+ }
97
+ }
98
+ return {
99
+ key: key,
100
+ index: index,
101
+ path: entry.path,
102
+ segments: entry.segments,
103
+ entry: entry,
104
+ };
105
+ }
106
+ function defaultStringify(value) {
107
+ if (typeof value === 'string')
108
+ return "\"".concat(value, "\"");
109
+ if (typeof value === 'boolean')
110
+ return value ? 'true' : 'false';
111
+ if (value === null)
112
+ return 'null';
113
+ if (typeof value === 'object')
114
+ return JSON.stringify(value);
115
+ return String(value);
116
+ }
117
+ function buildDiffViewModel(diffs, options) {
118
+ var resolveLabel = options.resolveLabel, _a = options.formatValue, formatValue = _a === void 0 ? defaultStringify : _a;
119
+ var seen = new Set();
120
+ var result = [];
121
+ for (var _i = 0, diffs_1 = diffs; _i < diffs_1.length; _i++) {
122
+ var entry = diffs_1[_i];
123
+ var ctx = buildLabelContext(entry);
124
+ var resolvedLabel = resolveLabel === null || resolveLabel === void 0 ? void 0 : resolveLabel(ctx);
125
+ if (resolvedLabel === null)
126
+ continue;
127
+ var label = resolvedLabel !== null && resolvedLabel !== void 0 ? resolvedLabel : entry.path;
128
+ var beforeFormatted = entry.before !== undefined ? formatValue(entry.before, ctx) : undefined;
129
+ var afterFormatted = entry.after !== undefined ? formatValue(entry.after, ctx) : undefined;
130
+ // якщо форматовано однаково — не зміна
131
+ if (entry.kind === 'changed' && beforeFormatted === afterFormatted) {
132
+ continue;
133
+ }
134
+ // 👇 КЛЮЧ ДЕДУПЛІКАЦІЇ
135
+ var dedupeKey = "".concat(entry.kind, "|").concat(entry.path);
136
+ if (seen.has(dedupeKey)) {
137
+ continue;
138
+ }
139
+ seen.add(dedupeKey);
140
+ result.push({
141
+ kind: entry.kind,
142
+ label: label,
143
+ path: entry.path,
144
+ index: ctx.index,
145
+ beforeRaw: entry.before,
146
+ afterRaw: entry.after,
147
+ before: beforeFormatted,
148
+ after: afterFormatted,
149
+ });
150
+ }
151
+ return result;
152
+ }
153
+ exports.buildDiffViewModel = buildDiffViewModel;
154
+ /**
155
+ * Повертає diff у вигляді масиву обʼєктів (DiffViewModel),
156
+ */
157
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
158
+ function getDiff(beforeObj, afterObj, diffOptions) {
159
+ var diffs = diffObjects(beforeObj, afterObj);
160
+ if (diffs.length === 0)
161
+ return null;
162
+ return buildDiffViewModel(diffs, diffOptions);
163
+ }
164
+ exports.getDiff = getDiff;
165
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/helpers/diff.ts"],"names":[],"mappings":"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"}
package/build/helpers.js CHANGED
@@ -3,33 +3,35 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createSnapshot = void 0;
4
4
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
5
  function createSnapshot(obj) {
6
- if (!obj) {
6
+ if (obj === null || obj === undefined) {
7
7
  return obj;
8
8
  }
9
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
10
- // @ts-ignore
9
+ // toSnapshot має найвищий пріоритет
10
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
11
  if (typeof obj.toSnapshot === 'function') {
12
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
13
- // @ts-ignore
12
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
13
  return obj.toSnapshot();
15
14
  }
16
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
17
- // @ts-ignore
15
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
16
  if (typeof obj.toJSON === 'function') {
19
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
20
- // @ts-ignore
17
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
21
18
  return obj.toJSON();
22
19
  }
20
+ // ✅ МАСИВИ
21
+ if (Array.isArray(obj)) {
22
+ return obj.map(function (item) { return createSnapshot(item); });
23
+ }
24
+ // primitives
25
+ if (typeof obj !== 'object') {
26
+ return obj;
27
+ }
28
+ // plain object
23
29
  var copy = {};
24
- for (var key in obj) {
25
- if (!Object.prototype.hasOwnProperty.call(obj, key)) {
26
- continue;
27
- }
28
- if (typeof obj[key] !== 'object') {
29
- copy[key] = obj[key];
30
- continue;
31
- }
32
- copy[key] = createSnapshot(obj[key]);
30
+ for (var _i = 0, _a = Object.keys(obj); _i < _a.length; _i++) {
31
+ var key = _a[_i];
32
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
33
+ var value = obj[key];
34
+ copy[key] = createSnapshot(value);
33
35
  }
34
36
  return copy;
35
37
  }
@@ -1 +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,6DAA6D;IAC7D,aAAa;IACb,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QACrC,6DAA6D;QAC7D,aAAa;QACb,OAAO,GAAG,CAAC,MAAM,EAAO,CAAC;IAC3B,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;AA9BD,wCA8BC"}
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":";;;AAAA,8DAA8D;AAC9D,SAAgB,cAAc,CAAI,GAAM;IACtC,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtC,OAAO,GAAG,CAAC;IACb,CAAC;IAED,oCAAoC;IACpC,8DAA8D;IAC9D,IAAI,OAAQ,GAAW,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;QAClD,8DAA8D;QAC9D,OAAQ,GAAW,CAAC,UAAU,EAAE,CAAC;IACnC,CAAC;IACD,8DAA8D;IAC9D,IAAI,OAAQ,GAAW,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QAC9C,8DAA8D;QAC9D,OAAQ,GAAW,CAAC,MAAM,EAAE,CAAC;IAC/B,CAAC;IAED,WAAW;IACX,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,GAAG,CAAC,GAAG,CAAC,UAAA,IAAI,IAAI,OAAA,cAAc,CAAC,IAAI,CAAC,EAApB,CAAoB,CAAiB,CAAC;IAC/D,CAAC;IAED,aAAa;IACb,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,GAAG,CAAC;IACb,CAAC;IAED,eAAe;IACf,IAAM,IAAI,GAAG,EAA6B,CAAC;IAE3C,KAAkB,UAA0B,EAA1B,KAAA,MAAM,CAAC,IAAI,CAAC,GAAa,CAAC,EAA1B,cAA0B,EAA1B,IAA0B,EAAE,CAAC;QAA1C,IAAM,GAAG,SAAA;QACZ,8DAA8D;QAC9D,IAAM,KAAK,GAAI,GAAW,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,IAAS,CAAC;AACnB,CAAC;AArCD,wCAqCC"}
package/build/index.d.ts CHANGED
@@ -10,4 +10,5 @@ import { Eventable } from './mixins/Eventable';
10
10
  import { Application } from './application/Application';
11
11
  import { ApplicationModule } from './application/ApplicationModule';
12
12
  import { bootstrap } from './bootstrap';
13
- export { Entity, EntityId, ValueObject, AggregateRoot, HashError, DomainEvent, DomainEventSubscriber, EventBus, Eventable, Application, ApplicationModule, bootstrap };
13
+ import { getDiff, DiffFormatterOptions, DiffViewModel } from './helpers/diff';
14
+ export { Entity, EntityId, ValueObject, AggregateRoot, HashError, DomainEvent, DomainEventSubscriber, EventBus, Eventable, Application, ApplicationModule, bootstrap, DiffViewModel, DiffFormatterOptions, getDiff };
package/build/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.bootstrap = exports.ApplicationModule = exports.Application = exports.Eventable = exports.DomainEvent = exports.HashError = exports.AggregateRoot = exports.ValueObject = exports.EntityId = exports.Entity = void 0;
3
+ exports.getDiff = exports.bootstrap = exports.ApplicationModule = exports.Application = exports.Eventable = 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");
@@ -21,4 +21,6 @@ var ApplicationModule_1 = require("./application/ApplicationModule");
21
21
  Object.defineProperty(exports, "ApplicationModule", { enumerable: true, get: function () { return ApplicationModule_1.ApplicationModule; } });
22
22
  var bootstrap_1 = require("./bootstrap");
23
23
  Object.defineProperty(exports, "bootstrap", { enumerable: true, get: function () { return bootstrap_1.bootstrap; } });
24
+ var diff_1 = require("./helpers/diff");
25
+ Object.defineProperty(exports, "getDiff", { enumerable: true, get: function () { return diff_1.getDiff; } });
24
26
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,mCAAkC;AAchC,uFAdO,eAAM,OAcP;AAbR,uCAAsC;AAcpC,yFAdO,mBAAQ,OAcP;AAbV,6CAA4C;AAc1C,4FAdO,yBAAW,OAcP;AAbb,iDAAgD;AAc9C,8FAdO,6BAAa,OAcP;AAbf,+CAA8C;AAc5C,0FAdO,qBAAS,OAcP;AAbX,6CAA4C;AAc1C,4FAdO,yBAAW,OAcP;AAXb,gDAA+C;AAc7C,0FAdO,qBAAS,OAcP;AAbX,yDAAwD;AAetD,4FAfO,yBAAW,OAeP;AAdb,qEAAoE;AAelE,kGAfO,qCAAiB,OAeP;AAdnB,yCAAwC;AAgBtC,0FAhBO,qBAAS,OAgBP"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,mCAAkC;AAehC,uFAfO,eAAM,OAeP;AAdR,uCAAsC;AAepC,yFAfO,mBAAQ,OAeP;AAdV,6CAA4C;AAe1C,4FAfO,yBAAW,OAeP;AAdb,iDAAgD;AAe9C,8FAfO,6BAAa,OAeP;AAdf,+CAA8C;AAe5C,0FAfO,qBAAS,OAeP;AAdX,6CAA4C;AAe1C,4FAfO,yBAAW,OAeP;AAZb,gDAA+C;AAe7C,0FAfO,qBAAS,OAeP;AAdX,yDAAwD;AAgBtD,4FAhBO,yBAAW,OAgBP;AAfb,qEAAoE;AAgBlE,kGAhBO,qCAAiB,OAgBP;AAfnB,yCAAwC;AAiBtC,0FAjBO,qBAAS,OAiBP;AAhBX,uCAA8E;AAoB5E,wFApBO,cAAO,OAoBP"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pocket-architect/core",
3
- "version": "0.1.23",
3
+ "version": "0.1.27",
4
4
  "description": "",
5
5
  "main": "build/index.js",
6
6
  "scripts": {
@@ -1,9 +1,19 @@
1
1
  import { Entity } from './Entity';
2
2
  import { EntityId } from './EntityId';
3
+ import {getDiff} from "./helpers/diff";
3
4
 
4
5
  interface TestProps {
5
6
  name: string;
6
7
  testId?: EntityId<string>;
8
+ test2: TestEntity2;
9
+ parts: {
10
+ amount: number;
11
+ entity: TestEntity2;
12
+ }[];
13
+ }
14
+ interface TestProps2 {
15
+ name: string;
16
+ testId?: EntityId<string>;
7
17
  }
8
18
  class TestEntity extends Entity<TestProps, string, EntityId<string>> {
9
19
  static create(props: TestProps, id?:EntityId<string>|string): TestEntity {
@@ -17,20 +27,44 @@ class TestEntity extends Entity<TestProps, string, EntityId<string>> {
17
27
  set testId(val: EntityId<string>) {
18
28
  this.props.testId = val;
19
29
  }
30
+
31
+ setFirstAmount(amount:number):void {
32
+ this.props.parts[0].amount = amount;
33
+ }
34
+ }
35
+ class TestEntity2 extends Entity<TestProps2, string, EntityId<string>> {
36
+ static create(props: TestProps2, id?:EntityId<string>|string): TestEntity2 {
37
+ return new TestEntity2(props, id);
38
+ }
20
39
  }
21
40
 
22
41
  describe('Entity', () => {
23
42
  let entity: TestEntity;
24
43
 
25
44
  beforeAll(() => {
26
- entity = TestEntity.create({ name: 'test', testId: new EntityId('1') }, '1');
45
+ entity = TestEntity.create({
46
+ name: 'test', testId: new EntityId('1'),
47
+ test2: TestEntity2.create({ name: 'test', testId: new EntityId('1') }),
48
+ parts: [{
49
+ amount: 1000,
50
+ entity: TestEntity2.create({ name: 'part entity', testId: new EntityId('2') })
51
+ }]
52
+ }, '1');
27
53
  });
28
54
 
29
55
  test('base', async () => {
30
- const entityNew = TestEntity.create({ name: 'test2' });
56
+ const entityNew = TestEntity.create({
57
+ name: 'test2',
58
+ test2: TestEntity2.create({ name: 'test', testId: new EntityId('1') }),
59
+ parts: []
60
+ });
31
61
  expect(entityNew.id.toString().length).toEqual(36); // random id
32
62
 
33
- const entity2 = TestEntity.create({ name: 'test2' }, '1');
63
+ const entity2 = TestEntity.create({
64
+ name: 'test2',
65
+ test2: TestEntity2.create({ name: 'test', testId: new EntityId('1') }),
66
+ parts: []
67
+ }, '1');
34
68
  expect(entity.equals(entity2)).toBeTruthy(); // same id
35
69
  expect(entity.equals(entity)).toBeTruthy(); // same instance
36
70
  expect(entity.equals(null)).toBeFalsy(); // null
@@ -38,7 +72,11 @@ describe('Entity', () => {
38
72
  expect(entity.id.toPrimitive()).toEqual('1');
39
73
  expect(entity.id.toString()).toEqual('6061cf31-edcb-5d22-9adc-927af7c186fa');
40
74
 
41
- const entity3 = TestEntity.create({ name: 'test2' }, entity.id);
75
+ const entity3 = TestEntity.create({
76
+ name: 'test2',
77
+ test2: TestEntity2.create({ name: 'test', testId: new EntityId('1') }),
78
+ parts: []
79
+ }, entity.id);
42
80
  expect(entity.equals(entity3)).toBeTruthy(); // same id
43
81
  expect(entity3.id.toPrimitive()).toEqual('1');
44
82
  expect(entity3.id.toString()).toEqual('6061cf31-edcb-5d22-9adc-927af7c186fa');
@@ -46,15 +84,72 @@ describe('Entity', () => {
46
84
 
47
85
  test('snapshot', async () => {
48
86
  const snapshot = entity.snapshot();
49
- expect(snapshot).toEqual({ name: 'test', testId: '3D4WX' });
87
+ expect(snapshot).toEqual({
88
+ "name": "test",
89
+ "parts": [
90
+ {
91
+ "amount": 1000,
92
+ "entity": {
93
+ "name": "part entity",
94
+ "testId": "QbPvX"
95
+ }
96
+ }
97
+ ],
98
+ "test2": {
99
+ "name": "test",
100
+ "testId": "3D4WX"
101
+ },
102
+ "testId": "3D4WX"
103
+ });
50
104
 
51
105
  expect(() => {
52
106
  snapshot.name = 'changed';
53
- }).toThrow()
107
+ }).toThrow();
108
+ const beforeSnapshot = entity.snapshot();
109
+ const formatter = {
110
+ resolveLabel({ key, index, path }) {
111
+ if (key === 'createdAt') return null; // ignore
112
+
113
+ if (key === 'amount' && index !== null) return `Ціна (позиція ${index + 1})`;
114
+ if (path === 'name') return 'Імʼя';
115
+
116
+ return undefined;
117
+ },
118
+ formatValue(value, { key }) {
119
+ if (value instanceof EntityId) {
120
+ return value.toHash();
121
+ }
122
+ if (key === 'amount' && typeof value === 'number') return `${value.toFixed(2)} грн`;
123
+ return String(value);
124
+ },
125
+ };
126
+
54
127
  expect(entity.isDirty()).toEqual(false);
55
- expect(entity.snapshotDiff()).toEqual(null);
128
+ expect(getDiff(beforeSnapshot, entity.snapshot(), formatter)).toEqual(null);
56
129
  entity.name = 'test changed';
130
+ entity.setFirstAmount(200);
57
131
  expect(entity.isDirty()).toEqual(true);
58
- expect(entity.snapshotDiff()).toEqual({"name": "test changed"});
132
+ expect(getDiff(beforeSnapshot, entity.snapshot(), formatter)).toEqual([
133
+ {
134
+ "after": "test changed",
135
+ "afterRaw": "test changed",
136
+ "before": "test",
137
+ "beforeRaw": "test",
138
+ "index": null,
139
+ "kind": "changed",
140
+ "label": "Імʼя",
141
+ "path": "name"
142
+ },
143
+ {
144
+ "after": "200.00 грн",
145
+ "afterRaw": 200,
146
+ "before": "1000.00 грн",
147
+ "beforeRaw": 1000,
148
+ "index": 0,
149
+ "kind": "changed",
150
+ "label": "Ціна (позиція 1)",
151
+ "path": "parts[0].amount"
152
+ }
153
+ ]);
59
154
  });
60
155
  });
package/src/Entity.ts CHANGED
@@ -11,27 +11,15 @@ export abstract class Entity<T, E, H extends EntityId<E>> {
11
11
  protected _snapshot: string;
12
12
 
13
13
  snapshot(): T {
14
- this._snapshot = JSON.stringify(this.props);
14
+ // важливо: snapshot має бути стабільним (createSnapshot)
15
+ const snapObj = createSnapshot(this.props);
16
+ this._snapshot = JSON.stringify(snapObj);
17
+
15
18
  const copy = JSON.parse(this._snapshot) as T;
16
19
  Object.freeze(copy);
17
20
  return copy;
18
21
  }
19
22
 
20
- snapshotDiff(): Partial<T> | null {
21
- if (!this._snapshot) {
22
- return null;
23
- }
24
- const diffs: Partial<T> = {};
25
- const copy = JSON.parse(this._snapshot);
26
- const snapshotObj = createSnapshot(this.props);
27
- for (const key in this.props) {
28
- if (JSON.stringify(snapshotObj[key]) !== JSON.stringify(copy[key])) {
29
- diffs[key] = this.props[key];
30
- }
31
- }
32
- return Object.keys(diffs).length > 0 ? diffs : null;
33
- }
34
-
35
23
  isDirty(): boolean {
36
24
  if (!this._snapshot) {
37
25
  return false;
package/src/EntityId.ts CHANGED
@@ -56,7 +56,7 @@ export class EntityId<T> {
56
56
  }
57
57
 
58
58
  toJSON(): string {
59
- return this.toHash();
59
+ return this._recordId ? this.toHash() : null;
60
60
  }
61
61
 
62
62
  equals(id: EntityId<T>): boolean {
@@ -3,6 +3,7 @@ import {DomainEventSubscriber} from "./DomainEventSubscriber";
3
3
  import {DomainEvent, DomainEventClass} from "./DomainEvent";
4
4
  import {EntityId} from "./EntityId";
5
5
  import {Entity} from "./Entity";
6
+ import {DiffFormatterOptions} from "./helpers/diff";
6
7
 
7
8
  describe('EventBus', () => {
8
9
  class NewUserCreated extends DomainEvent<{ username: string }> {
@@ -57,13 +58,25 @@ describe('EventBus', () => {
57
58
  get username(): string {
58
59
  return this.props.username;
59
60
  }
61
+
62
+ toDiff(): DiffFormatterOptions | null {
63
+ return {
64
+ resolveLabel({ key }) {
65
+ return key;
66
+ },
67
+ formatValue(value) {
68
+ return value?.toString();
69
+ },
70
+ };
71
+ }
60
72
  }
61
73
 
62
- class UserCreatedEvent extends DomainEvent<Partial<IUser>> {
74
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
75
+ class UserCreatedEvent extends DomainEvent<{ diff: any }> {
63
76
  readonly eventName = 'UserCreatedEvent'; // без цього не буде працювати статична типізація
64
77
 
65
- get username() {
66
- return this.props.username;
78
+ get diff() {
79
+ return this.props.diff;
67
80
  }
68
81
  }
69
82
 
@@ -75,7 +88,9 @@ describe('EventBus', () => {
75
88
 
76
89
  // Реалізуємо логіку обробки подій
77
90
  async on(domainEvent: UserCreatedEvent) {
78
- console.log('Username changed:', domainEvent.username);
91
+ expect(domainEvent.diff).toEqual([
92
+ { test: 1 }
93
+ ]);
79
94
  }
80
95
  }
81
96
 
@@ -91,11 +106,12 @@ describe('EventBus', () => {
91
106
  // Змінюємо ім'я користувача
92
107
  user.username = 'john_doe_updated';
93
108
  let event;
109
+ expect(user.isDirty()).toBeTruthy();
94
110
  // Перевіряємо, чи є зміни
95
111
  if (user.isDirty()) {
96
- const diff = user.snapshotDiff();
112
+ const diff = [{ test: 1 }];
97
113
  if (diff) {
98
- event = new UserCreatedEvent(diff);
114
+ event = new UserCreatedEvent({ diff });
99
115
  // записуємо подію в чергу (не publish). Бо якщо в циклі може бути багато подій і їх треба назбирати, а потім виконати, тому збираємо через push
100
116
  eventBus.push(event);
101
117
  }
@@ -0,0 +1,231 @@
1
+ export type DiffKind = 'added' | 'removed' | 'changed';
2
+
3
+ export type PathSegment =
4
+ | { type: 'key'; key: string }
5
+ | { type: 'index'; index: number };
6
+
7
+ export interface DiffEntry {
8
+ path: string;
9
+ segments: PathSegment[];
10
+ kind: DiffKind;
11
+ before?: unknown;
12
+ after?: unknown;
13
+ }
14
+
15
+ export interface LabelContext {
16
+ key: string | null; // назва поля (останній key)
17
+ index: number | null; // індекс масиву, якщо зміна всередині масиву
18
+ path: string; // items[2].price
19
+ segments: PathSegment[];
20
+ entry: DiffEntry;
21
+ }
22
+
23
+ export interface DiffFormatterOptions {
24
+ /**
25
+ * - string → label (людська назва поля)
26
+ * - null → ignore
27
+ * - undefined → fallback на path
28
+ */
29
+ resolveLabel?: (ctx: LabelContext) => string | null | undefined;
30
+
31
+ formatValue?: (value: unknown, ctx: LabelContext) => string;
32
+ }
33
+
34
+ export interface DiffViewModel {
35
+ kind: DiffKind;
36
+ label: string;
37
+ path: string;
38
+ index: number | null;
39
+
40
+ beforeRaw?: unknown;
41
+ afterRaw?: unknown;
42
+
43
+ before?: string;
44
+ after?: string;
45
+ }
46
+
47
+ export function diffObjects(before: unknown, after: unknown): DiffEntry[] {
48
+ const diffs: DiffEntry[] = [];
49
+ walk(before, after, [], diffs);
50
+ return diffs;
51
+ }
52
+
53
+ function walk(
54
+ before: unknown,
55
+ after: unknown,
56
+ segments: PathSegment[],
57
+ out: DiffEntry[]
58
+ ): void {
59
+ if (Object.is(before, after)) return;
60
+
61
+ const isPlainObject = (v: unknown) =>
62
+ typeof v === 'object' && v !== null && !Array.isArray(v);
63
+
64
+ // arrays
65
+ if (Array.isArray(before) || Array.isArray(after)) {
66
+ const bArr = Array.isArray(before) ? before : [];
67
+ const aArr = Array.isArray(after) ? after : [];
68
+ const max = Math.max(bArr.length, aArr.length);
69
+
70
+ for (let i = 0; i < max; i++) {
71
+ walk(bArr[i], aArr[i], [...segments, { type: 'index', index: i }], out);
72
+ }
73
+ return;
74
+ }
75
+
76
+ // primitives or mismatched types
77
+ if (!isPlainObject(before) || !isPlainObject(after)) {
78
+ out.push({
79
+ path: segmentsToPath(segments),
80
+ segments,
81
+ kind: 'changed',
82
+ before,
83
+ after,
84
+ });
85
+ return;
86
+ }
87
+
88
+ // objects
89
+ const bObj = before as Record<string, unknown>;
90
+ const aObj = after as Record<string, unknown>;
91
+ const keys = [...Object.keys(bObj), ...Object.keys(aObj)];
92
+
93
+ for (const key of keys) {
94
+ const b = bObj[key];
95
+ const a = aObj[key];
96
+ const nextSeg = [...segments, { type: 'key', key } as const];
97
+
98
+ if (b === undefined && a !== undefined) {
99
+ out.push({
100
+ path: segmentsToPath(nextSeg),
101
+ segments: nextSeg,
102
+ kind: 'added',
103
+ after: a,
104
+ });
105
+ continue;
106
+ }
107
+
108
+ if (b !== undefined && a === undefined) {
109
+ out.push({
110
+ path: segmentsToPath(nextSeg),
111
+ segments: nextSeg,
112
+ kind: 'removed',
113
+ before: b,
114
+ });
115
+ continue;
116
+ }
117
+
118
+ walk(b, a, nextSeg, out);
119
+ }
120
+ }
121
+
122
+ function segmentsToPath(segments: PathSegment[]): string {
123
+ let path = '';
124
+ for (const s of segments) {
125
+ if (s.type === 'key') {
126
+ path += path ? `.${s.key}` : s.key;
127
+ } else {
128
+ path += `[${s.index}]`;
129
+ }
130
+ }
131
+ return path || '';
132
+ }
133
+
134
+ function buildLabelContext(entry: DiffEntry): LabelContext {
135
+ let key: string | null = null;
136
+ let index: number | null = null;
137
+
138
+ for (let i = entry.segments.length - 1; i >= 0; i--) {
139
+ const s = entry.segments[i];
140
+ if (s.type === 'key') {
141
+ key = s.key;
142
+ break;
143
+ }
144
+ }
145
+
146
+ for (let i = entry.segments.length - 1; i >= 0; i--) {
147
+ const s = entry.segments[i];
148
+ if (s.type === 'index') {
149
+ index = s.index;
150
+ break;
151
+ }
152
+ }
153
+
154
+ return {
155
+ key,
156
+ index,
157
+ path: entry.path,
158
+ segments: entry.segments,
159
+ entry,
160
+ };
161
+ }
162
+
163
+ function defaultStringify(value: unknown): string {
164
+ if (typeof value === 'string') return `"${value}"`;
165
+ if (typeof value === 'boolean') return value ? 'true' : 'false';
166
+ if (value === null) return 'null';
167
+ if (typeof value === 'object') return JSON.stringify(value);
168
+ return String(value);
169
+ }
170
+
171
+ export function buildDiffViewModel(
172
+ diffs: DiffEntry[],
173
+ options: DiffFormatterOptions
174
+ ): DiffViewModel[] {
175
+ const { resolveLabel, formatValue = defaultStringify } = options;
176
+
177
+ const seen = new Set<string>();
178
+ const result: DiffViewModel[] = [];
179
+
180
+ for (const entry of diffs) {
181
+ const ctx = buildLabelContext(entry);
182
+
183
+ const resolvedLabel = resolveLabel?.(ctx);
184
+ if (resolvedLabel === null) continue;
185
+
186
+ const label = resolvedLabel ?? entry.path;
187
+
188
+ const beforeFormatted =
189
+ entry.before !== undefined ? formatValue(entry.before, ctx) : undefined;
190
+
191
+ const afterFormatted =
192
+ entry.after !== undefined ? formatValue(entry.after, ctx) : undefined;
193
+
194
+ // якщо форматовано однаково — не зміна
195
+ if (entry.kind === 'changed' && beforeFormatted === afterFormatted) {
196
+ continue;
197
+ }
198
+
199
+ // 👇 КЛЮЧ ДЕДУПЛІКАЦІЇ
200
+ const dedupeKey = `${entry.kind}|${entry.path}`;
201
+
202
+ if (seen.has(dedupeKey)) {
203
+ continue;
204
+ }
205
+ seen.add(dedupeKey);
206
+
207
+ result.push({
208
+ kind: entry.kind,
209
+ label,
210
+ path: entry.path,
211
+ index: ctx.index,
212
+ beforeRaw: entry.before,
213
+ afterRaw: entry.after,
214
+ before: beforeFormatted,
215
+ after: afterFormatted,
216
+ });
217
+ }
218
+
219
+ return result;
220
+ }
221
+
222
+ /**
223
+ * Повертає diff у вигляді масиву обʼєктів (DiffViewModel),
224
+ */
225
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
226
+ export function getDiff(beforeObj: any, afterObj: any, diffOptions: DiffFormatterOptions): DiffViewModel[] | null {
227
+ const diffs = diffObjects(beforeObj, afterObj);
228
+ if (diffs.length === 0) return null;
229
+
230
+ return buildDiffViewModel(diffs, diffOptions);
231
+ }
package/src/helpers.ts CHANGED
@@ -1,32 +1,39 @@
1
1
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
2
2
  export function createSnapshot<T>(obj: T): T {
3
- if (!obj) {
3
+ if (obj === null || obj === undefined) {
4
4
  return obj;
5
5
  }
6
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
7
- // @ts-ignore
8
- if (typeof obj.toSnapshot === 'function') {
9
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
10
- // @ts-ignore
11
- return obj.toSnapshot() as T;
6
+
7
+ // toSnapshot має найвищий пріоритет
8
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
+ if (typeof (obj as any).toSnapshot === 'function') {
10
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
+ return (obj as any).toSnapshot();
12
12
  }
13
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
14
- // @ts-ignore
15
- if (typeof obj.toJSON === 'function') {
16
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
17
- // @ts-ignore
18
- return obj.toJSON() as T;
13
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
+ if (typeof (obj as any).toJSON === 'function') {
15
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
16
+ return (obj as any).toJSON();
19
17
  }
20
- const copy:T = {} as T;
21
- for (const key in obj) {
22
- if (!Object.prototype.hasOwnProperty.call(obj, key)) {
23
- continue;
24
- }
25
- if (typeof obj[key] !== 'object') {
26
- copy[key] = obj[key];
27
- continue;
28
- }
29
- copy[key] = createSnapshot(obj[key]);
18
+
19
+ // МАСИВИ
20
+ if (Array.isArray(obj)) {
21
+ return obj.map(item => createSnapshot(item)) as unknown as T;
30
22
  }
31
- return copy;
23
+
24
+ // primitives
25
+ if (typeof obj !== 'object') {
26
+ return obj;
27
+ }
28
+
29
+ // plain object
30
+ const copy = {} as Record<string, unknown>;
31
+
32
+ for (const key of Object.keys(obj as object)) {
33
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
+ const value = (obj as any)[key];
35
+ copy[key] = createSnapshot(value);
36
+ }
37
+
38
+ return copy as T;
32
39
  }
package/src/index.ts CHANGED
@@ -10,6 +10,7 @@ import { Eventable } from './mixins/Eventable';
10
10
  import { Application } from './application/Application';
11
11
  import { ApplicationModule } from './application/ApplicationModule';
12
12
  import { bootstrap } from './bootstrap';
13
+ import { getDiff, DiffFormatterOptions, DiffViewModel } from './helpers/diff';
13
14
 
14
15
  export {
15
16
  Entity,
@@ -25,5 +26,9 @@ export {
25
26
  Application,
26
27
  ApplicationModule,
27
28
 
28
- bootstrap
29
+ bootstrap,
30
+
31
+ DiffViewModel,
32
+ DiffFormatterOptions,
33
+ getDiff
29
34
  }