@angular-architects/ngrx-toolkit 20.0.2 → 20.1.0
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/fesm2022/angular-architects-ngrx-toolkit-redux-connector.mjs +119 -0
- package/fesm2022/angular-architects-ngrx-toolkit-redux-connector.mjs.map +1 -0
- package/fesm2022/angular-architects-ngrx-toolkit.mjs +1888 -0
- package/fesm2022/angular-architects-ngrx-toolkit.mjs.map +1 -0
- package/index.d.ts +1084 -0
- package/package.json +21 -4
- package/redux-connector/index.d.ts +59 -0
- package/eslint.config.cjs +0 -43
- package/jest.config.ts +0 -22
- package/ng-package.json +0 -7
- package/project.json +0 -37
- package/redux-connector/docs/README.md +0 -131
- package/redux-connector/index.ts +0 -6
- package/redux-connector/ng-package.json +0 -5
- package/redux-connector/src/lib/create-redux.ts +0 -102
- package/redux-connector/src/lib/model.ts +0 -89
- package/redux-connector/src/lib/rxjs-interop/redux-method.ts +0 -66
- package/redux-connector/src/lib/signal-redux-store.ts +0 -59
- package/redux-connector/src/lib/util.ts +0 -22
- package/src/index.ts +0 -43
- package/src/lib/assertions/assertions.ts +0 -9
- package/src/lib/devtools/features/with-disabled-name-indicies.ts +0 -31
- package/src/lib/devtools/features/with-glitch-tracking.ts +0 -35
- package/src/lib/devtools/features/with-mapper.ts +0 -34
- package/src/lib/devtools/internal/current-action-names.ts +0 -1
- package/src/lib/devtools/internal/default-tracker.ts +0 -60
- package/src/lib/devtools/internal/devtools-feature.ts +0 -37
- package/src/lib/devtools/internal/devtools-syncer.service.ts +0 -202
- package/src/lib/devtools/internal/glitch-tracker.service.ts +0 -61
- package/src/lib/devtools/internal/models.ts +0 -29
- package/src/lib/devtools/provide-devtools-config.ts +0 -32
- package/src/lib/devtools/rename-devtools-name.ts +0 -21
- package/src/lib/devtools/tests/action-name.spec.ts +0 -48
- package/src/lib/devtools/tests/basic.spec.ts +0 -111
- package/src/lib/devtools/tests/connecting.spec.ts +0 -37
- package/src/lib/devtools/tests/helpers.spec.ts +0 -43
- package/src/lib/devtools/tests/naming.spec.ts +0 -216
- package/src/lib/devtools/tests/provide-devtools-config.spec.ts +0 -25
- package/src/lib/devtools/tests/types.spec.ts +0 -19
- package/src/lib/devtools/tests/update-state.spec.ts +0 -29
- package/src/lib/devtools/tests/with-devtools.spec.ts +0 -5
- package/src/lib/devtools/tests/with-glitch-tracking.spec.ts +0 -272
- package/src/lib/devtools/tests/with-mapper.spec.ts +0 -69
- package/src/lib/devtools/update-state.ts +0 -38
- package/src/lib/devtools/with-dev-tools-stub.ts +0 -6
- package/src/lib/devtools/with-devtools.ts +0 -81
- package/src/lib/immutable-state/deep-freeze.ts +0 -43
- package/src/lib/immutable-state/is-dev-mode.ts +0 -6
- package/src/lib/immutable-state/tests/with-immutable-state.spec.ts +0 -278
- package/src/lib/immutable-state/with-immutable-state.ts +0 -150
- package/src/lib/shared/prettify.ts +0 -3
- package/src/lib/shared/signal-store-models.ts +0 -30
- package/src/lib/shared/throw-if-null.ts +0 -7
- package/src/lib/storage-sync/features/with-indexed-db.ts +0 -81
- package/src/lib/storage-sync/features/with-local-storage.ts +0 -58
- package/src/lib/storage-sync/internal/indexeddb.service.ts +0 -124
- package/src/lib/storage-sync/internal/local-storage.service.ts +0 -19
- package/src/lib/storage-sync/internal/models.ts +0 -62
- package/src/lib/storage-sync/internal/session-storage.service.ts +0 -18
- package/src/lib/storage-sync/tests/indexeddb.service.spec.ts +0 -99
- package/src/lib/storage-sync/tests/with-storage-async.spec.ts +0 -305
- package/src/lib/storage-sync/tests/with-storage-sync.spec.ts +0 -273
- package/src/lib/storage-sync/with-storage-sync.ts +0 -236
- package/src/lib/with-call-state.spec.ts +0 -42
- package/src/lib/with-call-state.ts +0 -195
- package/src/lib/with-conditional.spec.ts +0 -125
- package/src/lib/with-conditional.ts +0 -74
- package/src/lib/with-data-service.spec.ts +0 -564
- package/src/lib/with-data-service.ts +0 -433
- package/src/lib/with-feature-factory.spec.ts +0 -69
- package/src/lib/with-feature-factory.ts +0 -56
- package/src/lib/with-pagination.spec.ts +0 -135
- package/src/lib/with-pagination.ts +0 -373
- package/src/lib/with-redux.spec.ts +0 -258
- package/src/lib/with-redux.ts +0 -387
- package/src/lib/with-reset.spec.ts +0 -112
- package/src/lib/with-reset.ts +0 -62
- package/src/lib/with-undo-redo.spec.ts +0 -274
- package/src/lib/with-undo-redo.ts +0 -200
- package/src/test-setup.ts +0 -6
- package/tsconfig.json +0 -29
- package/tsconfig.lib.json +0 -17
- package/tsconfig.lib.prod.json +0 -9
- package/tsconfig.spec.json +0 -17
package/src/lib/with-redux.ts
DELETED
|
@@ -1,387 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
EmptyFeatureResult,
|
|
3
|
-
SignalStoreFeature,
|
|
4
|
-
SignalStoreFeatureResult,
|
|
5
|
-
WritableStateSource,
|
|
6
|
-
} from '@ngrx/signals';
|
|
7
|
-
import { Observable, Subject } from 'rxjs';
|
|
8
|
-
import { assertActionFnSpecs } from './assertions/assertions';
|
|
9
|
-
|
|
10
|
-
/** Actions **/
|
|
11
|
-
|
|
12
|
-
type Payload = Record<string, unknown>;
|
|
13
|
-
|
|
14
|
-
type ActionFn<
|
|
15
|
-
Type extends string = string,
|
|
16
|
-
ActionPayload extends Payload = Payload,
|
|
17
|
-
> = ((payload: ActionPayload) => ActionPayload & { type: Type }) & {
|
|
18
|
-
type: Type;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
type ActionFns = Record<string, ActionFn>;
|
|
22
|
-
|
|
23
|
-
export type ActionsFnSpecs = Record<string, Payload>;
|
|
24
|
-
|
|
25
|
-
type ActionFnCreator<Spec extends ActionsFnSpecs> = {
|
|
26
|
-
[ActionName in keyof Spec]: (Record<never, never> extends Spec[ActionName]
|
|
27
|
-
? () => Spec[ActionName] & { type: ActionName }
|
|
28
|
-
: (
|
|
29
|
-
payload: Spec[ActionName],
|
|
30
|
-
) => Spec[ActionName] & { type: ActionName }) & {
|
|
31
|
-
type: ActionName & string;
|
|
32
|
-
};
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
type ActionFnPayload<Action> = Action extends (payload: infer Payload) => void
|
|
36
|
-
? Payload
|
|
37
|
-
: never;
|
|
38
|
-
|
|
39
|
-
type ActionFnsCreator<Spec extends ActionsFnSpecs> = Spec extends {
|
|
40
|
-
private: Record<string, Payload>;
|
|
41
|
-
public: Record<string, Payload>;
|
|
42
|
-
}
|
|
43
|
-
? ActionFnCreator<Spec['private']> & ActionFnCreator<Spec['public']>
|
|
44
|
-
: ActionFnCreator<Spec>;
|
|
45
|
-
|
|
46
|
-
type PublicActionFns<Spec extends ActionsFnSpecs> = Spec extends {
|
|
47
|
-
public: Record<string, Payload>;
|
|
48
|
-
}
|
|
49
|
-
? ActionFnCreator<Spec['public']>
|
|
50
|
-
: ActionFnCreator<Spec>;
|
|
51
|
-
|
|
52
|
-
export function payload<Type extends Payload>(): Type {
|
|
53
|
-
return {} as Type;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export const noPayload = {};
|
|
57
|
-
|
|
58
|
-
/** Reducer **/
|
|
59
|
-
|
|
60
|
-
type ReducerFunction<ReducerAction, State> = (
|
|
61
|
-
state: State,
|
|
62
|
-
action: ActionFnPayload<ReducerAction>,
|
|
63
|
-
) => void;
|
|
64
|
-
|
|
65
|
-
type ReducerFactory<StateActionFns extends ActionFns, State> = (
|
|
66
|
-
actions: StateActionFns,
|
|
67
|
-
on: <ReducerAction extends { type: string }>(
|
|
68
|
-
action: ReducerAction,
|
|
69
|
-
reducerFn: ReducerFunction<ReducerAction, State>,
|
|
70
|
-
) => void,
|
|
71
|
-
) => void;
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Creates a reducer function to separate the reducer logic into another file.
|
|
75
|
-
*
|
|
76
|
-
* ```typescript
|
|
77
|
-
* interface FlightState {
|
|
78
|
-
* flights: Flight[];
|
|
79
|
-
* effect1: boolean;
|
|
80
|
-
* effect2: boolean;
|
|
81
|
-
* }
|
|
82
|
-
*
|
|
83
|
-
* const initialState: FlightState = {
|
|
84
|
-
* flights: [],
|
|
85
|
-
* effect1: false,
|
|
86
|
-
* effect2: false,
|
|
87
|
-
* };
|
|
88
|
-
*
|
|
89
|
-
* const actions = {
|
|
90
|
-
* init: noPayload,
|
|
91
|
-
* updateEffect1: payload<{ value: boolean }>(),
|
|
92
|
-
* updateEffect2: payload<{ value: boolean }>(),
|
|
93
|
-
* };
|
|
94
|
-
*
|
|
95
|
-
* const reducer = createReducer<FlightState, typeof actions>((actions, on) => {
|
|
96
|
-
* on(actions.updateEffect1, (state, { value }) => {
|
|
97
|
-
* patchState(state, { effect1: value });
|
|
98
|
-
* });
|
|
99
|
-
*
|
|
100
|
-
* on(actions.updateEffect2, (state, { value }) => {
|
|
101
|
-
* patchState(state, { effect2: value });
|
|
102
|
-
* });
|
|
103
|
-
* });
|
|
104
|
-
*
|
|
105
|
-
* signalStore(
|
|
106
|
-
* withState(initialState),
|
|
107
|
-
* withRedux({
|
|
108
|
-
* actions,
|
|
109
|
-
* reducer,
|
|
110
|
-
* })
|
|
111
|
-
* );
|
|
112
|
-
* ```
|
|
113
|
-
* @param reducerFactory
|
|
114
|
-
*/
|
|
115
|
-
export function createReducer<
|
|
116
|
-
State extends object,
|
|
117
|
-
Actions extends ActionsFnSpecs,
|
|
118
|
-
>(
|
|
119
|
-
reducerFactory: ReducerFactory<
|
|
120
|
-
ActionFnsCreator<Actions>,
|
|
121
|
-
WritableStateSource<State>
|
|
122
|
-
>,
|
|
123
|
-
) {
|
|
124
|
-
return reducerFactory;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/** Effect **/
|
|
128
|
-
|
|
129
|
-
type EffectsFactory<StateActionFns extends ActionFns> = (
|
|
130
|
-
actions: StateActionFns,
|
|
131
|
-
create: <EffectAction extends { type: string }>(
|
|
132
|
-
action: EffectAction,
|
|
133
|
-
) => Observable<ActionFnPayload<EffectAction>>,
|
|
134
|
-
) => Record<string, Observable<unknown>>;
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* @deprecated Use NgRx's `@ngrx/signals/events` starting in 19.2
|
|
138
|
-
*
|
|
139
|
-
* Creates the effects function to separate the effects logic into another file.
|
|
140
|
-
*
|
|
141
|
-
* ```typescript
|
|
142
|
-
* interface FlightState {
|
|
143
|
-
* flights: Flight[];
|
|
144
|
-
* effect1: boolean;
|
|
145
|
-
* effect2: boolean;
|
|
146
|
-
* }
|
|
147
|
-
*
|
|
148
|
-
* const initialState: FlightState = {
|
|
149
|
-
* flights: [],
|
|
150
|
-
* effect1: false,
|
|
151
|
-
* effect2: false,
|
|
152
|
-
* };
|
|
153
|
-
*
|
|
154
|
-
* const actions = {
|
|
155
|
-
* init: noPayload,
|
|
156
|
-
* updateEffect1: payload<{ value: boolean }>(),
|
|
157
|
-
* updateEffect2: payload<{ value: boolean }>(),
|
|
158
|
-
* };
|
|
159
|
-
*
|
|
160
|
-
* const effects = createEffects(actions, (actions, create) => {
|
|
161
|
-
* return {
|
|
162
|
-
* init1$: create(actions.init).pipe(
|
|
163
|
-
* map(() => actions.updateEffect1({ value: true }))
|
|
164
|
-
* ),
|
|
165
|
-
* init2$: create(actions.init).pipe(
|
|
166
|
-
* map(() => actions.updateEffect2({ value: true }))
|
|
167
|
-
* ),
|
|
168
|
-
* };
|
|
169
|
-
* });
|
|
170
|
-
*
|
|
171
|
-
* signalStore(
|
|
172
|
-
* withState(initialState),
|
|
173
|
-
* withRedux({
|
|
174
|
-
* actions,
|
|
175
|
-
* effects,
|
|
176
|
-
* })
|
|
177
|
-
* );
|
|
178
|
-
* ```
|
|
179
|
-
* @param actions
|
|
180
|
-
* @param effectsFactory
|
|
181
|
-
*/
|
|
182
|
-
export function createEffects<Actions extends ActionsFnSpecs>(
|
|
183
|
-
actions: Actions,
|
|
184
|
-
effectsFactory: EffectsFactory<ActionFnsCreator<Actions>>,
|
|
185
|
-
) {
|
|
186
|
-
return effectsFactory;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// internal types
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Record which holds all effects for a specific action type.
|
|
193
|
-
* The values are Subject which the effect are subscribed to.
|
|
194
|
-
* `createActionFns` will call next on these subjects.
|
|
195
|
-
*/
|
|
196
|
-
type EffectsRegistry = Record<string, Subject<ActionFnPayload<unknown>>[]>;
|
|
197
|
-
|
|
198
|
-
function createActionFns<Spec extends ActionsFnSpecs>(
|
|
199
|
-
actionFnSpecs: Spec,
|
|
200
|
-
reducerRegistry: Record<
|
|
201
|
-
string,
|
|
202
|
-
(state: unknown, payload: ActionFnPayload<unknown>) => void
|
|
203
|
-
>,
|
|
204
|
-
effectsRegistry: EffectsRegistry,
|
|
205
|
-
state: unknown,
|
|
206
|
-
) {
|
|
207
|
-
const actionFns: Record<string, ActionFn> = {};
|
|
208
|
-
|
|
209
|
-
for (const type in actionFnSpecs) {
|
|
210
|
-
const actionFn = (payload: Payload) => {
|
|
211
|
-
const fullPayload = { ...payload, type };
|
|
212
|
-
const reducer = reducerRegistry[type];
|
|
213
|
-
if (reducer) {
|
|
214
|
-
(reducer as (state: unknown, payload: unknown) => void)(
|
|
215
|
-
state,
|
|
216
|
-
fullPayload as unknown,
|
|
217
|
-
);
|
|
218
|
-
}
|
|
219
|
-
const effectSubjects = effectsRegistry[type];
|
|
220
|
-
if (effectSubjects?.length) {
|
|
221
|
-
for (const effectSubject of effectSubjects) {
|
|
222
|
-
(effectSubject as unknown as Subject<unknown>).next(fullPayload);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
return fullPayload;
|
|
226
|
-
};
|
|
227
|
-
actionFn.type = type.toString();
|
|
228
|
-
actionFns[type] = actionFn;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
return actionFns;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
function createPublicAndAllActionsFns<Spec extends ActionsFnSpecs>(
|
|
235
|
-
actionFnSpecs: Spec,
|
|
236
|
-
reducerRegistry: Record<
|
|
237
|
-
string,
|
|
238
|
-
(state: unknown, payload: ActionFnPayload<unknown>) => void
|
|
239
|
-
>,
|
|
240
|
-
effectsRegistry: EffectsRegistry,
|
|
241
|
-
state: unknown,
|
|
242
|
-
): { all: ActionFns; publics: ActionFns } {
|
|
243
|
-
if ('public' in actionFnSpecs || 'private' in actionFnSpecs) {
|
|
244
|
-
const privates = actionFnSpecs['private'] || {};
|
|
245
|
-
const publics = actionFnSpecs['public'] || {};
|
|
246
|
-
|
|
247
|
-
assertActionFnSpecs(privates);
|
|
248
|
-
assertActionFnSpecs(publics);
|
|
249
|
-
|
|
250
|
-
const privateActionFns = createActionFns(
|
|
251
|
-
privates,
|
|
252
|
-
reducerRegistry,
|
|
253
|
-
effectsRegistry,
|
|
254
|
-
state,
|
|
255
|
-
);
|
|
256
|
-
const publicActionFns = createActionFns(
|
|
257
|
-
publics,
|
|
258
|
-
reducerRegistry,
|
|
259
|
-
effectsRegistry,
|
|
260
|
-
state,
|
|
261
|
-
);
|
|
262
|
-
|
|
263
|
-
return {
|
|
264
|
-
all: { ...privateActionFns, ...publicActionFns },
|
|
265
|
-
publics: publicActionFns,
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
const actionFns = createActionFns(
|
|
270
|
-
actionFnSpecs,
|
|
271
|
-
reducerRegistry,
|
|
272
|
-
effectsRegistry,
|
|
273
|
-
state,
|
|
274
|
-
);
|
|
275
|
-
|
|
276
|
-
return { all: actionFns, publics: actionFns };
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
function fillReducerRegistry(
|
|
280
|
-
reducer: ReducerFactory<ActionFns, unknown>,
|
|
281
|
-
actionFns: ActionFns,
|
|
282
|
-
reducerRegistry: Record<
|
|
283
|
-
string,
|
|
284
|
-
(state: unknown, payload: ActionFnPayload<unknown>) => void
|
|
285
|
-
>,
|
|
286
|
-
) {
|
|
287
|
-
function on(
|
|
288
|
-
action: { type: string },
|
|
289
|
-
reducerFn: (state: unknown, payload: ActionFnPayload<unknown>) => void,
|
|
290
|
-
) {
|
|
291
|
-
reducerRegistry[action.type] = reducerFn;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
reducer(actionFns, on);
|
|
295
|
-
|
|
296
|
-
return reducerRegistry;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
function fillEffects(
|
|
300
|
-
effects: EffectsFactory<ActionFns>,
|
|
301
|
-
actionFns: ActionFns,
|
|
302
|
-
effectsRegistry: EffectsRegistry = {},
|
|
303
|
-
): Observable<unknown>[] {
|
|
304
|
-
function create(action: { type: string }) {
|
|
305
|
-
const subject = new Subject<ActionFnPayload<unknown>>();
|
|
306
|
-
if (!(action.type in effectsRegistry)) {
|
|
307
|
-
effectsRegistry[action.type] = [];
|
|
308
|
-
}
|
|
309
|
-
effectsRegistry[action.type].push(subject);
|
|
310
|
-
return subject.asObservable();
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
const effectObservables = effects(actionFns, create);
|
|
314
|
-
return Object.values(effectObservables);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
function startSubscriptions(observables: Observable<unknown>[]) {
|
|
318
|
-
return observables.map((observable) => observable.subscribe());
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
function processRedux<Spec extends ActionsFnSpecs, ReturnType>(
|
|
322
|
-
actionFnSpecs: Spec,
|
|
323
|
-
reducer: ReducerFactory<ActionFns, unknown>,
|
|
324
|
-
effects: EffectsFactory<ActionFns>,
|
|
325
|
-
store: unknown,
|
|
326
|
-
) {
|
|
327
|
-
const reducerRegistry: Record<
|
|
328
|
-
string,
|
|
329
|
-
(state: unknown, payload: ActionFnPayload<unknown>) => void
|
|
330
|
-
> = {};
|
|
331
|
-
const effectsRegistry: Record<string, Subject<ActionFnPayload<unknown>>[]> =
|
|
332
|
-
{};
|
|
333
|
-
const actionsMap = createPublicAndAllActionsFns(
|
|
334
|
-
actionFnSpecs,
|
|
335
|
-
reducerRegistry,
|
|
336
|
-
effectsRegistry,
|
|
337
|
-
store,
|
|
338
|
-
);
|
|
339
|
-
const actionFns = actionsMap.all;
|
|
340
|
-
const publicActionsFns = actionsMap.publics;
|
|
341
|
-
|
|
342
|
-
fillReducerRegistry(reducer, actionFns, reducerRegistry);
|
|
343
|
-
const effectObservables = fillEffects(effects, actionFns, effectsRegistry);
|
|
344
|
-
const subscriptions = startSubscriptions(effectObservables);
|
|
345
|
-
|
|
346
|
-
return {
|
|
347
|
-
methods: publicActionsFns as ReturnType,
|
|
348
|
-
subscriptions: subscriptions,
|
|
349
|
-
};
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
/**
|
|
353
|
-
* @param redux redux
|
|
354
|
-
*
|
|
355
|
-
* properties do not start with `with` since they are not extension functions on their own.
|
|
356
|
-
*
|
|
357
|
-
* no dependency to NgRx
|
|
358
|
-
*
|
|
359
|
-
* actions are passed to reducer and effects, but it is also possible to use other actions.
|
|
360
|
-
* effects provide forAction and do not return anything. that is important because effects should stay inaccessible
|
|
361
|
-
*/
|
|
362
|
-
export function withRedux<
|
|
363
|
-
Spec extends ActionsFnSpecs,
|
|
364
|
-
Input extends SignalStoreFeatureResult,
|
|
365
|
-
StateActionFns extends ActionFnsCreator<Spec> = ActionFnsCreator<Spec>,
|
|
366
|
-
PublicStoreActionFns extends PublicActionFns<Spec> = PublicActionFns<Spec>,
|
|
367
|
-
>(redux: {
|
|
368
|
-
actions: Spec;
|
|
369
|
-
reducer: ReducerFactory<StateActionFns, WritableStateSource<Input['state']>>;
|
|
370
|
-
effects: EffectsFactory<StateActionFns>;
|
|
371
|
-
}): SignalStoreFeature<
|
|
372
|
-
Input,
|
|
373
|
-
EmptyFeatureResult & { methods: PublicStoreActionFns }
|
|
374
|
-
> {
|
|
375
|
-
return (store) => {
|
|
376
|
-
const { methods } = processRedux<Spec, PublicStoreActionFns>(
|
|
377
|
-
redux.actions,
|
|
378
|
-
redux.reducer as ReducerFactory<ActionFns, unknown>,
|
|
379
|
-
redux.effects as EffectsFactory<ActionFns>,
|
|
380
|
-
store,
|
|
381
|
-
);
|
|
382
|
-
return {
|
|
383
|
-
...store,
|
|
384
|
-
methods: { ...store.methods, ...methods },
|
|
385
|
-
};
|
|
386
|
-
};
|
|
387
|
-
}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { effect } from '@angular/core';
|
|
2
|
-
import { TestBed } from '@angular/core/testing';
|
|
3
|
-
import {
|
|
4
|
-
getState,
|
|
5
|
-
patchState,
|
|
6
|
-
signalStore,
|
|
7
|
-
withMethods,
|
|
8
|
-
withState,
|
|
9
|
-
} from '@ngrx/signals';
|
|
10
|
-
import { setResetState, withReset } from './with-reset';
|
|
11
|
-
|
|
12
|
-
describe('withReset', () => {
|
|
13
|
-
const setup = () => {
|
|
14
|
-
const initialState = {
|
|
15
|
-
user: { id: 1, name: 'Konrad' },
|
|
16
|
-
address: { city: 'Vienna', zip: '1010' },
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const Store = signalStore(
|
|
20
|
-
withState(initialState),
|
|
21
|
-
withReset(),
|
|
22
|
-
withMethods((store) => ({
|
|
23
|
-
changeUser(id: number, name: string) {
|
|
24
|
-
patchState(store, { user: { id, name } });
|
|
25
|
-
},
|
|
26
|
-
changeUserName(name: string) {
|
|
27
|
-
patchState(store, (value) => ({ user: { ...value.user, name } }));
|
|
28
|
-
},
|
|
29
|
-
changeAddress(city: string, zip: string) {
|
|
30
|
-
patchState(store, { address: { city, zip } });
|
|
31
|
-
},
|
|
32
|
-
})),
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
const store = TestBed.configureTestingModule({
|
|
36
|
-
providers: [Store],
|
|
37
|
-
}).inject(Store);
|
|
38
|
-
|
|
39
|
-
return { store, initialState };
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
it('should reset state to initial state', () => {
|
|
43
|
-
const { store, initialState } = setup();
|
|
44
|
-
|
|
45
|
-
store.changeUser(2, 'Max');
|
|
46
|
-
expect(getState(store)).toMatchObject({
|
|
47
|
-
user: { id: 2, name: 'Max' },
|
|
48
|
-
});
|
|
49
|
-
store.resetState();
|
|
50
|
-
expect(getState(store)).toStrictEqual(initialState);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('should not fire if reset is called on unchanged state', () => {
|
|
54
|
-
const { store } = setup();
|
|
55
|
-
let effectCounter = 0;
|
|
56
|
-
TestBed.runInInjectionContext(() => {
|
|
57
|
-
effect(() => {
|
|
58
|
-
store.user();
|
|
59
|
-
effectCounter++;
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
TestBed.flushEffects();
|
|
63
|
-
store.resetState();
|
|
64
|
-
TestBed.flushEffects();
|
|
65
|
-
expect(effectCounter).toBe(1);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('should not fire on props which are unchanged', () => {
|
|
69
|
-
const { store } = setup();
|
|
70
|
-
let effectCounter = 0;
|
|
71
|
-
TestBed.runInInjectionContext(() => {
|
|
72
|
-
effect(() => {
|
|
73
|
-
store.address();
|
|
74
|
-
effectCounter++;
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
TestBed.flushEffects();
|
|
79
|
-
expect(effectCounter).toBe(1);
|
|
80
|
-
store.changeUserName('Max');
|
|
81
|
-
TestBed.flushEffects();
|
|
82
|
-
store.changeUser(2, 'Ludwig');
|
|
83
|
-
TestBed.flushEffects();
|
|
84
|
-
expect(effectCounter).toBe(1);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('should be possible to change the reset state', () => {
|
|
88
|
-
const { store } = setup();
|
|
89
|
-
|
|
90
|
-
setResetState(store, {
|
|
91
|
-
user: { id: 2, name: 'Max' },
|
|
92
|
-
address: { city: 'London', zip: 'SW1' },
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
store.changeUser(3, 'Ludwig');
|
|
96
|
-
store.changeAddress('Paris', '75001');
|
|
97
|
-
|
|
98
|
-
store.resetState();
|
|
99
|
-
expect(getState(store)).toEqual({
|
|
100
|
-
user: { id: 2, name: 'Max' },
|
|
101
|
-
address: { city: 'London', zip: 'SW1' },
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('should throw on setResetState if store is not configured with withReset()', () => {
|
|
106
|
-
const Store = signalStore({ providedIn: 'root' }, withState({}));
|
|
107
|
-
const store = TestBed.inject(Store);
|
|
108
|
-
expect(() => setResetState(store, {})).toThrow(
|
|
109
|
-
'Cannot set reset state, since store is not configured with withReset()',
|
|
110
|
-
);
|
|
111
|
-
});
|
|
112
|
-
});
|
package/src/lib/with-reset.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getState,
|
|
3
|
-
patchState,
|
|
4
|
-
signalStoreFeature,
|
|
5
|
-
StateSource,
|
|
6
|
-
withHooks,
|
|
7
|
-
withMethods,
|
|
8
|
-
withProps,
|
|
9
|
-
} from '@ngrx/signals';
|
|
10
|
-
|
|
11
|
-
export type PublicMethods = {
|
|
12
|
-
resetState(): void;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Adds a `resetState` method to the store, which resets the state
|
|
17
|
-
* to the initial state.
|
|
18
|
-
*
|
|
19
|
-
* If you want to set a custom initial state, you can use {@link setResetState}.
|
|
20
|
-
*/
|
|
21
|
-
export function withReset() {
|
|
22
|
-
return signalStoreFeature(
|
|
23
|
-
withProps(() => ({ _resetState: { value: {} } })),
|
|
24
|
-
withMethods((store): PublicMethods => {
|
|
25
|
-
// workaround to TS excessive property check
|
|
26
|
-
const methods = {
|
|
27
|
-
resetState() {
|
|
28
|
-
patchState(store, store._resetState.value);
|
|
29
|
-
},
|
|
30
|
-
__setResetState__(state: object) {
|
|
31
|
-
store._resetState.value = state;
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
return methods;
|
|
36
|
-
}),
|
|
37
|
-
withHooks((store) => ({
|
|
38
|
-
onInit() {
|
|
39
|
-
store._resetState.value = getState(store);
|
|
40
|
-
},
|
|
41
|
-
})),
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Sets the reset state of the store to the given state.
|
|
47
|
-
*
|
|
48
|
-
* Throws an error if the store is not configured with {@link withReset}.
|
|
49
|
-
* @param store the instance of a SignalStore
|
|
50
|
-
* @param state the state to set as the reset state
|
|
51
|
-
*/
|
|
52
|
-
export function setResetState<State extends object>(
|
|
53
|
-
store: StateSource<State>,
|
|
54
|
-
state: State,
|
|
55
|
-
): void {
|
|
56
|
-
if (!('__setResetState__' in store)) {
|
|
57
|
-
throw new Error(
|
|
58
|
-
'Cannot set reset state, since store is not configured with withReset()',
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
(store.__setResetState__ as (state: State) => void)(state);
|
|
62
|
-
}
|