@signaltree/events 7.3.5 → 7.4.0

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 (54) hide show
  1. package/dist/angular/handlers.cjs +38 -0
  2. package/dist/angular/handlers.js +35 -0
  3. package/dist/angular/index.cjs +15 -0
  4. package/dist/angular/index.js +3 -0
  5. package/dist/angular/optimistic-updates.cjs +161 -0
  6. package/dist/angular/optimistic-updates.js +159 -0
  7. package/dist/angular/websocket.service.cjs +357 -0
  8. package/{angular.esm.js → dist/angular/websocket.service.js} +1 -191
  9. package/dist/core/error-classification.cjs +282 -0
  10. package/dist/core/error-classification.js +276 -0
  11. package/dist/core/factory.cjs +148 -0
  12. package/{factory.esm.js → dist/core/factory.js} +2 -37
  13. package/dist/core/idempotency.cjs +252 -0
  14. package/dist/core/idempotency.js +247 -0
  15. package/dist/core/registry.cjs +183 -0
  16. package/dist/core/registry.js +180 -0
  17. package/dist/core/types.cjs +41 -0
  18. package/dist/core/types.js +38 -0
  19. package/dist/core/validation.cjs +185 -0
  20. package/{index.esm.js → dist/core/validation.js} +1 -4
  21. package/dist/index.cjs +43 -0
  22. package/dist/index.js +7 -0
  23. package/dist/nestjs/base.subscriber.cjs +287 -0
  24. package/dist/nestjs/base.subscriber.js +287 -0
  25. package/dist/nestjs/decorators.cjs +35 -0
  26. package/dist/nestjs/decorators.js +32 -0
  27. package/dist/nestjs/dlq.service.cjs +249 -0
  28. package/dist/nestjs/dlq.service.js +249 -0
  29. package/dist/nestjs/event-bus.module.cjs +152 -0
  30. package/dist/nestjs/event-bus.module.js +152 -0
  31. package/dist/nestjs/event-bus.service.cjs +243 -0
  32. package/dist/nestjs/event-bus.service.js +243 -0
  33. package/dist/nestjs/index.cjs +33 -0
  34. package/dist/nestjs/index.js +6 -0
  35. package/dist/nestjs/tokens.cjs +14 -0
  36. package/dist/nestjs/tokens.js +9 -0
  37. package/dist/testing/assertions.cjs +172 -0
  38. package/dist/testing/assertions.js +169 -0
  39. package/dist/testing/factories.cjs +122 -0
  40. package/dist/testing/factories.js +119 -0
  41. package/dist/testing/helpers.cjs +233 -0
  42. package/dist/testing/helpers.js +227 -0
  43. package/dist/testing/index.cjs +20 -0
  44. package/dist/testing/index.js +4 -0
  45. package/dist/testing/mock-event-bus.cjs +237 -0
  46. package/dist/testing/mock-event-bus.js +234 -0
  47. package/package.json +22 -22
  48. package/angular.d.ts +0 -1
  49. package/idempotency.esm.js +0 -701
  50. package/index.d.ts +0 -1
  51. package/nestjs.d.ts +0 -1
  52. package/nestjs.esm.js +0 -944
  53. package/testing.d.ts +0 -1
  54. package/testing.esm.js +0 -743
