@ngrx/store-devtools 17.1.1 → 18.0.0-beta.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 (32) hide show
  1. package/esm2022/src/actions.mjs +1 -1
  2. package/esm2022/src/config.mjs +10 -10
  3. package/esm2022/src/devtools-dispatcher.mjs +4 -4
  4. package/esm2022/src/devtools.mjs +4 -4
  5. package/esm2022/src/extension.mjs +4 -4
  6. package/esm2022/src/instrument.mjs +5 -5
  7. package/esm2022/src/provide-store-devtools.mjs +1 -1
  8. package/esm2022/src/reducer.mjs +1 -1
  9. package/esm2022/src/utils.mjs +1 -1
  10. package/fesm2022/ngrx-store-devtools.mjs +823 -980
  11. package/fesm2022/ngrx-store-devtools.mjs.map +7 -1
  12. package/migrations/17_0_0-beta/index.js.map +1 -1
  13. package/package.json +2 -2
  14. package/schematics/ng-add/index.js +3 -3
  15. package/schematics/ng-add/index.js.map +1 -1
  16. package/schematics-core/utility/ast-utils.js.map +1 -1
  17. package/schematics-core/utility/change.js.map +1 -1
  18. package/schematics-core/utility/config.js.map +1 -1
  19. package/schematics-core/utility/find-component.js.map +1 -1
  20. package/schematics-core/utility/find-module.js.map +1 -1
  21. package/schematics-core/utility/json-utilts.js.map +1 -1
  22. package/schematics-core/utility/libs-version.js +1 -1
  23. package/schematics-core/utility/libs-version.js.map +1 -1
  24. package/schematics-core/utility/ngrx-utils.js.map +1 -1
  25. package/schematics-core/utility/package.js.map +1 -1
  26. package/schematics-core/utility/project.js.map +1 -1
  27. package/schematics-core/utility/standalone.js +406 -7
  28. package/schematics-core/utility/standalone.js.map +1 -1
  29. package/schematics-core/utility/strings.js.map +1 -1
  30. package/schematics-core/utility/update.js.map +1 -1
  31. package/schematics-core/utility/visitors.js.map +1 -1
  32. package/src/utils.d.ts +1 -1
@@ -1,1047 +1,890 @@
1
- import * as i0 from '@angular/core';
2
- import { InjectionToken, NgZone, inject, Injectable, Inject, makeEnvironmentProviders, NgModule } from '@angular/core';
3
- import * as i2 from '@ngrx/store';
4
- import { ActionsSubject, UPDATE, INIT, INITIAL_STATE, StateObservable, ReducerManagerDispatcher } from '@ngrx/store';
5
- import { EMPTY, Observable, of, queueScheduler, merge, ReplaySubject } from 'rxjs';
6
- import { share, filter, map, timeout, debounceTime, catchError, take, concatMap, takeUntil, switchMap, observeOn, skip, withLatestFrom, scan } from 'rxjs/operators';
7
- import { toSignal } from '@angular/core/rxjs-interop';
8
-
9
- const PERFORM_ACTION = 'PERFORM_ACTION';
10
- const REFRESH = 'REFRESH';
11
- const RESET = 'RESET';
12
- const ROLLBACK = 'ROLLBACK';
13
- const COMMIT = 'COMMIT';
14
- const SWEEP = 'SWEEP';
15
- const TOGGLE_ACTION = 'TOGGLE_ACTION';
16
- const SET_ACTIONS_ACTIVE = 'SET_ACTIONS_ACTIVE';
17
- const JUMP_TO_STATE = 'JUMP_TO_STATE';
18
- const JUMP_TO_ACTION = 'JUMP_TO_ACTION';
19
- const IMPORT_STATE = 'IMPORT_STATE';
20
- const LOCK_CHANGES = 'LOCK_CHANGES';
21
- const PAUSE_RECORDING = 'PAUSE_RECORDING';
22
- class PerformAction {
23
- constructor(action, timestamp) {
24
- this.action = action;
25
- this.timestamp = timestamp;
26
- this.type = PERFORM_ACTION;
27
- if (typeof action.type === 'undefined') {
28
- throw new Error('Actions may not have an undefined "type" property. ' +
29
- 'Have you misspelled a constant?');
30
- }
31
- }
32
- }
33
- class Refresh {
34
- constructor() {
35
- this.type = REFRESH;
36
- }
37
- }
38
- class Reset {
39
- constructor(timestamp) {
40
- this.timestamp = timestamp;
41
- this.type = RESET;
42
- }
43
- }
44
- class Rollback {
45
- constructor(timestamp) {
46
- this.timestamp = timestamp;
47
- this.type = ROLLBACK;
48
- }
49
- }
50
- class Commit {
51
- constructor(timestamp) {
52
- this.timestamp = timestamp;
53
- this.type = COMMIT;
54
- }
55
- }
56
- class Sweep {
57
- constructor() {
58
- this.type = SWEEP;
59
- }
60
- }
61
- class ToggleAction {
62
- constructor(id) {
63
- this.id = id;
64
- this.type = TOGGLE_ACTION;
65
- }
66
- }
67
- class SetActionsActive {
68
- constructor(start, end, active = true) {
69
- this.start = start;
70
- this.end = end;
71
- this.active = active;
72
- this.type = SET_ACTIONS_ACTIVE;
73
- }
74
- }
75
- class JumpToState {
76
- constructor(index) {
77
- this.index = index;
78
- this.type = JUMP_TO_STATE;
79
- }
80
- }
81
- class JumpToAction {
82
- constructor(actionId) {
83
- this.actionId = actionId;
84
- this.type = JUMP_TO_ACTION;
85
- }
86
- }
87
- class ImportState {
88
- constructor(nextLiftedState) {
89
- this.nextLiftedState = nextLiftedState;
90
- this.type = IMPORT_STATE;
91
- }
92
- }
93
- class LockChanges {
94
- constructor(status) {
95
- this.status = status;
96
- this.type = LOCK_CHANGES;
97
- }
98
- }
99
- class PauseRecording {
100
- constructor(status) {
101
- this.status = status;
102
- this.type = PAUSE_RECORDING;
103
- }
104
- }
1
+ // src/actions.mjs
2
+ var PERFORM_ACTION = "PERFORM_ACTION";
3
+ var REFRESH = "REFRESH";
4
+ var RESET = "RESET";
5
+ var ROLLBACK = "ROLLBACK";
6
+ var COMMIT = "COMMIT";
7
+ var SWEEP = "SWEEP";
8
+ var TOGGLE_ACTION = "TOGGLE_ACTION";
9
+ var SET_ACTIONS_ACTIVE = "SET_ACTIONS_ACTIVE";
10
+ var JUMP_TO_STATE = "JUMP_TO_STATE";
11
+ var JUMP_TO_ACTION = "JUMP_TO_ACTION";
12
+ var IMPORT_STATE = "IMPORT_STATE";
13
+ var LOCK_CHANGES = "LOCK_CHANGES";
14
+ var PAUSE_RECORDING = "PAUSE_RECORDING";
15
+ var PerformAction = class {
16
+ constructor(action, timestamp) {
17
+ this.action = action;
18
+ this.timestamp = timestamp;
19
+ this.type = PERFORM_ACTION;
20
+ if (typeof action.type === "undefined") {
21
+ throw new Error('Actions may not have an undefined "type" property. Have you misspelled a constant?');
22
+ }
23
+ }
24
+ };
25
+ var Refresh = class {
26
+ constructor() {
27
+ this.type = REFRESH;
28
+ }
29
+ };
30
+ var Reset = class {
31
+ constructor(timestamp) {
32
+ this.timestamp = timestamp;
33
+ this.type = RESET;
34
+ }
35
+ };
36
+ var Rollback = class {
37
+ constructor(timestamp) {
38
+ this.timestamp = timestamp;
39
+ this.type = ROLLBACK;
40
+ }
41
+ };
42
+ var Commit = class {
43
+ constructor(timestamp) {
44
+ this.timestamp = timestamp;
45
+ this.type = COMMIT;
46
+ }
47
+ };
48
+ var Sweep = class {
49
+ constructor() {
50
+ this.type = SWEEP;
51
+ }
52
+ };
53
+ var ToggleAction = class {
54
+ constructor(id) {
55
+ this.id = id;
56
+ this.type = TOGGLE_ACTION;
57
+ }
58
+ };
59
+ var SetActionsActive = class {
60
+ constructor(start, end, active = true) {
61
+ this.start = start;
62
+ this.end = end;
63
+ this.active = active;
64
+ this.type = SET_ACTIONS_ACTIVE;
65
+ }
66
+ };
67
+ var JumpToState = class {
68
+ constructor(index) {
69
+ this.index = index;
70
+ this.type = JUMP_TO_STATE;
71
+ }
72
+ };
73
+ var JumpToAction = class {
74
+ constructor(actionId) {
75
+ this.actionId = actionId;
76
+ this.type = JUMP_TO_ACTION;
77
+ }
78
+ };
79
+ var ImportState = class {
80
+ constructor(nextLiftedState) {
81
+ this.nextLiftedState = nextLiftedState;
82
+ this.type = IMPORT_STATE;
83
+ }
84
+ };
85
+ var LockChanges = class {
86
+ constructor(status) {
87
+ this.status = status;
88
+ this.type = LOCK_CHANGES;
89
+ }
90
+ };
91
+ var PauseRecording = class {
92
+ constructor(status) {
93
+ this.status = status;
94
+ this.type = PAUSE_RECORDING;
95
+ }
96
+ };
105
97
 
106
- /**
107
- * Chrome extension documentation
108
- * @see https://github.com/reduxjs/redux-devtools/blob/main/extension/docs/API/Arguments.md
109
- * Firefox extension documentation
110
- * @see https://github.com/zalmoxisus/redux-devtools-extension/blob/master/docs/API/Arguments.md
111
- */
112
- class StoreDevtoolsConfig {
113
- constructor() {
114
- /**
115
- * Maximum allowed actions to be stored in the history tree (default: `false`)
116
- */
117
- this.maxAge = false;
118
- }
119
- }
120
- const STORE_DEVTOOLS_CONFIG = new InjectionToken('@ngrx/store-devtools Options');
121
- /**
122
- * Used to provide a `StoreDevtoolsConfig` for the store-devtools.
123
- */
124
- const INITIAL_OPTIONS = new InjectionToken('@ngrx/store-devtools Initial Config');
98
+ // src/config.mjs
99
+ import { InjectionToken } from "@angular/core";
100
+ var StoreDevtoolsConfig = class {
101
+ constructor() {
102
+ this.maxAge = false;
103
+ }
104
+ };
105
+ var STORE_DEVTOOLS_CONFIG = new InjectionToken("@ngrx/store-devtools Options");
106
+ var INITIAL_OPTIONS = new InjectionToken("@ngrx/store-devtools Initial Config");
125
107
  function noMonitor() {
126
- return null;
108
+ return null;
127
109
  }
