@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.
- package/README.md +102 -0
- package/build/AggregateRoot.d.ts +0 -5
- package/build/AggregateRoot.js +1 -11
- package/build/AggregateRoot.js.map +1 -1
- package/build/DomainEvent.d.ts +4 -8
- package/build/DomainEvent.js +8 -4
- package/build/DomainEvent.js.map +1 -1
- package/build/Entity.d.ts +6 -1
- package/build/Entity.js +30 -0
- package/build/Entity.js.map +1 -1
- package/build/Entity.spec.js +33 -3
- package/build/Entity.spec.js.map +1 -1
- package/build/EntityId.d.ts +2 -2
- package/build/EntityId.js.map +1 -1
- package/build/EntityId.spec.js +6 -5
- package/build/EntityId.spec.js.map +1 -1
- package/build/EventBus.d.ts +2 -0
- package/build/EventBus.spec.d.ts +1 -0
- package/build/EventBus.spec.js +157 -0
- package/build/EventBus.spec.js.map +1 -0
- package/build/eventBus/InMemoryEventBus.d.ts +9 -2
- package/build/eventBus/InMemoryEventBus.js +43 -12
- package/build/eventBus/InMemoryEventBus.js.map +1 -1
- package/build/eventBus/InMemoryEventBus.spec.js +0 -3
- package/build/eventBus/InMemoryEventBus.spec.js.map +1 -1
- package/build/helpers.d.ts +1 -0
- package/build/helpers.js +30 -0
- package/build/helpers.js.map +1 -0
- package/build/helpers.spec.d.ts +1 -0
- package/build/helpers.spec.js +70 -0
- package/build/helpers.spec.js.map +1 -0
- package/build/index.d.ts +4 -1
- package/build/index.js +3 -1
- package/build/index.js.map +1 -1
- package/package.json +1 -1
- package/src/AggregateRoot.ts +0 -15
- package/src/DomainEvent.ts +10 -13
- package/src/Entity.spec.ts +28 -5
- package/src/Entity.ts +37 -2
- package/src/EntityId.spec.ts +5 -4
- package/src/EntityId.ts +3 -3
- package/src/EventBus.spec.ts +108 -0
- package/src/EventBus.ts +2 -0
- package/src/eventBus/InMemoryEventBus.spec.ts +1 -5
- package/src/eventBus/InMemoryEventBus.ts +30 -5
- package/src/helpers.spec.ts +62 -0
- package/src/helpers.ts +25 -0
- package/src/index.ts +7 -1
- 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
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
});
|