@@ -0,0 +1,237 @@
1
+ 'use strict';
2
+
3
+ var factory = require('../core/factory.cjs');
4
+
5
+ /**
6
+ * Mock Event Bus for testing
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const eventBus = createMockEventBus();
11
+ *
12
+ * // Subscribe to events
13
+ * eventBus.subscribe('TradeProposalCreated', (event) => {
14
+ * expect(event.data.tradeId).toBe('123');
15
+ * });
16
+ *
17
+ * // Publish an event
18
+ * await eventBus.publish({
19
+ * type: 'TradeProposalCreated',
20
+ * data: { tradeId: '123' },
21
+ * });
22
+ *
23
+ * // Assert published events
24
+ * expect(eventBus.getPublishedEvents()).toHaveLength(1);
25
+ * expect(eventBus.wasPublished('TradeProposalCreated')).toBe(true);
26
+ * ```
27
+ */
28
+ class MockEventBus {
29
+ options;
30
+ publishedEvents = [];
31
+ subscriptions = new Map();
32
+ allSubscriptions = new Set();
33
+ constructor(options = {}) {
34
+ this.options = options;
35
+ this.options = {
36
+ simulateAsync: false,
37
+ asyncDelayMs: 10,
38
+ autoGenerateIds: true,
39
+ throwOnError: false,
40
+ ...options
41
+ };
42
+ }
43
+ /**
44
+ * Publish an event
45
+ */
46
+ async publish(event, options) {
47
+ // Complete the event
48
+ const fullEvent = {
49
+ ...event,
50
+ id: event.id ?? (this.options.autoGenerateIds ? factory.generateEventId() : 'test-event-id'),
51
+ timestamp: event.timestamp ?? new Date().toISOString(),
52
+ correlationId: event.correlationId ?? factory.generateCorrelationId()
53
+ };
54
+ const queue = options?.queue ?? this.getQueueForPriority(fullEvent.priority);
55
+ // Record the published event
56
+ this.publishedEvents.push({
57
+ event: fullEvent,
58
+ queue,
59
+ publishedAt: new Date(),
60
+ delay: options?.delay
61
+ });
62
+ // Simulate async if configured
63
+ if (this.options.simulateAsync) {
64
+ await this.delay(this.options.asyncDelayMs ?? 10);
65
+ }
66
+ // Notify subscribers
67
+ await this.notifySubscribers(fullEvent);
68
+ return {
69
+ eventId: fullEvent.id,
70
+ queue
71
+ };
72
+ }
73
+ /**
74
+ * Publish multiple events
75
+ */
76
+ async publishBatch(events, options) {
77
+ const correlationId = factory.generateCorrelationId();
78
+ return Promise.all(events.map(event => this.publish({
79
+ ...event,
80
+ correlationId
81
+ }, {
82
+ ...options
83
+ })));
84
+ }
85
+ /**
86
+ * Subscribe to a specific event type
87
+ */
88
+ subscribe(eventType, handler) {
89
+ let handlers = this.subscriptions.get(eventType);
90
+ if (!handlers) {
91
+ handlers = new Set();
92
+ this.subscriptions.set(eventType, handlers);
93
+ }
94
+ handlers.add(handler);
95
+ // Return unsubscribe function
96
+ // handlers is guaranteed to exist at this point since we just set it above
97
+ return () => {
98
+ const h = this.subscriptions.get(eventType);
99
+ if (h) {
100
+ h.delete(handler);
101
+ }
102
+ };
103
+ }
104
+ /**
105
+ * Subscribe to all events
106
+ */
107
+ subscribeAll(handler) {
108
+ this.allSubscriptions.add(handler);
109
+ return () => {
110
+ this.allSubscriptions.delete(handler);
111
+ };
112
+ }
113
+ /**
114
+ * Get all published events
115
+ */
116
+ getPublishedEvents() {
117
+ return [...this.publishedEvents];
118
+ }
119
+ /**
120
+ * Get published events by type
121
+ */
122
+ getPublishedEventsByType(type) {
123
+ return this.publishedEvents.filter(p => p.event.type === type);
124
+ }
125
+ /**
126
+ * Get the last published event
127
+ */
128
+ getLastPublishedEvent() {
129
+ return this.publishedEvents[this.publishedEvents.length - 1];
130
+ }
131
+ /**
132
+ * Get the last published event of a specific type
133
+ */
134
+ getLastPublishedEventByType(type) {
135
+ const events = this.getPublishedEventsByType(type);
136
+ return events[events.length - 1];
137
+ }
138
+ /**
139
+ * Check if an event type was published
140
+ */
141
+ wasPublished(eventType) {
142
+ return this.publishedEvents.some(p => p.event.type === eventType);
143
+ }
144
+ /**
145
+ * Check if an event with specific data was published
146
+ */
147
+ wasPublishedWith(eventType, predicate) {
148
+ return this.publishedEvents.some(p => p.event.type === eventType && predicate(p.event));
149
+ }
150
+ /**
151
+ * Get count of published events
152
+ */
153
+ getPublishedCount(eventType) {
154
+ if (eventType) {
155
+ return this.publishedEvents.filter(p => p.event.type === eventType).length;
156
+ }
157
+ return this.publishedEvents.length;
158
+ }
159
+ /**
160
+ * Clear all published events (for test cleanup)
161
+ */
162
+ clearHistory() {
163
+ this.publishedEvents = [];
164
+ }
165
+ /**
166
+ * Clear all subscriptions
167
+ */
168
+ clearSubscriptions() {
169
+ this.subscriptions.clear();
170
+ this.allSubscriptions.clear();
171
+ }
172
+ /**
173
+ * Reset the mock (clear history and subscriptions)
174
+ */
175
+ reset() {
176
+ this.clearHistory();
177
+ this.clearSubscriptions();
178
+ }
179
+ /**
180
+ * Simulate an incoming event (as if received from server)
181
+ */
182
+ async simulateIncomingEvent(event) {
183
+ await this.notifySubscribers(event);
184
+ }
185
+ // Private methods
186
+ async notifySubscribers(event) {
187
+ const errors = [];
188
+ // Notify type-specific subscribers
189
+ const handlers = this.subscriptions.get(event.type);
190
+ if (handlers) {
191
+ for (const handler of handlers) {
192
+ try {
193
+ await handler(event);
194
+ } catch (error) {
195
+ errors.push(error instanceof Error ? error : new Error(String(error)));
196
+ }
197
+ }
198
+ }
199
+ // Notify all-event subscribers
200
+ for (const handler of this.allSubscriptions) {
201
+ try {
202
+ await handler(event);
203
+ } catch (error) {
204
+ errors.push(error instanceof Error ? error : new Error(String(error)));
205
+ }
206
+ }
207
+ if (errors.length > 0 && this.options.throwOnError) {
208
+ throw new AggregateError(errors, 'Subscriber errors');
209
+ }
210
+ }
211
+ getQueueForPriority(priority) {
212
+ switch (priority) {
213
+ case 'critical':
214
+ return 'events-critical';
215
+ case 'high':
216
+ return 'events-high';
217
+ case 'low':
218
+ return 'events-low';
219
+ case 'bulk':
220
+ return 'events-bulk';
221
+ default:
222
+ return 'events-normal';
223
+ }
224
+ }
225
+ delay(ms) {
226
+ return new Promise(resolve => setTimeout(resolve, ms));
227
+ }
228
+ }
229
+ /**
230
+ * Create a mock event bus for testing
231
+ */
232
+ function createMockEventBus(options) {
233
+ return new MockEventBus(options);
234
+ }
235
+
236
+ exports.MockEventBus = MockEventBus;
237
+ exports.createMockEventBus = createMockEventBus;
@@ -0,0 +1,234 @@
1
+ import { generateCorrelationId, generateEventId } from '../core/factory.js';
2
+
3
+ /**
4
+ * Mock Event Bus for testing
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * const eventBus = createMockEventBus();
9
+ *
10
+ * // Subscribe to events
11
+ * eventBus.subscribe('TradeProposalCreated', (event) => {
12
+ * expect(event.data.tradeId).toBe('123');
13
+ * });
14
+ *
15
+ * // Publish an event
16
+ * await eventBus.publish({
17
+ * type: 'TradeProposalCreated',
18
+ * data: { tradeId: '123' },
19
+ * });
20
+ *
21
+ * // Assert published events
22
+ * expect(eventBus.getPublishedEvents()).toHaveLength(1);
23
+ * expect(eventBus.wasPublished('TradeProposalCreated')).toBe(true);
24
+ * ```
25
+ */
26
+ class MockEventBus {
27
+ options;
28
+ publishedEvents = [];
29
+ subscriptions = new Map();
30
+ allSubscriptions = new Set();
31
+ constructor(options = {}) {
32
+ this.options = options;
33
+ this.options = {
34
+ simulateAsync: false,
35
+ asyncDelayMs: 10,
36
+ autoGenerateIds: true,
37
+ throwOnError: false,
38
+ ...options
39
+ };
40
+ }
41
+ /**
42
+ * Publish an event
43
+ */
44
+ async publish(event, options) {
45
+ // Complete the event
46
+ const fullEvent = {
47
+ ...event,
48
+ id: event.id ?? (this.options.autoGenerateIds ? generateEventId() : 'test-event-id'),
49
+ timestamp: event.timestamp ?? new Date().toISOString(),
50
+ correlationId: event.correlationId ?? generateCorrelationId()
51
+ };
52
+ const queue = options?.queue ?? this.getQueueForPriority(fullEvent.priority);
53
+ // Record the published event
54
+ this.publishedEvents.push({
55
+ event: fullEvent,
56
+ queue,
57
+ publishedAt: new Date(),
58
+ delay: options?.delay
59
+ });
60
+ // Simulate async if configured
61
+ if (this.options.simulateAsync) {
62
+ await this.delay(this.options.asyncDelayMs ?? 10);
63
+ }
64
+ // Notify subscribers
65
+ await this.notifySubscribers(fullEvent);
66
+ return {
67
+ eventId: fullEvent.id,
68
+ queue
69
+ };
70
+ }
71
+ /**
72
+ * Publish multiple events
73
+ */
74
+ async publishBatch(events, options) {
75
+ const correlationId = generateCorrelationId();
76
+ return Promise.all(events.map(event => this.publish({
77
+ ...event,
78
+ correlationId
79
+ }, {
80
+ ...options
81
+ })));
82
+ }
83
+ /**
84
+ * Subscribe to a specific event type
85
+ */
86
+ subscribe(eventType, handler) {
87
+ let handlers = this.subscriptions.get(eventType);
88
+ if (!handlers) {
89
+ handlers = new Set();
90
+ this.subscriptions.set(eventType, handlers);
91
+ }
92
+ handlers.add(handler);
93
+ // Return unsubscribe function
94
+ // handlers is guaranteed to exist at this point since we just set it above
95
+ return () => {
96
+ const h = this.subscriptions.get(eventType);
97
+ if (h) {
98
+ h.delete(handler);
99
+ }
100
+ };
101
+ }
102
+ /**
103
+ * Subscribe to all events
104
+ */
105
+ subscribeAll(handler) {
106
+ this.allSubscriptions.add(handler);
107
+ return () => {
108
+ this.allSubscriptions.delete(handler);
109
+ };
110
+ }
111
+ /**
112
+ * Get all published events
113
+ */
114
+ getPublishedEvents() {
115
+ return [...this.publishedEvents];
116
+ }
117
+ /**
118
+ * Get published events by type
119
+ */
120
+ getPublishedEventsByType(type) {
121
+ return this.publishedEvents.filter(p => p.event.type === type);
122
+ }
123
+ /**
124
+ * Get the last published event
125
+ */
126
+ getLastPublishedEvent() {
127
+ return this.publishedEvents[this.publishedEvents.length - 1];
128
+ }
129
+ /**
130
+ * Get the last published event of a specific type
131
+ */
132
+ getLastPublishedEventByType(type) {
133
+ const events = this.getPublishedEventsByType(type);
134
+ return events[events.length - 1];
135
+ }
136
+ /**
137
+ * Check if an event type was published
138
+ */
139
+ wasPublished(eventType) {
140
+ return this.publishedEvents.some(p => p.event.type === eventType);
141
+ }
142
+ /**
143
+ * Check if an event with specific data was published
144
+ */
145
+ wasPublishedWith(eventType, predicate) {
146
+ return this.publishedEvents.some(p => p.event.type === eventType && predicate(p.event));
147
+ }
148
+ /**
149
+ * Get count of published events
150
+ */
151
+ getPublishedCount(eventType) {
152
+ if (eventType) {
153
+ return this.publishedEvents.filter(p => p.event.type === eventType).length;
154
+ }
155
+ return this.publishedEvents.length;
156
+ }
157
+ /**
158
+ * Clear all published events (for test cleanup)
159
+ */
160
+ clearHistory() {
161
+ this.publishedEvents = [];
162
+ }
163
+ /**
164
+ * Clear all subscriptions
165
+ */
166
+ clearSubscriptions() {
167
+ this.subscriptions.clear();
168
+ this.allSubscriptions.clear();
169
+ }
170
+ /**
171
+ * Reset the mock (clear history and subscriptions)
172
+ */
173
+ reset() {
174
+ this.clearHistory();
175
+ this.clearSubscriptions();
176
+ }
177
+ /**
178
+ * Simulate an incoming event (as if received from server)
179
+ */
180
+ async simulateIncomingEvent(event) {
181
+ await this.notifySubscribers(event);
182
+ }
183
+ // Private methods
184
+ async notifySubscribers(event) {
185
+ const errors = [];
186
+ // Notify type-specific subscribers
187
+ const handlers = this.subscriptions.get(event.type);
188
+ if (handlers) {
189
+ for (const handler of handlers) {
190
+ try {
191
+ await handler(event);
192
+ } catch (error) {
193
+ errors.push(error instanceof Error ? error : new Error(String(error)));
194
+ }
195
+ }
196
+ }
197
+ // Notify all-event subscribers
198
+ for (const handler of this.allSubscriptions) {
199
+ try {
200
+ await handler(event);
201
+ } catch (error) {
202
+ errors.push(error instanceof Error ? error : new Error(String(error)));
203
+ }
204
+ }
205
+ if (errors.length > 0 && this.options.throwOnError) {
206
+ throw new AggregateError(errors, 'Subscriber errors');
207
+ }
208
+ }
209
+ getQueueForPriority(priority) {
210
+ switch (priority) {
211
+ case 'critical':
212
+ return 'events-critical';
213
+ case 'high':
214
+ return 'events-high';
215
+ case 'low':
216
+ return 'events-low';
217
+ case 'bulk':
218
+ return 'events-bulk';
219
+ default:
220
+ return 'events-normal';
221
+ }
222
+ }
223
+ delay(ms) {
224
+ return new Promise(resolve => setTimeout(resolve, ms));
225
+ }
226
+ }
227
+ /**
228
+ * Create a mock event bus for testing
229
+ */
230
+ function createMockEventBus(options) {
231
+ return new MockEventBus(options);
232
+ }
233
+
234
+ export { MockEventBus, createMockEventBus };
package/package.json CHANGED
@@ -1,37 +1,37 @@
1
1
  {
2
2
  "name": "@signaltree/events",
3
- "version": "7.3.5",
3
+ "version": "7.4.0",
4
4
  "description": "Event-driven architecture infrastructure for SignalTree - event bus, subscribers, validation, and real-time sync",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "sideEffects": false,
8
- "main": "./index.cjs.js",
8
+ "main": "./dist/index.cjs",
9
9
  "module": "./index.esm.js",
10
- "types": "./index.d.ts",
10
+ "types": "./src/index.d.ts",
11
11
  "exports": {
12
12
  ".": {
13
- "types": "./index.d.ts",
14
- "import": "./index.esm.js",
15
- "require": "./index.cjs.js",
16
- "default": "./index.esm.js"
13
+ "types": "./src/index.d.ts",
14
+ "import": "./dist/index.js",
15
+ "require": "./dist/index.cjs",
16
+ "default": "./dist/index.js"
17
17
  },
18
18
  "./nestjs": {
19
- "types": "./nestjs.d.ts",
20
- "import": "./nestjs.esm.js",
21
- "require": "./nestjs.cjs.js",
22
- "default": "./nestjs.esm.js"
19
+ "types": "./src/nestjs/index.d.ts",
20
+ "import": "./dist/nestjs/index.js",
21
+ "require": "./dist/nestjs/index.cjs",
22
+ "default": "./dist/nestjs/index.js"
23
23
  },
24
24
  "./angular": {
25
- "types": "./angular.d.ts",
26
- "import": "./angular.esm.js",
27
- "require": "./angular.cjs.js",
28
- "default": "./angular.esm.js"
25
+ "types": "./src/angular/index.d.ts",
26
+ "import": "./dist/angular/index.js",
27
+ "require": "./dist/angular/index.cjs",
28
+ "default": "./dist/angular/index.js"
29
29
  },
30
30
  "./testing": {
31
- "types": "./testing.d.ts",
32
- "import": "./testing.esm.js",
33
- "require": "./testing.cjs.js",
34
- "default": "./testing.esm.js"
31
+ "types": "./src/testing/index.d.ts",
32
+ "import": "./dist/testing/index.js",
33
+ "require": "./dist/testing/index.cjs",
34
+ "default": "./dist/testing/index.js"
35
35
  },
36
36
  "./package.json": "./package.json"
37
37
  },
@@ -89,8 +89,8 @@
89
89
  "access": "public"
90
90
  },
91
91
  "files": [
92
- "*.esm.js",
93
- "*.d.ts",
92
+ "dist/**/*.js",
93
+ "dist/**/*.cjs",
94
94
  "src/**/*.d.ts",
95
95
  "README.md"
96
96
  ],
@@ -115,4 +115,4 @@
115
115
  "url": "https://github.com/JBorgia/signaltree/issues"
116
116
  },
117
117
  "homepage": "https://github.com/JBorgia/signaltree/tree/main/packages/events#readme"
118
- }
118
+ }
package/angular.d.ts DELETED
@@ -1 +0,0 @@
1
- export * from "./src/angular";