128
- const DEFAULT_NAME = 'NgRx Store DevTools';
110
+ var DEFAULT_NAME = "NgRx Store DevTools";
129
111
  function createConfig(optionsInput) {
130
- const DEFAULT_OPTIONS = {
131
- maxAge: false,
132
- monitor: noMonitor,
133
- actionSanitizer: undefined,
134
- stateSanitizer: undefined,
135
- name: DEFAULT_NAME,
136
- serialize: false,
137
- logOnly: false,
138
- autoPause: false,
139
- trace: false,
140
- traceLimit: 75,
141
- // Add all features explicitly. This prevent buggy behavior for
142
- // options like "lock" which might otherwise not show up.
143
- features: {
144
- pause: true,
145
- lock: true,
146
- persist: true,
147
- export: true,
148
- import: 'custom',
149
- jump: true,
150
- skip: true,
151
- reorder: true,
152
- dispatch: true,
153
- test: true, // Generate tests for the selected actions
154
- },
155
- connectInZone: false,
156
- };
157
- const options = typeof optionsInput === 'function' ? optionsInput() : optionsInput;
158
- const logOnly = options.logOnly
159
- ? { pause: true, export: true, test: true }
160
- : false;
161
- const features = options.features ||
162
- logOnly ||
163
- DEFAULT_OPTIONS.features;
164
- if (features.import === true) {
165
- features.import = 'custom';
166
- }
167
- const config = Object.assign({}, DEFAULT_OPTIONS, { features }, options);
168
- if (config.maxAge && config.maxAge < 2) {
169
- throw new Error(`Devtools 'maxAge' cannot be less than 2, got ${config.maxAge}`);
170
- }
171
- return config;
112
+ const DEFAULT_OPTIONS = {
113
+ maxAge: false,
114
+ monitor: noMonitor,
115
+ actionSanitizer: void 0,
116
+ stateSanitizer: void 0,
117
+ name: DEFAULT_NAME,
118
+ serialize: false,
119
+ logOnly: false,
120
+ autoPause: false,
121
+ trace: false,
122
+ traceLimit: 75,
123
+ // Add all features explicitly. This prevent buggy behavior for
124
+ // options like "lock" which might otherwise not show up.
125
+ features: {
126
+ pause: true,
127
+ // Start/pause recording of dispatched actions
128
+ lock: true,
129
+ // Lock/unlock dispatching actions and side effects
130
+ persist: true,
131
+ // Persist states on page reloading
132
+ export: true,
133
+ // Export history of actions in a file
134
+ import: "custom",
135
+ // Import history of actions from a file
136
+ jump: true,
137
+ // Jump back and forth (time travelling)
138
+ skip: true,
139
+ // Skip (cancel) actions
140
+ reorder: true,
141
+ // Drag and drop actions in the history list
142
+ dispatch: true,
143
+ // Dispatch custom actions or action creators
144
+ test: true
145
+ // Generate tests for the selected actions
146
+ },
147
+ connectInZone: false
148
+ };
149
+ const options = typeof optionsInput === "function" ? optionsInput() : optionsInput;
150
+ const logOnly = options.logOnly ? { pause: true, export: true, test: true } : false;
151
+ const features = options.features || logOnly || DEFAULT_OPTIONS.features;
152
+ if (features.import === true) {
153
+ features.import = "custom";
154
+ }
155
+ const config = Object.assign({}, DEFAULT_OPTIONS, { features }, options);
156
+ if (config.maxAge && config.maxAge < 2) {
157
+ throw new Error(`Devtools 'maxAge' cannot be less than 2, got ${config.maxAge}`);
158
+ }
159
+ return config;
172
160
  }
173
161
 
162
+ // src/utils.mjs
174
163
  function difference(first, second) {
175
- return first.filter((item) => second.indexOf(item) < 0);
164
+ return first.filter((item) => second.indexOf(item) < 0);
176
165
  }
177
- /**
178
- * Provides an app's view into the state of the lifted store.
179
- */
180
166
  function unliftState(liftedState) {
181
- const { computedStates, currentStateIndex } = liftedState;
182
- // At start up NgRx dispatches init actions,
183
- // When these init actions are being filtered out by the predicate or safe/block list options
184
- // we don't have a complete computed states yet.
185
- // At this point it could happen that we're out of bounds, when this happens we fall back to the last known state
186
- if (currentStateIndex >= computedStates.length) {
187
- const { state } = computedStates[computedStates.length - 1];
188
- return state;
189
- }
190
- const { state } = computedStates[currentStateIndex];
191
- return state;
167
+ const { computedStates, currentStateIndex } = liftedState;
168
+ if (currentStateIndex >= computedStates.length) {
169
+ const { state: state2 } = computedStates[computedStates.length - 1];
170
+ return state2;
171
+ }
172
+ const { state } = computedStates[currentStateIndex];
173
+ return state;
192
174
  }
193
175
  function unliftAction(liftedState) {
194
- return liftedState.actionsById[liftedState.nextActionId - 1];
176
+ return liftedState.actionsById[liftedState.nextActionId - 1];
195
177
  }
196
- /**
197
- * Lifts an app's action into an action on the lifted store.
198
- */
199
178
  function liftAction(action) {
200
- return new PerformAction(action, +Date.now());
179
+ return new PerformAction(action, +Date.now());
201
180
  }
202
- /**
203
- * Sanitizes given actions with given function.
204
- */
205
181
  function sanitizeActions(actionSanitizer, actions) {
206
- return Object.keys(actions).reduce((sanitizedActions, actionIdx) => {
207
- const idx = Number(actionIdx);
208
- sanitizedActions[idx] = sanitizeAction(actionSanitizer, actions[idx], idx);
209
- return sanitizedActions;
210
- }, {});
182
+ return Object.keys(actions).reduce((sanitizedActions, actionIdx) => {
183
+ const idx = Number(actionIdx);
184
+ sanitizedActions[idx] = sanitizeAction(actionSanitizer, actions[idx], idx);
185
+ return sanitizedActions;
186
+ }, {});
211
187
  }
212
- /**
213
- * Sanitizes given action with given function.
214
- */
215
188
  function sanitizeAction(actionSanitizer, action, actionIdx) {
216
- return {
217
- ...action,
218
- action: actionSanitizer(action.action, actionIdx),
219
- };
189
+ return {
190
+ ...action,
191
+ action: actionSanitizer(action.action, actionIdx)
192
+ };
220
193
  }
221
- /**
222
- * Sanitizes given states with given function.
223
- */
224
194
  function sanitizeStates(stateSanitizer, states) {
225
- return states.map((computedState, idx) => ({
226
- state: sanitizeState(stateSanitizer, computedState.state, idx),
227
- error: computedState.error,
228
- }));
195
+ return states.map((computedState, idx) => ({
196
+ state: sanitizeState(stateSanitizer, computedState.state, idx),
197
+ error: computedState.error
198
+ }));
229
199
  }
230
- /**
231
- * Sanitizes given state with given function.
232
- */
233
200
  function sanitizeState(stateSanitizer, state, stateIdx) {
234
- return stateSanitizer(state, stateIdx);
201
+ return stateSanitizer(state, stateIdx);
235
202
  }
236
- /**
237
- * Read the config and tell if actions should be filtered
238
- */
239
203
  function shouldFilterActions(config) {
240
- return config.predicate || config.actionsSafelist || config.actionsBlocklist;
204
+ return config.predicate || config.actionsSafelist || config.actionsBlocklist;
241
205
  }
242
- /**
243
- * Return a full filtered lifted state
244
- */
245
206
  function filterLiftedState(liftedState, predicate, safelist, blocklist) {
246
- const filteredStagedActionIds = [];
247
- const filteredActionsById = {};
248
- const filteredComputedStates = [];
249
- liftedState.stagedActionIds.forEach((id, idx) => {
250
- const liftedAction = liftedState.actionsById[id];
251
- if (!liftedAction)
252
- return;
253
- if (idx &&
254
- isActionFiltered(liftedState.computedStates[idx], liftedAction, predicate, safelist, blocklist)) {
255
- return;
256
- }
257
- filteredActionsById[id] = liftedAction;
258
- filteredStagedActionIds.push(id);
259
- filteredComputedStates.push(liftedState.computedStates[idx]);
260
- });
261
- return {
262
- ...liftedState,
263
- stagedActionIds: filteredStagedActionIds,
264
- actionsById: filteredActionsById,
265
- computedStates: filteredComputedStates,
266
- };
207
+ const filteredStagedActionIds = [];
208
+ const filteredActionsById = {};
209
+ const filteredComputedStates = [];
210
+ liftedState.stagedActionIds.forEach((id, idx) => {
211
+ const liftedAction = liftedState.actionsById[id];
212
+ if (!liftedAction)
213
+ return;
214
+ if (idx && isActionFiltered(liftedState.computedStates[idx], liftedAction, predicate, safelist, blocklist)) {
215
+ return;
216
+ }
217
+ filteredActionsById[id] = liftedAction;
218
+ filteredStagedActionIds.push(id);
219
+ filteredComputedStates.push(liftedState.computedStates[idx]);
220
+ });
221
+ return {
222
+ ...liftedState,
223
+ stagedActionIds: filteredStagedActionIds,
224
+ actionsById: filteredActionsById,
225
+ computedStates: filteredComputedStates
226
+ };
267
227
  }
268
- /**
269
- * Return true is the action should be ignored
270
- */
271
228
  function isActionFiltered(state, action, predicate, safelist, blockedlist) {
272
- const predicateMatch = predicate && !predicate(state, action.action);
273
- const safelistMatch = safelist &&
274
- !action.action.type.match(safelist.map((s) => escapeRegExp(s)).join('|'));
275
- const blocklistMatch = blockedlist &&
276
- action.action.type.match(blockedlist.map((s) => escapeRegExp(s)).join('|'));
277
- return predicateMatch || safelistMatch || blocklistMatch;
229
+ const predicateMatch = predicate && !predicate(state, action.action);
230
+ const safelistMatch = safelist && !action.action.type.match(safelist.map((s) => escapeRegExp(s)).join("|"));
231
+ const blocklistMatch = blockedlist && action.action.type.match(blockedlist.map((s) => escapeRegExp(s)).join("|"));
232
+ return predicateMatch || safelistMatch || blocklistMatch;
278
233
  }
279
- /**
280
- * Return string with escaped RegExp special characters
281
- * https://stackoverflow.com/a/6969486/1337347
282
- */
283
234
  function escapeRegExp(s) {
284
- return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
235
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
285
236
  }
