@bgord/bun 1.13.0 → 1.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/event-finder-noop.adapter.d.ts +9 -0
- package/dist/event-finder-noop.adapter.d.ts.map +1 -0
- package/dist/event-finder-noop.adapter.js +10 -0
- package/dist/event-finder-noop.adapter.js.map +1 -0
- package/dist/event-finder.port.d.ts +6 -0
- package/dist/event-finder.port.d.ts.map +1 -0
- package/dist/event-finder.port.js +2 -0
- package/dist/event-finder.port.js.map +1 -0
- package/dist/event-inserter-noop.adapter.d.ts +6 -0
- package/dist/event-inserter-noop.adapter.d.ts.map +1 -0
- package/dist/event-inserter-noop.adapter.js +6 -0
- package/dist/event-inserter-noop.adapter.js.map +1 -0
- package/dist/event-inserter.port.d.ts +5 -0
- package/dist/event-inserter.port.d.ts.map +1 -0
- package/dist/event-inserter.port.js +2 -0
- package/dist/event-inserter.port.js.map +1 -0
- package/dist/event-revision-assigner.adapter.d.ts +7 -0
- package/dist/event-revision-assigner.adapter.d.ts.map +1 -0
- package/dist/event-revision-assigner.adapter.js +7 -0
- package/dist/event-revision-assigner.adapter.js.map +1 -0
- package/dist/event-revision-assigner.port.d.ts +5 -0
- package/dist/event-revision-assigner.port.d.ts.map +1 -0
- package/dist/event-revision-assigner.port.js +2 -0
- package/dist/event-revision-assigner.port.js.map +1 -0
- package/dist/event-serializer-collecting.adapter.d.ts +8 -0
- package/dist/event-serializer-collecting.adapter.d.ts.map +1 -0
- package/dist/event-serializer-collecting.adapter.js +13 -0
- package/dist/event-serializer-collecting.adapter.js.map +1 -0
- package/dist/event-serializer-json.adapter.d.ts +6 -0
- package/dist/event-serializer-json.adapter.d.ts.map +1 -0
- package/dist/event-serializer-json.adapter.js +9 -0
- package/dist/event-serializer-json.adapter.js.map +1 -0
- package/dist/event-serializer.port.d.ts +5 -0
- package/dist/event-serializer.port.d.ts.map +1 -0
- package/dist/event-serializer.port.js +2 -0
- package/dist/event-serializer.port.js.map +1 -0
- package/dist/event-store-collecting.adapter.d.ts +10 -0
- package/dist/event-store-collecting.adapter.d.ts.map +1 -0
- package/dist/event-store-collecting.adapter.js +11 -0
- package/dist/event-store-collecting.adapter.js.map +1 -0
- package/dist/event-store-dispatching.adapter.d.ts +17 -0
- package/dist/event-store-dispatching.adapter.d.ts.map +1 -0
- package/dist/event-store-dispatching.adapter.js +15 -0
- package/dist/event-store-dispatching.adapter.js.map +1 -0
- package/dist/event-store-noop.adapter.d.ts +9 -0
- package/dist/event-store-noop.adapter.d.ts.map +1 -0
- package/dist/event-store-noop.adapter.js +9 -0
- package/dist/event-store-noop.adapter.js.map +1 -0
- package/dist/event-store.adapter.d.ts +20 -0
- package/dist/event-store.adapter.d.ts.map +1 -0
- package/dist/event-store.adapter.js +27 -0
- package/dist/event-store.adapter.js.map +1 -0
- package/dist/event-store.port.d.ts +8 -0
- package/dist/event-store.port.d.ts.map +1 -0
- package/dist/event-store.port.js +2 -0
- package/dist/event-store.port.js.map +1 -0
- package/dist/event-validator-registry-zod.adapter.d.ts +24 -0
- package/dist/event-validator-registry-zod.adapter.d.ts.map +1 -0
- package/dist/event-validator-registry-zod.adapter.js +25 -0
- package/dist/event-validator-registry-zod.adapter.js.map +1 -0
- package/dist/event-validator-registry.port.d.ts +7 -0
- package/dist/event-validator-registry.port.d.ts.map +1 -0
- package/dist/event-validator-registry.port.js +2 -0
- package/dist/event-validator-registry.port.js.map +1 -0
- package/dist/event.types.d.ts +13 -14
- package/dist/event.types.d.ts.map +1 -1
- package/dist/index.d.ts +21 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -7
- package/dist/index.js.map +1 -1
- package/dist/message-handler-bare.strategy.d.ts +8 -0
- package/dist/message-handler-bare.strategy.d.ts.map +1 -0
- package/dist/message-handler-bare.strategy.js +8 -0
- package/dist/message-handler-bare.strategy.js.map +1 -0
- package/dist/message-handler-noop.strategy.d.ts +8 -0
- package/dist/message-handler-noop.strategy.d.ts.map +1 -0
- package/dist/message-handler-noop.strategy.js +8 -0
- package/dist/message-handler-noop.strategy.js.map +1 -0
- package/dist/message-handler-with-logger.strategy.d.ts +17 -0
- package/dist/message-handler-with-logger.strategy.d.ts.map +1 -0
- package/dist/message-handler-with-logger.strategy.js +27 -0
- package/dist/message-handler-with-logger.strategy.js.map +1 -0
- package/dist/message-handler.strategy.d.ts +7 -0
- package/dist/message-handler.strategy.d.ts.map +1 -0
- package/dist/message-handler.strategy.js +2 -0
- package/dist/message-handler.strategy.js.map +1 -0
- package/dist/modules/preferences/command-handlers/handleSetUserLanguageCommand.d.ts +2 -2
- package/dist/modules/preferences/command-handlers/handleSetUserLanguageCommand.d.ts.map +1 -1
- package/dist/modules/system/services/passage-of-time-hourly.service.d.ts +2 -2
- package/dist/modules/system/services/passage-of-time-hourly.service.d.ts.map +1 -1
- package/dist/modules/system/services/passage-of-time-minute.service.d.ts +2 -2
- package/dist/modules/system/services/passage-of-time-minute.service.d.ts.map +1 -1
- package/dist/security-countermeasure-ban.strategy.d.ts +2 -2
- package/dist/security-countermeasure-ban.strategy.d.ts.map +1 -1
- package/dist/sse-hono.handler.js +1 -1
- package/dist/sse-hono.handler.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/readme.md +20 -7
- package/src/event-finder-noop.adapter.ts +14 -0
- package/src/event-finder.port.ts +9 -0
- package/src/event-inserter-noop.adapter.ts +10 -0
- package/src/event-inserter.port.ts +5 -0
- package/src/event-revision-assigner.adapter.ts +13 -0
- package/src/event-revision-assigner.port.ts +8 -0
- package/src/event-serializer-collecting.adapter.ts +19 -0
- package/src/event-serializer-json.adapter.ts +11 -0
- package/src/event-serializer.port.ts +4 -0
- package/src/event-store-collecting.adapter.ts +21 -0
- package/src/event-store-dispatching.adapter.ts +29 -0
- package/src/event-store-noop.adapter.ts +17 -0
- package/src/event-store.adapter.ts +49 -0
- package/src/event-store.port.ts +12 -0
- package/src/event-validator-registry-zod.adapter.ts +47 -0
- package/src/event-validator-registry.port.ts +7 -0
- package/src/event.types.ts +12 -15
- package/src/index.ts +21 -7
- package/src/message-handler-bare.strategy.ts +11 -0
- package/src/message-handler-noop.strategy.ts +11 -0
- package/src/message-handler-with-logger.strategy.ts +32 -0
- package/src/message-handler.strategy.ts +8 -0
- package/src/modules/preferences/command-handlers/handleSetUserLanguageCommand.ts +2 -2
- package/src/modules/system/services/passage-of-time-hourly.service.ts +2 -2
- package/src/modules/system/services/passage-of-time-minute.service.ts +2 -2
- package/src/security-countermeasure-ban.strategy.ts +2 -2
- package/src/sse-hono.handler.ts +1 -1
- package/dist/dispatching-event-store.d.ts +0 -15
- package/dist/dispatching-event-store.d.ts.map +0 -1
- package/dist/dispatching-event-store.js +0 -16
- package/dist/dispatching-event-store.js.map +0 -1
- package/dist/event-handler-bare.strategy.d.ts +0 -6
- package/dist/event-handler-bare.strategy.d.ts.map +0 -1
- package/dist/event-handler-bare.strategy.js +0 -6
- package/dist/event-handler-bare.strategy.js.map +0 -1
- package/dist/event-handler-noop.strategy.d.ts +0 -6
- package/dist/event-handler-noop.strategy.d.ts.map +0 -1
- package/dist/event-handler-noop.strategy.js +0 -6
- package/dist/event-handler-noop.strategy.js.map +0 -1
- package/dist/event-handler-with-logger.strategy.d.ts +0 -15
- package/dist/event-handler-with-logger.strategy.d.ts.map +0 -1
- package/dist/event-handler-with-logger.strategy.js +0 -25
- package/dist/event-handler-with-logger.strategy.js.map +0 -1
- package/dist/event-handler.strategy.d.ts +0 -5
- package/dist/event-handler.strategy.d.ts.map +0 -1
- package/dist/event-handler.strategy.js +0 -2
- package/dist/event-handler.strategy.js.map +0 -1
- package/dist/event-store-like.types.d.ts +0 -5
- package/dist/event-store-like.types.d.ts.map +0 -1
- package/dist/event-store-like.types.js +0 -2
- package/dist/event-store-like.types.js.map +0 -1
- package/dist/event-store.d.ts +0 -22
- package/dist/event-store.d.ts.map +0 -1
- package/dist/event-store.js +0 -37
- package/dist/event-store.js.map +0 -1
- package/src/dispatching-event-store.ts +0 -34
- package/src/event-handler-bare.strategy.ts +0 -8
- package/src/event-handler-noop.strategy.ts +0 -8
- package/src/event-handler-with-logger.strategy.ts +0 -29
- package/src/event-handler.strategy.ts +0 -5
- package/src/event-store-like.types.ts +0 -5
- package/src/event-store.ts +0 -64
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bgord/bun",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Bartosz Gordon",
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
"preinstall": "bunx only-allow bun"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@biomejs/biome": "2.4.
|
|
24
|
-
"@commitlint/cli": "20.
|
|
25
|
-
"@commitlint/config-conventional": "20.
|
|
23
|
+
"@biomejs/biome": "2.4.7",
|
|
24
|
+
"@commitlint/cli": "20.5.0",
|
|
25
|
+
"@commitlint/config-conventional": "20.5.0",
|
|
26
26
|
"@stryker-mutator/core": "9.6.0",
|
|
27
27
|
"@types/bun": "1.3.10",
|
|
28
28
|
"@types/nodemailer": "7.0.11",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@bgord/tools": "1.3.24",
|
|
47
47
|
"emittery": "2.0.0",
|
|
48
|
-
"hono": "4.12.
|
|
48
|
+
"hono": "4.12.8",
|
|
49
49
|
"node-cache": "5.1.2"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
package/readme.md
CHANGED
|
@@ -96,7 +96,6 @@ src/
|
|
|
96
96
|
├── disk-space-checker-noop.adapter.ts
|
|
97
97
|
├── disk-space-checker-shell.adapter.ts
|
|
98
98
|
├── disk-space-checker.port.ts
|
|
99
|
-
├── dispatching-event-store.ts
|
|
100
99
|
├── dynamic-import.service.ts
|
|
101
100
|
├── encryption-aes-gcm.adapter.ts
|
|
102
101
|
├── encryption-iv.vo.ts
|
|
@@ -113,15 +112,25 @@ src/
|
|
|
113
112
|
├── etag-extractor-hono.middleware.ts
|
|
114
113
|
├── etag-extractor.middleware.ts
|
|
115
114
|
├── event-envelope.ts
|
|
116
|
-
├── event-
|
|
117
|
-
├── event-
|
|
118
|
-
├── event-
|
|
119
|
-
├── event-
|
|
115
|
+
├── event-finder-noop.adapter.ts
|
|
116
|
+
├── event-finder.port.ts
|
|
117
|
+
├── event-inserter-noop.adapter.ts
|
|
118
|
+
├── event-inserter.port.ts
|
|
120
119
|
├── event-loop-lag.service.ts
|
|
121
120
|
├── event-loop-utilization.service.ts
|
|
122
|
-
├── event-
|
|
123
|
-
├── event-
|
|
121
|
+
├── event-revision-assigner.adapter.ts
|
|
122
|
+
├── event-revision-assigner.port.ts
|
|
123
|
+
├── event-serializer-collecting.adapter.ts
|
|
124
|
+
├── event-serializer-json.adapter.ts
|
|
125
|
+
├── event-serializer.port.ts
|
|
126
|
+
├── event-store-collecting.adapter.ts
|
|
127
|
+
├── event-store-dispatching.adapter.ts
|
|
128
|
+
├── event-store-noop.adapter.ts
|
|
129
|
+
├── event-store.adapter.ts
|
|
130
|
+
├── event-store.port.ts
|
|
124
131
|
├── event-stream.vo.ts
|
|
132
|
+
├── event-validator-registry-zod.adapter.ts
|
|
133
|
+
├── event-validator-registry.port.ts
|
|
125
134
|
├── event.types.ts
|
|
126
135
|
├── file-cleaner-forgiving.adapter.ts
|
|
127
136
|
├── file-cleaner-noop.adapter.ts
|
|
@@ -250,6 +259,10 @@ src/
|
|
|
250
259
|
├── message-bus-noop.adapter.ts
|
|
251
260
|
├── message-bus-with-logger.adapter.ts
|
|
252
261
|
├── message-bus.port.ts
|
|
262
|
+
├── message-handler-bare.strategy.ts
|
|
263
|
+
├── message-handler-noop.strategy.ts
|
|
264
|
+
├── message-handler-with-logger.strategy.ts
|
|
265
|
+
├── message-handler.strategy.ts
|
|
253
266
|
├── message.types.ts
|
|
254
267
|
├── middleware-hono-noop.adapter.ts
|
|
255
268
|
├── middleware-hono.port.ts
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { GenericEvent, GenericEventSerialized } from "./event.types";
|
|
2
|
+
import type { EventFinderPort } from "./event-finder.port";
|
|
3
|
+
import type { EventStreamType } from "./event-stream.vo";
|
|
4
|
+
|
|
5
|
+
export class EventFinderNoopAdapter implements EventFinderPort {
|
|
6
|
+
constructor(private readonly events: ReadonlyArray<GenericEventSerialized>) {}
|
|
7
|
+
|
|
8
|
+
async find(
|
|
9
|
+
_stream: EventStreamType,
|
|
10
|
+
_names: ReadonlyArray<GenericEvent["name"]>,
|
|
11
|
+
): Promise<ReadonlyArray<GenericEventSerialized>> {
|
|
12
|
+
return this.events;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { GenericEvent, GenericEventSerialized } from "./event.types";
|
|
2
|
+
import type { EventStreamType } from "./event-stream.vo";
|
|
3
|
+
|
|
4
|
+
export interface EventFinderPort {
|
|
5
|
+
find(
|
|
6
|
+
stream: EventStreamType,
|
|
7
|
+
names: ReadonlyArray<GenericEvent["name"]>,
|
|
8
|
+
): Promise<ReadonlyArray<GenericEventSerialized>>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { GenericEventSerialized } from "./event.types";
|
|
2
|
+
import type { EventInserterPort } from "./event-inserter.port";
|
|
3
|
+
|
|
4
|
+
export class EventInserterNoopAdapter implements EventInserterPort {
|
|
5
|
+
async insert(
|
|
6
|
+
events: ReadonlyArray<GenericEventSerialized>,
|
|
7
|
+
): Promise<ReadonlyArray<GenericEventSerialized>> {
|
|
8
|
+
return events;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { GenericEventSerialized } from "./event.types";
|
|
2
|
+
import type { EventRevisionAssignerPort } from "./event-revision-assigner.port";
|
|
3
|
+
|
|
4
|
+
export class EventRevisionAssignerAdapter implements EventRevisionAssignerPort {
|
|
5
|
+
static readonly EMPTY_STREAM_REVISION = -1;
|
|
6
|
+
|
|
7
|
+
assign(
|
|
8
|
+
events: ReadonlyArray<GenericEventSerialized>,
|
|
9
|
+
currentMax: number,
|
|
10
|
+
): ReadonlyArray<GenericEventSerialized> {
|
|
11
|
+
return events.map((event, index) => ({ ...event, revision: currentMax + index + 1 }));
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { EventSerializerPort } from "./event-serializer.port";
|
|
2
|
+
|
|
3
|
+
export class EventSerializerCollectingAdapter implements EventSerializerPort {
|
|
4
|
+
readonly serialized: Array<unknown> = [];
|
|
5
|
+
|
|
6
|
+
readonly deserialized: Array<string> = [];
|
|
7
|
+
|
|
8
|
+
serialize(payload: unknown): string {
|
|
9
|
+
this.serialized.push(payload);
|
|
10
|
+
|
|
11
|
+
return JSON.stringify(payload);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
deserialize(raw: string): unknown {
|
|
15
|
+
this.deserialized.push(raw);
|
|
16
|
+
|
|
17
|
+
return JSON.parse(raw);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { EventSerializerPort } from "./event-serializer.port";
|
|
2
|
+
|
|
3
|
+
export class EventSerializerJsonAdapter implements EventSerializerPort {
|
|
4
|
+
serialize(payload: unknown): string {
|
|
5
|
+
return JSON.stringify(payload);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
deserialize(raw: string): unknown {
|
|
9
|
+
return JSON.parse(raw);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { GenericEvent } from "./event.types";
|
|
2
|
+
import type { EventStorePort } from "./event-store.port";
|
|
3
|
+
import type { EventStreamType } from "./event-stream.vo";
|
|
4
|
+
import type { EventValidatorRegistryPort } from "./event-validator-registry.port";
|
|
5
|
+
|
|
6
|
+
export class EventStoreCollectingAdapter<TEvent extends GenericEvent> implements EventStorePort<TEvent> {
|
|
7
|
+
readonly saved: Array<TEvent> = [];
|
|
8
|
+
|
|
9
|
+
async find<FoundEvent extends TEvent>(
|
|
10
|
+
_registry: EventValidatorRegistryPort<FoundEvent>,
|
|
11
|
+
_stream: EventStreamType,
|
|
12
|
+
): Promise<ReadonlyArray<FoundEvent>> {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async save(events: ReadonlyArray<TEvent>): Promise<ReadonlyArray<TEvent>> {
|
|
17
|
+
this.saved.push(...events);
|
|
18
|
+
|
|
19
|
+
return [...events];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { GenericEvent } from "./event.types";
|
|
2
|
+
import type { EventStorePort } from "./event-store.port";
|
|
3
|
+
import type { EventStreamType } from "./event-stream.vo";
|
|
4
|
+
import type { EventValidatorRegistryPort } from "./event-validator-registry.port";
|
|
5
|
+
import type { EventBusPort } from "./message-bus.port";
|
|
6
|
+
|
|
7
|
+
type Dependencies<TEvent extends GenericEvent> = {
|
|
8
|
+
inner: EventStorePort<TEvent>;
|
|
9
|
+
EventBus: EventBusPort<TEvent>;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export class EventStoreDispatchingAdapter<Event extends GenericEvent> implements EventStorePort<Event> {
|
|
13
|
+
constructor(private readonly deps: Dependencies<Event>) {}
|
|
14
|
+
|
|
15
|
+
async find<FoundEvent extends Event>(
|
|
16
|
+
registry: EventValidatorRegistryPort<FoundEvent>,
|
|
17
|
+
stream: EventStreamType,
|
|
18
|
+
): Promise<ReadonlyArray<FoundEvent>> {
|
|
19
|
+
return this.deps.inner.find(registry, stream);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async save(events: ReadonlyArray<Event>): Promise<ReadonlyArray<Event>> {
|
|
23
|
+
const saved = await this.deps.inner.save(events);
|
|
24
|
+
|
|
25
|
+
await Promise.all(saved.map((event) => this.deps.EventBus.emit(event)));
|
|
26
|
+
|
|
27
|
+
return saved;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { GenericEvent } from "./event.types";
|
|
2
|
+
import type { EventStorePort } from "./event-store.port";
|
|
3
|
+
import type { EventStreamType } from "./event-stream.vo";
|
|
4
|
+
import type { EventValidatorRegistryPort } from "./event-validator-registry.port";
|
|
5
|
+
|
|
6
|
+
export class EventStoreNoopAdapter<Event extends GenericEvent> implements EventStorePort<Event> {
|
|
7
|
+
async find<FoundEvent extends Event>(
|
|
8
|
+
_registry: EventValidatorRegistryPort<FoundEvent>,
|
|
9
|
+
_stream: EventStreamType,
|
|
10
|
+
): Promise<ReadonlyArray<FoundEvent>> {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async save(_events: ReadonlyArray<Event>): Promise<ReadonlyArray<Event>> {
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { GenericEvent } from "./event.types";
|
|
2
|
+
import type { EventFinderPort } from "./event-finder.port";
|
|
3
|
+
import type { EventInserterPort } from "./event-inserter.port";
|
|
4
|
+
import type { EventSerializerPort } from "./event-serializer.port";
|
|
5
|
+
import type { EventStorePort } from "./event-store.port";
|
|
6
|
+
import type { EventStreamType } from "./event-stream.vo";
|
|
7
|
+
import type { EventValidatorRegistryPort } from "./event-validator-registry.port";
|
|
8
|
+
|
|
9
|
+
type Config = {
|
|
10
|
+
finder: EventFinderPort;
|
|
11
|
+
inserter: EventInserterPort;
|
|
12
|
+
serializer: EventSerializerPort;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const EventStoreAdapterError = { UniqueStream: "event.store.adapter.error.unique.stream" };
|
|
16
|
+
|
|
17
|
+
export class EventStoreAdapter<Event extends GenericEvent> implements EventStorePort<Event> {
|
|
18
|
+
constructor(private readonly config: Config) {}
|
|
19
|
+
|
|
20
|
+
async find<FoundEvent extends Event>(
|
|
21
|
+
registry: EventValidatorRegistryPort<FoundEvent>,
|
|
22
|
+
stream: EventStreamType,
|
|
23
|
+
): Promise<ReadonlyArray<FoundEvent>> {
|
|
24
|
+
const events = await this.config.finder.find(stream, registry.names);
|
|
25
|
+
|
|
26
|
+
return events
|
|
27
|
+
.map((event) => ({ ...event, payload: this.config.serializer.deserialize(event.payload) }))
|
|
28
|
+
.map((event) => registry.validate(event));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async save(events: ReadonlyArray<Event>): Promise<ReadonlyArray<Event>> {
|
|
32
|
+
if (!events[0]) return [];
|
|
33
|
+
|
|
34
|
+
const stream = events[0].stream;
|
|
35
|
+
|
|
36
|
+
if (!events.every((event) => event.stream === stream)) {
|
|
37
|
+
throw new Error(EventStoreAdapterError.UniqueStream);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const serialized = await this.config.inserter.insert(
|
|
41
|
+
events.map((event) => ({ ...event, payload: this.config.serializer.serialize(event.payload) })),
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
return serialized.map((event) => ({
|
|
45
|
+
...event,
|
|
46
|
+
payload: this.config.serializer.deserialize(event.payload),
|
|
47
|
+
})) as Array<Event>;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { GenericEvent } from "./event.types";
|
|
2
|
+
import type { EventStreamType } from "./event-stream.vo";
|
|
3
|
+
import type { EventValidatorRegistryPort } from "./event-validator-registry.port";
|
|
4
|
+
|
|
5
|
+
export interface EventStorePort<Event extends GenericEvent> {
|
|
6
|
+
find<FoundEvent extends Event>(
|
|
7
|
+
registry: EventValidatorRegistryPort<FoundEvent>,
|
|
8
|
+
stream: EventStreamType,
|
|
9
|
+
): Promise<ReadonlyArray<FoundEvent>>;
|
|
10
|
+
|
|
11
|
+
save(events: ReadonlyArray<Event>): Promise<ReadonlyArray<Event>>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type * as z from "zod/v4";
|
|
2
|
+
import type { GenericEvent } from "./event.types";
|
|
3
|
+
import type { EventValidatorRegistryPort } from "./event-validator-registry.port";
|
|
4
|
+
|
|
5
|
+
export type GenericEventSchema = z.ZodObject<{
|
|
6
|
+
id: z.ZodType<string>;
|
|
7
|
+
correlationId: z.ZodType<string>;
|
|
8
|
+
createdAt: z.ZodType<number>;
|
|
9
|
+
stream: z.ZodString;
|
|
10
|
+
revision: z.ZodOptional<z.ZodType<number>>;
|
|
11
|
+
name: z.ZodLiteral<string>;
|
|
12
|
+
version: z.ZodLiteral<number>;
|
|
13
|
+
payload: z.ZodType<any>;
|
|
14
|
+
}>;
|
|
15
|
+
|
|
16
|
+
export type GenericParsedEventSchema = z.ZodObject<
|
|
17
|
+
Omit<GenericEventSchema["shape"], "payload"> & { payload: z.ZodString }
|
|
18
|
+
>;
|
|
19
|
+
|
|
20
|
+
const EventValidatorRegistryZodAdapterError = {
|
|
21
|
+
MissingName: "event.validator.registry.zod.adapter.error.missing.name",
|
|
22
|
+
UnknownEvent: "event.validator.registry.zod.adapter.error.unknown.event",
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export class EventValidatorRegistryZodAdapter<TEvent> implements EventValidatorRegistryPort<TEvent> {
|
|
26
|
+
private readonly map: Map<GenericEvent["name"], GenericEventSchema>;
|
|
27
|
+
readonly names: ReadonlyArray<GenericEvent["name"]>;
|
|
28
|
+
|
|
29
|
+
constructor(schemas: ReadonlyArray<GenericEventSchema>) {
|
|
30
|
+
this.map = new Map(schemas.map((schema) => [schema.shape.name.value, schema]));
|
|
31
|
+
this.names = [...this.map.keys()];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
accepts(name: GenericEvent["name"]): boolean {
|
|
35
|
+
return this.map.has(name);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
validate(raw: unknown): TEvent {
|
|
39
|
+
const name = (raw as { name?: GenericEvent["name"] }).name;
|
|
40
|
+
if (!name) throw new Error(EventValidatorRegistryZodAdapterError.MissingName);
|
|
41
|
+
|
|
42
|
+
const schema = this.map.get(name);
|
|
43
|
+
if (!schema) throw new Error(EventValidatorRegistryZodAdapterError.UnknownEvent);
|
|
44
|
+
|
|
45
|
+
return schema.parse(raw) as TEvent;
|
|
46
|
+
}
|
|
47
|
+
}
|
package/src/event.types.ts
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
// TODO: use proper VO types.
|
|
2
|
+
export type GenericEvent = {
|
|
3
|
+
id: string;
|
|
4
|
+
correlationId: string;
|
|
5
|
+
createdAt: number;
|
|
6
|
+
stream: string;
|
|
7
|
+
revision?: number;
|
|
8
|
+
name: string;
|
|
9
|
+
version: number;
|
|
10
|
+
payload: unknown;
|
|
11
|
+
};
|
|
2
12
|
|
|
3
|
-
export type
|
|
4
|
-
id: z.ZodType<string>;
|
|
5
|
-
correlationId: z.ZodType<string>;
|
|
6
|
-
createdAt: z.ZodType<number>;
|
|
7
|
-
stream: z.ZodString;
|
|
8
|
-
revision: z.ZodOptional<z.ZodType<number>>;
|
|
9
|
-
name: z.ZodLiteral<string>;
|
|
10
|
-
version: z.ZodLiteral<number>;
|
|
11
|
-
payload: z.ZodType<any>;
|
|
12
|
-
}>;
|
|
13
|
-
|
|
14
|
-
export type GenericParsedEventSchema = z.ZodObject<
|
|
15
|
-
Omit<GenericEventSchema["shape"], "payload"> & { payload: z.ZodString }
|
|
16
|
-
>;
|
|
13
|
+
export type GenericEventSerialized = Omit<GenericEvent, "payload"> & { payload: string };
|
package/src/index.ts
CHANGED
|
@@ -68,7 +68,6 @@ export * from "./directory-ensurer-noop.adapter";
|
|
|
68
68
|
export * from "./disk-space-checker.port";
|
|
69
69
|
export * from "./disk-space-checker-noop.adapter";
|
|
70
70
|
export * from "./disk-space-checker-shell.adapter";
|
|
71
|
-
export * from "./dispatching-event-store";
|
|
72
71
|
export * from "./dynamic-import.service";
|
|
73
72
|
export * from "./encryption.port";
|
|
74
73
|
export * from "./encryption-aes-gcm.adapter";
|
|
@@ -85,15 +84,26 @@ export * from "./etag-extractor.middleware";
|
|
|
85
84
|
export * from "./etag-extractor-hono.middleware";
|
|
86
85
|
export * from "./event.types";
|
|
87
86
|
export * from "./event-envelope";
|
|
88
|
-
export * from "./event-
|
|
89
|
-
export * from "./event-
|
|
90
|
-
export * from "./event-
|
|
91
|
-
export * from "./event-
|
|
87
|
+
export * from "./event-finder.port";
|
|
88
|
+
export * from "./event-finder-noop.adapter";
|
|
89
|
+
export * from "./event-inserter.port";
|
|
90
|
+
export * from "./event-inserter-noop.adapter";
|
|
92
91
|
export * from "./event-loop-lag.service";
|
|
93
92
|
export * from "./event-loop-utilization.service";
|
|
94
|
-
export * from "./event-
|
|
95
|
-
export * from "./event-
|
|
93
|
+
export * from "./event-revision-assigner.adapter";
|
|
94
|
+
export * from "./event-revision-assigner.port";
|
|
95
|
+
export * from "./event-serializer.port";
|
|
96
|
+
export * from "./event-serializer-collecting.adapter";
|
|
97
|
+
export * from "./event-serializer-json.adapter";
|
|
98
|
+
export * from "./event-store.adapter";
|
|
99
|
+
export * from "./event-store.port";
|
|
100
|
+
export * from "./event-store-collecting.adapter";
|
|
101
|
+
export * from "./event-store-collecting.adapter";
|
|
102
|
+
export * from "./event-store-dispatching.adapter";
|
|
103
|
+
export * from "./event-store-noop.adapter";
|
|
96
104
|
export * from "./event-stream.vo";
|
|
105
|
+
export * from "./event-validator-registry.port";
|
|
106
|
+
export * from "./event-validator-registry-zod.adapter";
|
|
97
107
|
export * from "./file-cleaner.adapter";
|
|
98
108
|
export * from "./file-cleaner.port";
|
|
99
109
|
export * from "./file-cleaner-forgiving.adapter";
|
|
@@ -221,6 +231,10 @@ export * from "./message-bus-collecting.adapter";
|
|
|
221
231
|
export * from "./message-bus-emittery.adapter";
|
|
222
232
|
export * from "./message-bus-noop.adapter";
|
|
223
233
|
export * from "./message-bus-with-logger.adapter";
|
|
234
|
+
export * from "./message-handler.strategy";
|
|
235
|
+
export * from "./message-handler-bare.strategy";
|
|
236
|
+
export * from "./message-handler-noop.strategy";
|
|
237
|
+
export * from "./message-handler-with-logger.strategy";
|
|
224
238
|
export * from "./middleware-hono.port";
|
|
225
239
|
export * from "./middleware-hono-noop.adapter";
|
|
226
240
|
export * as History from "./modules/history";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Message } from "./message.types";
|
|
2
|
+
import type { MessageHandlerStrategy } from "./message-handler.strategy";
|
|
3
|
+
|
|
4
|
+
export class MessageHandlerBareStrategy implements MessageHandlerStrategy {
|
|
5
|
+
handle<M extends Message>(handler: (message: M) => Promise<void>) {
|
|
6
|
+
return async (message: M) => handler(message);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const EventHandlerBareStrategy = MessageHandlerBareStrategy;
|
|
11
|
+
export const CommandHandlerBareStrategy = MessageHandlerBareStrategy;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Message } from "./message.types";
|
|
2
|
+
import type { MessageHandlerStrategy } from "./message-handler.strategy";
|
|
3
|
+
|
|
4
|
+
export class MessageHandlerNoopStrategy implements MessageHandlerStrategy {
|
|
5
|
+
handle<M extends Message>(_handler: (message: M) => Promise<void>) {
|
|
6
|
+
return async (_message: M) => {};
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const EventHandlerNoopStrategy = MessageHandlerNoopStrategy;
|
|
11
|
+
export const CommandHandlerNoopStrategy = MessageHandlerNoopStrategy;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ClockPort } from "./clock.port";
|
|
2
|
+
import type { LoggerPort } from "./logger.port";
|
|
3
|
+
import type { Message } from "./message.types";
|
|
4
|
+
import type { MessageHandlerStrategy } from "./message-handler.strategy";
|
|
5
|
+
import { Stopwatch } from "./stopwatch.service";
|
|
6
|
+
|
|
7
|
+
type Dependencies = { Logger: LoggerPort; Clock: ClockPort };
|
|
8
|
+
|
|
9
|
+
export class MessageHandlerWithLoggerStrategy implements MessageHandlerStrategy {
|
|
10
|
+
constructor(private readonly deps: Dependencies) {}
|
|
11
|
+
|
|
12
|
+
handle<M extends Message>(handler: (message: M) => Promise<void>) {
|
|
13
|
+
return async (message: M) => {
|
|
14
|
+
const duration = new Stopwatch(this.deps);
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
await handler(message);
|
|
18
|
+
} catch (error) {
|
|
19
|
+
this.deps.Logger.error({
|
|
20
|
+
message: `Unknown ${message.name} message handler error`,
|
|
21
|
+
component: "infra",
|
|
22
|
+
operation: "message_handler",
|
|
23
|
+
metadata: { name: message.name, duration: duration.stop() },
|
|
24
|
+
error,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const EventHandlerWithLoggerStrategy = MessageHandlerWithLoggerStrategy;
|
|
32
|
+
export const CommandHandlerWithLoggerStrategy = MessageHandlerWithLoggerStrategy;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Message } from "./message.types";
|
|
2
|
+
|
|
3
|
+
export interface MessageHandlerStrategy {
|
|
4
|
+
handle<M extends Message>(handler: (message: M) => Promise<void>): (message: M) => Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export type EventHandlerStrategy = MessageHandlerStrategy;
|
|
8
|
+
export type CommandHandlerStrategy = MessageHandlerStrategy;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type * as tools from "@bgord/tools";
|
|
2
2
|
import type { ClockPort } from "../../../clock.port";
|
|
3
3
|
import { createEventEnvelope } from "../../../event-envelope";
|
|
4
|
-
import type {
|
|
4
|
+
import type { EventStorePort } from "../../../event-store.port";
|
|
5
5
|
import type { IdProviderPort } from "../../../id-provider.port";
|
|
6
6
|
import type { Languages } from "../../../languages.vo";
|
|
7
7
|
import type * as Commands from "../commands";
|
|
@@ -14,7 +14,7 @@ export const HandleSetUserLanguageCommandError = {
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
type Dependencies = {
|
|
17
|
-
EventStore:
|
|
17
|
+
EventStore: EventStorePort<AcceptedEvent>;
|
|
18
18
|
IdProvider: IdProviderPort;
|
|
19
19
|
Clock: ClockPort;
|
|
20
20
|
UserLanguageQuery: Ports.UserLanguageQueryPort;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ClockPort } from "../../../clock.port";
|
|
2
2
|
import { createEventEnvelope } from "../../../event-envelope";
|
|
3
|
-
import type {
|
|
3
|
+
import type { EventStorePort } from "../../../event-store.port";
|
|
4
4
|
import type { IdProviderPort } from "../../../id-provider.port";
|
|
5
5
|
import type { UnitOfWork } from "../../../job-handler.strategy";
|
|
6
6
|
import { Jobs } from "../../../jobs.service";
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "../events/HOUR_HAS_PASSED_EVENT";
|
|
12
12
|
|
|
13
13
|
type Dependencies = {
|
|
14
|
-
EventStore:
|
|
14
|
+
EventStore: EventStorePort<HourHasPassedEventType>;
|
|
15
15
|
Clock: ClockPort;
|
|
16
16
|
IdProvider: IdProviderPort;
|
|
17
17
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ClockPort } from "../../../clock.port";
|
|
2
2
|
import { createEventEnvelope } from "../../../event-envelope";
|
|
3
|
-
import type {
|
|
3
|
+
import type { EventStorePort } from "../../../event-store.port";
|
|
4
4
|
import type { IdProviderPort } from "../../../id-provider.port";
|
|
5
5
|
import type { UnitOfWork } from "../../../job-handler.strategy";
|
|
6
6
|
import { Jobs } from "../../../jobs.service";
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "../events/MINUTE_HAS_PASSED_EVENT";
|
|
12
12
|
|
|
13
13
|
type Dependencies = {
|
|
14
|
-
EventStore:
|
|
14
|
+
EventStore: EventStorePort<MinuteHasPassedEventType>;
|
|
15
15
|
Clock: ClockPort;
|
|
16
16
|
IdProvider: IdProviderPort;
|
|
17
17
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ClockPort } from "./clock.port";
|
|
2
2
|
import { CorrelationStorage } from "./correlation-storage.service";
|
|
3
3
|
import { createEventEnvelope } from "./event-envelope";
|
|
4
|
-
import type {
|
|
4
|
+
import type { EventStorePort } from "./event-store.port";
|
|
5
5
|
import type { IdProviderPort } from "./id-provider.port";
|
|
6
6
|
import type { LoggerPort } from "./logger.port";
|
|
7
7
|
import {
|
|
@@ -24,7 +24,7 @@ type Dependencies = {
|
|
|
24
24
|
IdProvider: IdProviderPort;
|
|
25
25
|
Clock: ClockPort;
|
|
26
26
|
Logger: LoggerPort;
|
|
27
|
-
EventStore:
|
|
27
|
+
EventStore: EventStorePort<SecurityViolationDetectedEventType>;
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
type Config = { response: { status: number } };
|
package/src/sse-hono.handler.ts
CHANGED
|
@@ -44,7 +44,7 @@ export class SseHonoHandler<Messages extends Message> implements HandlerHonoPort
|
|
|
44
44
|
|
|
45
45
|
while (!stream.closed) {
|
|
46
46
|
await stream.sleep(this.config.keepalive.ms);
|
|
47
|
-
await stream.writeSSE({ event: "ping", data:
|
|
47
|
+
await stream.writeSSE({ event: "ping", data: JSON.stringify({ keepalive: true }) });
|
|
48
48
|
}
|
|
49
49
|
});
|
|
50
50
|
});
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type * as z from "zod/v4";
|
|
2
|
-
import type { GenericEventSchema, GenericParsedEventSchema } from "./event.types";
|
|
3
|
-
import { EventStore as BaseStore } from "./event-store";
|
|
4
|
-
import type { EventStreamType } from "./event-stream.vo";
|
|
5
|
-
import type { EventBusPort } from "./message-bus.port";
|
|
6
|
-
export declare class DispatchingEventStore<AllEvents extends GenericEventSchema> extends BaseStore<AllEvents> {
|
|
7
|
-
private readonly publisher;
|
|
8
|
-
static EMPTY_STREAM_REVISION: number;
|
|
9
|
-
constructor(config: {
|
|
10
|
-
finder: (stream: EventStreamType, names: ReadonlyArray<string>) => Promise<ReadonlyArray<z.infer<GenericEventSchema>>>;
|
|
11
|
-
inserter: (events: ReadonlyArray<z.infer<GenericParsedEventSchema>>) => Promise<ReadonlyArray<z.infer<GenericParsedEventSchema>>>;
|
|
12
|
-
}, publisher: EventBusPort<z.infer<AllEvents>>);
|
|
13
|
-
save(_events: ReadonlyArray<z.infer<AllEvents>>): Promise<ReadonlyArray<z.infer<AllEvents>>>;
|
|
14
|
-
}
|
|
15
|
-
//# sourceMappingURL=dispatching-event-store.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dispatching-event-store.d.ts","sourceRoot":"","sources":["../src/dispatching-event-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,CAAC,MAAM,QAAQ,CAAC;AACjC,OAAO,KAAK,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,UAAU,IAAI,SAAS,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,qBAAa,qBAAqB,CAAC,SAAS,SAAS,kBAAkB,CAAE,SAAQ,SAAS,CAAC,SAAS,CAAC;IAajG,OAAO,CAAC,QAAQ,CAAC,SAAS;IAZ5B,MAAM,CAAC,qBAAqB,SAAM;gBAGhC,MAAM,EAAE;QACN,MAAM,EAAE,CACN,MAAM,EAAE,eAAe,EACvB,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,KACzB,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;QACzD,QAAQ,EAAE,CACR,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,KACrD,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC;KAChE,EACgB,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAKxD,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;CAOnG"}
|