@angular-architects/ngrx-toolkit 19.4.0 → 19.4.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.
Files changed (128) hide show
  1. package/fesm2022/angular-architects-ngrx-toolkit-redux-connector.mjs +119 -0
  2. package/fesm2022/angular-architects-ngrx-toolkit-redux-connector.mjs.map +1 -0
  3. package/fesm2022/angular-architects-ngrx-toolkit.mjs +2108 -0
  4. package/fesm2022/angular-architects-ngrx-toolkit.mjs.map +1 -0
  5. package/{src/index.ts → index.d.ts} +5 -32
  6. package/lib/assertions/assertions.d.ts +2 -0
  7. package/{src/lib/devtools/features/with-disabled-name-indicies.ts → lib/devtools/features/with-disabled-name-indicies.d.ts} +1 -5
  8. package/{src/lib/devtools/features/with-glitch-tracking.ts → lib/devtools/features/with-glitch-tracking.d.ts} +1 -6
  9. package/{src/lib/devtools/features/with-mapper.ts → lib/devtools/features/with-mapper.d.ts} +1 -7
  10. package/lib/devtools/internal/current-action-names.d.ts +1 -0
  11. package/lib/devtools/internal/default-tracker.d.ts +13 -0
  12. package/lib/devtools/internal/devtools-feature.d.ts +24 -0
  13. package/lib/devtools/internal/devtools-syncer.service.d.ts +39 -0
  14. package/lib/devtools/internal/glitch-tracker.service.d.ts +18 -0
  15. package/lib/devtools/internal/models.d.ts +24 -0
  16. package/{src/lib/devtools/provide-devtools-config.ts → lib/devtools/provide-devtools-config.d.ts} +4 -16
  17. package/lib/devtools/rename-devtools-name.d.ts +7 -0
  18. package/lib/devtools/update-state.d.ts +15 -0
  19. package/{src/lib/devtools/with-dev-tools-stub.ts → lib/devtools/with-dev-tools-stub.d.ts} +1 -2
  20. package/lib/devtools/with-devtools.d.ts +24 -0
  21. package/lib/flattening-operator.d.ts +14 -0
  22. package/lib/immutable-state/deep-freeze.d.ts +11 -0
  23. package/lib/immutable-state/is-dev-mode.d.ts +1 -0
  24. package/lib/immutable-state/with-immutable-state.d.ts +60 -0
  25. package/lib/mutation/http-mutation.d.ts +86 -0
  26. package/lib/mutation/mutation.d.ts +20 -0
  27. package/lib/mutation/rx-mutation.d.ts +76 -0
  28. package/{src/lib/shared/signal-store-models.ts → lib/shared/signal-store-models.d.ts} +4 -8
  29. package/lib/shared/throw-if-null.d.ts +1 -0
  30. package/lib/storage-sync/features/with-indexed-db.d.ts +2 -0
  31. package/lib/storage-sync/features/with-local-storage.d.ts +3 -0
  32. package/lib/storage-sync/internal/indexeddb.service.d.ts +29 -0
  33. package/lib/storage-sync/internal/local-storage.service.d.ts +8 -0
  34. package/lib/storage-sync/internal/models.d.ts +45 -0
  35. package/lib/storage-sync/internal/session-storage.service.d.ts +8 -0
  36. package/lib/storage-sync/with-storage-sync.d.ts +45 -0
  37. package/lib/with-call-state.d.ts +58 -0
  38. package/{src/lib/with-conditional.ts → lib/with-conditional.d.ts} +7 -31
  39. package/lib/with-data-service.d.ts +109 -0
  40. package/{src/lib/with-feature-factory.ts → lib/with-feature-factory.d.ts} +4 -32
  41. package/lib/with-mutations.d.ts +51 -0
  42. package/lib/with-pagination.d.ts +98 -0
  43. package/lib/with-redux.d.ts +147 -0
  44. package/lib/with-reset.d.ts +29 -0
  45. package/lib/with-undo-redo.d.ts +31 -0
  46. package/package.json +21 -4
  47. package/redux-connector/index.d.ts +2 -0
  48. package/redux-connector/src/lib/create-redux.d.ts +13 -0
  49. package/redux-connector/src/lib/model.d.ts +40 -0
  50. package/redux-connector/src/lib/rxjs-interop/redux-method.d.ts +14 -0
  51. package/redux-connector/src/lib/signal-redux-store.d.ts +11 -0
  52. package/redux-connector/src/lib/util.d.ts +5 -0
  53. package/eslint.config.cjs +0 -43
  54. package/jest.config.ts +0 -22
  55. package/ng-package.json +0 -7
  56. package/project.json +0 -37
  57. package/redux-connector/docs/README.md +0 -131
  58. package/redux-connector/index.ts +0 -6
  59. package/redux-connector/ng-package.json +0 -5
  60. package/redux-connector/src/lib/create-redux.ts +0 -102
  61. package/redux-connector/src/lib/model.ts +0 -89
  62. package/redux-connector/src/lib/rxjs-interop/redux-method.ts +0 -66
  63. package/redux-connector/src/lib/signal-redux-store.ts +0 -59
  64. package/redux-connector/src/lib/util.ts +0 -22
  65. package/src/lib/assertions/assertions.ts +0 -9
  66. package/src/lib/devtools/internal/current-action-names.ts +0 -1
  67. package/src/lib/devtools/internal/default-tracker.ts +0 -60
  68. package/src/lib/devtools/internal/devtools-feature.ts +0 -37
  69. package/src/lib/devtools/internal/devtools-syncer.service.ts +0 -202
  70. package/src/lib/devtools/internal/glitch-tracker.service.ts +0 -61
  71. package/src/lib/devtools/internal/models.ts +0 -29
  72. package/src/lib/devtools/rename-devtools-name.ts +0 -21
  73. package/src/lib/devtools/tests/action-name.spec.ts +0 -48
  74. package/src/lib/devtools/tests/basic.spec.ts +0 -111
  75. package/src/lib/devtools/tests/connecting.spec.ts +0 -37
  76. package/src/lib/devtools/tests/helpers.spec.ts +0 -43
  77. package/src/lib/devtools/tests/naming.spec.ts +0 -216
  78. package/src/lib/devtools/tests/provide-devtools-config.spec.ts +0 -25
  79. package/src/lib/devtools/tests/types.spec.ts +0 -19
  80. package/src/lib/devtools/tests/update-state.spec.ts +0 -29
  81. package/src/lib/devtools/tests/with-devtools.spec.ts +0 -5
  82. package/src/lib/devtools/tests/with-glitch-tracking.spec.ts +0 -272
  83. package/src/lib/devtools/tests/with-mapper.spec.ts +0 -69
  84. package/src/lib/devtools/update-state.ts +0 -38
  85. package/src/lib/devtools/with-devtools.ts +0 -81
  86. package/src/lib/flattening-operator.ts +0 -42
  87. package/src/lib/immutable-state/deep-freeze.ts +0 -43
  88. package/src/lib/immutable-state/is-dev-mode.ts +0 -6
  89. package/src/lib/immutable-state/tests/with-immutable-state.spec.ts +0 -260
  90. package/src/lib/immutable-state/with-immutable-state.ts +0 -115
  91. package/src/lib/mutation/http-mutation.spec.ts +0 -473
  92. package/src/lib/mutation/http-mutation.ts +0 -172
  93. package/src/lib/mutation/mutation.ts +0 -26
  94. package/src/lib/mutation/rx-mutation.spec.ts +0 -594
  95. package/src/lib/mutation/rx-mutation.ts +0 -208
  96. package/src/lib/shared/prettify.ts +0 -3
  97. package/src/lib/shared/throw-if-null.ts +0 -7
  98. package/src/lib/storage-sync/features/with-indexed-db.ts +0 -81
  99. package/src/lib/storage-sync/features/with-local-storage.ts +0 -58
  100. package/src/lib/storage-sync/internal/indexeddb.service.ts +0 -124
  101. package/src/lib/storage-sync/internal/local-storage.service.ts +0 -19
  102. package/src/lib/storage-sync/internal/models.ts +0 -62
  103. package/src/lib/storage-sync/internal/session-storage.service.ts +0 -18
  104. package/src/lib/storage-sync/tests/indexeddb.service.spec.ts +0 -99
  105. package/src/lib/storage-sync/tests/with-storage-async.spec.ts +0 -308
  106. package/src/lib/storage-sync/tests/with-storage-sync.spec.ts +0 -268
  107. package/src/lib/storage-sync/with-storage-sync.ts +0 -233
  108. package/src/lib/with-call-state.spec.ts +0 -42
  109. package/src/lib/with-call-state.ts +0 -195
  110. package/src/lib/with-conditional.spec.ts +0 -125
  111. package/src/lib/with-data-service.spec.ts +0 -564
  112. package/src/lib/with-data-service.ts +0 -433
  113. package/src/lib/with-feature-factory.spec.ts +0 -69
  114. package/src/lib/with-mutations.spec.ts +0 -537
  115. package/src/lib/with-mutations.ts +0 -146
  116. package/src/lib/with-pagination.spec.ts +0 -90
  117. package/src/lib/with-pagination.ts +0 -353
  118. package/src/lib/with-redux.spec.ts +0 -258
  119. package/src/lib/with-redux.ts +0 -387
  120. package/src/lib/with-reset.spec.ts +0 -112
  121. package/src/lib/with-reset.ts +0 -62
  122. package/src/lib/with-undo-redo.spec.ts +0 -287
  123. package/src/lib/with-undo-redo.ts +0 -199
  124. package/src/test-setup.ts +0 -8
  125. package/tsconfig.json +0 -29
  126. package/tsconfig.lib.json +0 -17
  127. package/tsconfig.lib.prod.json +0 -9
  128. package/tsconfig.spec.json +0 -17