286
237
 
238
+ // src/zone-config.mjs
239
+ import { NgZone, inject } from "@angular/core";
287
240
  function injectZoneConfig(connectInZone) {
288
- const ngZone = connectInZone ? inject(NgZone) : null;
289
- return { ngZone, connectInZone };
241
+ const ngZone = connectInZone ? inject(NgZone) : null;
242
+ return { ngZone, connectInZone };
290
243
  }
291
244
 
292
- class DevtoolsDispatcher extends ActionsSubject {
293
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: DevtoolsDispatcher, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
294
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: DevtoolsDispatcher }); }
295
- }
296
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: DevtoolsDispatcher, decorators: [{
297
- type: Injectable
298
- }] });
245
+ // src/devtools-dispatcher.mjs
246
+ import { ActionsSubject } from "@ngrx/store";
247
+ import { Injectable } from "@angular/core";
248
+ import * as i0 from "@angular/core";
249
+ var DevtoolsDispatcher = class _DevtoolsDispatcher extends ActionsSubject {
250
+ static {
251
+ this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.0-next.6", ngImport: i0, type: _DevtoolsDispatcher, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
252
+ }
253
+ static {
254
+ this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.0-next.6", ngImport: i0, type: _DevtoolsDispatcher });
255
+ }
256
+ };
257
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.0-next.6", ngImport: i0, type: DevtoolsDispatcher, decorators: [{
258
+ type: Injectable
259
+ }] });
299
260
 
300
- const ExtensionActionTypes = {
301
- START: 'START',
302
- DISPATCH: 'DISPATCH',
303
- STOP: 'STOP',
304
- ACTION: 'ACTION',
261
+ // src/extension.mjs
262
+ import { Inject, Injectable as Injectable2, InjectionToken as InjectionToken2 } from "@angular/core";
263
+ import { UPDATE } from "@ngrx/store";
264
+ import { EMPTY, Observable, of } from "rxjs";
265
+ import { catchError, concatMap, debounceTime, filter, map, share, switchMap, take, takeUntil, timeout } from "rxjs/operators";
266
+ import * as i02 from "@angular/core";
267
+ var ExtensionActionTypes = {
268
+ START: "START",
269
+ DISPATCH: "DISPATCH",
270
+ STOP: "STOP",
271
+ ACTION: "ACTION"
305
272
  };
306
- const REDUX_DEVTOOLS_EXTENSION = new InjectionToken('@ngrx/store-devtools Redux Devtools Extension');
307
- class DevtoolsExtension {
308
- constructor(devtoolsExtension, config, dispatcher) {
309
- this.config = config;
310
- this.dispatcher = dispatcher;
311
- this.zoneConfig = injectZoneConfig(this.config.connectInZone);
312
- this.devtoolsExtension = devtoolsExtension;
313
- this.createActionStreams();
314
- }
315
- notify(action, state) {
316
- if (!this.devtoolsExtension) {
317
- return;
318
- }
319
- // Check to see if the action requires a full update of the liftedState.
320
- // If it is a simple action generated by the user's app and the recording
321
- // is not locked/paused, only send the action and the current state (fast).
322
- //
323
- // A full liftedState update (slow: serializes the entire liftedState) is
324
- // only required when:
325
- // a) redux-devtools-extension fires the @@Init action (ignored by
326
- // @ngrx/store-devtools)
327
- // b) an action is generated by an @ngrx module (e.g. @ngrx/effects/init
328
- // or @ngrx/store/update-reducers)
329
- // c) the state has been recomputed due to time-traveling
330
- // d) any action that is not a PerformAction to err on the side of
331
- // caution.
332
- if (action.type === PERFORM_ACTION) {
333
- if (state.isLocked || state.isPaused) {
334
- return;
335
- }
336
- const currentState = unliftState(state);
337
- if (shouldFilterActions(this.config) &&
338
- isActionFiltered(currentState, action, this.config.predicate, this.config.actionsSafelist, this.config.actionsBlocklist)) {
339
- return;
340
- }
341
- const sanitizedState = this.config.stateSanitizer
342
- ? sanitizeState(this.config.stateSanitizer, currentState, state.currentStateIndex)
343
- : currentState;
344
- const sanitizedAction = this.config.actionSanitizer
345
- ? sanitizeAction(this.config.actionSanitizer, action, state.nextActionId)
346
- : action;
347
- this.sendToReduxDevtools(() => this.extensionConnection.send(sanitizedAction, sanitizedState));
348
- }
349
- else {
350
- // Requires full state update
351
- const sanitizedLiftedState = {
352
- ...state,
353
- stagedActionIds: state.stagedActionIds,
354
- actionsById: this.config.actionSanitizer
355
- ? sanitizeActions(this.config.actionSanitizer, state.actionsById)
356
- : state.actionsById,
357
- computedStates: this.config.stateSanitizer
358
- ? sanitizeStates(this.config.stateSanitizer, state.computedStates)
359
- : state.computedStates,
360
- };
361
- this.sendToReduxDevtools(() => this.devtoolsExtension.send(null, sanitizedLiftedState, this.getExtensionConfig(this.config)));
362
- }
363
- }
364
- createChangesObservable() {
365
- if (!this.devtoolsExtension) {
366
- return EMPTY;
367
- }
368
- return new Observable((subscriber) => {
369
- const connection = this.zoneConfig.connectInZone
370
- ? // To reduce change detection cycles, we need to run the `connect` method
371
- // outside of the Angular zone. The `connect` method adds a `message`
372
- // event listener to communicate with an extension using `window.postMessage`
373
- // and handle message events.
374
- this.zoneConfig.ngZone.runOutsideAngular(() => this.devtoolsExtension.connect(this.getExtensionConfig(this.config)))
375
- : this.devtoolsExtension.connect(this.getExtensionConfig(this.config));
376
- this.extensionConnection = connection;
377
- connection.init();
378
- connection.subscribe((change) => subscriber.next(change));
379
- return connection.unsubscribe;
380
- });
381
- }
382
- createActionStreams() {
383
- // Listens to all changes
384
- const changes$ = this.createChangesObservable().pipe(share());
385
- // Listen for the start action
386
- const start$ = changes$.pipe(filter((change) => change.type === ExtensionActionTypes.START));
387
- // Listen for the stop action
388
- const stop$ = changes$.pipe(filter((change) => change.type === ExtensionActionTypes.STOP));
389
- // Listen for lifted actions
390
- const liftedActions$ = changes$.pipe(filter((change) => change.type === ExtensionActionTypes.DISPATCH), map((change) => this.unwrapAction(change.payload)), concatMap((action) => {
391
- if (action.type === IMPORT_STATE) {
392
- // State imports may happen in two situations:
393
- // 1. Explicitly by user
394
- // 2. User activated the "persist state accross reloads" option
395
- // and now the state is imported during reload.
396
- // Because of option 2, we need to give possible
397
- // lazy loaded reducers time to instantiate.
398
- // As soon as there is no UPDATE action within 1 second,
399
- // it is assumed that all reducers are loaded.
400
- return this.dispatcher.pipe(filter((action) => action.type === UPDATE), timeout(1000), debounceTime(1000), map(() => action), catchError(() => of(action)), take(1));
401
- }
402
- else {
403
- return of(action);
404
- }
405
- }));
406
- // Listen for unlifted actions
407
- const actions$ = changes$.pipe(filter((change) => change.type === ExtensionActionTypes.ACTION), map((change) => this.unwrapAction(change.payload)));
408
- const actionsUntilStop$ = actions$.pipe(takeUntil(stop$));
409
- const liftedUntilStop$ = liftedActions$.pipe(takeUntil(stop$));
410
- this.start$ = start$.pipe(takeUntil(stop$));
411
- // Only take the action sources between the start/stop events
412
- this.actions$ = this.start$.pipe(switchMap(() => actionsUntilStop$));
413
- this.liftedActions$ = this.start$.pipe(switchMap(() => liftedUntilStop$));
414
- }
415
- unwrapAction(action) {
416
- // indirect eval according to https://esbuild.github.io/content-types/#direct-eval
417
- return typeof action === 'string' ? (0, eval)(`(${action})`) : action;
418
- }
419
- getExtensionConfig(config) {
420
- const extensionOptions = {
421
- name: config.name,
422
- features: config.features,
423
- serialize: config.serialize,
424
- autoPause: config.autoPause ?? false,
425
- trace: config.trace ?? false,
426
- traceLimit: config.traceLimit ?? 75,
427
- // The action/state sanitizers are not added to the config
428
- // because sanitation is done in this class already.
429
- // It is done before sending it to the devtools extension for consistency:
430
- // - If we call extensionConnection.send(...),
431
- // the extension would call the sanitizers.
432
- // - If we call devtoolsExtension.send(...) (aka full state update),
433
- // the extension would NOT call the sanitizers, so we have to do it ourselves.
434
- };
435
- if (config.maxAge !== false /* support === 0 */) {
436
- extensionOptions.maxAge = config.maxAge;
437
- }
438
- return extensionOptions;
439
- }
440
- sendToReduxDevtools(send) {
441
- try {
442
- send();
443
- }
444
- catch (err) {
445
- console.warn('@ngrx/store-devtools: something went wrong inside the redux devtools', err);
446
- }
273
+ var REDUX_DEVTOOLS_EXTENSION = new InjectionToken2("@ngrx/store-devtools Redux Devtools Extension");
274
+ var DevtoolsExtension = class _DevtoolsExtension {
275
+ constructor(devtoolsExtension, config, dispatcher) {
276
+ this.config = config;
277
+ this.dispatcher = dispatcher;
278
+ this.zoneConfig = injectZoneConfig(this.config.connectInZone);
279
+ this.devtoolsExtension = devtoolsExtension;
280
+ this.createActionStreams();
281
+ }
282
+ notify(action, state) {
283
+ if (!this.devtoolsExtension) {
284
+ return;
285
+ }
286
+ if (action.type === PERFORM_ACTION) {
287
+ if (state.isLocked || state.isPaused) {
288
+ return;
289
+ }
290
+ const currentState = unliftState(state);
291
+ if (shouldFilterActions(this.config) && isActionFiltered(currentState, action, this.config.predicate, this.config.actionsSafelist, this.config.actionsBlocklist)) {
292
+ return;
293
+ }
294
+ const sanitizedState = this.config.stateSanitizer ? sanitizeState(this.config.stateSanitizer, currentState, state.currentStateIndex) : currentState;
295
+ const sanitizedAction = this.config.actionSanitizer ? sanitizeAction(this.config.actionSanitizer, action, state.nextActionId) : action;
296
+ this.sendToReduxDevtools(() => this.extensionConnection.send(sanitizedAction, sanitizedState));
297
+ } else {
298
+ const sanitizedLiftedState = {
299
+ ...state,
300
+ stagedActionIds: state.stagedActionIds,
301
+ actionsById: this.config.actionSanitizer ? sanitizeActions(this.config.actionSanitizer, state.actionsById) : state.actionsById,
302
+ computedStates: this.config.stateSanitizer ? sanitizeStates(this.config.stateSanitizer, state.computedStates) : state.computedStates
303
+ };
304
+ this.sendToReduxDevtools(() => this.devtoolsExtension.send(null, sanitizedLiftedState, this.getExtensionConfig(this.config)));
305
+ }
306
+ }
307
+ createChangesObservable() {
308
+ if (!this.devtoolsExtension) {
309
+ return EMPTY;
310
+ }
311
+ return new Observable((subscriber) => {
312
+ const connection = this.zoneConfig.connectInZone ? (
313
+ // To reduce change detection cycles, we need to run the `connect` method
314
+ // outside of the Angular zone. The `connect` method adds a `message`
315
+ // event listener to communicate with an extension using `window.postMessage`
316
+ // and handle message events.
317
+ this.zoneConfig.ngZone.runOutsideAngular(() => this.devtoolsExtension.connect(this.getExtensionConfig(this.config)))
318
+ ) : this.devtoolsExtension.connect(this.getExtensionConfig(this.config));
319
+ this.extensionConnection = connection;
320
+ connection.init();
321
+ connection.subscribe((change) => subscriber.next(change));
322
+ return connection.unsubscribe;
323
+ });
324
+ }
325
+ createActionStreams() {
326
+ const changes$ = this.createChangesObservable().pipe(share());
327
+ const start$ = changes$.pipe(filter((change) => change.type === ExtensionActionTypes.START));
328
+ const stop$ = changes$.pipe(filter((change) => change.type === ExtensionActionTypes.STOP));
329
+ const liftedActions$ = changes$.pipe(filter((change) => change.type === ExtensionActionTypes.DISPATCH), map((change) => this.unwrapAction(change.payload)), concatMap((action) => {
330
+ if (action.type === IMPORT_STATE) {
331
+ return this.dispatcher.pipe(filter((action2) => action2.type === UPDATE), timeout(1e3), debounceTime(1e3), map(() => action), catchError(() => of(action)), take(1));
332
+ } else {
333
+ return of(action);
334
+ }
335
+ }));
336
+ const actions$ = changes$.pipe(filter((change) => change.type === ExtensionActionTypes.ACTION), map((change) => this.unwrapAction(change.payload)));
337
+ const actionsUntilStop$ = actions$.pipe(takeUntil(stop$));
338
+ const liftedUntilStop$ = liftedActions$.pipe(takeUntil(stop$));
339
+ this.start$ = start$.pipe(takeUntil(stop$));
340
+ this.actions$ = this.start$.pipe(switchMap(() => actionsUntilStop$));
341
+ this.liftedActions$ = this.start$.pipe(switchMap(() => liftedUntilStop$));
342
+ }
343
+ unwrapAction(action) {
344
+ return typeof action === "string" ? (0, eval)(`(${action})`) : action;
345
+ }
346
+ getExtensionConfig(config) {
347
+ const extensionOptions = {
348
+ name: config.name,
349
+ features: config.features,
350
+ serialize: config.serialize,
351
+ autoPause: config.autoPause ?? false,
352
+ trace: config.trace ?? false,
353
+ traceLimit: config.traceLimit ?? 75
354
+ // The action/state sanitizers are not added to the config
355
+ // because sanitation is done in this class already.
356
+ // It is done before sending it to the devtools extension for consistency:
357
+ // - If we call extensionConnection.send(...),
358
+ // the extension would call the sanitizers.
359
+ // - If we call devtoolsExtension.send(...) (aka full state update),
360
+ // the extension would NOT call the sanitizers, so we have to do it ourselves.
361
+ };
362
+ if (config.maxAge !== false) {
363
+ extensionOptions.maxAge = config.maxAge;
447
364
  }
448
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: DevtoolsExtension, deps: [{ token: REDUX_DEVTOOLS_EXTENSION }, { token: STORE_DEVTOOLS_CONFIG }, { token: DevtoolsDispatcher }], target: i0.ɵɵFactoryTarget.Injectable }); }
449
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: DevtoolsExtension }); }
450
- }
451
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: DevtoolsExtension, decorators: [{
452
- type: Injectable
453
- }], ctorParameters: () => [{ type: undefined, decorators: [{
454
- type: Inject,
455
- args: [REDUX_DEVTOOLS_EXTENSION]
456
- }] }, { type: StoreDevtoolsConfig, decorators: [{
457
- type: Inject,
458
- args: [STORE_DEVTOOLS_CONFIG]
459
- }] }, { type: DevtoolsDispatcher }] });
365
+ return extensionOptions;
366
+ }
367
+ sendToReduxDevtools(send) {
368
+ try {
369
+ send();
370
+ } catch (err) {
371
+ console.warn("@ngrx/store-devtools: something went wrong inside the redux devtools", err);
372
+ }
373
+ }
374
+ static {
375
+ this.ɵfac = i02.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.0-next.6", ngImport: i02, type: _DevtoolsExtension, deps: [{ token: REDUX_DEVTOOLS_EXTENSION }, { token: STORE_DEVTOOLS_CONFIG }, { token: DevtoolsDispatcher }], target: i02.ɵɵFactoryTarget.Injectable });
376
+ }
377
+ static {
378
+ this.ɵprov = i02.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.0-next.6", ngImport: i02, type: _DevtoolsExtension });
379
+ }
380
+ };
381
+ i02.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.0-next.6", ngImport: i02, type: DevtoolsExtension, decorators: [{
382
+ type: Injectable2
383
+ }], ctorParameters: () => [{ type: void 0, decorators: [{
384
+ type: Inject,
385
+ args: [REDUX_DEVTOOLS_EXTENSION]
386
+ }] }, { type: StoreDevtoolsConfig, decorators: [{
387
+ type: Inject,
388
+ args: [STORE_DEVTOOLS_CONFIG]
389
+ }] }, { type: DevtoolsDispatcher }] });
460
390
 
