@amadeus-it-group/ngrx-devtool 0.1.3 → 0.2.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.
- package/ngrx-devtool/fesm2022/amadeus-it-group-ngrx-devtool.mjs +68 -29
- package/ngrx-devtool/fesm2022/amadeus-it-group-ngrx-devtool.mjs.map +1 -1
- package/ngrx-devtool/types/amadeus-it-group-ngrx-devtool.d.ts +7 -3
- package/ngrx-devtool-ui/browser/index.html +1 -1
- package/ngrx-devtool-ui/browser/main-KY6E46FI.js +249 -0
- package/package.json +4 -1
- package/ngrx-devtool-ui/browser/main-EDJFMLO7.js +0 -249
|
@@ -6,6 +6,8 @@ import { takeUntil, tap as tap$1 } from 'rxjs/operators';
|
|
|
6
6
|
import { isPlatformBrowser } from '@angular/common';
|
|
7
7
|
import { createSelector } from '@ngrx/store';
|
|
8
8
|
|
|
9
|
+
const DEFAULT_WS_URL = 'ws://localhost:4000';
|
|
10
|
+
|
|
9
11
|
const REPLAY_BUFFER_SIZE$1 = 100;
|
|
10
12
|
const TIMELINE_MAX_SIZE = 1000;
|
|
11
13
|
const TIMELINE_TRIM_SIZE = 500;
|
|
@@ -17,7 +19,7 @@ class EffectTrackerService {
|
|
|
17
19
|
actionTimeline = [];
|
|
18
20
|
effectTimeline = [];
|
|
19
21
|
effectActionPatterns = new Set();
|
|
20
|
-
pendingCorrelations =
|
|
22
|
+
pendingCorrelations = [];
|
|
21
23
|
correlationCounter = 0;
|
|
22
24
|
lastTriggerAction = null;
|
|
23
25
|
effectEvents$ = new ReplaySubject(REPLAY_BUFFER_SIZE$1);
|
|
@@ -80,8 +82,12 @@ class EffectTrackerService {
|
|
|
80
82
|
if (!isEffect) {
|
|
81
83
|
this.lastTriggerAction = action;
|
|
82
84
|
}
|
|
85
|
+
// Resolve trigger action type to match the correct correlation.
|
|
86
|
+
const triggerActionType = isEffect
|
|
87
|
+
? this.findTriggerActionType(action.type)
|
|
88
|
+
: undefined;
|
|
83
89
|
const correlationId = isEffect
|
|
84
|
-
? this.
|
|
90
|
+
? this.consumeCorrelation(triggerActionType)
|
|
85
91
|
: this.createCorrelation(action);
|
|
86
92
|
const effectName = this.findEffectNameForAction(action.type);
|
|
87
93
|
const tracked = {
|
|
@@ -103,22 +109,48 @@ class EffectTrackerService {
|
|
|
103
109
|
}
|
|
104
110
|
clearTimeline() {
|
|
105
111
|
this.actionTimeline = [];
|
|
106
|
-
this.
|
|
112
|
+
this.clearPendingCorrelations();
|
|
107
113
|
}
|
|
108
114
|
createCorrelation(action) {
|
|
109
115
|
const correlationId = `corr_${++this.correlationCounter}_${Date.now()}`;
|
|
110
|
-
|
|
111
|
-
|
|
116
|
+
const timeoutId = setTimeout(() => {
|
|
117
|
+
this.pendingCorrelations = this.pendingCorrelations.filter(c => c.correlationId !== correlationId);
|
|
118
|
+
}, CORRELATION_TIMEOUT_MS);
|
|
119
|
+
this.pendingCorrelations.push({
|
|
120
|
+
correlationId,
|
|
121
|
+
actionType: action.type,
|
|
112
122
|
timestamp: Date.now(),
|
|
123
|
+
timeoutId,
|
|
113
124
|
});
|
|
114
|
-
setTimeout(() => {
|
|
115
|
-
this.pendingCorrelations.delete(correlationId);
|
|
116
|
-
}, CORRELATION_TIMEOUT_MS);
|
|
117
125
|
return correlationId;
|
|
118
126
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
127
|
+
// Find and consume the best-matching pending correlation (by trigger type, then FIFO fallback).
|
|
128
|
+
consumeCorrelation(triggerActionType) {
|
|
129
|
+
let idx = -1;
|
|
130
|
+
// Prefer matching by trigger action type (oldest match first)
|
|
131
|
+
if (triggerActionType) {
|
|
132
|
+
idx = this.pendingCorrelations.findIndex(c => c.actionType === triggerActionType);
|
|
133
|
+
}
|
|
134
|
+
// Fallback: oldest pending correlation (FIFO)
|
|
135
|
+
if (idx === -1 && this.pendingCorrelations.length > 0) {
|
|
136
|
+
idx = 0;
|
|
137
|
+
}
|
|
138
|
+
if (idx === -1) {
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
const [entry] = this.pendingCorrelations.splice(idx, 1);
|
|
142
|
+
clearTimeout(entry.timeoutId);
|
|
143
|
+
return entry.correlationId;
|
|
144
|
+
}
|
|
145
|
+
// Resolve which user action type triggered a given effect-result action type.
|
|
146
|
+
findTriggerActionType(effectActionType) {
|
|
147
|
+
for (let i = this.effectTimeline.length - 1; i >= Math.max(0, this.effectTimeline.length - 10); i--) {
|
|
148
|
+
const effect = this.effectTimeline[i];
|
|
149
|
+
if (effect.resultAction === effectActionType && effect.triggerAction) {
|
|
150
|
+
return effect.triggerAction;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return undefined;
|
|
122
154
|
}
|
|
123
155
|
findEffectNameForAction(actionType) {
|
|
124
156
|
for (let i = this.effectTimeline.length - 1; i >= Math.max(0, this.effectTimeline.length - 10); i--) {
|
|
@@ -129,10 +161,17 @@ class EffectTrackerService {
|
|
|
129
161
|
}
|
|
130
162
|
return undefined;
|
|
131
163
|
}
|
|
164
|
+
clearPendingCorrelations() {
|
|
165
|
+
for (const entry of this.pendingCorrelations) {
|
|
166
|
+
clearTimeout(entry.timeoutId);
|
|
167
|
+
}
|
|
168
|
+
this.pendingCorrelations = [];
|
|
169
|
+
}
|
|
132
170
|
ngOnDestroy() {
|
|
133
171
|
this.destroy$.next();
|
|
134
172
|
this.destroy$.complete();
|
|
135
173
|
this.effectEvents$.complete();
|
|
174
|
+
this.clearPendingCorrelations();
|
|
136
175
|
}
|
|
137
176
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: EffectTrackerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
138
177
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: EffectTrackerService, providedIn: 'root' });
|
|
@@ -142,6 +181,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
142
181
|
args: [{ providedIn: 'root' }]
|
|
143
182
|
}], ctorParameters: () => [] });
|
|
144
183
|
|
|
184
|
+
const MAX_BUFFER_SIZE = 200;
|
|
145
185
|
class WebSocketService {
|
|
146
186
|
platformId = inject(PLATFORM_ID);
|
|
147
187
|
isBrowser = isPlatformBrowser(this.platformId);
|
|
@@ -160,7 +200,7 @@ class WebSocketService {
|
|
|
160
200
|
get messages$() {
|
|
161
201
|
return this.incomingMessages$.asObservable();
|
|
162
202
|
}
|
|
163
|
-
initialize(wsUrl =
|
|
203
|
+
initialize(wsUrl = DEFAULT_WS_URL) {
|
|
164
204
|
if (this.initialized) {
|
|
165
205
|
// If already initialized with same URL, skip
|
|
166
206
|
if (this.wsUrl === wsUrl) {
|
|
@@ -174,19 +214,16 @@ class WebSocketService {
|
|
|
174
214
|
this.setupWebSocket(wsUrl);
|
|
175
215
|
}
|
|
176
216
|
send(message) {
|
|
177
|
-
|
|
178
|
-
if (this.isConnected && this.socket?.readyState === WebSocket.OPEN) {
|
|
179
|
-
this.socket.send(payload);
|
|
180
|
-
}
|
|
181
|
-
else if (this.isBrowser) {
|
|
182
|
-
this.messageBuffer.push(payload);
|
|
183
|
-
}
|
|
217
|
+
this.bufferOrSend(JSON.stringify(message));
|
|
184
218
|
}
|
|
185
219
|
sendRaw(payload) {
|
|
220
|
+
this.bufferOrSend(payload);
|
|
221
|
+
}
|
|
222
|
+
bufferOrSend(payload) {
|
|
186
223
|
if (this.isConnected && this.socket?.readyState === WebSocket.OPEN) {
|
|
187
224
|
this.socket.send(payload);
|
|
188
225
|
}
|
|
189
|
-
else if (this.isBrowser) {
|
|
226
|
+
else if (this.isBrowser && this.messageBuffer.length < MAX_BUFFER_SIZE) {
|
|
190
227
|
this.messageBuffer.push(payload);
|
|
191
228
|
}
|
|
192
229
|
}
|
|
@@ -198,6 +235,7 @@ class WebSocketService {
|
|
|
198
235
|
close() {
|
|
199
236
|
this.socket?.close();
|
|
200
237
|
this.socket = null;
|
|
238
|
+
this.messageBuffer = [];
|
|
201
239
|
this.connectionState$.next(false);
|
|
202
240
|
this.initialized = false;
|
|
203
241
|
this.wsUrl = null;
|
|
@@ -228,9 +266,10 @@ class WebSocketService {
|
|
|
228
266
|
};
|
|
229
267
|
}
|
|
230
268
|
flushBuffer() {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
269
|
+
const buffered = this.messageBuffer;
|
|
270
|
+
this.messageBuffer = [];
|
|
271
|
+
for (const message of buffered) {
|
|
272
|
+
if (this.isConnected && this.socket?.readyState === WebSocket.OPEN) {
|
|
234
273
|
this.socket.send(message);
|
|
235
274
|
}
|
|
236
275
|
}
|
|
@@ -249,7 +288,7 @@ class ActionsInterceptorService {
|
|
|
249
288
|
webSocketService = inject(WebSocketService);
|
|
250
289
|
destroy$ = new Subject();
|
|
251
290
|
initialized = false;
|
|
252
|
-
initialize(wsUrl =
|
|
291
|
+
initialize(wsUrl = DEFAULT_WS_URL) {
|
|
253
292
|
if (this.initialized) {
|
|
254
293
|
return;
|
|
255
294
|
}
|
|
@@ -1269,11 +1308,11 @@ function TrackedSelector(name) {
|
|
|
1269
1308
|
};
|
|
1270
1309
|
}
|
|
1271
1310
|
|
|
1272
|
-
function createDevToolMetaReducer(wsUrlOrConfig =
|
|
1311
|
+
function createDevToolMetaReducer(wsUrlOrConfig = DEFAULT_WS_URL) {
|
|
1273
1312
|
const config = typeof wsUrlOrConfig === 'string'
|
|
1274
1313
|
? { wsUrl: wsUrlOrConfig }
|
|
1275
1314
|
: wsUrlOrConfig;
|
|
1276
|
-
const wsUrl = config.wsUrl ??
|
|
1315
|
+
const wsUrl = config.wsUrl ?? DEFAULT_WS_URL;
|
|
1277
1316
|
const enablePerf = config.enablePerformanceTracking ?? true;
|
|
1278
1317
|
return function devToolMetaReducer(reducer) {
|
|
1279
1318
|
const performanceTracker = inject(PerformanceTrackerService);
|
|
@@ -1313,7 +1352,7 @@ function createDevToolMetaReducer(wsUrlOrConfig = 'ws://localhost:4000') {
|
|
|
1313
1352
|
};
|
|
1314
1353
|
}
|
|
1315
1354
|
function loggerMetaReducer(reducer) {
|
|
1316
|
-
return createDevToolMetaReducer(
|
|
1355
|
+
return createDevToolMetaReducer(DEFAULT_WS_URL)(reducer);
|
|
1317
1356
|
}
|
|
1318
1357
|
|
|
1319
1358
|
function provideNgrxDevTool(config = {}) {
|
|
@@ -1321,7 +1360,7 @@ function provideNgrxDevTool(config = {}) {
|
|
|
1321
1360
|
{
|
|
1322
1361
|
provide: APP_INITIALIZER,
|
|
1323
1362
|
useFactory: (interceptor) => () => {
|
|
1324
|
-
interceptor.initialize(config.wsUrl ??
|
|
1363
|
+
interceptor.initialize(config.wsUrl ?? DEFAULT_WS_URL);
|
|
1325
1364
|
},
|
|
1326
1365
|
deps: [ActionsInterceptorService],
|
|
1327
1366
|
multi: true,
|
|
@@ -1350,5 +1389,5 @@ function provideEffectTracking() {
|
|
|
1350
1389
|
* Generated bundle index. Do not edit.
|
|
1351
1390
|
*/
|
|
1352
1391
|
|
|
1353
|
-
export { ActionsInterceptorService, DevToolsEffectSources, EffectTrackerService, PerformanceAnalyzerService, PerformanceTrackerService, PerformanceWarningType, SelectorTrackerService, TrackedSelector, WebSocketService, createDevToolMetaReducer, createTrackedSelector, estimateRenderImpact, loggerMetaReducer, provideEffectTracking, provideNgrxDevTool, setSelectorTracker, trackSelector };
|
|
1392
|
+
export { ActionsInterceptorService, DEFAULT_WS_URL, DevToolsEffectSources, EffectTrackerService, PerformanceAnalyzerService, PerformanceTrackerService, PerformanceWarningType, SelectorTrackerService, TrackedSelector, WebSocketService, createDevToolMetaReducer, createTrackedSelector, estimateRenderImpact, loggerMetaReducer, provideEffectTracking, provideNgrxDevTool, setSelectorTracker, trackSelector };
|
|
1354
1393
|
//# sourceMappingURL=amadeus-it-group-ngrx-devtool.mjs.map
|