ngx-dev-toolbar 3.0.0 โ 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -1,77 +1,30 @@
|
|
|
1
|
-
# Angular
|
|
1
|
+
# Angular Toolbar
|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
4
|
|
|
5
|
-
[](https://github.com/alfredoperez/ngx-dev-toolbar)
|
|
5
|
+
[](https://www.npmjs.com/package/ngx-dev-toolbar)
|
|
6
|
+
[](https://www.npmjs.com/package/ngx-dev-toolbar)
|
|
7
|
+
[](https://angular.dev/)
|
|
8
|
+
[](LICENSE)
|
|
10
9
|
|
|
11
|
-
|
|
10
|
+
**A development toolbar for Angular applications.**
|
|
12
11
|
|
|
12
|
+
[Documentation](https://alfredoperez.github.io/ngx-dev-toolbar/) ยท [Demo](https://alfredoperez.github.io/ngx-dev-toolbar/)
|
|
13
13
|
|
|
14
|
-
[
|
|
14
|
+

|
|
15
15
|
|
|
16
16
|
</div>
|
|
17
17
|
|
|
18
|
+
## Features
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
- **Feature Flags** - Override feature flags without backend changes
|
|
21
|
+
- **Permissions** - Test different user permission states
|
|
22
|
+
- **App Features** - Toggle application features by tier
|
|
23
|
+
- **Language** - Switch languages instantly
|
|
24
|
+
- **Presets** - Save and load configuration presets
|
|
25
|
+
- **Zero Bundle Impact** - Dynamic imports exclude toolbar from production
|
|
20
26
|
|
|
21
|
-
|
|
22
|
-
<table>
|
|
23
|
-
<tr>
|
|
24
|
-
<td align="center">๐ฅ</td>
|
|
25
|
-
<td>Toggle feature flags without backend changes</td>
|
|
26
|
-
</tr>
|
|
27
|
-
<td align="center">๐</td>
|
|
28
|
-
<td>Switch languages instantly</td>
|
|
29
|
-
</tr>
|
|
30
|
-
<td align="center">๐จ</td>
|
|
31
|
-
<td>Switch themes on the fly</td>
|
|
32
|
-
</tr>
|
|
33
|
-
<td align="center">๐ค</td>
|
|
34
|
-
<td>Change user sessions effortlessly</td>
|
|
35
|
-
</tr>
|
|
36
|
-
<td align="center">๐</td>
|
|
37
|
-
<td>Mock network requests in real-time</td>
|
|
38
|
-
</tr>
|
|
39
|
-
</table>
|
|
40
|
-
</div>
|
|
41
|
-
|
|
42
|
-
No more context switching or backend dependencies - everything you need is right in your browser!
|
|
43
|
-
|
|
44
|
-
## ๐ฏ Features
|
|
45
|
-
|
|
46
|
-
<div class="feature-grid">
|
|
47
|
-
|
|
48
|
-
### ๐ฆ Available Tools
|
|
49
|
-
|
|
50
|
-
- Feature Flags
|
|
51
|
-
- Language Switcher
|
|
52
|
-
- Themes `Coming Soon`
|
|
53
|
-
- User Session `Coming Soon`
|
|
54
|
-
- Network Requests Mocker `Coming Soon`
|
|
55
|
-
|
|
56
|
-
### ๐ ๏ธ Extensible
|
|
57
|
-
|
|
58
|
-
- Create custom tools
|
|
59
|
-
- Add your own functionality
|
|
60
|
-
|
|
61
|
-
### ๐ Production Ready
|
|
62
|
-
|
|
63
|
-
- **Zero bundle impact** - Dynamic imports exclude toolbar from production builds
|
|
64
|
-
- No template changes needed
|
|
65
|
-
- Secure implementation
|
|
66
|
-
|
|
67
|
-
### ๐พ Persistent State
|
|
68
|
-
|
|
69
|
-
- Settings persist across reloads
|
|
70
|
-
- Import/Export configuration `Coming Soon`
|
|
71
|
-
|
|
72
|
-
</div>
|
|
73
|
-
|
|
74
|
-
## ๐ฑ Quick Start
|
|
27
|
+
## Quick Start
|
|
75
28
|
|
|
76
29
|
### 1. Install
|
|
77
30
|
|
|
@@ -83,16 +36,14 @@ npm install ngx-dev-toolbar
|
|
|
83
36
|
|
|
84
37
|
```typescript
|
|
85
38
|
import { bootstrapApplication } from '@angular/platform-browser';
|
|
86
|
-
import { AppComponent } from './app/app.component';
|
|
87
39
|
import { isDevMode } from '@angular/core';
|
|
88
40
|
|
|
89
41
|
async function bootstrap() {
|
|
90
42
|
const appRef = await bootstrapApplication(AppComponent, appConfig);
|
|
91
43
|
|
|
92
|
-
// Initialize toolbar only in development
|
|
93
44
|
if (isDevMode()) {
|
|
94
|
-
const {
|
|
95
|
-
|
|
45
|
+
const { initToolbar } = await import('ngx-dev-toolbar');
|
|
46
|
+
initToolbar(appRef);
|
|
96
47
|
}
|
|
97
48
|
}
|
|
98
49
|
|
|
@@ -101,304 +52,137 @@ bootstrap();
|
|
|
101
52
|
|
|
102
53
|
That's it! No template changes needed. The toolbar automatically attaches to the DOM.
|
|
103
54
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
```typescript
|
|
107
|
-
initDevToolbar(appRef, {
|
|
108
|
-
config: {
|
|
109
|
-
showFeatureFlagsTool: true,
|
|
110
|
-
showPermissionsTool: true,
|
|
111
|
-
showLanguageTool: true,
|
|
112
|
-
showAppFeaturesTool: true,
|
|
113
|
-
showPresetsTool: true,
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
## Available Tools
|
|
119
|
-
|
|
120
|
-
The tools come with a default implementation, but you can create your own tools and add them to the toolbar.
|
|
121
|
-
|
|
122
|
-
They have a service that you can use to interact with them.
|
|
55
|
+
## Tools
|
|
123
56
|
|
|
124
57
|
### Feature Flags
|
|
125
58
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
In order to use the feature flags tool, you need to import the `DevToolbarFeatureFlagService` and inject it in your component.
|
|
129
|
-
|
|
130
|
-
Then you just need to call the `setAvailableOptions` method with the available feature flags that can come from your backend or a third party service.
|
|
59
|
+
Configure available feature flags:
|
|
131
60
|
|
|
132
61
|
```typescript
|
|
133
|
-
import {
|
|
134
|
-
import { inject } from '@angular/core';
|
|
62
|
+
import { ToolbarFeatureFlagService } from 'ngx-dev-toolbar';
|
|
135
63
|
|
|
136
|
-
@Component({
|
|
137
|
-
// ... component decorator
|
|
138
|
-
})
|
|
64
|
+
@Component({...})
|
|
139
65
|
export class AppComponent {
|
|
140
|
-
private
|
|
66
|
+
private featureFlags = inject(ToolbarFeatureFlagService);
|
|
141
67
|
|
|
142
68
|
constructor() {
|
|
143
|
-
|
|
144
|
-
this.featureFlagsService.setAvailableOptions([
|
|
69
|
+
this.featureFlags.setAvailableOptions([
|
|
145
70
|
{ id: 'darkMode', name: 'Dark Mode' },
|
|
146
71
|
{ id: 'betaFeatures', name: 'Beta Features' },
|
|
147
|
-
{ id: 'experimentalUI', name: 'Experimental UI' },
|
|
148
72
|
]);
|
|
149
73
|
}
|
|
150
74
|
}
|
|
151
75
|
```
|
|
152
76
|
|
|
153
|
-
Once it is added you should see them in the Feature Flags tool in the Angular Dev Toolbar.
|
|
154
|
-
|
|
155
77
|

|
|
156
78
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
The toolbar provides two methods for retrieving feature flag values:
|
|
160
|
-
|
|
161
|
-
##### Option 1: Using `getValues()` (Recommended โจ)
|
|
162
|
-
|
|
163
|
-
The `getValues()` method returns ALL feature flags with overrides already applied, simplifying integration:
|
|
79
|
+
Get flags with overrides applied:
|
|
164
80
|
|
|
165
81
|
```typescript
|
|
166
|
-
@Component({
|
|
167
|
-
// ... component decorator
|
|
168
|
-
})
|
|
82
|
+
@Component({...})
|
|
169
83
|
export class FeatureComponent {
|
|
170
|
-
private
|
|
84
|
+
private featureFlags = inject(ToolbarFeatureFlagService);
|
|
171
85
|
|
|
172
86
|
ngOnInit() {
|
|
173
|
-
|
|
174
|
-
this.featureFlagsService.getValues().pipe(
|
|
87
|
+
this.featureFlags.getValues().pipe(
|
|
175
88
|
map(flags => flags.find(f => f.id === 'darkMode')),
|
|
176
89
|
map(flag => flag?.isEnabled ?? false)
|
|
177
90
|
).subscribe(isDarkMode => {
|
|
178
|
-
if (isDarkMode) {
|
|
179
|
-
// Apply dark mode logic
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
**Benefits:**
|
|
187
|
-
- โ
No manual merging with `combineLatest` needed
|
|
188
|
-
- โ
60-80% less integration code
|
|
189
|
-
- โ
Includes `isForced` property to identify overridden flags
|
|
190
|
-
- โ
Returns all flags (both overridden and natural state)
|
|
191
|
-
|
|
192
|
-
##### Option 2: Using `getForcedValues()` (Legacy)
|
|
193
|
-
|
|
194
|
-
The `getForcedValues()` method returns only flags that have been overridden:
|
|
195
|
-
|
|
196
|
-
```typescript
|
|
197
|
-
@Component({
|
|
198
|
-
// ... component decorator
|
|
199
|
-
})
|
|
200
|
-
export class FeatureComponent {
|
|
201
|
-
private featureFlagsService = inject(DevToolbarFeatureFlagService);
|
|
202
|
-
|
|
203
|
-
ngOnInit() {
|
|
204
|
-
this.featureFlagsService.getForcedValues().subscribe((forcedFlags) => {
|
|
205
|
-
const isDarkMode = forcedFlags.some((flag) => flag.id === 'darkMode');
|
|
206
91
|
// Apply dark mode logic
|
|
207
92
|
});
|
|
208
93
|
}
|
|
209
94
|
}
|
|
210
95
|
```
|
|
211
96
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
#### Dev Toolbar Interface
|
|
215
|
-
|
|
216
|
-
[Screenshot placeholder showing the feature flags interface in the dev toolbar]
|
|
217
|
-
|
|
218
|
-
### Language Switcher
|
|
219
|
-
|
|
220
|
-
#### Configuration
|
|
97
|
+
### Permissions
|
|
221
98
|
|
|
222
99
|
```typescript
|
|
223
|
-
import {
|
|
224
|
-
import { inject } from '@angular/core';
|
|
100
|
+
import { ToolbarPermissionsService } from 'ngx-dev-toolbar';
|
|
225
101
|
|
|
226
|
-
@Component({
|
|
227
|
-
// ... component decorator
|
|
228
|
-
})
|
|
102
|
+
@Component({...})
|
|
229
103
|
export class AppComponent {
|
|
230
|
-
private
|
|
104
|
+
private permissions = inject(ToolbarPermissionsService);
|
|
231
105
|
|
|
232
106
|
constructor() {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
{
|
|
236
|
-
{ code: 'es', name: 'Spanish' },
|
|
237
|
-
{ code: 'fr', name: 'French' },
|
|
107
|
+
this.permissions.setAvailableOptions([
|
|
108
|
+
{ id: 'admin', name: 'Admin Access' },
|
|
109
|
+
{ id: 'editor', name: 'Editor Access' },
|
|
238
110
|
]);
|
|
239
111
|
}
|
|
240
112
|
}
|
|
241
113
|
```
|
|
242
114
|
|
|
243
|
-
|
|
115
|
+
### App Features
|
|
244
116
|
|
|
245
117
|
```typescript
|
|
246
|
-
|
|
247
|
-
// ... component decorator
|
|
248
|
-
})
|
|
249
|
-
export class TranslatedComponent {
|
|
250
|
-
private languageService = inject(DevToolbarLanguageService);
|
|
118
|
+
import { ToolbarAppFeaturesService } from 'ngx-dev-toolbar';
|
|
251
119
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
120
|
+
@Component({...})
|
|
121
|
+
export class AppComponent {
|
|
122
|
+
private appFeatures = inject(ToolbarAppFeaturesService);
|
|
123
|
+
|
|
124
|
+
constructor() {
|
|
125
|
+
this.appFeatures.setAvailableOptions([
|
|
126
|
+
{ id: 'premium', name: 'Premium Features', tier: 'premium' },
|
|
127
|
+
{ id: 'basic', name: 'Basic Features', tier: 'basic' },
|
|
128
|
+
]);
|
|
258
129
|
}
|
|
259
130
|
}
|
|
260
131
|
```
|
|
261
132
|
|
|
262
|
-
|
|
133
|
+
### Language
|
|
263
134
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
If you're using the legacy `getForcedValues()` with manual `combineLatest` merging, you can simplify your code significantly:
|
|
135
|
+
```typescript
|
|
136
|
+
import { ToolbarLanguageService } from 'ngx-dev-toolbar';
|
|
267
137
|
|
|
268
|
-
|
|
138
|
+
@Component({...})
|
|
139
|
+
export class AppComponent {
|
|
140
|
+
private language = inject(ToolbarLanguageService);
|
|
269
141
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
getFlag(flagId: string): Observable<boolean> {
|
|
277
|
-
return combineLatest([
|
|
278
|
-
this.store.select(state => state.flags[flagId]),
|
|
279
|
-
this.devToolbar.getForcedValues().pipe(startWith([]))
|
|
280
|
-
]).pipe(
|
|
281
|
-
map(([baseValue, overrides]) => {
|
|
282
|
-
const override = overrides.find(o => o.id === flagId);
|
|
283
|
-
return override ? override.isEnabled : baseValue;
|
|
284
|
-
})
|
|
285
|
-
);
|
|
142
|
+
constructor() {
|
|
143
|
+
this.language.setAvailableOptions([
|
|
144
|
+
{ code: 'en', name: 'English' },
|
|
145
|
+
{ code: 'es', name: 'Spanish' },
|
|
146
|
+
{ code: 'fr', name: 'French' },
|
|
147
|
+
]);
|
|
286
148
|
}
|
|
287
149
|
}
|
|
288
150
|
```
|
|
289
151
|
|
|
290
|
-
|
|
152
|
+
## Configuration
|
|
291
153
|
|
|
292
|
-
|
|
293
|
-
@Injectable()
|
|
294
|
-
export class FeatureFlagService {
|
|
295
|
-
private store = inject(Store);
|
|
296
|
-
private devToolbar = inject(DevToolbarFeatureFlagService);
|
|
297
|
-
|
|
298
|
-
getFlag(flagId: string): Observable<boolean> {
|
|
299
|
-
return this.devToolbar.getValues().pipe(
|
|
300
|
-
map(flags => flags.find(f => f.id === flagId)),
|
|
301
|
-
map(flag => flag?.isEnabled ?? this.getBaseValue(flagId))
|
|
302
|
-
);
|
|
303
|
-
}
|
|
154
|
+
Customize which tools are visible:
|
|
304
155
|
|
|
305
|
-
|
|
306
|
-
|
|
156
|
+
```typescript
|
|
157
|
+
initToolbar(appRef, {
|
|
158
|
+
config: {
|
|
159
|
+
showFeatureFlagsTool: true,
|
|
160
|
+
showPermissionsTool: true,
|
|
161
|
+
showLanguageTool: true,
|
|
162
|
+
showAppFeaturesTool: true,
|
|
163
|
+
showPresetsTool: true,
|
|
307
164
|
}
|
|
308
|
-
}
|
|
165
|
+
});
|
|
309
166
|
```
|
|
310
167
|
|
|
311
|
-
|
|
312
|
-
- โ Removed `combineLatest` complexity
|
|
313
|
-
- โ Removed manual override merging logic
|
|
314
|
-
- โ
Single observable with merged state
|
|
315
|
-
- โ
~60% less code
|
|
316
|
-
|
|
317
|
-
### Available for All Tools
|
|
318
|
-
|
|
319
|
-
The `getValues()` method is available for:
|
|
320
|
-
- โ
**DevToolbarFeatureFlagService** - Feature flags with overrides
|
|
321
|
-
- โ
**DevToolbarPermissionsService** - Permissions with overrides
|
|
322
|
-
- โ
**DevToolbarAppFeaturesService** - App features with overrides
|
|
323
|
-
- โน๏ธ **DevToolbarLanguageService** - Returns forced language (same as `getForcedValues()`)
|
|
168
|
+
### Keyboard Shortcuts
|
|
324
169
|
|
|
325
|
-
|
|
170
|
+
- **Ctrl+Shift+D** - Toggle toolbar visibility
|
|
326
171
|
|
|
327
|
-
|
|
328
|
-
- `getValues()` - New, recommended method
|
|
329
|
-
- `getForcedValues()` - Legacy method, still supported
|
|
172
|
+
## API Reference
|
|
330
173
|
|
|
331
|
-
|
|
174
|
+
All tool services implement the `ToolbarService<T>` interface:
|
|
332
175
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
@Component({
|
|
339
|
-
imports: [DevToolbarComponent, DevToolbarToolComponent],
|
|
340
|
-
template: `
|
|
341
|
-
<ndt-toolbar>
|
|
342
|
-
<ndt-toolbar-tool [options]="options" [icon]="'bolt'" [title]="'My Tool'">
|
|
343
|
-
<p>Custom content here</p>
|
|
344
|
-
</ndt-toolbar-tool>
|
|
345
|
-
</ndt-toolbar>
|
|
346
|
-
`
|
|
347
|
-
})
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
Note: When using custom tools, the toolbar will be bundled with your application.
|
|
176
|
+
| Method | Description |
|
|
177
|
+
|--------|-------------|
|
|
178
|
+
| `setAvailableOptions(options: T[])` | Set options displayed in the tool |
|
|
179
|
+
| `getValues()` | Get all values with overrides applied |
|
|
180
|
+
| `getForcedValues()` | Get only overridden values |
|
|
351
181
|
|
|
352
182
|
## Contributing
|
|
353
183
|
|
|
354
|
-
|
|
184
|
+
Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
355
185
|
|
|
356
186
|
## License
|
|
357
187
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
## Support
|
|
361
|
-
|
|
362
|
-
<div align="center">
|
|
363
|
-
|
|
364
|
-
<table>
|
|
365
|
-
<tr>
|
|
366
|
-
<td align="center">
|
|
367
|
-
<a href="https://alfredoperez.github.io/ngx-dev-toolbar/">
|
|
368
|
-
๐
|
|
369
|
-
<br />
|
|
370
|
-
Documentation
|
|
371
|
-
</a>
|
|
372
|
-
</td>
|
|
373
|
-
<td align="center">
|
|
374
|
-
<a href="https://github.com/alfredoperez/ngx-dev-toolbar/issues">
|
|
375
|
-
๐
|
|
376
|
-
<br />
|
|
377
|
-
Issue Tracker
|
|
378
|
-
</a>
|
|
379
|
-
</td>
|
|
380
|
-
<td align="center">
|
|
381
|
-
<a href="https://github.com/alfredoperez/ngx-dev-toolbar/discussions">
|
|
382
|
-
๐ฌ
|
|
383
|
-
<br />
|
|
384
|
-
Discussions
|
|
385
|
-
</a>
|
|
386
|
-
</td>
|
|
387
|
-
</tr>
|
|
388
|
-
</table>
|
|
389
|
-
|
|
390
|
-
</div>
|
|
391
|
-
|
|
392
|
-
## ๐ Stay Connected
|
|
393
|
-
|
|
394
|
-
<div align="center">
|
|
395
|
-
|
|
396
|
-
[](https://www.linkedin.com/in/alfredo-perez/)
|
|
397
|
-
[](https://bsky.app/profile/alfredo-perez.bsky.social)
|
|
398
|
-
[](https://github.com/alfredoperez/ngx-dev-toolbar)
|
|
399
|
-
|
|
400
|
-
<hr />
|
|
401
|
-
|
|
402
|
-
<p>Built with โค๏ธ using <a href="https://nx.dev">Nx</a></p>
|
|
403
|
-
|
|
404
|
-
</div>
|
|
188
|
+
MIT
|
|
@@ -12,7 +12,7 @@ export declare class ToolbarSelectComponent {
|
|
|
12
12
|
ariaLabel: import("@angular/core").InputSignal<string>;
|
|
13
13
|
label: import("@angular/core").InputSignal<string>;
|
|
14
14
|
size: import("@angular/core").InputSignal<"small" | "medium">;
|
|
15
|
-
readonly theme: import("@angular/core").Signal<"
|
|
15
|
+
readonly theme: import("@angular/core").Signal<"light" | "dark">;
|
|
16
16
|
protected readonly selectMenuId: string;
|
|
17
17
|
isOpen: import("@angular/core").WritableSignal<boolean>;
|
|
18
18
|
selectedLabel: import("@angular/core").Signal<string>;
|
|
@@ -7,7 +7,7 @@ export declare class ToolbarWindowComponent {
|
|
|
7
7
|
readonly closed: import("@angular/core").OutputEmitterRef<void>;
|
|
8
8
|
readonly maximize: import("@angular/core").OutputEmitterRef<void>;
|
|
9
9
|
readonly minimize: import("@angular/core").OutputEmitterRef<void>;
|
|
10
|
-
readonly theme: import("@angular/core").Signal<"
|
|
10
|
+
readonly theme: import("@angular/core").Signal<"light" | "dark">;
|
|
11
11
|
protected onClose(): void;
|
|
12
12
|
protected onMaximize(): void;
|
|
13
13
|
protected onMinimize(): void;
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@ export declare class ToolbarStateService {
|
|
|
7
7
|
readonly activeToolId: import("@angular/core").Signal<string | null>;
|
|
8
8
|
readonly hasActiveTool: import("@angular/core").Signal<boolean>;
|
|
9
9
|
readonly error: import("@angular/core").Signal<string | null>;
|
|
10
|
-
readonly theme: import("@angular/core").Signal<"
|
|
10
|
+
readonly theme: import("@angular/core").Signal<"light" | "dark">;
|
|
11
11
|
/**
|
|
12
12
|
* The delay to hide the toolbar
|
|
13
13
|
*/
|