461
- const INIT_ACTION = { type: INIT };
462
- const RECOMPUTE = '@ngrx/store-devtools/recompute';
463
- const RECOMPUTE_ACTION = { type: RECOMPUTE };
464
- /**
465
- * Computes the next entry in the log by applying an action.
466
- */
391
+ // src/reducer.mjs
392
+ import { UPDATE as UPDATE2, INIT } from "@ngrx/store";
393
+ var INIT_ACTION = { type: INIT };
394
+ var RECOMPUTE = "@ngrx/store-devtools/recompute";
395
+ var RECOMPUTE_ACTION = { type: RECOMPUTE };
467
396
  function computeNextEntry(reducer, action, state, error, errorHandler) {
468
- if (error) {
469
- return {
470
- state,
471
- error: 'Interrupted by an error up the chain',
472
- };
473
- }
474
- let nextState = state;
475
- let nextError;
476
- try {
477
- nextState = reducer(state, action);
478
- }
479
- catch (err) {
480
- nextError = err.toString();
481
- errorHandler.handleError(err);
482
- }
397
+ if (error) {
483
398
  return {
484
- state: nextState,
485
- error: nextError,
399
+ state,
400
+ error: "Interrupted by an error up the chain"
486
401
  };
402
+ }
403
+ let nextState = state;
404
+ let nextError;
405
+ try {
406
+ nextState = reducer(state, action);
407
+ } catch (err) {
408
+ nextError = err.toString();
409
+ errorHandler.handleError(err);
410
+ }
411
+ return {
412
+ state: nextState,
413
+ error: nextError
414
+ };
487
415
  }
488
- /**
489
- * Runs the reducer on invalidated actions to get a fresh computation log.
490
- */
491
416
  function recomputeStates(computedStates, minInvalidatedStateIndex, reducer, committedState, actionsById, stagedActionIds, skippedActionIds, errorHandler, isPaused) {
492
- // Optimization: exit early and return the same reference
493
- // if we know nothing could have changed.
494
- if (minInvalidatedStateIndex >= computedStates.length &&
495
- computedStates.length === stagedActionIds.length) {
496
- return computedStates;
497
- }
498
- const nextComputedStates = computedStates.slice(0, minInvalidatedStateIndex);
499
- // If the recording is paused, recompute all states up until the pause state,
500
- // else recompute all states.
501
- const lastIncludedActionId = stagedActionIds.length - (isPaused ? 1 : 0);
502
- for (let i = minInvalidatedStateIndex; i < lastIncludedActionId; i++) {
503
- const actionId = stagedActionIds[i];
504
- const action = actionsById[actionId].action;
505
- const previousEntry = nextComputedStates[i - 1];
506
- const previousState = previousEntry ? previousEntry.state : committedState;
507
- const previousError = previousEntry ? previousEntry.error : undefined;
508
- const shouldSkip = skippedActionIds.indexOf(actionId) > -1;
509
- const entry = shouldSkip
510
- ? previousEntry
511
- : computeNextEntry(reducer, action, previousState, previousError, errorHandler);
512
- nextComputedStates.push(entry);
513
- }
514
- // If the recording is paused, the last state will not be recomputed,
515
- // because it's essentially not part of the state history.
516
- if (isPaused) {
517
- nextComputedStates.push(computedStates[computedStates.length - 1]);
518
- }
519
- return nextComputedStates;
417
+ if (minInvalidatedStateIndex >= computedStates.length && computedStates.length === stagedActionIds.length) {
418
+ return computedStates;
419
+ }
420
+ const nextComputedStates = computedStates.slice(0, minInvalidatedStateIndex);
421
+ const lastIncludedActionId = stagedActionIds.length - (isPaused ? 1 : 0);
422
+ for (let i = minInvalidatedStateIndex; i < lastIncludedActionId; i++) {
423
+ const actionId = stagedActionIds[i];
424
+ const action = actionsById[actionId].action;
425
+ const previousEntry = nextComputedStates[i - 1];
426
+ const previousState = previousEntry ? previousEntry.state : committedState;
427
+ const previousError = previousEntry ? previousEntry.error : void 0;
428
+ const shouldSkip = skippedActionIds.indexOf(actionId) > -1;
429
+ const entry = shouldSkip ? previousEntry : computeNextEntry(reducer, action, previousState, previousError, errorHandler);
430
+ nextComputedStates.push(entry);
431
+ }
432
+ if (isPaused) {
433
+ nextComputedStates.push(computedStates[computedStates.length - 1]);
434
+ }
435
+ return nextComputedStates;
520
436
  }
