@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.
Files changed (161) hide show
  1. package/dist/event-finder-noop.adapter.d.ts +9 -0
  2. package/dist/event-finder-noop.adapter.d.ts.map +1 -0
  3. package/dist/event-finder-noop.adapter.js +10 -0
  4. package/dist/event-finder-noop.adapter.js.map +1 -0
  5. package/dist/event-finder.port.d.ts +6 -0
  6. package/dist/event-finder.port.d.ts.map +1 -0
  7. package/dist/event-finder.port.js +2 -0
  8. package/dist/event-finder.port.js.map +1 -0
  9. package/dist/event-inserter-noop.adapter.d.ts +6 -0
  10. package/dist/event-inserter-noop.adapter.d.ts.map +1 -0
  11. package/dist/event-inserter-noop.adapter.js +6 -0
  12. package/dist/event-inserter-noop.adapter.js.map +1 -0
  13. package/dist/event-inserter.port.d.ts +5 -0
  14. package/dist/event-inserter.port.d.ts.map +1 -0
  15. package/dist/event-inserter.port.js +2 -0
  16. package/dist/event-inserter.port.js.map +1 -0
  17. package/dist/event-revision-assigner.adapter.d.ts +7 -0
  18. package/dist/event-revision-assigner.adapter.d.ts.map +1 -0
  19. package/dist/event-revision-assigner.adapter.js +7 -0
  20. package/dist/event-revision-assigner.adapter.js.map +1 -0
  21. package/dist/event-revision-assigner.port.d.ts +5 -0
  22. package/dist/event-revision-assigner.port.d.ts.map +1 -0
  23. package/dist/event-revision-assigner.port.js +2 -0
  24. package/dist/event-revision-assigner.port.js.map +1 -0
  25. package/dist/event-serializer-collecting.adapter.d.ts +8 -0
  26. package/dist/event-serializer-collecting.adapter.d.ts.map +1 -0
  27. package/dist/event-serializer-collecting.adapter.js +13 -0
  28. package/dist/event-serializer-collecting.adapter.js.map +1 -0
  29. package/dist/event-serializer-json.adapter.d.ts +6 -0
  30. package/dist/event-serializer-json.adapter.d.ts.map +1 -0
  31. package/dist/event-serializer-json.adapter.js +9 -0
  32. package/dist/event-serializer-json.adapter.js.map +1 -0
  33. package/dist/event-serializer.port.d.ts +5 -0
  34. package/dist/event-serializer.port.d.ts.map +1 -0
  35. package/dist/event-serializer.port.js +2 -0
  36. package/dist/event-serializer.port.js.map +1 -0
  37. package/dist/event-store-collecting.adapter.d.ts +10 -0
  38. package/dist/event-store-collecting.adapter.d.ts.map +1 -0
  39. package/dist/event-store-collecting.adapter.js +11 -0
  40. package/dist/event-store-collecting.adapter.js.map +1 -0
  41. package/dist/event-store-dispatching.adapter.d.ts +17 -0
  42. package/dist/event-store-dispatching.adapter.d.ts.map +1 -0
  43. package/dist/event-store-dispatching.adapter.js +15 -0
  44. package/dist/event-store-dispatching.adapter.js.map +1 -0
  45. package/dist/event-store-noop.adapter.d.ts +9 -0
  46. package/dist/event-store-noop.adapter.d.ts.map +1 -0
  47. package/dist/event-store-noop.adapter.js +9 -0
  48. package/dist/event-store-noop.adapter.js.map +1 -0
  49. package/dist/event-store.adapter.d.ts +20 -0
  50. package/dist/event-store.adapter.d.ts.map +1 -0
  51. package/dist/event-store.adapter.js +27 -0
  52. package/dist/event-store.adapter.js.map +1 -0
  53. package/dist/event-store.port.d.ts +8 -0
  54. package/dist/event-store.port.d.ts.map +1 -0
  55. package/dist/event-store.port.js +2 -0
  56. package/dist/event-store.port.js.map +1 -0
  57. package/dist/event-validator-registry-zod.adapter.d.ts +24 -0
  58. package/dist/event-validator-registry-zod.adapter.d.ts.map +1 -0
  59. package/dist/event-validator-registry-zod.adapter.js +25 -0
  60. package/dist/event-validator-registry-zod.adapter.js.map +1 -0
  61. package/dist/event-validator-registry.port.d.ts +7 -0
  62. package/dist/event-validator-registry.port.d.ts.map +1 -0
  63. package/dist/event-validator-registry.port.js +2 -0
  64. package/dist/event-validator-registry.port.js.map +1 -0
  65. package/dist/event.types.d.ts +13 -14
  66. package/dist/event.types.d.ts.map +1 -1
  67. package/dist/index.d.ts +21 -7
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +21 -7
  70. package/dist/index.js.map +1 -1
  71. package/dist/message-handler-bare.strategy.d.ts +8 -0
  72. package/dist/message-handler-bare.strategy.d.ts.map +1 -0
  73. package/dist/message-handler-bare.strategy.js +8 -0
  74. package/dist/message-handler-bare.strategy.js.map +1 -0
  75. package/dist/message-handler-noop.strategy.d.ts +8 -0
  76. package/dist/message-handler-noop.strategy.d.ts.map +1 -0
  77. package/dist/message-handler-noop.strategy.js +8 -0
  78. package/dist/message-handler-noop.strategy.js.map +1 -0
  79. package/dist/message-handler-with-logger.strategy.d.ts +17 -0
  80. package/dist/message-handler-with-logger.strategy.d.ts.map +1 -0
  81. package/dist/message-handler-with-logger.strategy.js +27 -0
  82. package/dist/message-handler-with-logger.strategy.js.map +1 -0
  83. package/dist/message-handler.strategy.d.ts +7 -0
  84. package/dist/message-handler.strategy.d.ts.map +1 -0
  85. package/dist/message-handler.strategy.js +2 -0
  86. package/dist/message-handler.strategy.js.map +1 -0
  87. package/dist/modules/preferences/command-handlers/handleSetUserLanguageCommand.d.ts +2 -2
  88. package/dist/modules/preferences/command-handlers/handleSetUserLanguageCommand.d.ts.map +1 -1
  89. package/dist/modules/system/services/passage-of-time-hourly.service.d.ts +2 -2
  90. package/dist/modules/system/services/passage-of-time-hourly.service.d.ts.map +1 -1
  91. package/dist/modules/system/services/passage-of-time-minute.service.d.ts +2 -2
  92. package/dist/modules/system/services/passage-of-time-minute.service.d.ts.map +1 -1
  93. package/dist/security-countermeasure-ban.strategy.d.ts +2 -2
  94. package/dist/security-countermeasure-ban.strategy.d.ts.map +1 -1
  95. package/dist/sse-hono.handler.js +1 -1
  96. package/dist/sse-hono.handler.js.map +1 -1
  97. package/dist/tsconfig.tsbuildinfo +1 -1
  98. package/package.json +5 -5
  99. package/readme.md +20 -7
  100. package/src/event-finder-noop.adapter.ts +14 -0
  101. package/src/event-finder.port.ts +9 -0
  102. package/src/event-inserter-noop.adapter.ts +10 -0
  103. package/src/event-inserter.port.ts +5 -0
  104. package/src/event-revision-assigner.adapter.ts +13 -0
  105. package/src/event-revision-assigner.port.ts +8 -0
  106. package/src/event-serializer-collecting.adapter.ts +19 -0
  107. package/src/event-serializer-json.adapter.ts +11 -0
  108. package/src/event-serializer.port.ts +4 -0
  109. package/src/event-store-collecting.adapter.ts +21 -0
  110. package/src/event-store-dispatching.adapter.ts +29 -0
  111. package/src/event-store-noop.adapter.ts +17 -0
  112. package/src/event-store.adapter.ts +49 -0
  113. package/src/event-store.port.ts +12 -0
  114. package/src/event-validator-registry-zod.adapter.ts +47 -0
  115. package/src/event-validator-registry.port.ts +7 -0
  116. package/src/event.types.ts +12 -15
  117. package/src/index.ts +21 -7
  118. package/src/message-handler-bare.strategy.ts +11 -0
  119. package/src/message-handler-noop.strategy.ts +11 -0
  120. package/src/message-handler-with-logger.strategy.ts +32 -0
  121. package/src/message-handler.strategy.ts +8 -0
  122. package/src/modules/preferences/command-handlers/handleSetUserLanguageCommand.ts +2 -2
  123. package/src/modules/system/services/passage-of-time-hourly.service.ts +2 -2
  124. package/src/modules/system/services/passage-of-time-minute.service.ts +2 -2
  125. package/src/security-countermeasure-ban.strategy.ts +2 -2
  126. package/src/sse-hono.handler.ts +1 -1
  127. package/dist/dispatching-event-store.d.ts +0 -15
  128. package/dist/dispatching-event-store.d.ts.map +0 -1
  129. package/dist/dispatching-event-store.js +0 -16
  130. package/dist/dispatching-event-store.js.map +0 -1
  131. package/dist/event-handler-bare.strategy.d.ts +0 -6
  132. package/dist/event-handler-bare.strategy.d.ts.map +0 -1
  133. package/dist/event-handler-bare.strategy.js +0 -6
  134. package/dist/event-handler-bare.strategy.js.map +0 -1
  135. package/dist/event-handler-noop.strategy.d.ts +0 -6
  136. package/dist/event-handler-noop.strategy.d.ts.map +0 -1
  137. package/dist/event-handler-noop.strategy.js +0 -6
  138. package/dist/event-handler-noop.strategy.js.map +0 -1
  139. package/dist/event-handler-with-logger.strategy.d.ts +0 -15
  140. package/dist/event-handler-with-logger.strategy.d.ts.map +0 -1
  141. package/dist/event-handler-with-logger.strategy.js +0 -25
  142. package/dist/event-handler-with-logger.strategy.js.map +0 -1
  143. package/dist/event-handler.strategy.d.ts +0 -5
  144. package/dist/event-handler.strategy.d.ts.map +0 -1
  145. package/dist/event-handler.strategy.js +0 -2
  146. package/dist/event-handler.strategy.js.map +0 -1
  147. package/dist/event-store-like.types.d.ts +0 -5
  148. package/dist/event-store-like.types.d.ts.map +0 -1
  149. package/dist/event-store-like.types.js +0 -2
  150. package/dist/event-store-like.types.js.map +0 -1
  151. package/dist/event-store.d.ts +0 -22
  152. package/dist/event-store.d.ts.map +0 -1
  153. package/dist/event-store.js +0 -37
  154. package/dist/event-store.js.map +0 -1
  155. package/src/dispatching-event-store.ts +0 -34
  156. package/src/event-handler-bare.strategy.ts +0 -8
  157. package/src/event-handler-noop.strategy.ts +0 -8
  158. package/src/event-handler-with-logger.strategy.ts +0 -29
  159. package/src/event-handler.strategy.ts +0 -5
  160. package/src/event-store-like.types.ts +0 -5
  161. 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.13.0",
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.6",
24
- "@commitlint/cli": "20.4.4",
25
- "@commitlint/config-conventional": "20.4.4",
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.7",
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-handler-bare.strategy.ts
117
- ├── event-handler-noop.strategy.ts
118
- ├── event-handler-with-logger.strategy.ts
119
- ├── event-handler.strategy.ts
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-store-like.types.ts
123
- ├── event-store.ts
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,5 @@
1
+ import type { GenericEventSerialized } from "./event.types";
2
+
3
+ export interface EventInserterPort {
4
+ insert(events: ReadonlyArray<GenericEventSerialized>): Promise<ReadonlyArray<GenericEventSerialized>>;
5
+ }
@@ -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,8 @@
1
+ import type { GenericEventSerialized } from "./event.types";
2
+
3
+ export interface EventRevisionAssignerPort {
4
+ assign(
5
+ events: ReadonlyArray<GenericEventSerialized>,
6
+ currentMax: number,
7
+ ): ReadonlyArray<GenericEventSerialized>;
8
+ }
@@ -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,4 @@
1
+ export interface EventSerializerPort {
2
+ serialize(payload: unknown): string;
3
+ deserialize(raw: string): unknown;
4
+ }
@@ -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
+ }
@@ -0,0 +1,7 @@
1
+ import type { GenericEvent } from "./event.types";
2
+
3
+ export interface EventValidatorRegistryPort<TEvent> {
4
+ readonly names: ReadonlyArray<GenericEvent["name"]>;
5
+ accepts(name: GenericEvent["name"]): boolean;
6
+ validate(raw: unknown): TEvent;
7
+ }
@@ -1,16 +1,13 @@
1
- import type * as z from "zod/v4";
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 GenericEventSchema = z.ZodObject<{
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-handler.strategy";
89
- export * from "./event-handler-bare.strategy";
90
- export * from "./event-handler-noop.strategy";
91
- export * from "./event-handler-with-logger.strategy";
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-store";
95
- export * from "./event-store-like.types";
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 { EventStoreLike } from "../../../event-store-like.types";
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: EventStoreLike<AcceptedEvent>;
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 { EventStoreLike } from "../../../event-store-like.types";
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: EventStoreLike<HourHasPassedEventType>;
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 { EventStoreLike } from "../../../event-store-like.types";
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: EventStoreLike<MinuteHasPassedEventType>;
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 { EventStoreLike } from "./event-store-like.types";
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: EventStoreLike<SecurityViolationDetectedEventType>;
27
+ EventStore: EventStorePort<SecurityViolationDetectedEventType>;
28
28
  };
29
29
 
30
30
  type Config = { response: { status: number } };
@@ -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"}