@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,18 +3,43 @@ import { AnyDomainEvent } from '../DomainEvent';
3
3
  import { EventBus } from '../EventBus';
4
4
  import {DomainEventSubscriber} from "../DomainEventSubscriber";
5
5
 
6
- export class InMemoryEventBus extends EventEmitter implements EventBus {
7
- async publish(events: AnyDomainEvent[]): Promise<void> {
8
- for (const event of events) {
9
- this.emit(event.eventName, event);
6
+ export class InMemoryEventBus implements EventBus {
7
+ protected _events: AnyDomainEvent[] = [];
8
+ protected _emitter: EventEmitter;
9
+
10
+ constructor() {
11
+ this._emitter = new EventEmitter();
12
+ }
13
+
14
+ async push(event: AnyDomainEvent): Promise<void> {
15
+ this._events.push(event);
16
+ }
17
+
18
+ async clear(): Promise<void> {
19
+ this._events = [];
20
+ }
21
+
22
+ async publish(events: AnyDomainEvent[] = []): Promise<void> {
23
+ const allEvents = (this._events || []).concat(events ?? []);
24
+ for (const event of allEvents) {
25
+ this._emitter.emit(event.eventName, event);
10
26
  }
27
+ await this.clear();
28
+ }
29
+
30
+ on(event: string, listener: (...args: never[]) => void): void {
31
+ this._emitter.on(event, listener);
32
+ }
33
+
34
+ listenerCount(event: string): number {
35
+ return this._emitter.listenerCount(event);
11
36
  }
12
37
 
13
38
  addSubscribers(subscribers: DomainEventSubscriber[]): void {
14
39
  for (const subscriber of subscribers) {
15
40
  const events = subscriber.subscribedTo();
16
41
  for (const event of events) {
17
- this.on(event.EVENT_NAME, subscriber.on.bind(subscriber));
42
+ this._emitter.on(event.EVENT_NAME ?? event.name, subscriber.on.bind(subscriber));
18
43
  }
19
44
  }
20
45
  }
@@ -0,0 +1,62 @@
1
+ import {createSnapshot} from "./helpers";
2
+ import {EntityId} from "./EntityId";
3
+ import {Entity} from "./Entity";
4
+
5
+ interface TestProps {
6
+ name: string;
7
+ testId?: EntityId<string>;
8
+ }
9
+ class TestEntity extends Entity<TestProps, string, EntityId<string>> {
10
+ static create(props: TestProps, id?:EntityId<string>|string): TestEntity {
11
+ return new TestEntity(props, id);
12
+ }
13
+
14
+ set name(name: string) {
15
+ this.props.name = name;
16
+ }
17
+
18
+ set testId(val: EntityId<string>) {
19
+ this.props.testId = val;
20
+ }
21
+
22
+ toSnapshot():never {
23
+ return {
24
+ ...this.props,
25
+ testId: undefined
26
+ } as never;
27
+ }
28
+ }
29
+
30
+ describe('helpers', () => {
31
+ test('createSnapshot', async () => {
32
+ const original = {
33
+ a: 1,
34
+ b: 'test',
35
+ c: {
36
+ d: 2,
37
+ e: 'nested',
38
+ f: {
39
+ g: 3
40
+ }
41
+ },
42
+ id: new EntityId<string>('1'),
43
+ };
44
+ const snapshot = createSnapshot(original);
45
+ expect(snapshot).toEqual(original);
46
+ expect(snapshot).not.toBe(original);
47
+ expect(snapshot.c).not.toBe(original.c);
48
+ expect(snapshot.c.f).not.toBe(original.c.f);
49
+ expect(snapshot.id).not.toBe(original.id);
50
+ expect(snapshot.id).toEqual(new EntityId<string>('1'));
51
+
52
+ const item = TestEntity.create({
53
+ name: 'test',
54
+ testId: new EntityId('2')
55
+ }, '2');
56
+ const itemSnapshot = createSnapshot(item);
57
+ expect(itemSnapshot).toEqual({
58
+ name: 'test',
59
+ testId: undefined
60
+ });
61
+ });
62
+ });
package/src/helpers.ts ADDED
@@ -0,0 +1,25 @@
1
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2
+ export function createSnapshot<T>(obj: T): T {
3
+ if (!obj) {
4
+ return obj;
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;
12
+ }
13
+ const copy:T = {} as T;
14
+ for (const key in obj) {
15
+ if (!Object.prototype.hasOwnProperty.call(obj, key)) {
16
+ continue;
17
+ }
18
+ if (typeof obj[key] !== 'object') {
19
+ copy[key] = obj[key];
20
+ continue;
21
+ }
22
+ copy[key] = createSnapshot(obj[key]);
23
+ }
24
+ return copy;
25
+ }
package/src/index.ts CHANGED
@@ -3,11 +3,17 @@ import { EntityId } from './EntityId';
3
3
  import { ValueObject } from './ValueObject';
4
4
  import { AggregateRoot } from './AggregateRoot';
5
5
  import { HashError } from './error/HashError';
6
+ import { DomainEvent } from './DomainEvent';
7
+ import { DomainEventSubscriber } from './DomainEventSubscriber';
8
+ import { EventBus } from './EventBus';
6
9
 
7
10
  export {
8
11
  Entity,
9
12
  EntityId,
10
13
  ValueObject,
11
14
  AggregateRoot,
12
- HashError
15
+ HashError,
16
+ DomainEvent,
17
+ DomainEventSubscriber,
18
+ EventBus
13
19
  }
@@ -1,35 +0,0 @@
1
- import {AggregateRoot} from "./AggregateRoot";
2
- import {EntityId} from "./EntityId";
3
- import {DomainEvent} from "./DomainEvent";
4
-
5
- interface TestProps {
6
- name: string;
7
- }
8
- class TestEntity extends AggregateRoot<TestProps, number, EntityId<number>> {
9
- static create(props: TestProps, id?:EntityId<number>|number): TestEntity {
10
- return new TestEntity(props, id);
11
- }
12
- }
13
- class TestEvent extends DomainEvent<number> {
14
- readonly eventName = 'TestEvent';
15
-
16
- toPrimitives() {
17
- return {};
18
- }
19
- }
20
-
21
- describe('AggregateRoot', () => {
22
- let root: TestEntity;
23
-
24
- beforeAll(() => {
25
- root = TestEntity.create({ name: 'test' }, 1);
26
- });
27
-
28
- test('events', async () => {
29
- const event = new TestEvent(root);
30
- root.pushDomainEvent(event);
31
-
32
- expect(root.pullDomainEvents()).toEqual([event]);
33
- expect(root.pullDomainEvents()).toEqual([]);
34
- });
35
- });