0
# Core Debugging Service
1
2
The main devtools service providing programmatic access to debugging functionality including time-travel operations, state inspection, and recording controls.
3
4
## Capabilities
5
6
### StoreDevtools Service
7
8
Core service that manages devtools state and provides debugging methods.
9
10
```typescript { .api }
11
/**
12
* Main devtools service implementing Observer pattern for action handling
13
*/
14
class StoreDevtools implements Observer<any>, OnDestroy {
15
/** Action dispatcher for devtools actions */
16
dispatcher: ActionsSubject;
17
/** Observable of enhanced state with devtools metadata */
18
liftedState: Observable<LiftedState>;
19
/** Observable of current application state */
20
state: StateObservable;
21
22
/**
23
* Dispatch an action through the devtools system
24
* @param action - Action to dispatch
25
*/
26
dispatch(action: Action): void;
27
28
/**
29
* Observer interface method for handling next action
30
* @param action - Action to handle
31
*/
32
next(action: any): void;
33
34
/**
35
* Observer interface method for handling errors
36
* @param error - Error to handle
37
*/
38
error(error: any): void;
39
40
/**
41
* Observer interface method for completion
42
*/
43
complete(): void;
44
45
/**
46
* Perform a user action through the devtools system
47
* @param action - User action to perform
48
*/
49
performAction(action: any): void;
50
51
/**
52
* Refresh the devtools state
53
*/
54
refresh(): void;
55
56
/**
57
* Reset the devtools to initial state
58
*/
59
reset(): void;
60
61
/**
62
* Rollback to the previous committed state
63
*/
64
rollback(): void;
65
66
/**
67
* Commit the current state as the new baseline
68
*/
69
commit(): void;
70
71
/**
72
* Remove all skipped actions from history
73
*/
74
sweep(): void;
75
76
/**
77
* Toggle an action between active and inactive state
78
* @param id - ID of the action to toggle
79
*/
80
toggleAction(id: number): void;
81
82
/**
83
* Jump to a specific action in the history
84
* @param actionId - ID of the action to jump to
85
*/
86
jumpToAction(actionId: number): void;
87
88
/**
89
* Jump to a specific state index in the history
90
* @param index - Index of the state to jump to
91
*/
92
jumpToState(index: number): void;
93
94
/**
95
* Import a previously exported state
96
* @param nextLiftedState - Lifted state to import
97
*/
98
importState(nextLiftedState: any): void;
99
100
/**
101
* Lock or unlock state changes
102
* @param status - True to lock changes, false to unlock
103
*/
104
lockChanges(status: boolean): void;
105
106
/**
107
* Pause or resume recording of actions
108
* @param status - True to pause recording, false to resume
109
*/
110
pauseRecording(status: boolean): void;
111
112
/**
113
* Cleanup method called when service is destroyed
114
*/
115
ngOnDestroy(): void;
116
}
117
```
118
119
**Usage Examples:**
120
121
```typescript
122
import { Component, OnInit } from "@angular/core";
123
import { StoreDevtools } from "@ngrx/store-devtools";
124
125
@Component({
126
selector: "app-debug-controls",
127
template: `
128
<button (click)="reset()">Reset</button>
129
<button (click)="commit()">Commit</button>
130
<button (click)="rollback()">Rollback</button>
131
<button (click)="toggleRecording()">
132
{{ isPaused ? 'Resume' : 'Pause' }} Recording
133
</button>
134
`,
135
})
136
export class DebugControlsComponent implements OnInit {
137
isPaused = false;
138
139
constructor(private devtools: StoreDevtools) {}
140
141
ngOnInit() {
142
// Subscribe to lifted state to monitor devtools state
143
this.devtools.liftedState.subscribe((liftedState) => {
144
this.isPaused = liftedState.isPaused;
145
console.log("Current action count:", liftedState.nextActionId);
146
});
147
}
148
149
reset() {
150
this.devtools.reset();
151
}
152
153
commit() {
154
this.devtools.commit();
155
}
156
157
rollback() {
158
this.devtools.rollback();
159
}
160
161
toggleRecording() {
162
this.devtools.pauseRecording(!this.isPaused);
163
}
164
}
165
```
166
167
### DevtoolsDispatcher
168
169
Specialized dispatcher extending ActionsSubject for devtools operations.
170
171
```typescript { .api }
172
/**
173
* Injectable dispatcher service extending ActionsSubject for devtools
174
*/
175
class DevtoolsDispatcher extends ActionsSubject {}
176
```
177
178
### Extension Integration Service
179
180
Service managing connection to Redux DevTools browser extension.
181
182
```typescript { .api }
183
/**
184
* Service for integrating with Redux DevTools browser extension
185
*/
186
class DevtoolsExtension {
187
/** Observable of actions from the extension */
188
actions$: Observable<any>;
189
/** Observable of lifted actions from the extension */
190
liftedActions$: Observable<any>;
191
/** Observable indicating when extension starts */
192
start$: Observable<any>;
193
194
/**
195
* Notify the extension of state changes
196
* @param action - Action that caused the change
197
* @param state - New lifted state
198
*/
199
notify(action: any, state: LiftedState): void;
200
}
201
202
/**
203
* Interface for Redux DevTools extension connection
204
*/
205
interface ReduxDevtoolsExtensionConnection {
206
/** Subscribe to extension changes */
207
subscribe(listener: (change: any) => void): void;
208
/** Unsubscribe from extension changes */
209
unsubscribe(): void;
210
/** Send action and state to extension */
211
send(action: any, state: any): void;
212
/** Initialize extension with state */
213
init(state: any): void;
214
/** Send error message to extension */
215
error(message: string): void;
216
}
217
218
/**
219
* Redux DevTools browser extension interface
220
*/
221
interface ReduxDevtoolsExtension {
222
connect(options?: any): ReduxDevtoolsExtensionConnection;
223
}
224
```
225
226
### State Observable Factory
227
228
Factory function for creating state observable from devtools service.
229
230
```typescript { .api }
231
/**
232
* Create state observable from devtools service
233
* @param devtools - StoreDevtools service instance
234
* @returns StateObservable for current application state
235
*/
236
function createStateObservable(devtools: StoreDevtools): StateObservable;
237
```
238
239
### Zone Configuration
240
241
Zone configuration utilities for controlling Angular zone behavior with devtools.
242
243
```typescript { .api }
244
/**
245
* Zone configuration type for devtools connection
246
*/
247
type ZoneConfig =
248
| { connectInZone: true; ngZone: NgZone }
249
| { connectInZone: false; ngZone: null };
250
251
/**
252
* Inject zone configuration based on connectInZone setting
253
* @param connectInZone - Whether to connect within Angular zone
254
* @returns Zone configuration object
255
*/
256
function injectZoneConfig(connectInZone: boolean): ZoneConfig;
257
```
258
259
**Advanced Usage Example:**
260
261
```typescript
262
import { Injectable } from "@angular/core";
263
import { StoreDevtools } from "@ngrx/store-devtools";
264
import { map, filter, take } from "rxjs/operators";
265
266
@Injectable({
267
providedIn: "root",
268
})
269
export class CustomDebuggingService {
270
constructor(private devtools: StoreDevtools) {}
271
272
// Monitor specific action types
273
watchActionType(actionType: string) {
274
return this.devtools.liftedState.pipe(
275
map((liftedState) => liftedState.actionsById),
276
map((actions) =>
277
Object.values(actions).filter((action) => action.action.type === actionType)
278
)
279
);
280
}
281
282
// Get current error state
283
getCurrentErrors() {
284
return this.devtools.liftedState.pipe(
285
map((liftedState) => liftedState.computedStates),
286
map((states) => states.filter((state) => state.error)),
287
filter((errorStates) => errorStates.length > 0)
288
);
289
}
290
291
// Jump to first occurrence of action type
292
jumpToFirstAction(actionType: string) {
293
this.devtools.liftedState.pipe(take(1)).subscribe((liftedState) => {
294
const actionId = Object.keys(liftedState.actionsById).find(
295
(id) => liftedState.actionsById[parseInt(id)].action.type === actionType
296
);
297
298
if (actionId) {
299
this.devtools.jumpToAction(parseInt(actionId));
300
}
301
});
302
}
303
304
// Export current devtools state
305
exportState() {
306
return this.devtools.liftedState.pipe(
307
take(1),
308
map((liftedState) => JSON.stringify(liftedState, null, 2))
309
);
310
}
311
312
// Import devtools state from JSON
313
importStateFromJson(jsonState: string) {
314
try {
315
const liftedState = JSON.parse(jsonState);
316
this.devtools.importState(liftedState);
317
} catch (error) {
318
console.error("Failed to import state:", error);
319
}
320
}
321
}
322
```