Skip to content

Commit 71349df

Browse files
feat(devtools): add provideDevtoolsConfig
`provideDevtoolsConfig` provides an option to define the name of the SignalStore in the Redux Devtools.
1 parent cef73de commit 71349df

File tree

6 files changed

+102
-4
lines changed

6 files changed

+102
-4
lines changed

docs/docs/with-redux.md

+33
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,36 @@ signalStore(
107107
})
108108
);
109109
```
110+
111+
### Configuring the Redux Devtools Extension
112+
113+
The `provideDevtoolsConfig` function allows you to configure the Redux DevTools integration for your NgRx SignalStore. This function is essential for setting up the DevTools with custom options. The function only needs to be called once in your appConfig or AppModule.
114+
115+
To use `provideDevtoolsConfig`, you need to import it and call it in your providers array.
116+
117+
Here is an example of how to use it with the standalone api:
118+
119+
```typescript
120+
// app.config.ts
121+
import { ApplicationConfig } from '@angular/core';
122+
import { provideDevtoolsConfig } from '@angular-architects/ngrx-toolkit';
123+
124+
export const appConfig: ApplicationConfig = {
125+
providers: [
126+
provideDevtoolsConfig({
127+
name: 'MyApp',
128+
}),
129+
],
130+
};
131+
132+
// main.ts
133+
import { bootstrapApplication } from '@angular/platform-browser';
134+
import { AppComponent } from './app/app.component';
135+
import { appConfig } from './app/app.config.ts';
136+
137+
await bootstrapApplication(AppComponent, appConfig);
138+
```
139+
140+
### Additional Information
141+
142+
For more details on the available options and their usage, refer to the [Redux DevTools Extension documentation](https://github.com/reduxjs/redux-devtools).

libs/ngrx-toolkit/src/index.ts

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ export { withMapper } from './lib/devtools/features/with-mapper';
55
export { withGlitchTracking } from './lib/devtools/features/with-glitch-tracking';
66
export { patchState, updateState } from './lib/devtools/update-state';
77
export { renameDevtoolsName } from './lib/devtools/rename-devtools-name';
8+
export {
9+
provideDevtoolsConfig,
10+
ReduxDevtoolsConfig,
11+
} from './lib/devtools/provide-devtools-config';
812

913
export {
1014
withRedux,

libs/ngrx-toolkit/src/lib/devtools/internal/devtools-syncer.service.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { StateSource } from '@ngrx/signals';
55
import { DevtoolsInnerOptions } from './devtools-feature';
66
import { throwIfNull } from '../../shared/throw-if-null';
77
import { Connection, StoreRegistry, Tracker } from './models';
8+
import { REDUX_DEVTOOLS_CONFIG } from '../provide-devtools-config';
89

910
const dummyConnection: Connection = {
1011
send: () => void true,
@@ -30,6 +31,10 @@ export class DevtoolsSyncer implements OnDestroy {
3031
#stores: StoreRegistry = {};
3132
readonly #isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
3233
readonly #trackers = [] as Tracker[];
34+
readonly #devtoolsConfig = {
35+
name: 'NgRx SignalStore',
36+
...inject(REDUX_DEVTOOLS_CONFIG, { optional: true }),
37+
};
3338

3439
/**
3540
* Maintains the current states of all stores to avoid conflicts
@@ -50,9 +55,7 @@ export class DevtoolsSyncer implements OnDestroy {
5055

5156
readonly #connection: Connection = this.#isBrowser
5257
? window.__REDUX_DEVTOOLS_EXTENSION__
53-
? window.__REDUX_DEVTOOLS_EXTENSION__.connect({
54-
name: 'NgRx SignalStore',
55-
})
58+
? window.__REDUX_DEVTOOLS_EXTENSION__.connect(this.#devtoolsConfig)
5659
: dummyConnection
5760
: dummyConnection;
5861

libs/ngrx-toolkit/src/lib/devtools/internal/models.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { StateSource } from '@ngrx/signals';
22
import { DevtoolsInnerOptions } from './devtools-feature';
3+
import { ReduxDevtoolsConfig } from '../provide-devtools-config';
34

45
export type Action = { type: string };
56
export type Connection = {
67
send: (action: Action, state: Record<string, unknown>) => void;
78
};
89
export type ReduxDevtoolsExtension = {
9-
connect: (options: { name: string }) => Connection;
10+
connect: (options: ReduxDevtoolsConfig) => Connection;
1011
};
1112

1213
export type StoreRegistry = Record<
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { InjectionToken, ValueProvider } from '@angular/core';
2+
3+
/**
4+
* Provides the configuration options for connecting to the Redux DevTools Extension.
5+
*/
6+
export function provideDevtoolsConfig(
7+
config: ReduxDevtoolsConfig
8+
): ValueProvider {
9+
return {
10+
provide: REDUX_DEVTOOLS_CONFIG,
11+
useValue: config,
12+
};
13+
}
14+
15+
/**
16+
* Injection token for the configuration options for connecting to the Redux DevTools Extension.
17+
*/
18+
export const REDUX_DEVTOOLS_CONFIG = new InjectionToken<ReduxDevtoolsConfig>(
19+
'ReduxDevtoolsConfig'
20+
);
21+
22+
/**
23+
* Options for connecting to the Redux DevTools Extension.
24+
* @example
25+
* const devToolsOptions: ReduxDevtoolsConfig = {
26+
* name: 'My App',
27+
* };
28+
*/
29+
export type ReduxDevtoolsConfig = {
30+
/** Optional name for the devtools instance. If empty, "NgRx SignalStore" will be used. */
31+
name?: string;
32+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { TestBed } from '@angular/core/testing';
2+
import { provideDevtoolsConfig } from '../provide-devtools-config';
3+
import { DevtoolsSyncer } from '../internal/devtools-syncer.service';
4+
import { setupExtensions } from './helpers.spec';
5+
6+
describe('provideDevtoolsConfig', () => {
7+
it('DevtoolsSyncer should use the default configuration if none is provided', () => {
8+
const { connectSpy } = setupExtensions();
9+
TestBed.inject(DevtoolsSyncer);
10+
expect(connectSpy).toHaveBeenCalledWith({
11+
name: 'NgRx SignalStore',
12+
});
13+
});
14+
15+
it('DevtoolsSyncer should use the configuration provided', () => {
16+
const { connectSpy } = setupExtensions();
17+
TestBed.configureTestingModule({
18+
providers: [provideDevtoolsConfig({ name: 'test' })],
19+
});
20+
TestBed.inject(DevtoolsSyncer);
21+
expect(connectSpy).toHaveBeenCalledWith({
22+
name: 'test',
23+
});
24+
});
25+
});

0 commit comments

Comments
 (0)