521
437
  function liftInitialState(initialCommittedState, monitorReducer) {
522
- return {
523
- monitorState: monitorReducer(undefined, {}),
524
- nextActionId: 1,
525
- actionsById: { 0: liftAction(INIT_ACTION) },
526
- stagedActionIds: [0],
527
- skippedActionIds: [],
528
- committedState: initialCommittedState,
529
- currentStateIndex: 0,
530
- computedStates: [],
531
- isLocked: false,
532
- isPaused: false,
533
- };
438
+ return {
439
+ monitorState: monitorReducer(void 0, {}),
440
+ nextActionId: 1,
441
+ actionsById: { 0: liftAction(INIT_ACTION) },
442
+ stagedActionIds: [0],
443
+ skippedActionIds: [],
444
+ committedState: initialCommittedState,
445
+ currentStateIndex: 0,
446
+ computedStates: [],
447
+ isLocked: false,
448
+ isPaused: false
449
+ };
534
450
  }
535
- /**
536
- * Creates a history state reducer from an app's reducer.
537
- */
538
451
  function liftReducerWith(initialCommittedState, initialLiftedState, errorHandler, monitorReducer, options = {}) {
539
- /**
540
- * Manages how the history actions modify the history state.
541
- */
542
- return (reducer) => (liftedState, liftedAction) => {
543
- let { monitorState, actionsById, nextActionId, stagedActionIds, skippedActionIds, committedState, currentStateIndex, computedStates, isLocked, isPaused, } = liftedState || initialLiftedState;
544
- if (!liftedState) {
545
- // Prevent mutating initialLiftedState
546
- actionsById = Object.create(actionsById);
452
+ return (reducer) => (liftedState, liftedAction) => {
453
+ let { monitorState, actionsById, nextActionId, stagedActionIds, skippedActionIds, committedState, currentStateIndex, computedStates, isLocked, isPaused } = liftedState || initialLiftedState;
454
+ if (!liftedState) {
455
+ actionsById = Object.create(actionsById);
456
+ }
457
+ function commitExcessActions(n) {
458
+ let excess = n;
459
+ let idsToDelete = stagedActionIds.slice(1, excess + 1);
460
+ for (let i = 0; i < idsToDelete.length; i++) {
461
+ if (computedStates[i + 1].error) {
462
+ excess = i;
463
+ idsToDelete = stagedActionIds.slice(1, excess + 1);
464
+ break;
465
+ } else {
466
+ delete actionsById[idsToDelete[i]];
547
467
  }
548
- function commitExcessActions(n) {
549
- // Auto-commits n-number of excess actions.
550
- let excess = n;
551
- let idsToDelete = stagedActionIds.slice(1, excess + 1);
552
- for (let i = 0; i < idsToDelete.length; i++) {
553
- if (computedStates[i + 1].error) {
554
- // Stop if error is found. Commit actions up to error.
555
- excess = i;
556
- idsToDelete = stagedActionIds.slice(1, excess + 1);
557
- break;
558
- }
559
- else {
560
- delete actionsById[idsToDelete[i]];
561
- }
562
- }
563
- skippedActionIds = skippedActionIds.filter((id) => idsToDelete.indexOf(id) === -1);
564
- stagedActionIds = [0, ...stagedActionIds.slice(excess + 1)];
565
- committedState = computedStates[excess].state;
566
- computedStates = computedStates.slice(excess);
567
- currentStateIndex =
568
- currentStateIndex > excess ? currentStateIndex - excess : 0;
468
+ }
469
+ skippedActionIds = skippedActionIds.filter((id) => idsToDelete.indexOf(id) === -1);
470
+ stagedActionIds = [0, ...stagedActionIds.slice(excess + 1)];
471
+ committedState = computedStates[excess].state;
472
+ computedStates = computedStates.slice(excess);
473
+ currentStateIndex = currentStateIndex > excess ? currentStateIndex - excess : 0;
474
+ }
475
+ function commitChanges() {
476
+ actionsById = { 0: liftAction(INIT_ACTION) };
477
+ nextActionId = 1;
478
+ stagedActionIds = [0];
479
+ skippedActionIds = [];
480
+ committedState = computedStates[currentStateIndex].state;
481
+ currentStateIndex = 0;
482
+ computedStates = [];
483
+ }
484
+ let minInvalidatedStateIndex = 0;
485
+ switch (liftedAction.type) {
486
+ case LOCK_CHANGES: {
487
+ isLocked = liftedAction.status;
488
+ minInvalidatedStateIndex = Infinity;
489
+ break;
490
+ }
491
+ case PAUSE_RECORDING: {
492
+ isPaused = liftedAction.status;
493
+ if (isPaused) {
494
+ stagedActionIds = [...stagedActionIds, nextActionId];
495
+ actionsById[nextActionId] = new PerformAction({
496
+ type: "@ngrx/devtools/pause"
497
+ }, +Date.now());
498
+ nextActionId++;
499
+ minInvalidatedStateIndex = stagedActionIds.length - 1;
500
+ computedStates = computedStates.concat(computedStates[computedStates.length - 1]);
501
+ if (currentStateIndex === stagedActionIds.length - 2) {
502
+ currentStateIndex++;
503
+ }
504
+ minInvalidatedStateIndex = Infinity;
505
+ } else {
506
+ commitChanges();
569
507
  }
570
- function commitChanges() {
571
- // Consider the last committed state the new starting point.
572
- // Squash any staged actions into a single committed state.
573
- actionsById = { 0: liftAction(INIT_ACTION) };
574
- nextActionId = 1;
575
- stagedActionIds = [0];
576
- skippedActionIds = [];
577
- committedState = computedStates[currentStateIndex].state;
578
- currentStateIndex = 0;
579
- computedStates = [];
508
+ break;
509
+ }
510
+ case RESET: {
511
+ actionsById = { 0: liftAction(INIT_ACTION) };
512
+ nextActionId = 1;
513
+ stagedActionIds = [0];
514
+ skippedActionIds = [];
515
+ committedState = initialCommittedState;
516
+ currentStateIndex = 0;
517
+ computedStates = [];
518
+ break;
519
+ }
520
+ case COMMIT: {
521
+ commitChanges();
522
+ break;
523
+ }
524
+ case ROLLBACK: {
525
+ actionsById = { 0: liftAction(INIT_ACTION) };
526
+ nextActionId = 1;
527
+ stagedActionIds = [0];
528
+ skippedActionIds = [];
529
+ currentStateIndex = 0;
530
+ computedStates = [];
531
+ break;
532
+ }
533
+ case TOGGLE_ACTION: {
534
+ const { id: actionId } = liftedAction;
535
+ const index = skippedActionIds.indexOf(actionId);
536
+ if (index === -1) {
537
+ skippedActionIds = [actionId, ...skippedActionIds];
538
+ } else {
539
+ skippedActionIds = skippedActionIds.filter((id) => id !== actionId);
580
540
  }
581
- // By default, aggressively recompute every state whatever happens.
582
- // This has O(n) performance, so we'll override this to a sensible
583
- // value whenever we feel like we don't have to recompute the states.
584
- let minInvalidatedStateIndex = 0;
585
- switch (liftedAction.type) {
586
- case LOCK_CHANGES: {
587
- isLocked = liftedAction.status;
588
- minInvalidatedStateIndex = Infinity;
589
- break;
590
- }
591
- case PAUSE_RECORDING: {
592
- isPaused = liftedAction.status;
593
- if (isPaused) {
594
- // Add a pause action to signal the devtools-user the recording is paused.
595
- // The corresponding state will be overwritten on each update to always contain
596
- // the latest state (see Actions.PERFORM_ACTION).
597
- stagedActionIds = [...stagedActionIds, nextActionId];
598
- actionsById[nextActionId] = new PerformAction({
599
- type: '@ngrx/devtools/pause',
600
- }, +Date.now());
601
- nextActionId++;
602
- minInvalidatedStateIndex = stagedActionIds.length - 1;
603
- computedStates = computedStates.concat(computedStates[computedStates.length - 1]);
604
- if (currentStateIndex === stagedActionIds.length - 2) {
605
- currentStateIndex++;
606
- }
607
- minInvalidatedStateIndex = Infinity;
608
- }
609
- else {
610
- commitChanges();
611
- }
612
- break;
613
- }
614
- case RESET: {
615
- // Get back to the state the store was created with.
616
- actionsById = { 0: liftAction(INIT_ACTION) };
617
- nextActionId = 1;
618
- stagedActionIds = [0];
619
- skippedActionIds = [];
620
- committedState = initialCommittedState;
621
- currentStateIndex = 0;
622
- computedStates = [];
623
- break;
624
- }
625
- case COMMIT: {
626
- commitChanges();
627
- break;
628
- }
629
- case ROLLBACK: {
630
- // Forget about any staged actions.
631
- // Start again from the last committed state.
632
- actionsById = { 0: liftAction(INIT_ACTION) };
633
- nextActionId = 1;
634
- stagedActionIds = [0];
635
- skippedActionIds = [];
636
- currentStateIndex = 0;
637
- computedStates = [];
638
- break;
639
- }
640
- case TOGGLE_ACTION: {
641
- // Toggle whether an action with given ID is skipped.
642
- // Being skipped means it is a no-op during the computation.
643
- const { id: actionId } = liftedAction;
644
- const index = skippedActionIds.indexOf(actionId);
645
- if (index === -1) {
646
- skippedActionIds = [actionId, ...skippedActionIds];
647
- }
648
- else {
649
- skippedActionIds = skippedActionIds.filter((id) => id !== actionId);
650
- }
651
- // Optimization: we know history before this action hasn't changed
652
- minInvalidatedStateIndex = stagedActionIds.indexOf(actionId);
653
- break;
654
- }
655
- case SET_ACTIONS_ACTIVE: {
656
- // Toggle whether an action with given ID is skipped.
657
- // Being skipped means it is a no-op during the computation.
658
- const { start, end, active } = liftedAction;
659
- const actionIds = [];
660
- for (let i = start; i < end; i++)
661
- actionIds.push(i);
662
- if (active) {
663
- skippedActionIds = difference(skippedActionIds, actionIds);
664
- }
665
- else {
666
- skippedActionIds = [...skippedActionIds, ...actionIds];
667
- }
668
- // Optimization: we know history before this action hasn't changed
669
- minInvalidatedStateIndex = stagedActionIds.indexOf(start);
670
- break;
671
- }
672
- case JUMP_TO_STATE: {
673
- // Without recomputing anything, move the pointer that tell us
674
- // which state is considered the current one. Useful for sliders.
675
- currentStateIndex = liftedAction.index;
676
- // Optimization: we know the history has not changed.
677
- minInvalidatedStateIndex = Infinity;
678
- break;
679
- }
680
- case JUMP_TO_ACTION: {
681
- // Jumps to a corresponding state to a specific action.
682
- // Useful when filtering actions.
683
- const index = stagedActionIds.indexOf(liftedAction.actionId);
684
- if (index !== -1)
685
- currentStateIndex = index;
686
- minInvalidatedStateIndex = Infinity;
687
- break;
688
- }
689
- case SWEEP: {
690
- // Forget any actions that are currently being skipped.
691
- stagedActionIds = difference(stagedActionIds, skippedActionIds);
692
- skippedActionIds = [];
693
- currentStateIndex = Math.min(currentStateIndex, stagedActionIds.length - 1);
694
- break;
695
- }
696
- case PERFORM_ACTION: {
697
- // Ignore action and return state as is if recording is locked
698
- if (isLocked) {
699
- return liftedState || initialLiftedState;
700
- }
701
- if (isPaused ||
702
- (liftedState &&
703
- isActionFiltered(liftedState.computedStates[currentStateIndex], liftedAction, options.predicate, options.actionsSafelist, options.actionsBlocklist))) {
704
- // If recording is paused or if the action should be ignored, overwrite the last state
705
- // (corresponds to the pause action) and keep everything else as is.
706
- // This way, the app gets the new current state while the devtools
707
- // do not record another action.
708
- const lastState = computedStates[computedStates.length - 1];
709
- computedStates = [
710
- ...computedStates.slice(0, -1),
711
- computeNextEntry(reducer, liftedAction.action, lastState.state, lastState.error, errorHandler),
712
- ];
713
- minInvalidatedStateIndex = Infinity;
714
- break;
715
- }
716
- // Auto-commit as new actions come in.
717
- if (options.maxAge && stagedActionIds.length === options.maxAge) {
718
- commitExcessActions(1);
719
- }
720
- if (currentStateIndex === stagedActionIds.length - 1) {
721
- currentStateIndex++;
722
- }
723
- const actionId = nextActionId++;
724
- // Mutation! This is the hottest path, and we optimize on purpose.
725
- // It is safe because we set a new key in a cache dictionary.
726
- actionsById[actionId] = liftedAction;
727
- stagedActionIds = [...stagedActionIds, actionId];
728
- // Optimization: we know that only the new action needs computing.
729
- minInvalidatedStateIndex = stagedActionIds.length - 1;
730
- break;
731
- }
732
- case IMPORT_STATE: {
733
- // Completely replace everything.
734
- ({
735
- monitorState,
736
- actionsById,
737
- nextActionId,
738
- stagedActionIds,
739
- skippedActionIds,
740
- committedState,
741
- currentStateIndex,
742
- computedStates,
743
- isLocked,
744
- isPaused,
745
- } = liftedAction.nextLiftedState);
746
- break;
747
- }
748
- case INIT: {
749
- // Always recompute states on hot reload and init.
750
- minInvalidatedStateIndex = 0;
751
- if (options.maxAge && stagedActionIds.length > options.maxAge) {
752
- // States must be recomputed before committing excess.
753
- computedStates = recomputeStates(computedStates, minInvalidatedStateIndex, reducer, committedState, actionsById, stagedActionIds, skippedActionIds, errorHandler, isPaused);
754
- commitExcessActions(stagedActionIds.length - options.maxAge);
755
- // Avoid double computation.
756
- minInvalidatedStateIndex = Infinity;
757
- }
758
- break;
759
- }
760
- case UPDATE: {
761
- const stateHasErrors = computedStates.filter((state) => state.error).length > 0;
762
- if (stateHasErrors) {
763
- // Recompute all states
764
- minInvalidatedStateIndex = 0;
765
- if (options.maxAge && stagedActionIds.length > options.maxAge) {
766
- // States must be recomputed before committing excess.
767
- computedStates = recomputeStates(computedStates, minInvalidatedStateIndex, reducer, committedState, actionsById, stagedActionIds, skippedActionIds, errorHandler, isPaused);
768
- commitExcessActions(stagedActionIds.length - options.maxAge);
769
- // Avoid double computation.
770
- minInvalidatedStateIndex = Infinity;
771
- }
772
- }
773
- else {
774
- // If not paused/locked, add a new action to signal devtools-user
775
- // that there was a reducer update.
776
- if (!isPaused && !isLocked) {
777
- if (currentStateIndex === stagedActionIds.length - 1) {
778
- currentStateIndex++;
779
- }
780
- // Add a new action to only recompute state
781
- const actionId = nextActionId++;
782
- actionsById[actionId] = new PerformAction(liftedAction, +Date.now());
783
- stagedActionIds = [...stagedActionIds, actionId];
784
- minInvalidatedStateIndex = stagedActionIds.length - 1;
785
- computedStates = recomputeStates(computedStates, minInvalidatedStateIndex, reducer, committedState, actionsById, stagedActionIds, skippedActionIds, errorHandler, isPaused);
786
- }
787
- // Recompute state history with latest reducer and update action
788
- computedStates = computedStates.map((cmp) => ({
789
- ...cmp,
790
- state: reducer(cmp.state, RECOMPUTE_ACTION),
791
- }));
792
- currentStateIndex = stagedActionIds.length - 1;
793
- if (options.maxAge && stagedActionIds.length > options.maxAge) {
794
- commitExcessActions(stagedActionIds.length - options.maxAge);
795
- }
796
- // Avoid double computation.
797
- minInvalidatedStateIndex = Infinity;
798
- }
799
- break;
800
- }
801
- default: {
802
- // If the action is not recognized, it's a monitor action.
803
- // Optimization: a monitor action can't change history.
804
- minInvalidatedStateIndex = Infinity;
805
- break;
541
+ minInvalidatedStateIndex = stagedActionIds.indexOf(actionId);
542
+ break;
543
+ }
544
+ case SET_ACTIONS_ACTIVE: {
545
+ const { start, end, active } = liftedAction;
546
+ const actionIds = [];
547
+ for (let i = start; i < end; i++)
548
+ actionIds.push(i);
549
+ if (active) {
550
+ skippedActionIds = difference(skippedActionIds, actionIds);
551
+ } else {
552
+ skippedActionIds = [...skippedActionIds, ...actionIds];
553
+ }
554
+ minInvalidatedStateIndex = stagedActionIds.indexOf(start);
555
+ break;
556
+ }
557
+ case JUMP_TO_STATE: {
558
+ currentStateIndex = liftedAction.index;
559
+ minInvalidatedStateIndex = Infinity;
560
+ break;
561
+ }
562
+ case JUMP_TO_ACTION: {
563
+ const index = stagedActionIds.indexOf(liftedAction.actionId);
564
+ if (index !== -1)
565
+ currentStateIndex = index;
566
+ minInvalidatedStateIndex = Infinity;
567
+ break;
568
+ }
569
+ case SWEEP: {
570
+ stagedActionIds = difference(stagedActionIds, skippedActionIds);
571
+ skippedActionIds = [];
572
+ currentStateIndex = Math.min(currentStateIndex, stagedActionIds.length - 1);
573
+ break;
574
+ }
575
+ case PERFORM_ACTION: {
576
+ if (isLocked) {
577
+ return liftedState || initialLiftedState;
578
+ }
579
+ if (isPaused || liftedState && isActionFiltered(liftedState.computedStates[currentStateIndex], liftedAction, options.predicate, options.actionsSafelist, options.actionsBlocklist)) {
580
+ const lastState = computedStates[computedStates.length - 1];
581
+ computedStates = [
582
+ ...computedStates.slice(0, -1),
583
+ computeNextEntry(reducer, liftedAction.action, lastState.state, lastState.error, errorHandler)
584
+ ];
585
+ minInvalidatedStateIndex = Infinity;
586
+ break;
587
+ }
588
+ if (options.maxAge && stagedActionIds.length === options.maxAge) {
589
+ commitExcessActions(1);
590
+ }
591
+ if (currentStateIndex === stagedActionIds.length - 1) {
592
+ currentStateIndex++;
593
+ }
594
+ const actionId = nextActionId++;
595
+ actionsById[actionId] = liftedAction;
596
+ stagedActionIds = [...stagedActionIds, actionId];
597
+ minInvalidatedStateIndex = stagedActionIds.length - 1;
598
+ break;
599
+ }
600
+ case IMPORT_STATE: {
601
+ ({
602
+ monitorState,
603
+ actionsById,
604
+ nextActionId,
605
+ stagedActionIds,
606
+ skippedActionIds,
607
+ committedState,
608
+ currentStateIndex,
609
+ computedStates,
610
+ isLocked,
611
+ isPaused
612
+ } = liftedAction.nextLiftedState);
613
+ break;
614
+ }
615
+ case INIT: {
616
+ minInvalidatedStateIndex = 0;
617
+ if (options.maxAge && stagedActionIds.length > options.maxAge) {
618
+ computedStates = recomputeStates(computedStates, minInvalidatedStateIndex, reducer, committedState, actionsById, stagedActionIds, skippedActionIds, errorHandler, isPaused);
619
+ commitExcessActions(stagedActionIds.length - options.maxAge);
620
+ minInvalidatedStateIndex = Infinity;
621
+ }
622
+ break;
623
+ }
624
+ case UPDATE2: {
625
+ const stateHasErrors = computedStates.filter((state) => state.error).length > 0;
626
+ if (stateHasErrors) {
627
+ minInvalidatedStateIndex = 0;
628
+ if (options.maxAge && stagedActionIds.length > options.maxAge) {
629
+ computedStates = recomputeStates(computedStates, minInvalidatedStateIndex, reducer, committedState, actionsById, stagedActionIds, skippedActionIds, errorHandler, isPaused);
630
+ commitExcessActions(stagedActionIds.length - options.maxAge);
631
+ minInvalidatedStateIndex = Infinity;
632
+ }
633
+ } else {
634
+ if (!isPaused && !isLocked) {
635
+ if (currentStateIndex === stagedActionIds.length - 1) {
636
+ currentStateIndex++;
806
637
  }
638
+ const actionId = nextActionId++;
639
+ actionsById[actionId] = new PerformAction(liftedAction, +Date.now());
640
+ stagedActionIds = [...stagedActionIds, actionId];
641
+ minInvalidatedStateIndex = stagedActionIds.length - 1;
642
+ computedStates = recomputeStates(computedStates, minInvalidatedStateIndex, reducer, committedState, actionsById, stagedActionIds, skippedActionIds, errorHandler, isPaused);
643
+ }
644
+ computedStates = computedStates.map((cmp) => ({
645
+ ...cmp,
646
+ state: reducer(cmp.state, RECOMPUTE_ACTION)
647
+ }));
648
+ currentStateIndex = stagedActionIds.length - 1;
649
+ if (options.maxAge && stagedActionIds.length > options.maxAge) {
650
+ commitExcessActions(stagedActionIds.length - options.maxAge);
651
+ }
652
+ minInvalidatedStateIndex = Infinity;
807
653
  }
808
- computedStates = recomputeStates(computedStates, minInvalidatedStateIndex, reducer, committedState, actionsById, stagedActionIds, skippedActionIds, errorHandler, isPaused);
809
- monitorState = monitorReducer(monitorState, liftedAction);
810
- return {
811
- monitorState,
812
- actionsById,
813
- nextActionId,
814
- stagedActionIds,
815
- skippedActionIds,
816
- committedState,
817
- currentStateIndex,
818
- computedStates,
819
- isLocked,
820
- isPaused,
821
- };
654
+ break;
655
+ }
656
+ default: {
657
+ minInvalidatedStateIndex = Infinity;
658
+ break;
659
+ }
660
+ }
661
+ computedStates = recomputeStates(computedStates, minInvalidatedStateIndex, reducer, committedState, actionsById, stagedActionIds, skippedActionIds, errorHandler, isPaused);
662
+ monitorState = monitorReducer(monitorState, liftedAction);
663
+ return {
664
+ monitorState,
665
+ actionsById,
666
+ nextActionId,
667
+ stagedActionIds,
668
+ skippedActionIds,
669
+ committedState,
670
+ currentStateIndex,
671
+ computedStates,
672
+ isLocked,
673
+ isPaused
822
674
  };
675
+ };
823
676
  }
824
677
 
825
- class StoreDevtools {
826
- constructor(dispatcher, actions$, reducers$, extension, scannedActions, errorHandler, initialState, config) {
827
- const liftedInitialState = liftInitialState(initialState, config.monitor);
828
- const liftReducer = liftReducerWith(initialState, liftedInitialState, errorHandler, config.monitor, config);
829
- const liftedAction$ = merge(merge(actions$.asObservable().pipe(skip(1)), extension.actions$).pipe(map(liftAction)), dispatcher, extension.liftedActions$).pipe(observeOn(queueScheduler));
830
- const liftedReducer$ = reducers$.pipe(map(liftReducer));
831
- const zoneConfig = injectZoneConfig(config.connectInZone);
832
- const liftedStateSubject = new ReplaySubject(1);
833
- this.liftedStateSubscription = liftedAction$
834
- .pipe(withLatestFrom(liftedReducer$),
835
- // The extension would post messages back outside of the Angular zone
836
- // because we call `connect()` wrapped with `runOutsideAngular`. We run change
837
- // detection only once at the end after all the required asynchronous tasks have
838
- // been processed (for instance, `setInterval` scheduled by the `timeout` operator).
839
- // We have to re-enter the Angular zone before the `scan` since it runs the reducer
840
- // which must be run within the Angular zone.
841
- emitInZone(zoneConfig), scan(({ state: liftedState }, [action, reducer]) => {
842
- let reducedLiftedState = reducer(liftedState, action);
843
- // On full state update
844
- // If we have actions filters, we must filter completely our lifted state to be sync with the extension
845
- if (action.type !== PERFORM_ACTION && shouldFilterActions(config)) {
846
- reducedLiftedState = filterLiftedState(reducedLiftedState, config.predicate, config.actionsSafelist, config.actionsBlocklist);
847
- }
848
- // Extension should be sent the sanitized lifted state
849
- extension.notify(action, reducedLiftedState);
850
- return { state: reducedLiftedState, action };
851
- }, { state: liftedInitialState, action: null }))
852
- .subscribe(({ state, action }) => {
853
- liftedStateSubject.next(state);
854
- if (action.type === PERFORM_ACTION) {
855
- const unliftedAction = action.action;
856
- scannedActions.next(unliftedAction);
857
- }
858
- });
859
- this.extensionStartSubscription = extension.start$
860
- .pipe(emitInZone(zoneConfig))
861
- .subscribe(() => {
862
- this.refresh();
863
- });
864
- const liftedState$ = liftedStateSubject.asObservable();
865
- const state$ = liftedState$.pipe(map(unliftState));
866
- Object.defineProperty(state$, 'state', {
867
- value: toSignal(state$, { manualCleanup: true, requireSync: true }),
868
- });
869
- this.dispatcher = dispatcher;
870
- this.liftedState = liftedState$;
871
- this.state = state$;
872
- }
873
- ngOnDestroy() {
874
- // Even though the store devtools plugin is recommended to be
875
- // used only in development mode, it can still cause a memory leak
876
- // in microfrontend applications that are being created and destroyed
877
- // multiple times during development. This results in excessive memory
878
- // consumption, as it prevents entire apps from being garbage collected.
879
- this.liftedStateSubscription.unsubscribe();
880
- this.extensionStartSubscription.unsubscribe();
881
- }
882
- dispatch(action) {
883
- this.dispatcher.next(action);
884
- }
885
- next(action) {
886
- this.dispatcher.next(action);
887
- }
888
- error(error) { }
889
- complete() { }
890
- performAction(action) {
891
- this.dispatch(new PerformAction(action, +Date.now()));
892
- }
893
- refresh() {
894
- this.dispatch(new Refresh());
895
- }
896
- reset() {
897
- this.dispatch(new Reset(+Date.now()));
898
- }
899
- rollback() {
900
- this.dispatch(new Rollback(+Date.now()));
901
- }
902
- commit() {
903
- this.dispatch(new Commit(+Date.now()));
904
- }
905
- sweep() {
906
- this.dispatch(new Sweep());
907
- }
908
- toggleAction(id) {
909
- this.dispatch(new ToggleAction(id));
910
- }
911
- jumpToAction(actionId) {
912
- this.dispatch(new JumpToAction(actionId));
913
- }
914
- jumpToState(index) {
915
- this.dispatch(new JumpToState(index));
916
- }
917
- importState(nextLiftedState) {
918
- this.dispatch(new ImportState(nextLiftedState));
919
- }
920
- lockChanges(status) {
921
- this.dispatch(new LockChanges(status));
922
- }
923
- pauseRecording(status) {
924
- this.dispatch(new PauseRecording(status));
925
- }
926
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: StoreDevtools, deps: [{ token: DevtoolsDispatcher }, { token: i2.ActionsSubject }, { token: i2.ReducerObservable }, { token: DevtoolsExtension }, { token: i2.ScannedActionsSubject }, { token: i0.ErrorHandler }, { token: INITIAL_STATE }, { token: STORE_DEVTOOLS_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable }); }
927
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: StoreDevtools }); }
928
- }
929
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: StoreDevtools, decorators: [{
930
- type: Injectable
931
- }], ctorParameters: () => [{ type: DevtoolsDispatcher }, { type: i2.ActionsSubject }, { type: i2.ReducerObservable }, { type: DevtoolsExtension }, { type: i2.ScannedActionsSubject }, { type: i0.ErrorHandler }, { type: undefined, decorators: [{
932
- type: Inject,
933
- args: [INITIAL_STATE]
934
- }] }, { type: StoreDevtoolsConfig, decorators: [{
935
- type: Inject,
936
- args: [STORE_DEVTOOLS_CONFIG]
937
- }] }] });
938
- /**
939
- * If the devtools extension is connected out of the Angular zone,
940
- * this operator will emit all events within the zone.
941
- */
942
- function emitInZone({ ngZone, connectInZone, }) {
943
- return (source) => connectInZone
944
- ? new Observable((subscriber) => source.subscribe({
945
- next: (value) => ngZone.run(() => subscriber.next(value)),
946
- error: (error) => ngZone.run(() => subscriber.error(error)),
947
- complete: () => ngZone.run(() => subscriber.complete()),
948
- }))
949
- : source;
678
+ // src/devtools.mjs
679
+ import { Injectable as Injectable3, Inject as Inject2 } from "@angular/core";
680
+ import { toSignal } from "@angular/core/rxjs-interop";
681
+ import { INITIAL_STATE } from "@ngrx/store";
682
+ import { merge, Observable as Observable2, queueScheduler, ReplaySubject } from "rxjs";
683
+ import { map as map2, observeOn, scan, skip, withLatestFrom } from "rxjs/operators";
684
+ import * as i03 from "@angular/core";
685
+ import * as i2 from "@ngrx/store";
686
+ var StoreDevtools = class _StoreDevtools {
687
+ constructor(dispatcher, actions$, reducers$, extension, scannedActions, errorHandler, initialState, config) {
688
+ const liftedInitialState = liftInitialState(initialState, config.monitor);
689
+ const liftReducer = liftReducerWith(initialState, liftedInitialState, errorHandler, config.monitor, config);
690
+ const liftedAction$ = merge(merge(actions$.asObservable().pipe(skip(1)), extension.actions$).pipe(map2(liftAction)), dispatcher, extension.liftedActions$).pipe(observeOn(queueScheduler));
691
+ const liftedReducer$ = reducers$.pipe(map2(liftReducer));
692
+ const zoneConfig = injectZoneConfig(config.connectInZone);
693
+ const liftedStateSubject = new ReplaySubject(1);
694
+ this.liftedStateSubscription = liftedAction$.pipe(
695
+ withLatestFrom(liftedReducer$),
696
+ // The extension would post messages back outside of the Angular zone
697
+ // because we call `connect()` wrapped with `runOutsideAngular`. We run change
698
+ // detection only once at the end after all the required asynchronous tasks have
699
+ // been processed (for instance, `setInterval` scheduled by the `timeout` operator).
700
+ // We have to re-enter the Angular zone before the `scan` since it runs the reducer
701
+ // which must be run within the Angular zone.
702
+ emitInZone(zoneConfig),
703
+ scan(({ state: liftedState }, [action, reducer]) => {
704
+ let reducedLiftedState = reducer(liftedState, action);
705
+ if (action.type !== PERFORM_ACTION && shouldFilterActions(config)) {
706
+ reducedLiftedState = filterLiftedState(reducedLiftedState, config.predicate, config.actionsSafelist, config.actionsBlocklist);
707
+ }
708
+ extension.notify(action, reducedLiftedState);
709
+ return { state: reducedLiftedState, action };
710
+ }, { state: liftedInitialState, action: null })
711
+ ).subscribe(({ state, action }) => {
712
+ liftedStateSubject.next(state);
713
+ if (action.type === PERFORM_ACTION) {
714
+ const unliftedAction = action.action;
715
+ scannedActions.next(unliftedAction);
716
+ }
717
+ });
718
+ this.extensionStartSubscription = extension.start$.pipe(emitInZone(zoneConfig)).subscribe(() => {
719
+ this.refresh();
720
+ });
721
+ const liftedState$ = liftedStateSubject.asObservable();
722
+ const state$ = liftedState$.pipe(map2(unliftState));
723
+ Object.defineProperty(state$, "state", {
724
+ value: toSignal(state$, { manualCleanup: true, requireSync: true })
725
+ });
726
+ this.dispatcher = dispatcher;
727
+ this.liftedState = liftedState$;
728
+ this.state = state$;
729
+ }
730
+ ngOnDestroy() {
731
+ this.liftedStateSubscription.unsubscribe();
732
+ this.extensionStartSubscription.unsubscribe();
733
+ }
734
+ dispatch(action) {
735
+ this.dispatcher.next(action);
736
+ }
737
+ next(action) {
738
+ this.dispatcher.next(action);
739
+ }
740
+ error(error) {
741
+ }
742
+ complete() {
743
+ }
744
+ performAction(action) {
745
+ this.dispatch(new PerformAction(action, +Date.now()));
746
+ }
747
+ refresh() {
748
+ this.dispatch(new Refresh());
749
+ }
750
+ reset() {
751
+ this.dispatch(new Reset(+Date.now()));
752
+ }
753
+ rollback() {
754
+ this.dispatch(new Rollback(+Date.now()));
755
+ }
756
+ commit() {
757
+ this.dispatch(new Commit(+Date.now()));
758
+ }
759
+ sweep() {
760
+ this.dispatch(new Sweep());
761
+ }
762
+ toggleAction(id) {
763
+ this.dispatch(new ToggleAction(id));
764
+ }
765
+ jumpToAction(actionId) {
766
+ this.dispatch(new JumpToAction(actionId));
767
+ }
768
+ jumpToState(index) {
769
+ this.dispatch(new JumpToState(index));
770
+ }
771
+ importState(nextLiftedState) {
772
+ this.dispatch(new ImportState(nextLiftedState));
773
+ }
774
+ lockChanges(status) {
775
+ this.dispatch(new LockChanges(status));
776
+ }
777
+ pauseRecording(status) {
778
+ this.dispatch(new PauseRecording(status));
779
+ }
780
+ static {
781
+ this.ɵfac = i03.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.0-next.6", ngImport: i03, type: _StoreDevtools, deps: [{ token: DevtoolsDispatcher }, { token: i2.ActionsSubject }, { token: i2.ReducerObservable }, { token: DevtoolsExtension }, { token: i2.ScannedActionsSubject }, { token: i03.ErrorHandler }, { token: INITIAL_STATE }, { token: STORE_DEVTOOLS_CONFIG }], target: i03.ɵɵFactoryTarget.Injectable });
782
+ }
783
+ static {
784
+ this.ɵprov = i03.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.0-next.6", ngImport: i03, type: _StoreDevtools });
785
+ }
786
+ };
787
+ i03.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.0-next.6", ngImport: i03, type: StoreDevtools, decorators: [{
788
+ type: Injectable3
789
+ }], ctorParameters: () => [{ type: DevtoolsDispatcher }, { type: i2.ActionsSubject }, { type: i2.ReducerObservable }, { type: DevtoolsExtension }, { type: i2.ScannedActionsSubject }, { type: i03.ErrorHandler }, { type: void 0, decorators: [{
790
+ type: Inject2,
791
+ args: [INITIAL_STATE]
792
+ }] }, { type: StoreDevtoolsConfig, decorators: [{
793
+ type: Inject2,
794
+ args: [STORE_DEVTOOLS_CONFIG]
795
+ }] }] });
796
+ function emitInZone({ ngZone, connectInZone }) {
797
+ return (source) => connectInZone ? new Observable2((subscriber) => source.subscribe({
798
+ next: (value) => ngZone.run(() => subscriber.next(value)),
799
+ error: (error) => ngZone.run(() => subscriber.error(error)),
800
+ complete: () => ngZone.run(() => subscriber.complete())
801
+ })) : source;
950
802
  }
