@angular-architects/ngrx-toolkit 20.0.0 → 20.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.
Files changed (84) hide show
  1. package/eslint.config.cjs +43 -0
  2. package/jest.config.ts +22 -0
  3. package/ng-package.json +7 -0
  4. package/package.json +4 -21
  5. package/project.json +37 -0
  6. package/redux-connector/docs/README.md +131 -0
  7. package/redux-connector/index.ts +6 -0
  8. package/redux-connector/ng-package.json +5 -0
  9. package/redux-connector/src/lib/create-redux.ts +102 -0
  10. package/redux-connector/src/lib/model.ts +89 -0
  11. package/redux-connector/src/lib/rxjs-interop/redux-method.ts +66 -0
  12. package/redux-connector/src/lib/signal-redux-store.ts +59 -0
  13. package/redux-connector/src/lib/util.ts +22 -0
  14. package/src/index.ts +43 -0
  15. package/src/lib/assertions/assertions.ts +9 -0
  16. package/src/lib/devtools/features/with-disabled-name-indicies.ts +31 -0
  17. package/src/lib/devtools/features/with-glitch-tracking.ts +35 -0
  18. package/src/lib/devtools/features/with-mapper.ts +34 -0
  19. package/src/lib/devtools/internal/current-action-names.ts +1 -0
  20. package/src/lib/devtools/internal/default-tracker.ts +60 -0
  21. package/src/lib/devtools/internal/devtools-feature.ts +37 -0
  22. package/src/lib/devtools/internal/devtools-syncer.service.ts +202 -0
  23. package/src/lib/devtools/internal/glitch-tracker.service.ts +61 -0
  24. package/src/lib/devtools/internal/models.ts +29 -0
  25. package/src/lib/devtools/provide-devtools-config.ts +32 -0
  26. package/src/lib/devtools/rename-devtools-name.ts +21 -0
  27. package/src/lib/devtools/tests/action-name.spec.ts +48 -0
  28. package/src/lib/devtools/tests/basic.spec.ts +111 -0
  29. package/src/lib/devtools/tests/connecting.spec.ts +37 -0
  30. package/src/lib/devtools/tests/helpers.spec.ts +43 -0
  31. package/src/lib/devtools/tests/naming.spec.ts +216 -0
  32. package/src/lib/devtools/tests/provide-devtools-config.spec.ts +25 -0
  33. package/src/lib/devtools/tests/types.spec.ts +19 -0
  34. package/src/lib/devtools/tests/update-state.spec.ts +29 -0
  35. package/src/lib/devtools/tests/with-devtools.spec.ts +5 -0
  36. package/src/lib/devtools/tests/with-glitch-tracking.spec.ts +272 -0
  37. package/src/lib/devtools/tests/with-mapper.spec.ts +69 -0
  38. package/src/lib/devtools/update-state.ts +38 -0
  39. package/src/lib/devtools/with-dev-tools-stub.ts +6 -0
  40. package/src/lib/devtools/with-devtools.ts +81 -0
  41. package/src/lib/immutable-state/deep-freeze.ts +43 -0
  42. package/src/lib/immutable-state/is-dev-mode.ts +6 -0
  43. package/src/lib/immutable-state/tests/with-immutable-state.spec.ts +278 -0
  44. package/src/lib/immutable-state/with-immutable-state.ts +150 -0
  45. package/src/lib/shared/prettify.ts +3 -0
  46. package/src/lib/shared/signal-store-models.ts +30 -0
  47. package/src/lib/shared/throw-if-null.ts +7 -0
  48. package/src/lib/storage-sync/features/with-indexed-db.ts +81 -0
  49. package/src/lib/storage-sync/features/with-local-storage.ts +58 -0
  50. package/src/lib/storage-sync/internal/indexeddb.service.ts +124 -0
  51. package/src/lib/storage-sync/internal/local-storage.service.ts +19 -0
  52. package/src/lib/storage-sync/internal/models.ts +62 -0
  53. package/src/lib/storage-sync/internal/session-storage.service.ts +18 -0
  54. package/src/lib/storage-sync/tests/indexeddb.service.spec.ts +99 -0
  55. package/src/lib/storage-sync/tests/with-storage-async.spec.ts +305 -0
  56. package/src/lib/storage-sync/tests/with-storage-sync.spec.ts +273 -0
  57. package/src/lib/storage-sync/with-storage-sync.ts +236 -0
  58. package/src/lib/with-call-state.spec.ts +42 -0
  59. package/src/lib/with-call-state.ts +195 -0
  60. package/src/lib/with-conditional.spec.ts +125 -0
  61. package/src/lib/with-conditional.ts +74 -0
  62. package/src/lib/with-data-service.spec.ts +564 -0
  63. package/src/lib/with-data-service.ts +433 -0
  64. package/src/lib/with-feature-factory.spec.ts +69 -0
  65. package/src/lib/with-feature-factory.ts +56 -0
  66. package/src/lib/with-pagination.spec.ts +135 -0
  67. package/src/lib/with-pagination.ts +373 -0
  68. package/src/lib/with-redux.spec.ts +258 -0
  69. package/src/lib/with-redux.ts +387 -0
  70. package/src/lib/with-reset.spec.ts +112 -0
  71. package/src/lib/with-reset.ts +62 -0
  72. package/src/lib/with-undo-redo.spec.ts +274 -0
  73. package/src/lib/with-undo-redo.ts +200 -0
  74. package/src/test-setup.ts +6 -0
  75. package/tsconfig.json +29 -0
  76. package/tsconfig.lib.json +17 -0
  77. package/tsconfig.lib.prod.json +9 -0
  78. package/tsconfig.spec.json +17 -0
  79. package/fesm2022/angular-architects-ngrx-toolkit-redux-connector.mjs +0 -119
  80. package/fesm2022/angular-architects-ngrx-toolkit-redux-connector.mjs.map +0 -1
  81. package/fesm2022/angular-architects-ngrx-toolkit.mjs +0 -1780
  82. package/fesm2022/angular-architects-ngrx-toolkit.mjs.map +0 -1
  83. package/index.d.ts +0 -938
  84. package/redux-connector/index.d.ts +0 -59