@@ -1,216 +0,0 @@
1
- import {
2
- createEnvironmentInjector,
3
- EnvironmentInjector,
4
- inject,
5
- runInInjectionContext,
6
- } from '@angular/core';
7
- import { TestBed } from '@angular/core/testing';
8
- import { signalStore, withState } from '@ngrx/signals';
9
- import { withDisabledNameIndices } from '../features/with-disabled-name-indicies';
10
- import { renameDevtoolsName } from '../rename-devtools-name';
11
- import { withDevtools } from '../with-devtools';
12
- import { setupExtensions } from './helpers.spec';
13
-
14
- describe('withDevtools / renaming', () => {
15
- it('should automatically index multiple instances', () => {
16
- const { sendSpy } = setupExtensions();
17
- const Store = signalStore(
18
- { providedIn: 'root' },
19
- withDevtools('flights'),
20
- withState({ airline: 'Lufthansa' }),
21
- );
22
-
23
- const childContext = createEnvironmentInjector(
24
- [Store],
25
- TestBed.inject(EnvironmentInjector),
26
- );
27
-
28
- TestBed.inject(Store);
29
- runInInjectionContext(childContext, () => inject(Store));
30
-
31
- TestBed.flushEffects();
32
-
33
- expect(sendSpy).lastCalledWith(
34
- { type: 'Store Update' },
35
- {
36
- flights: { airline: 'Lufthansa' },
37
- 'flights-1': { airline: 'Lufthansa' },
38
- },
39
- );
40
- });
41
-
42
- it('not index, if multiple instances do not exist simultaneously', () => {
43
- const { sendSpy } = setupExtensions();
44
- const Store = signalStore(
45
- withDevtools('flights'),
46
- withState({ airline: 'Lufthansa' }),
47
- );
48
-
49
- const envInjector = TestBed.inject(EnvironmentInjector);
50
- const childContext1 = createEnvironmentInjector([Store], envInjector);
51
- const childContext2 = createEnvironmentInjector([Store], envInjector);
52
-
53
- runInInjectionContext(childContext1, () => inject(Store));
54
- TestBed.flushEffects();
55
- childContext1.destroy();
56
-
57
- expect(sendSpy.mock.calls).toEqual([
58
- [
59
- { type: 'Store Update' },
60
- {
61
- flights: { airline: 'Lufthansa' },
62
- },
63
- ],
64
- ]);
65
-
66
- runInInjectionContext(childContext2, () => inject(Store));
67
- TestBed.flushEffects();
68
- expect(sendSpy.mock.calls).toEqual([
69
- [
70
- { type: 'Store Update' },
71
- {
72
- flights: { airline: 'Lufthansa' },
73
- },
74
- ],
75
- [
76
- { type: 'Store Update' },
77
- {
78
- flights: { airline: 'Lufthansa' },
79
- },
80
- ],
81
- ]);
82
- });
83
-
84
- it('should throw if automatic indexing is disabled', () => {
85
- setupExtensions();
86
- const Store = signalStore(
87
- { providedIn: 'root' },
88
- withDevtools('flights', withDisabledNameIndices()),
89
- withState({ airline: 'Lufthansa' }),
90
- );
91
-
92
- const childContext = createEnvironmentInjector(
93
- [Store],
94
- TestBed.inject(EnvironmentInjector),
95
- );
96
-
97
- TestBed.inject(Store);
98
- expect(() =>
99
- runInInjectionContext(childContext, () => inject(Store)),
100
- ).toThrow(
101
- `An instance of the store flights already exists. \
102
- Enable automatic indexing via withDevTools('flights', { indexNames: true }), or rename it upon instantiation.`,
103
- );
104
- });
105
-
106
- it('should index for two different stores with same devtools name', () => {
107
- const { sendSpy } = setupExtensions();
108
-
109
- TestBed.inject(
110
- signalStore({ providedIn: 'root' }, withDevtools('flights')),
111
- );
112
- TestBed.inject(
113
- signalStore({ providedIn: 'root' }, withDevtools('flights')),
114
- );
115
-
116
- TestBed.flushEffects();
117
- expect(sendSpy.mock.calls).toEqual([
118
- [
119
- { type: 'Store Update' },
120
- {
121
- flights: {},
122
- 'flights-1': {},
123
- },
124
- ],
125
- ]);
126
- });
127
-
128
- it('should throw for two different stores when indexing is disabled', () => {
129
- setupExtensions();
130
-
131
- TestBed.inject(
132
- signalStore({ providedIn: 'root' }, withDevtools('flights')),
133
- );
134
- expect(() =>
135
- TestBed.inject(
136
- signalStore(
137
- { providedIn: 'root' },
138
- withDevtools('flights', withDisabledNameIndices()),
139
- ),
140
- ),
141
- ).toThrow();
142
- });
143
-
144
- it('should not throw for two different stores if only the first one has indexing disabled', () => {
145
- setupExtensions();
146
-
147
- TestBed.inject(
148
- signalStore(
149
- { providedIn: 'root' },
150
- withDevtools('flights', withDisabledNameIndices()),
151
- ),
152
- );
153
- expect(() =>
154
- TestBed.inject(
155
- signalStore({ providedIn: 'root' }, withDevtools('flights')),
156
- ),
157
- ).not.toThrow();
158
- });
159
-
160
- describe('renaming', () => {
161
- it('should allow to rename the store before first sync', () => {
162
- const { sendSpy } = setupExtensions();
163
-
164
- const Store = signalStore(
165
- { providedIn: 'root' },
166
- withState({ name: 'Product', price: 10.5 }),
167
- withDevtools('flight'),
168
- );
169
-
170
- const store = TestBed.inject(Store);
171
- renameDevtoolsName(store, 'flights');
172
- TestBed.flushEffects();
173
-
174
- expect(sendSpy).toHaveBeenCalledWith(
175
- { type: 'Store Update' },
176
- { flights: { name: 'Product', price: 10.5 } },
177
- );
178
- });
179
-
180
- it('should throw on rename if name already exists', () => {
181
- setupExtensions();
182
- const Store1 = signalStore(
183
- { providedIn: 'root' },
184
- withState({ name: 'Product', price: 10.5 }),
185
- withDevtools('shop'),
186
- );
187
-
188
- const Store2 = signalStore(
189
- { providedIn: 'root' },
190
- withState({ name: 'Product', price: 10.5 }),
191
- withDevtools('mall'),
192
- );
193
- TestBed.inject(Store1);
194
- const store = TestBed.inject(Store2);
195
- TestBed.flushEffects();
196
-
197
- expect(() => renameDevtoolsName(store, 'shop')).toThrow(
198
- 'NgRx Toolkit/DevTools: cannot rename from mall to shop. shop is already assigned to another SignalStore instance.',
199
- );
200
- });
201
-
202
- it('should throw if applied to a SignalStore without DevTools', () => {
203
- setupExtensions();
204
- const Store = signalStore(
205
- { providedIn: 'root' },
206
- withState({ name: 'Product', price: 10.5 }),
207
- );
208
-
209
- const store = TestBed.inject(Store);
210
-
211
- expect(() => renameDevtoolsName(store, 'shop')).toThrow(
212
- "Devtools extensions haven't been added to this store.",
213
- );
214
- });
215
- });
216
- });
@@ -1,25 +0,0 @@
1
- import { TestBed } from '@angular/core/testing';
2
- import { DevtoolsSyncer } from '../internal/devtools-syncer.service';
3
- import { provideDevtoolsConfig } from '../provide-devtools-config';
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
- });
@@ -1,19 +0,0 @@
1
- import { computed } from '@angular/core';
2
- import { patchState, signalStore, withState } from '@ngrx/signals';
3
- import { withDevtools } from '../with-devtools';
4
-
5
- it('should compile when signalStore is extended from', () => {
6
- class CounterStore extends signalStore(
7
- { protectedState: false },
8
- withState({ count: 0 }),
9
- withDevtools('counter-store'),
10
- ) {
11
- readonly myReadonlyProp = 42;
12
-
13
- readonly doubleCount = computed(() => this.count() * 2);
14
-
15
- increment(): void {
16
- patchState(this, { count: this.count() + 1 });
17
- }
18
- }
19
- });
@@ -1,29 +0,0 @@
1
- import { signalStore, withMethods } from '@ngrx/signals';
2
- import { setAllEntities, withEntities } from '@ngrx/signals/entities';
3
- import { setLoaded, withCallState } from '../../with-call-state';
4
- import { updateState } from '../update-state';
5
-
6
- describe('updateState', () => {
7
- it('should work with multiple updaters', () => {
8
- interface Item {
9
- id: string;
10
- name: string;
11
- }
12
-
13
- signalStore(
14
- withEntities<Item>(),
15
- withCallState({ collection: 'items' }),
16
- withMethods((store) => ({
17
- loadItems() {
18
- // This should not cause a type error
19
- updateState(
20
- store,
21
- 'Items loaded successfully',
22
- setAllEntities([] as Item[]),
23
- setLoaded('items'),
24
- );
25
- },
26
- })),
27
- );
28
- });
29
- });
@@ -1,5 +0,0 @@
1
- describe('Devtools', () => {
2
- it.todo('should group multiple patchStates (glitch-free) in one action');
3
- it.todo('should allow time-travel (revert state via devtools');
4
- it.todo('should clear actionNames automatically onDestroy');
5
- });
@@ -1,272 +0,0 @@
1
- import {
2
- createEnvironmentInjector,
3
- EnvironmentInjector,
4
- inject,
5
- runInInjectionContext,
6
- } from '@angular/core';
7
- import { TestBed } from '@angular/core/testing';
8
- import { patchState, signalStore, withMethods, withState } from '@ngrx/signals';
9
- import { withGlitchTracking } from '../features/with-glitch-tracking';
10
- import { renameDevtoolsName } from '../rename-devtools-name';
11
- import { withDevtools } from '../with-devtools';
12
- import { setupExtensions } from './helpers.spec';
13
-
14
- describe('withGlitchTracking', () => {
15
- it('should sync immediately upon instantiation', () => {
16
- const { sendSpy } = setupExtensions();
17
-
18
- const Store = signalStore(
19
- { providedIn: 'root' },
20
- withDevtools('counter', withGlitchTracking()),
21
- withState({ count: 0 }),
22
- );
23
-
24
- expect(sendSpy).not.toHaveBeenCalled();
25
- TestBed.inject(Store);
26
-
27
- expect(sendSpy).toHaveBeenCalledWith(
28
- { type: 'Store Update' },
29
- { counter: { count: 0 } },
30
- );
31
- });
32
-
33
- it('should sync synchronous state changes', () => {
34
- const { sendSpy } = setupExtensions();
35
-
36
- const Store = signalStore(
37
- { providedIn: 'root' },
38
- withState({ count: 0 }),
39
- withDevtools('counter', withGlitchTracking()),
40
- withMethods((store) => ({
41
- increase: () =>
42
- patchState(store, (value) => ({ count: value.count + 1 })),
43
- })),
44
- );
45
-
46
- const store = TestBed.inject(Store);
47
-
48
- store.increase();
49
- store.increase();
50
- store.increase();
51
- TestBed.flushEffects();
52
-
53
- expect(sendSpy.mock.calls).toEqual([
54
- [{ type: 'Store Update' }, { counter: { count: 0 } }],
55
- [{ type: 'Store Update' }, { counter: { count: 1 } }],
56
- [{ type: 'Store Update' }, { counter: { count: 2 } }],
57
- [{ type: 'Store Update' }, { counter: { count: 3 } }],
58
- ]);
59
- });
60
-
61
- it('should support a mixed approach', () => {
62
- const { sendSpy } = setupExtensions();
63
-
64
- const GlitchFreeStore = signalStore(
65
- { providedIn: 'root' },
66
- withState({ count: 0 }),
67
- withDevtools('glitch-free counter'),
68
- withMethods((store) => ({
69
- increase: () =>
70
- patchState(store, (value) => ({ count: value.count + 1 })),
71
- })),
72
- );
73
-
74
- const GlitchStore = signalStore(
75
- { providedIn: 'root' },
76
- withState({ count: 0 }),
77
- withDevtools('glitch counter', withGlitchTracking()),
78
- withMethods((store) => ({
79
- increase: () =>
80
- patchState(store, (value) => ({ count: value.count + 1 })),
81
- })),
82
- );
83
-
84
- const glitchFreeStore = TestBed.inject(GlitchFreeStore);
85
- const glitchStore = TestBed.inject(GlitchStore);
86
-
87
- TestBed.flushEffects();
88
- for (let i = 0; i < 2; i++) {
89
- glitchFreeStore.increase();
90
- glitchStore.increase();
91
- }
92
- TestBed.flushEffects();
93
-
94
- expect(sendSpy.mock.calls).toEqual([
95
- [{ type: 'Store Update' }, { 'glitch counter': { count: 0 } }],
96
- [
97
- { type: 'Store Update' },
98
- { 'glitch-free counter': { count: 0 }, 'glitch counter': { count: 0 } },
99
- ],
100
- [
101
- { type: 'Store Update' },
102
- { 'glitch-free counter': { count: 0 }, 'glitch counter': { count: 1 } },
103
- ],
104
- [
105
- { type: 'Store Update' },
106
- { 'glitch-free counter': { count: 0 }, 'glitch counter': { count: 2 } },
107
- ],
108
- [
109
- { type: 'Store Update' },
110
- { 'glitch-free counter': { count: 2 }, 'glitch counter': { count: 2 } },
111
- ],
112
- ]);
113
- });
114
-
115
- it('two glitch stores should sync per change', () => {
116
- const { sendSpy } = setupExtensions();
117
-
118
- const GlitchStore1 = signalStore(
119
- { providedIn: 'root' },
120
- withState({ count: 0 }),
121
- withDevtools('glitch counter 1', withGlitchTracking()),
122
- withMethods((store) => ({
123
- increase: () =>
124
- patchState(store, (value) => ({ count: value.count + 1 })),
125
- })),
126
- );
127
-
128
- const GlitchStore2 = signalStore(
129
- { providedIn: 'root' },
130
- withState({ count: 0 }),
131
- withDevtools('glitch counter 2', withGlitchTracking()),
132
- withMethods((store) => ({
133
- increase: () =>
134
- patchState(store, (value) => ({ count: value.count + 1 })),
135
- })),
136
- );
137
-
138
- const glitchStore1 = TestBed.inject(GlitchStore1);
139
- const glitchStore2 = TestBed.inject(GlitchStore2);
140
-
141
- for (let i = 0; i < 2; i++) {
142
- glitchStore1.increase();
143
- glitchStore2.increase();
144
- }
145
- TestBed.flushEffects();
146
-
147
- expect(sendSpy.mock.calls).toEqual([
148
- [{ type: 'Store Update' }, { 'glitch counter 1': { count: 0 } }],
149
- [
150
- { type: 'Store Update' },
151
- { 'glitch counter 1': { count: 0 }, 'glitch counter 2': { count: 0 } },
152
- ],
153
- [
154
- { type: 'Store Update' },
155
- { 'glitch counter 1': { count: 1 }, 'glitch counter 2': { count: 0 } },
156
- ],
157
- [
158
- { type: 'Store Update' },
159
- { 'glitch counter 1': { count: 1 }, 'glitch counter 2': { count: 1 } },
160
- ],
161
- [
162
- { type: 'Store Update' },
163
- { 'glitch counter 1': { count: 2 }, 'glitch counter 2': { count: 1 } },
164
- ],
165
- [
166
- { type: 'Store Update' },
167
- { 'glitch counter 1': { count: 2 }, 'glitch counter 2': { count: 2 } },
168
- ],
169
- ]);
170
- });
171
-
172
- it('should not sync glitch-free if glitched is renamed', () => {
173
- const { sendSpy } = setupExtensions();
174
-
175
- const GlitchFreeStore = signalStore(
176
- { providedIn: 'root' },
177
- withState({ name: 'Product', price: 10.5 }),
178
- withDevtools('flight1'),
179
- );
180
-
181
- const GlitchStore = signalStore(
182
- { providedIn: 'root' },
183
- withState({ name: 'Product', price: 10.5 }),
184
- withDevtools('flight2', withGlitchTracking()),
185
- );
186
-
187
- TestBed.inject(GlitchFreeStore);
188
- const glitchStore = TestBed.inject(GlitchStore);
189
-
190
- TestBed.flushEffects();
191
-
192
- expect(sendSpy.mock.calls).toEqual([
193
- [{ type: 'Store Update' }, { flight2: { name: 'Product', price: 10.5 } }],
194
- [
195
- { type: 'Store Update' },
196
- {
197
- flight1: { name: 'Product', price: 10.5 },
198
- flight2: { name: 'Product', price: 10.5 },
199
- },
200
- ],
201
- ]);
202
- sendSpy.mockClear();
203
-
204
- renameDevtoolsName(glitchStore, 'flights2');
205
- TestBed.flushEffects();
206
-
207
- expect(sendSpy.mock.calls).toEqual([
208
- [
209
- { type: 'Store Update' },
210
- {
211
- flight1: { name: 'Product', price: 10.5 },
212
- flights2: { name: 'Product', price: 10.5 },
213
- },
214
- ],
215
- ]);
216
- });
217
-
218
- it('should not sync glitch tracker if glitch-free store is renamed', () => {
219
- const { sendSpy } = setupExtensions();
220
-
221
- const GlitchFreeStore = signalStore(
222
- { providedIn: 'root' },
223
- withState({ name: 'Product', price: 10.5 }),
224
- withDevtools('flight1'),
225
- );
226
-
227
- const GlitchStore = signalStore(
228
- { providedIn: 'root' },
229
- withState({ name: 'Product', price: 10.5 }),
230
- withDevtools('glitched Flights', withGlitchTracking()),
231
- );
232
-
233
- const glitchFreeStore = TestBed.inject(GlitchFreeStore);
234
- TestBed.inject(GlitchStore);
235
- TestBed.flushEffects();
236
-
237
- sendSpy.mockClear();
238
- renameDevtoolsName(glitchFreeStore, 'glitch-free Flights');
239
- expect(sendSpy).not.toHaveBeenCalled();
240
- TestBed.flushEffects();
241
-
242
- expect(sendSpy.mock.calls).toEqual([
243
- [
244
- { type: 'Store Update' },
245
- {
246
- 'glitch-free Flights': { name: 'Product', price: 10.5 },
247
- 'glitched Flights': { name: 'Product', price: 10.5 },
248
- },
249
- ],
250
- ]);
251
- });
252
-
253
- it('should destroy watcher if store is destroyed', () => {
254
- const { sendSpy } = setupExtensions();
255
-
256
- const GlitchStore = signalStore(
257
- withState({ name: 'Product', price: 10.5 }),
258
- withDevtools('Glitched Store', withGlitchTracking()),
259
- );
260
-
261
- const childContext = createEnvironmentInjector(
262
- [GlitchStore],
263
- TestBed.inject(EnvironmentInjector),
264
- );
265
- runInInjectionContext(childContext, () => inject(GlitchStore));
266
-
267
- expect(sendSpy).toHaveBeenCalled();
268
- sendSpy.mockClear();
269
- childContext.destroy();
270
- expect(sendSpy).toHaveBeenCalledWith({ type: 'Store Update' }, {});
271
- });
272
- });
@@ -1,69 +0,0 @@
1
- import { TestBed } from '@angular/core/testing';
2
- import { signalStore, withState } from '@ngrx/signals';
3
- import { withMapper } from '../features/with-mapper';
4
- import { withDevtools } from '../with-devtools';
5
- import { setupExtensions } from './helpers.spec';
6
-
7
- function domRemover(state: Record<string, unknown>) {
8
- return Object.keys(state).reduce((acc, key) => {
9
- const value = state[key];
10
-
11
- if (value instanceof HTMLElement) {
12
- return acc;
13
- } else {
14
- return { ...acc, [key]: value };
15
- }
16
- }, {});
17
- }
18
-
19
- describe('with-mapper', () => {
20
- it('should remove DOM Nodes', () => {
21
- const { sendSpy } = setupExtensions();
22
-
23
- const Store = signalStore(
24
- { providedIn: 'root' },
25
- withState({
26
- name: 'Car',
27
- carElement: document.createElement('div'),
28
- }),
29
- withDevtools('shop', withMapper(domRemover)),
30
- );
31
-
32
- TestBed.inject(Store);
33
- TestBed.flushEffects();
34
- expect(sendSpy).toHaveBeenCalledWith(
35
- { type: 'Store Update' },
36
- { shop: { name: 'Car' } },
37
- );
38
- });
39
-
40
- it('should every property ending with *Key', () => {
41
- const { sendSpy } = setupExtensions();
42
- const Store = signalStore(
43
- { providedIn: 'root' },
44
- withState({
45
- name: 'Car',
46
- unlockKey: '1234',
47
- }),
48
- withDevtools(
49
- 'shop',
50
- withMapper((state: Record<string, unknown>) =>
51
- Object.keys(state).reduce((acc, key) => {
52
- if (key.endsWith('Key')) {
53
- return acc;
54
- } else {
55
- return { ...acc, [key]: state[key] };
56
- }
57
- }, {}),
58
- ),
59
- ),
60
- );
61
-
62
- TestBed.inject(Store);
63
- TestBed.flushEffects();
64
- expect(sendSpy).toHaveBeenCalledWith(
65
- { type: 'Store Update' },
66
- { shop: { name: 'Car' } },
67
- );
68
- });
69
- });
@@ -1,38 +0,0 @@
1
- import {
2
- patchState as originalPatchState,
3
- PartialStateUpdater,
4
- WritableStateSource,
5
- } from '@ngrx/signals';
6
- import { currentActionNames } from './internal/current-action-names';
7
-
8
- type PatchFn = typeof originalPatchState extends (
9
- arg1: infer First,
10
- ...args: infer Rest
11
- ) => infer Returner
12
- ? (state: First, action: string, ...rest: Rest) => Returner
13
- : never;
14
-
15
- /**
16
- * @deprecated Has been renamed to `updateState`
17
- */
18
- export const patchState: PatchFn = (state, action, ...rest) => {
19
- updateState(state, action, ...rest);
20
- };
21
-
22
- /**
23
- * Wrapper of `patchState` for DevTools integration. Next to updating the state,
24
- * it also sends the action to the DevTools.
25
- * @param stateSource state of Signal Store
26
- * @param action name of action how it will show in DevTools
27
- * @param updaters updater functions or objects
28
- */
29
- export function updateState<State extends object>(
30
- stateSource: WritableStateSource<State>,
31
- action: string,
32
- ...updaters: Array<
33
- Partial<NoInfer<State>> | PartialStateUpdater<NoInfer<State>>
34
- >
35
- ): void {
36
- currentActionNames.add(action);
37
- return originalPatchState(stateSource, ...updaters);
38
- }