951
803
 
952
- const IS_EXTENSION_OR_MONITOR_PRESENT = new InjectionToken('@ngrx/store-devtools Is Devtools Extension or Monitor Present');
804
+ // src/provide-store-devtools.mjs
805
+ import { InjectionToken as InjectionToken3, makeEnvironmentProviders } from "@angular/core";
806
+ import { ReducerManagerDispatcher, StateObservable } from "@ngrx/store";
807
+ var IS_EXTENSION_OR_MONITOR_PRESENT = new InjectionToken3("@ngrx/store-devtools Is Devtools Extension or Monitor Present");
953
808
  function createIsExtensionOrMonitorPresent(extension, config) {
954
- return Boolean(extension) || config.monitor !== noMonitor;
809
+ return Boolean(extension) || config.monitor !== noMonitor;
955
810
  }
956
811
  function createReduxDevtoolsExtension() {
957
- const extensionKey = '__REDUX_DEVTOOLS_EXTENSION__';
958
- if (typeof window === 'object' &&
959
- typeof window[extensionKey] !== 'undefined') {
960
- return window[extensionKey];
961
- }
962
- else {
963
- return null;
964
- }
812
+ const extensionKey = "__REDUX_DEVTOOLS_EXTENSION__";
813
+ if (typeof window === "object" && typeof window[extensionKey] !== "undefined") {
814
+ return window[extensionKey];
815
+ } else {
816
+ return null;
817
+ }
965
818
  }