@@ -0,0 +1,274 @@
1
+ import { computed, inject } from '@angular/core';
2
+ import { TestBed } from '@angular/core/testing';
3
+ import {
4
+ patchState,
5
+ signalStore,
6
+ type,
7
+ withComputed,
8
+ withMethods,
9
+ withState,
10
+ } from '@ngrx/signals';
11
+ import { addEntity, withEntities } from '@ngrx/signals/entities';
12
+ import { withCallState } from './with-call-state';
13
+ import { withUndoRedo } from './with-undo-redo';
14
+
15
+ const testState = { test: '' };
16
+ const testKeys = ['test' as const];
17
+ const newValue = 'new value';
18
+ const newerValue = 'newer value';
19
+
20
+ describe('withUndoRedo', () => {
21
+ it('adds methods for undo, redo, canUndo, canRedo', () => {
22
+ TestBed.runInInjectionContext(() => {
23
+ const Store = signalStore(
24
+ withState(testState),
25
+ withUndoRedo({ keys: testKeys }),
26
+ );
27
+ const store = new Store();
28
+
29
+ expect(Object.keys(store)).toEqual([
30
+ 'test',
31
+ 'canUndo',
32
+ 'canRedo',
33
+ 'undo',
34
+ 'redo',
35
+ 'clearStack',
36
+ ]);
37
+ });
38
+ });
39
+
40
+ it('should check keys and collection types', () => {
41
+ signalStore(
42
+ withState(testState),
43
+ // @ts-expect-error - should not allow invalid keys
44
+ withUndoRedo({ keys: ['tes'] }),
45
+ );
46
+ signalStore(
47
+ withState(testState),
48
+ withEntities({ entity: type(), collection: 'flight' }),
49
+ // @ts-expect-error - should not allow invalid keys when entities are present
50
+ withUndoRedo({ keys: ['flightIdsTest'] }),
51
+ );
52
+ signalStore(
53
+ withState(testState),
54
+ // @ts-expect-error - should not allow collections without named entities
55
+ withUndoRedo({ collections: ['tee'] }),
56
+ );
57
+ signalStore(
58
+ withState(testState),
59
+ withComputed((store) => ({ testComputed: computed(() => store.test()) })),
60
+ // @ts-expect-error - should not allow collections without named entities with other computed
61
+ withUndoRedo({ collections: ['tested'] }),
62
+ );
63
+ signalStore(
64
+ withEntities({ entity: type() }),
65
+ // @ts-expect-error - should not allow collections without named entities
66
+ withUndoRedo({ collections: ['test'] }),
67
+ );
68
+ signalStore(
69
+ withEntities({ entity: type(), collection: 'flight' }),
70
+ // @ts-expect-error - should not allow invalid collections
71
+ withUndoRedo({ collections: ['test'] }),
72
+ );
73
+ });
74
+
75
+ describe('undo and redo', () => {
76
+ it('restores previous state for regular store key', () => {
77
+ TestBed.runInInjectionContext(() => {
78
+ const Store = signalStore(
79
+ withState(testState),
80
+ withMethods((store) => ({
81
+ updateTest: (newTest: string) =>
82
+ patchState(store, { test: newTest }),
83
+ })),
84
+ withUndoRedo({ keys: testKeys }),
85
+ );
86
+
87
+ const store = new Store();
88
+
89
+ store.updateTest(newValue);
90
+
91
+ expect(store.test()).toEqual(newValue);
92
+ expect(store.canUndo()).toBe(true);
93
+ expect(store.canRedo()).toBe(false);
94
+
95
+ store.undo();
96
+
97
+ expect(store.test()).toEqual('');
98
+ expect(store.canUndo()).toBe(false);
99
+ expect(store.canRedo()).toBe(true);
100
+ });
101
+ });
102
+
103
+ it('restores previous state for regular store key and respects skip', () => {
104
+ TestBed.runInInjectionContext(() => {
105
+ const Store = signalStore(
106
+ withState(testState),
107
+ withMethods((store) => ({
108
+ updateTest: (newTest: string) =>
109
+ patchState(store, { test: newTest }),
110
+ })),
111
+ withUndoRedo({ keys: testKeys, skip: 1 }),
112
+ );
113
+
114
+ const store = new Store();
115
+
116
+ store.updateTest(newValue);
117
+
118
+ expect(store.test()).toEqual(newValue);
119
+
120
+ store.updateTest(newerValue);
121
+
122
+ store.undo();
123
+
124
+ expect(store.test()).toEqual(newValue);
125
+ expect(store.canUndo()).toBe(false);
126
+
127
+ store.undo();
128
+
129
+ // should not change
130
+ expect(store.test()).toEqual(newValue);
131
+ });
132
+ });
133
+
134
+ it('undoes and redoes previous state for entity', () => {
135
+ const Store = signalStore(
136
+ withEntities({ entity: type<{ id: string }>() }),
137
+ withMethods((store) => ({
138
+ addEntity: (newTest: string) =>
139
+ patchState(store, addEntity({ id: newTest })),
140
+ })),
141
+ withUndoRedo(),
142
+ );
143
+ TestBed.configureTestingModule({ providers: [Store] });
144
+ TestBed.runInInjectionContext(() => {
145
+ const store = inject(Store);
146
+
147
+ expect(store.entities()).toEqual([]);
148
+ expect(store.canUndo()).toBe(false);
149
+ expect(store.canRedo()).toBe(false);
150
+
151
+ store.addEntity(newValue);
152
+
153
+ expect(store.entities()).toEqual([{ id: newValue }]);
154
+ expect(store.canUndo()).toBe(true);
155
+ expect(store.canRedo()).toBe(false);
156
+
157
+ store.addEntity(newerValue);
158
+
159
+ expect(store.entities()).toEqual([
160
+ { id: newValue },
161
+ { id: newerValue },
162
+ ]);
163
+ expect(store.canUndo()).toBe(true);
164
+ expect(store.canRedo()).toBe(false);
165
+
166
+ store.undo();
167
+
168
+ expect(store.entities()).toEqual([{ id: newValue }]);
169
+ expect(store.canUndo()).toBe(true);
170
+ expect(store.canRedo()).toBe(true);
171
+
172
+ store.undo();
173
+
174
+ expect(store.entities()).toEqual([]);
175
+ expect(store.canUndo()).toBe(false);
176
+ expect(store.canRedo()).toBe(true);
177
+
178
+ store.redo();
179
+
180
+ expect(store.entities()).toEqual([{ id: newValue }]);
181
+ expect(store.canUndo()).toBe(true);
182
+ expect(store.canRedo()).toBe(true);
183
+
184
+ // should return canRedo=false after a change
185
+ store.addEntity('newest');
186
+
187
+ expect(store.canUndo()).toBe(true);
188
+ expect(store.canRedo()).toBe(false);
189
+ });
190
+ });
191
+
192
+ it('restores previous state for named entity', () => {
193
+ TestBed.runInInjectionContext(() => {
194
+ const Store = signalStore(
195
+ withEntities({
196
+ entity: type<{ id: string }>(),
197
+ collection: 'flight',
198
+ }),
199
+ withMethods((store) => ({
200
+ addEntity: (newTest: string) =>
201
+ patchState(
202
+ store,
203
+ addEntity({ id: newTest }, { collection: 'flight' }),
204
+ ),
205
+ })),
206
+ withCallState({ collection: 'flight' }),
207
+ withUndoRedo({ collections: ['flight'] }),
208
+ );
209
+
210
+ const store = new Store();
211
+
212
+ store.addEntity(newValue);
213
+
214
+ expect(store.flightEntities()).toEqual([{ id: newValue }]);
215
+ expect(store.canUndo()).toBe(true);
216
+ expect(store.canRedo()).toBe(false);
217
+
218
+ store.undo();
219
+
220
+ expect(store.flightEntities()).toEqual([]);
221
+ expect(store.canUndo()).toBe(false);
222
+ expect(store.canRedo()).toBe(true);
223
+ });
224
+ });
225
+
226
+ it('clears undo redo stack', () => {
227
+ const Store = signalStore(
228
+ { providedIn: 'root' },
229
+ withState(testState),
230
+ withMethods((store) => ({
231
+ update: (value: string) => patchState(store, { test: value }),
232
+ })),
233
+ withUndoRedo({ keys: testKeys }),
234
+ );
235
+
236
+ const store = TestBed.inject(Store);
237
+
238
+ store.update('Foo');
239
+ store.update('Bar');
240
+ store.undo();
241
+ store.clearStack();
242
+
243
+ expect(store.canUndo()).toBe(false);
244
+ expect(store.canRedo()).toBe(false);
245
+ });
246
+
247
+ it('cannot undo after clearing and setting a new value', () => {
248
+ const Store = signalStore(
249
+ { providedIn: 'root' },
250
+ withState(testState),
251
+ withMethods((store) => ({
252
+ update: (value: string) => patchState(store, { test: value }),
253
+ })),
254
+ withUndoRedo({ keys: testKeys }),
255
+ );
256
+
257
+ const store = TestBed.inject(Store);
258
+
259
+ store.update('Alan');
260
+
261
+ store.update('Gordon');
262
+
263
+ store.clearStack();
264
+
265
+ // After clearing the undo/redo stack, there is no previous item anymore.
266
+ // The following update becomes the first value.
267
+ // Since there is no other value before, it cannot be undone.
268
+ store.update('Hugh');
269
+
270
+ expect(store.canUndo()).toBe(false);
271
+ expect(store.canRedo()).toBe(false);
272
+ });
273
+ });
274
+ });
@@ -0,0 +1,200 @@
1
+ import { Signal, isSignal, signal, untracked } from '@angular/core';
2
+ import {
3
+ EmptyFeatureResult,
4
+ SignalStoreFeature,
5
+ SignalStoreFeatureResult,
6
+ patchState,
7
+ signalStoreFeature,
8
+ watchState,
9
+ withComputed,
10
+ withHooks,
11
+ withMethods,
12
+ } from '@ngrx/signals';
13
+ import { capitalize } from './with-data-service';
14
+
15
+ export type StackItem = Record<string, unknown>;
16
+
17
+ export type NormalizedUndoRedoOptions = {
18
+ maxStackSize: number;
19
+ collections?: string[];
20
+ keys: string[];
21
+ skip: number;
22
+ };
23
+
24
+ const defaultOptions: NormalizedUndoRedoOptions = {
25
+ maxStackSize: 100,
26
+ keys: [],
27
+ skip: 0,
28
+ };
29
+
30
+ export function getUndoRedoKeys(collections?: string[]): string[] {
31
+ if (collections) {
32
+ return collections.flatMap((c) => [
33
+ `${c}EntityMap`,
34
+ `${c}Ids`,
35
+ `selected${capitalize(c)}Ids`,
36
+ `${c}Filter`,
37
+ ]);
38
+ }
39
+ return ['entityMap', 'ids', 'selectedIds', 'filter'];
40
+ }
41
+
42
+ type NonNever<T> = T extends never ? never : T;
43
+
44
+ type ExtractEntityCollection<T> = T extends `${infer U}Entities` ? U : never;
45
+
46
+ type ExtractEntityCollections<Store extends SignalStoreFeatureResult> =
47
+ NonNever<
48
+ {
49
+ [K in keyof Store['props']]: ExtractEntityCollection<K>;
50
+ }[keyof Store['props']]
51
+ >;
52
+
53
+ type OptionsForState<Store extends SignalStoreFeatureResult> = Partial<
54
+ Omit<NormalizedUndoRedoOptions, 'collections' | 'keys'>
55
+ > & {
56
+ collections?: ExtractEntityCollections<Store>[];
57
+ keys?: (keyof Store['state'])[];
58
+ };
59
+
60
+ export function withUndoRedo<Input extends EmptyFeatureResult>(
61
+ options?: OptionsForState<Input>,
62
+ ): SignalStoreFeature<
63
+ Input,
64
+ EmptyFeatureResult & {
65
+ props: {
66
+ canUndo: Signal<boolean>;
67
+ canRedo: Signal<boolean>;
68
+ };
69
+ methods: {
70
+ undo: () => void;
71
+ redo: () => void;
72
+ clearStack: () => void;
73
+ };
74
+ }
75
+ > {
76
+ let previous: StackItem | null = null;
77
+ let skipOnce = false;
78
+
79
+ const normalized = {
80
+ ...defaultOptions,
81
+ ...options,
82
+ };
83
+
84
+ //
85
+ // Design Decision: This feature has its own
86
+ // internal state.
87
+ //
88
+
89
+ const undoStack: StackItem[] = [];
90
+ const redoStack: StackItem[] = [];
91
+
92
+ const canUndo = signal(false);
93
+ const canRedo = signal(false);
94
+
95
+ const updateInternal = () => {
96
+ canUndo.set(undoStack.length !== 0);
97
+ canRedo.set(redoStack.length !== 0);
98
+ };
99
+
100
+ const keys = [...getUndoRedoKeys(normalized.collections), ...normalized.keys];
101
+
102
+ return signalStoreFeature(
103
+ withComputed(() => ({
104
+ canUndo: canUndo.asReadonly(),
105
+ canRedo: canRedo.asReadonly(),
106
+ })),
107
+ withMethods((store) => ({
108
+ undo(): void {
109
+ const item = undoStack.pop();
110
+
111
+ if (item && previous) {
112
+ redoStack.push(previous);
113
+ }
114
+
115
+ if (item) {
116
+ skipOnce = true;
117
+ patchState(store, item);
118
+ previous = item;
119
+ }
120
+
121
+ updateInternal();
122
+ },
123
+ redo(): void {
124
+ const item = redoStack.pop();
125
+
126
+ if (item && previous) {
127
+ undoStack.push(previous);
128
+ }
129
+
130
+ if (item) {
131
+ skipOnce = true;
132
+ patchState(store, item);
133
+ previous = item;
134
+ }
135
+
136
+ updateInternal();
137
+ },
138
+ clearStack(): void {
139
+ undoStack.splice(0);
140
+ redoStack.splice(0);
141
+ previous = null;
142
+ updateInternal();
143
+ },
144
+ })),
145
+ withHooks({
146
+ onInit(store) {
147
+ watchState(store, () => {
148
+ const cand = keys.reduce((acc, key) => {
149
+ const s = (store as Record<string | keyof Input['state'], unknown>)[
150
+ key
151
+ ];
152
+ if (s && isSignal(s)) {
153
+ return {
154
+ ...acc,
155
+ [key]: s(),
156
+ };
157
+ }
158
+ return acc;
159
+ }, {});
160
+
161
+ if (normalized.skip > 0) {
162
+ normalized.skip--;
163
+ return;
164
+ }
165
+
166
+ if (skipOnce) {
167
+ skipOnce = false;
168
+ return;
169
+ }
170
+
171
+ //
172
+ // Deep Comparison to prevent duplicated entries
173
+ // on the stack. This can e.g. happen after an undo
174
+ // if the component sends back the undone filter
175
+ // to the store.
176
+ //
177
+ if (JSON.stringify(cand) === JSON.stringify(previous)) {
178
+ return;
179
+ }
180
+
181
+ // Clear redoStack after recorded action
182
+ redoStack.splice(0);
183
+
184
+ if (previous) {
185
+ undoStack.push(previous);
186
+ }
187
+
188
+ if (redoStack.length > normalized.maxStackSize) {
189
+ undoStack.unshift();
190
+ }
191
+
192
+ previous = cand;
193
+
194
+ // Don't propogate current reactive context
195
+ untracked(() => updateInternal());
196
+ });
197
+ },
198
+ }),
199
+ );
200
+ }
@@ -0,0 +1,6 @@
1
+ import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone';
2
+
3
+ setupZoneTestEnv({
4
+ errorOnUnknownElements: true,
5
+ errorOnUnknownProperties: true,
6
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2022",
4
+ "useDefineForClassFields": false,
5
+ "forceConsistentCasingInFileNames": true,
6
+ "strict": true,
7
+ "noImplicitOverride": true,
8
+ "noPropertyAccessFromIndexSignature": true,
9
+ "noImplicitReturns": true,
10
+ "noFallthroughCasesInSwitch": true
11
+ },
12
+ "files": [],
13
+ "include": [],
14
+ "references": [
15
+ {
16
+ "path": "./tsconfig.lib.json"
17
+ },
18
+ {
19
+ "path": "./tsconfig.spec.json"
20
+ }
21
+ ],
22
+ "extends": "../../tsconfig.base.json",
23
+ "angularCompilerOptions": {
24
+ "enableI18nLegacyMessageIdFormat": false,
25
+ "strictInjectionParameters": true,
26
+ "strictInputAccessModifiers": true,
27
+ "strictTemplates": true
28
+ }
29
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../dist/out-tsc",
5
+ "declaration": true,
6
+ "declarationMap": true,
7
+ "inlineSources": true,
8
+ "types": []
9
+ },
10
+ "exclude": [
11
+ "src/**/*.spec.ts",
12
+ "src/test-setup.ts",
13
+ "jest.config.ts",
14
+ "src/**/*.test.ts"
15
+ ],
16
+ "include": ["src/**/*.ts"]
17
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "./tsconfig.lib.json",
3
+ "compilerOptions": {
4
+ "declarationMap": false
5
+ },
6
+ "angularCompilerOptions": {
7
+ "compilationMode": "partial"
8
+ }
9
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../dist/out-tsc",
5
+ "module": "commonjs",
6
+ "target": "es2016",
7
+ "types": ["jest", "node"]
8
+ },
9
+ "files": ["src/test-setup.ts"],
10
+ "include": [
11
+ "jest.config.ts",
12
+ "src/**/*.test.ts",
13
+ "src/**/*.spec.ts",
14
+ "src/**/*.d.ts",
15
+ "src/lib/storage-sync/tests/with-storage-sync-indexedb.spec.ts"
16
+ ]
17
+ }
@@ -1,119 +0,0 @@
1
- import * as i0 from '@angular/core';
2
- import { Injectable, inject, makeEnvironmentProviders, provideEnvironmentInitializer, Injector } from '@angular/core';
3
- import { rxMethod } from '@ngrx/signals/rxjs-interop';
4
- import { pipe, tap, map } from 'rxjs';
5
-
6
- function isUnsubscribable(fn) {
7
- return !!fn?.unsubscribe;
8
- }
9
- function capitalize(str) {
10
- return str ? str[0].toUpperCase() + str.substring(1) : str;
11
- }
12
- function isActionCreator(action) {
13
- return Boolean(typeof action === 'function' &&
14
- action &&
15
- 'type' in action &&
16
- action.type &&
17
- typeof action.type === 'string');
18
- }
19
-
20
- class SignalReduxStore {
21
- constructor() {
22
- this.mapperDict = {};
23
- this.dispatch = rxMethod(pipe(tap((action) => {
24
- const callbacks = this.mapperDict[action.type];
25
- if (callbacks?.storeMethod) {
26
- if (isUnsubscribable(callbacks.storeMethod) &&
27
- callbacks.resultMethod) {
28
- return callbacks.storeMethod(action, (a) => {
29
- const resultAction = callbacks.resultMethod?.(a);
30
- this.dispatch(resultAction);
31
- });
32
- }
33
- return callbacks?.storeMethod(action);
34
- }
35
- return;
36
- })));
37
- }
38
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
39
- connectFeatureStore(mappers) {
40
- mappers.forEach((mapper) => mapper.types.forEach((action) => (this.mapperDict[action] = {
41
- storeMethod: mapper.storeMethod,
42
- resultMethod: mapper.resultMethod,
43
- })));
44
- }
45
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: SignalReduxStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
46
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: SignalReduxStore, providedIn: 'root' }); }
47
- }
48
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: SignalReduxStore, decorators: [{
49
- type: Injectable,
50
- args: [{
51
- providedIn: 'root',
52
- }]
53
- }] });
54
- function injectReduxDispatch() {
55
- return inject(SignalReduxStore).dispatch;
56
- }
57
-
58
- function mapAction(...args) {
59
- let resultMethod = args.pop();
60
- let storeMethod = args.pop();
61
- if (isActionCreator(storeMethod)) {
62
- args.push(storeMethod);
63
- storeMethod = resultMethod || storeMethod;
64
- resultMethod = undefined;
65
- }
66
- const types = args.map((creator) => creator.type);
67
- return {
68
- types,
69
- storeMethod,
70
- resultMethod,
71
- };
72
- }
73
- function withActionMappers(...mappers) {
74
- return mappers;
75
- }
76
- function createReduxState(storeName, signalStore, withActionMappers) {
77
- const isRootProvider = signalStore?.ɵprov?.providedIn === 'root';
78
- return {
79
- [`provide${capitalize(storeName)}Store`]: (connectReduxDevtools = false) => makeEnvironmentProviders([
80
- isRootProvider ? [] : signalStore,
81
- provideEnvironmentInitializer(() => {
82
- const initializerFn = ((signalReduxStore = inject(SignalReduxStore), store = inject(signalStore)) => () => {
83
- if (connectReduxDevtools) {
84
- // addStoreToReduxDevtools(store, storeName, false);
85
- }
86
- signalReduxStore.connectFeatureStore(withActionMappers(store));
87
- })();
88
- return initializerFn();
89
- }),
90
- ]),
91
- [`inject${capitalize(storeName)}Store`]: () => Object.assign(inject(signalStore), { dispatch: injectReduxDispatch() }),
92
- };
93
- }
94
-
95
- function reduxMethod(generator, resultMethodOrConfig, config) {
96
- const injector = inject(Injector);
97
- if (typeof resultMethodOrConfig === 'function') {
98
- let unsubscribable;
99
- const inputResultFn = ((input, resultMethod = resultMethodOrConfig) => {
100
- const rxMethodWithResult = rxMethod(pipe(generator, map(resultMethod)), {
101
- ...(config || {}),
102
- injector: config?.injector || injector,
103
- });
104
- const rxWithInput = rxMethodWithResult(input);
105
- unsubscribable = { unsubscribe: rxWithInput.destroy.bind(rxWithInput) };
106
- return rxWithInput;
107
- });
108
- inputResultFn.destroy = () => unsubscribable?.unsubscribe();
109
- return inputResultFn;
110
- }
111
- return rxMethod(generator, resultMethodOrConfig);
112
- }
113
-
114
- /**
115
- * Generated bundle index. Do not edit.
116
- */
117
-
118
- export { createReduxState, mapAction, reduxMethod, withActionMappers };
119
- //# sourceMappingURL=angular-architects-ngrx-toolkit-redux-connector.mjs.map