966
- /**
967
- * Provides developer tools and instrumentation for `Store`.
968
- *
969
- * @usageNotes
970
- *
971
- * ```ts
972
- * bootstrapApplication(AppComponent, {
973
- * providers: [
974
- * provideStoreDevtools({
975
- * maxAge: 25,
976
- * logOnly: !isDevMode(),
977
- * }),
978
- * ],
979
- * });
980
- * ```
981
- */
982
819
  function provideStoreDevtools(options = {}) {
983
- return makeEnvironmentProviders([
984
- DevtoolsExtension,
985
- DevtoolsDispatcher,
986
- StoreDevtools,
987
- {
988
- provide: INITIAL_OPTIONS,
989
- useValue: options,
990
- },
991
- {
992
- provide: IS_EXTENSION_OR_MONITOR_PRESENT,
993
- deps: [REDUX_DEVTOOLS_EXTENSION, STORE_DEVTOOLS_CONFIG],
994
- useFactory: createIsExtensionOrMonitorPresent,
995
- },
996
- {
997
- provide: REDUX_DEVTOOLS_EXTENSION,
998
- useFactory: createReduxDevtoolsExtension,
999
- },
1000
- {
1001
- provide: STORE_DEVTOOLS_CONFIG,
1002
- deps: [INITIAL_OPTIONS],
1003
- useFactory: createConfig,
1004
- },
1005
- {
1006
- provide: StateObservable,
1007
- deps: [StoreDevtools],
1008
- useFactory: createStateObservable,
1009
- },
1010
- {
1011
- provide: ReducerManagerDispatcher,
1012
- useExisting: DevtoolsDispatcher,
1013
- },
1014
- ]);
820
+ return makeEnvironmentProviders([
821
+ DevtoolsExtension,
822
+ DevtoolsDispatcher,
823
+ StoreDevtools,
824
+ {
825
+ provide: INITIAL_OPTIONS,
826
+ useValue: options
827
+ },
828
+ {
829
+ provide: IS_EXTENSION_OR_MONITOR_PRESENT,
830
+ deps: [REDUX_DEVTOOLS_EXTENSION, STORE_DEVTOOLS_CONFIG],
831
+ useFactory: createIsExtensionOrMonitorPresent
832
+ },
833
+ {
834
+ provide: REDUX_DEVTOOLS_EXTENSION,
835
+ useFactory: createReduxDevtoolsExtension
836
+ },
837
+ {
838
+ provide: STORE_DEVTOOLS_CONFIG,
839
+ deps: [INITIAL_OPTIONS],
840
+ useFactory: createConfig
841
+ },
842
+ {
843
+ provide: StateObservable,
844
+ deps: [StoreDevtools],
845
+ useFactory: createStateObservable
846
+ },
847
+ {
848
+ provide: ReducerManagerDispatcher,
849
+ useExisting: DevtoolsDispatcher
850
+ }
851
+ ]);
1015
852
  }
1016
853
 
854
+ // src/instrument.mjs
855
+ import { NgModule } from "@angular/core";
856
+ import * as i04 from "@angular/core";
1017
857
  function createStateObservable(devtools) {
1018
- return devtools.state;
858
+ return devtools.state;
1019
859
  }
1020
- class StoreDevtoolsModule {
1021
- static instrument(options = {}) {
1022
- return {
1023
- ngModule: StoreDevtoolsModule,
1024
- providers: [provideStoreDevtools(options)],
1025
- };
1026
- }
1027
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: StoreDevtoolsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1028
- /** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.0.0", ngImport: i0, type: StoreDevtoolsModule }); }
1029
- /** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: StoreDevtoolsModule }); }
1030
- }
1031
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: StoreDevtoolsModule, decorators: [{
1032
- type: NgModule,
1033
- args: [{}]
1034
- }] });
1035
-
1036
- /**
1037
- * DO NOT EDIT
1038
- *
1039
- * This file is automatically generated at build
1040
- */
1041
-
1042
- /**
1043
- * Generated bundle index. Do not edit.
1044
- */
1045
-
1046
- export { INITIAL_OPTIONS, RECOMPUTE, REDUX_DEVTOOLS_EXTENSION, StoreDevtools, StoreDevtoolsConfig, StoreDevtoolsModule, provideStoreDevtools };
860
+ var StoreDevtoolsModule = class _StoreDevtoolsModule {
861
+ static instrument(options = {}) {
862
+ return {
863
+ ngModule: _StoreDevtoolsModule,
864
+ providers: [provideStoreDevtools(options)]
865
+ };
866
+ }
867
+ static {
868
+ this.ɵfac = i04.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.0-next.6", ngImport: i04, type: _StoreDevtoolsModule, deps: [], target: i04.ɵɵFactoryTarget.NgModule });
869
+ }
870
+ static {
871
+ this.ɵmod = i04.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.0.0-next.6", ngImport: i04, type: _StoreDevtoolsModule });
872
+ }
873
+ static {
874
+ this.ɵinj = i04.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.0.0-next.6", ngImport: i04, type: _StoreDevtoolsModule });
875
+ }
876
+ };
877
+ i04.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.0-next.6", ngImport: i04, type: StoreDevtoolsModule, decorators: [{
878
+ type: NgModule,
879
+ args: [{}]
880
+ }] });
881
+ export {
882
+ INITIAL_OPTIONS,
883
+ RECOMPUTE,
884
+ REDUX_DEVTOOLS_EXTENSION,
885
+ StoreDevtools,
886
+ StoreDevtoolsConfig,
887
+ StoreDevtoolsModule,
888
+ provideStoreDevtools
889
+ };
1047
890
  //# sourceMappingURL=ngrx-store-devtools.mjs.map