@angular-architects/ngrx-toolkit 0.1.0 → 0.1.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 (62) hide show
  1. package/esm2022/angular-architects-ngrx-toolkit.mjs +5 -0
  2. package/esm2022/index.mjs +9 -0
  3. package/esm2022/lib/assertions/assertions.mjs +6 -0
  4. package/esm2022/lib/redux-connector/create-redux.mjs +41 -0
  5. package/esm2022/lib/redux-connector/index.mjs +2 -0
  6. package/esm2022/lib/redux-connector/model.mjs +2 -0
  7. package/esm2022/lib/redux-connector/rxjs-interop/index.mjs +2 -0
  8. package/esm2022/lib/redux-connector/rxjs-interop/redux-method.mjs +22 -0
  9. package/esm2022/lib/redux-connector/signal-redux-store.mjs +43 -0
  10. package/esm2022/lib/redux-connector/util.mjs +13 -0
  11. package/esm2022/lib/shared/empty.mjs +2 -0
  12. package/esm2022/lib/with-call-state.mjs +58 -0
  13. package/esm2022/lib/with-data-service.mjs +161 -0
  14. package/esm2022/lib/with-devtools.mjs +79 -0
  15. package/esm2022/lib/with-redux.mjs +95 -0
  16. package/esm2022/lib/with-storage-sync.mjs +56 -0
  17. package/esm2022/lib/with-undo-redo.mjs +93 -0
  18. package/fesm2022/angular-architects-ngrx-toolkit.mjs +653 -0
  19. package/fesm2022/angular-architects-ngrx-toolkit.mjs.map +1 -0
  20. package/{src/index.ts → index.d.ts} +2 -3
  21. package/lib/assertions/assertions.d.ts +2 -0
  22. package/lib/redux-connector/create-redux.d.ts +13 -0
  23. package/{src/lib/redux-connector/index.ts → lib/redux-connector/index.d.ts} +0 -1
  24. package/lib/redux-connector/model.d.ts +36 -0
  25. package/{src/lib/redux-connector/rxjs-interop/index.ts → lib/redux-connector/rxjs-interop/index.d.ts} +0 -1
  26. package/lib/redux-connector/rxjs-interop/redux-method.d.ts +11 -0
  27. package/lib/redux-connector/signal-redux-store.d.ts +11 -0
  28. package/lib/redux-connector/util.d.ts +5 -0
  29. package/lib/shared/empty.d.ts +1 -0
  30. package/lib/with-call-state.d.ts +56 -0
  31. package/lib/with-data-service.d.ts +115 -0
  32. package/lib/with-devtools.d.ts +32 -0
  33. package/lib/with-redux.d.ts +57 -0
  34. package/lib/with-storage-sync.d.ts +58 -0
  35. package/lib/with-undo-redo.d.ts +55 -0
  36. package/package.json +16 -3
  37. package/.eslintrc.json +0 -43
  38. package/jest.config.ts +0 -22
  39. package/ng-package.json +0 -7
  40. package/project.json +0 -37
  41. package/src/lib/assertions/assertions.ts +0 -9
  42. package/src/lib/redux-connector/create-redux.ts +0 -94
  43. package/src/lib/redux-connector/model.ts +0 -67
  44. package/src/lib/redux-connector/rxjs-interop/redux-method.ts +0 -61
  45. package/src/lib/redux-connector/signal-redux-store.ts +0 -54
  46. package/src/lib/redux-connector/util.ts +0 -22
  47. package/src/lib/shared/empty.ts +0 -2
  48. package/src/lib/with-call-state.spec.ts +0 -24
  49. package/src/lib/with-call-state.ts +0 -136
  50. package/src/lib/with-data-service.ts +0 -312
  51. package/src/lib/with-devtools.spec.ts +0 -157
  52. package/src/lib/with-devtools.ts +0 -128
  53. package/src/lib/with-redux.spec.ts +0 -100
  54. package/src/lib/with-redux.ts +0 -261
  55. package/src/lib/with-storage-sync.spec.ts +0 -237
  56. package/src/lib/with-storage-sync.ts +0 -160
  57. package/src/lib/with-undo-redo.ts +0 -184
  58. package/src/test-setup.ts +0 -8
  59. package/tsconfig.json +0 -29
  60. package/tsconfig.lib.json +0 -17
  61. package/tsconfig.lib.prod.json +0 -9
  62. package/tsconfig.spec.json +0 -16
@@ -1,261 +0,0 @@
1
- import { Observable, Subject } from 'rxjs';
2
- import { SignalStoreFeature } from '@ngrx/signals';
3
- import {
4
- EmptyFeatureResult,
5
- SignalStoreFeatureResult,
6
- } from '@ngrx/signals/src/signal-store-models';
7
- import { StateSignal } from '@ngrx/signals/src/state-signal';
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]: ((
27
- payload: Spec[ActionName]
28
- ) => Spec[ActionName] & { type: ActionName }) & { type: ActionName & string };
29
- };
30
-
31
- type ActionFnPayload<Action> = Action extends (payload: infer Payload) => void
32
- ? Payload
33
- : never;
34
-
35
- type ActionFnsCreator<Spec extends ActionsFnSpecs> = Spec extends {
36
- private: Record<string, Payload>;
37
- public: Record<string, Payload>;
38
- }
39
- ? ActionFnCreator<Spec['private']> & ActionFnCreator<Spec['public']>
40
- : ActionFnCreator<Spec>;
41
-
42
- type PublicActionFns<Spec extends ActionsFnSpecs> = Spec extends {
43
- public: Record<string, Payload>;
44
- }
45
- ? ActionFnCreator<Spec['public']>
46
- : ActionFnCreator<Spec>;
47
-
48
- export function payload<Type extends Payload>(): Type {
49
- return {} as Type;
50
- }
51
-
52
- export const noPayload = {};
53
-
54
- /** Reducer **/
55
-
56
- type ReducerFunction<ReducerAction, State> = (
57
- state: State,
58
- action: ActionFnPayload<ReducerAction>
59
- ) => void;
60
-
61
- type ReducerFactory<StateActionFns extends ActionFns, State> = (
62
- actions: StateActionFns,
63
- on: <ReducerAction extends { type: string }>(
64
- action: ReducerAction,
65
- reducerFn: ReducerFunction<ReducerAction, State>
66
- ) => void
67
- ) => void;
68
-
69
- /** Effect **/
70
-
71
- type EffectsFactory<StateActionFns extends ActionFns> = (
72
- actions: StateActionFns,
73
- create: <EffectAction extends { type: string }>(
74
- action: EffectAction
75
- ) => Observable<ActionFnPayload<EffectAction>>
76
- ) => Record<string, Observable<unknown>>;
77
-
78
- function createActionFns<Spec extends ActionsFnSpecs>(
79
- actionFnSpecs: Spec,
80
- reducerRegistry: Record<
81
- string,
82
- (state: unknown, payload: ActionFnPayload<unknown>) => void
83
- >,
84
- effectsRegistry: Record<string, Subject<ActionFnPayload<unknown>>>,
85
- state: unknown
86
- ) {
87
- const actionFns: Record<string, ActionFn> = {};
88
-
89
- for (const type in actionFnSpecs) {
90
- const actionFn = (payload: Payload) => {
91
- const fullPayload = { ...payload, type };
92
- const reducer = reducerRegistry[type];
93
- if (reducer) {
94
- (reducer as (state: unknown, payload: unknown) => void)(
95
- state,
96
- fullPayload as unknown
97
- );
98
- }
99
- const effectSubject = effectsRegistry[type];
100
- if (effectSubject) {
101
- (effectSubject as unknown as Subject<unknown>).next(fullPayload);
102
- }
103
- return fullPayload;
104
- };
105
- actionFn.type = type.toString();
106
- actionFns[type] = actionFn;
107
- }
108
-
109
- return actionFns;
110
- }
111
-
112
- function createPublicAndAllActionsFns<Spec extends ActionsFnSpecs>(
113
- actionFnSpecs: Spec,
114
- reducerRegistry: Record<
115
- string,
116
- (state: unknown, payload: ActionFnPayload<unknown>) => void
117
- >,
118
- effectsRegistry: Record<string, Subject<ActionFnPayload<unknown>>>,
119
- state: unknown
120
- ): { all: ActionFns; publics: ActionFns } {
121
- if ('public' in actionFnSpecs || 'private' in actionFnSpecs) {
122
- const privates = actionFnSpecs['private'] || {};
123
- const publics = actionFnSpecs['public'] || {};
124
-
125
- assertActionFnSpecs(privates);
126
- assertActionFnSpecs(publics);
127
-
128
- const privateActionFns = createActionFns(
129
- privates,
130
- reducerRegistry,
131
- effectsRegistry,
132
- state
133
- );
134
- const publicActionFns = createActionFns(
135
- publics,
136
- reducerRegistry,
137
- effectsRegistry,
138
- state
139
- );
140
-
141
- return {
142
- all: { ...privateActionFns, ...publicActionFns },
143
- publics: publicActionFns,
144
- };
145
- }
146
-
147
- const actionFns = createActionFns(
148
- actionFnSpecs,
149
- reducerRegistry,
150
- effectsRegistry,
151
- state
152
- );
153
-
154
- return { all: actionFns, publics: actionFns };
155
- }
156
-
157
- function fillReducerRegistry(
158
- reducer: ReducerFactory<ActionFns, unknown>,
159
- actionFns: ActionFns,
160
- reducerRegistry: Record<
161
- string,
162
- (state: unknown, payload: ActionFnPayload<unknown>) => void
163
- >
164
- ) {
165
- function on(
166
- action: { type: string },
167
- reducerFn: (state: unknown, payload: ActionFnPayload<unknown>) => void
168
- ) {
169
- reducerRegistry[action.type] = reducerFn;
170
- }
171
-
172
- reducer(actionFns, on);
173
-
174
- return reducerRegistry;
175
- }
176
-
177
- function fillEffects(
178
- effects: EffectsFactory<ActionFns>,
179
- actionFns: ActionFns,
180
- effectsRegistry: Record<string, Subject<ActionFnPayload<unknown>>> = {}
181
- ): Observable<unknown>[] {
182
- function create(action: { type: string }) {
183
- const subject = new Subject<ActionFnPayload<unknown>>();
184
- effectsRegistry[action.type] = subject;
185
- return subject.asObservable();
186
- }
187
-
188
- const effectObservables = effects(actionFns, create);
189
- return Object.values(effectObservables);
190
- }
191
-
192
- function startSubscriptions(observables: Observable<unknown>[]) {
193
- return observables.map((observable) => observable.subscribe());
194
- }
195
-
196
- function processRedux<Spec extends ActionsFnSpecs, ReturnType>(
197
- actionFnSpecs: Spec,
198
- reducer: ReducerFactory<ActionFns, unknown>,
199
- effects: EffectsFactory<ActionFns>,
200
- store: unknown
201
- ) {
202
- const reducerRegistry: Record<
203
- string,
204
- (state: unknown, payload: ActionFnPayload<unknown>) => void
205
- > = {};
206
- const effectsRegistry: Record<string, Subject<ActionFnPayload<unknown>>> = {};
207
- const actionsMap = createPublicAndAllActionsFns(
208
- actionFnSpecs,
209
- reducerRegistry,
210
- effectsRegistry,
211
- store
212
- );
213
- const actionFns = actionsMap.all;
214
- const publicActionsFns = actionsMap.publics;
215
-
216
- fillReducerRegistry(reducer, actionFns, reducerRegistry);
217
- const effectObservables = fillEffects(effects, actionFns, effectsRegistry);
218
- const subscriptions = startSubscriptions(effectObservables);
219
-
220
- return {
221
- methods: publicActionsFns as ReturnType,
222
- subscriptions: subscriptions,
223
- };
224
- }
225
-
226
- /**
227
- * @param redux redux
228
- *
229
- * properties do not start with `with` since they are not extension functions on their own.
230
- *
231
- * no dependency to NgRx
232
- *
233
- * actions are passed to reducer and effects, but it is also possible to use other actions.
234
- * effects provide forAction and do not return anything. that is important because effects should stay inaccessible
235
- */
236
- export function withRedux<
237
- Spec extends ActionsFnSpecs,
238
- Input extends SignalStoreFeatureResult,
239
- StateActionFns extends ActionFnsCreator<Spec> = ActionFnsCreator<Spec>,
240
- PublicStoreActionFns extends PublicActionFns<Spec> = PublicActionFns<Spec>
241
- >(redux: {
242
- actions: Spec;
243
- reducer: ReducerFactory<StateActionFns, StateSignal<Input['state']>>;
244
- effects: EffectsFactory<StateActionFns>;
245
- }): SignalStoreFeature<
246
- Input,
247
- EmptyFeatureResult & { methods: PublicStoreActionFns }
248
- > {
249
- return (store) => {
250
- const { methods, subscriptions } = processRedux<Spec, PublicStoreActionFns>(
251
- redux.actions,
252
- redux.reducer as ReducerFactory<ActionFns, unknown>,
253
- redux.effects as EffectsFactory<ActionFns>,
254
- store
255
- );
256
- return {
257
- ...store,
258
- methods,
259
- };
260
- };
261
- }
@@ -1,237 +0,0 @@
1
- import { getState, patchState, signalStore, withState } from '@ngrx/signals';
2
- import { withStorageSync } from './with-storage-sync';
3
- import { TestBed } from '@angular/core/testing';
4
-
5
- interface StateObject {
6
- foo: string;
7
- age: number;
8
- }
9
- const initialState: StateObject = {
10
- foo: 'bar',
11
- age: 18,
12
- };
13
- const key = 'FooBar';
14
-
15
- describe('withStorageSync', () => {
16
- beforeEach(() => {
17
- // make sure to start with a clean storage
18
- localStorage.removeItem(key);
19
- });
20
-
21
- it('adds methods for storage access to the store', () => {
22
- TestBed.runInInjectionContext(() => {
23
- const Store = signalStore(withStorageSync({ key }));
24
- const store = new Store();
25
-
26
- expect(Object.keys(store)).toEqual([
27
- 'clearStorage',
28
- 'readFromStorage',
29
- 'writeToStorage',
30
- ]);
31
- });
32
- });
33
-
34
- it('offers manual sync using provided methods', () => {
35
- TestBed.runInInjectionContext(() => {
36
- // prefill storage
37
- localStorage.setItem(
38
- key,
39
- JSON.stringify({
40
- foo: 'baz',
41
- age: 99,
42
- } as StateObject)
43
- );
44
-
45
- const Store = signalStore(withStorageSync({ key, autoSync: false }));
46
- const store = new Store();
47
- expect(getState(store)).toEqual({});
48
-
49
- store.readFromStorage();
50
- expect(getState(store)).toEqual({
51
- foo: 'baz',
52
- age: 99,
53
- });
54
-
55
- patchState(store, { ...initialState });
56
- TestBed.flushEffects();
57
-
58
- let storeItem = JSON.parse(localStorage.getItem(key) || '{}');
59
- expect(storeItem).toEqual({
60
- foo: 'baz',
61
- age: 99,
62
- });
63
-
64
- store.writeToStorage();
65
- storeItem = JSON.parse(localStorage.getItem(key) || '{}');
66
- expect(storeItem).toEqual({
67
- ...initialState,
68
- });
69
-
70
- store.clearStorage();
71
- storeItem = localStorage.getItem(key);
72
- expect(storeItem).toEqual(null);
73
- });
74
- });
75
-
76
- describe('autoSync', () => {
77
- it('inits from storage and write to storage on changes when set to `true`', () => {
78
- TestBed.runInInjectionContext(() => {
79
- // prefill storage
80
- localStorage.setItem(
81
- key,
82
- JSON.stringify({
83
- foo: 'baz',
84
- age: 99,
85
- } as StateObject)
86
- );
87
-
88
- const Store = signalStore(withStorageSync(key));
89
- const store = new Store();
90
- expect(getState(store)).toEqual({
91
- foo: 'baz',
92
- age: 99,
93
- });
94
-
95
- patchState(store, { ...initialState });
96
- TestBed.flushEffects();
97
-
98
- expect(getState(store)).toEqual({
99
- ...initialState,
100
- });
101
- const storeItem = JSON.parse(localStorage.getItem(key) || '{}');
102
- expect(storeItem).toEqual({
103
- ...initialState,
104
- });
105
- });
106
- });
107
-
108
- it('does not init from storage and does write to storage on changes when set to `false`', () => {
109
- TestBed.runInInjectionContext(() => {
110
- // prefill storage
111
- localStorage.setItem(
112
- key,
113
- JSON.stringify({
114
- foo: 'baz',
115
- age: 99,
116
- } as StateObject)
117
- );
118
-
119
- const Store = signalStore(withStorageSync({ key, autoSync: false }));
120
- const store = new Store();
121
- expect(getState(store)).toEqual({});
122
-
123
- patchState(store, { ...initialState });
124
- const storeItem = JSON.parse(localStorage.getItem(key) || '{}');
125
- expect(storeItem).toEqual({
126
- foo: 'baz',
127
- age: 99,
128
- });
129
- });
130
- });
131
- });
132
-
133
- describe('select', () => {
134
- it('syncs the whole state by default', () => {
135
- TestBed.runInInjectionContext(() => {
136
- const Store = signalStore(withStorageSync(key));
137
- const store = new Store();
138
-
139
- patchState(store, { ...initialState });
140
- TestBed.flushEffects();
141
-
142
- const storeItem = JSON.parse(localStorage.getItem(key) || '{}');
143
- expect(storeItem).toEqual({
144
- ...initialState,
145
- });
146
- });
147
- });
148
-
149
- it('syncs selected slices when specified', () => {
150
- TestBed.runInInjectionContext(() => {
151
- const Store = signalStore(
152
- withState(initialState),
153
- withStorageSync({ key, select: ({ foo }) => ({ foo }) })
154
- );
155
- const store = new Store();
156
-
157
- patchState(store, { foo: 'baz' });
158
- TestBed.flushEffects();
159
-
160
- const storeItem = JSON.parse(localStorage.getItem(key) || '{}');
161
- expect(storeItem).toEqual({
162
- foo: 'baz',
163
- });
164
- });
165
- });
166
- });
167
-
168
- describe('parse/stringify', () => {
169
- it('uses custom parsing/stringification when specified', () => {
170
- const parse = (stateString: string) => {
171
- const [foo, age] = stateString.split('_');
172
- return {
173
- foo,
174
- age: +age,
175
- };
176
- };
177
-
178
- TestBed.runInInjectionContext(() => {
179
- const Store = signalStore(
180
- withState(initialState),
181
- withStorageSync({
182
- key,
183
- parse,
184
- stringify: (state) => `${state.foo}_${state.age}`,
185
- })
186
- );
187
- const store = new Store();
188
-
189
- patchState(store, { foo: 'baz' });
190
- TestBed.flushEffects();
191
-
192
- const storeItem = parse(localStorage.getItem(key) || '');
193
- expect(storeItem).toEqual({
194
- ...initialState,
195
- foo: 'baz',
196
- });
197
- });
198
- });
199
- });
200
-
201
- describe('storage factory', () => {
202
- it('uses specified storage', () => {
203
- TestBed.runInInjectionContext(() => {
204
- // prefill storage
205
- sessionStorage.setItem(
206
- key,
207
- JSON.stringify({
208
- foo: 'baz',
209
- age: 99,
210
- } as StateObject)
211
- );
212
-
213
- const Store = signalStore(
214
- withStorageSync({ key, storage: () => sessionStorage })
215
- );
216
- const store = new Store();
217
- expect(getState(store)).toEqual({
218
- foo: 'baz',
219
- age: 99,
220
- });
221
-
222
- patchState(store, { ...initialState });
223
- TestBed.flushEffects();
224
-
225
- expect(getState(store)).toEqual({
226
- ...initialState,
227
- });
228
- const storeItem = JSON.parse(sessionStorage.getItem(key) || '{}');
229
- expect(storeItem).toEqual({
230
- ...initialState,
231
- });
232
-
233
- store.clearStorage();
234
- });
235
- });
236
- });
237
- });
@@ -1,160 +0,0 @@
1
- import { isPlatformServer } from '@angular/common';
2
- import { PLATFORM_ID, effect, inject } from '@angular/core';
3
- import {
4
- SignalStoreFeature,
5
- getState,
6
- patchState,
7
- signalStoreFeature,
8
- withHooks,
9
- withMethods,
10
- } from '@ngrx/signals';
11
- import { Emtpy } from './shared/empty';
12
-
13
- type SignalStoreFeatureInput<State> = Pick<
14
- Parameters<SignalStoreFeature>[0],
15
- 'signals' | 'methods'
16
- > & {
17
- state: State;
18
- };
19
-
20
- const NOOP = () => {};
21
-
22
- type WithStorageSyncFeatureResult = {
23
- state: Emtpy;
24
- signals: Emtpy;
25
- methods: {
26
- clearStorage(): void;
27
- readFromStorage(): void;
28
- writeToStorage(): void;
29
- };
30
- };
31
-
32
- const StorageSyncStub: Pick<
33
- WithStorageSyncFeatureResult,
34
- 'methods'
35
- >['methods'] = {
36
- clearStorage: NOOP,
37
- readFromStorage: NOOP,
38
- writeToStorage: NOOP,
39
- };
40
-
41
- export type SyncConfig<State> = {
42
- /**
43
- * The key which is used to access the storage.
44
- */
45
- key: string;
46
- /**
47
- * Flag indicating if the store should read from storage on init and write to storage on every state change.
48
- *
49
- * `true` by default
50
- */
51
- autoSync?: boolean;
52
- /**
53
- * Function to select that portion of the state which should be stored.
54
- *
55
- * Returns the whole state object by default
56
- */
57
- select?: (state: State) => Partial<State>;
58
- /**
59
- * Function used to parse the state coming from storage.
60
- *
61
- * `JSON.parse()` by default
62
- */
63
- parse?: (stateString: string) => State;
64
- /**
65
- * Function used to tranform the state into a string representation.
66
- *
67
- * `JSON.stringify()` by default
68
- */
69
- stringify?: (state: State) => string;
70
- /**
71
- * Factory function used to select the storage.
72
- *
73
- * `localstorage` by default
74
- */
75
- storage?: () => Storage;
76
- };
77
-
78
- /**
79
- * Enables store synchronization with storage.
80
- *
81
- * Only works on browser platform.
82
- */
83
- export function withStorageSync<
84
- State extends object,
85
- Input extends SignalStoreFeatureInput<State>
86
- >(key: string): SignalStoreFeature<Input, WithStorageSyncFeatureResult>;
87
- export function withStorageSync<
88
- State extends object,
89
- Input extends SignalStoreFeatureInput<State>
90
- >(
91
- config: SyncConfig<Input['state']>
92
- ): SignalStoreFeature<Input, WithStorageSyncFeatureResult>;
93
- export function withStorageSync<
94
- State extends object,
95
- Input extends SignalStoreFeatureInput<State>
96
- >(
97
- configOrKey: SyncConfig<Input['state']> | string
98
- ): SignalStoreFeature<Input, WithStorageSyncFeatureResult> {
99
- const {
100
- key,
101
- autoSync = true,
102
- select = (state: State) => state,
103
- parse = JSON.parse,
104
- stringify = JSON.stringify,
105
- storage: storageFactory = () => localStorage,
106
- } = typeof configOrKey === 'string' ? { key: configOrKey } : configOrKey;
107
-
108
- return signalStoreFeature(
109
- withMethods((store, platformId = inject(PLATFORM_ID)) => {
110
- if (isPlatformServer(platformId)) {
111
- console.warn(
112
- `'withStorageSync' provides non-functional implementation due to server-side execution`
113
- );
114
- return StorageSyncStub;
115
- }
116
-
117
- const storage = storageFactory();
118
-
119
- return {
120
- /**
121
- * Removes the item stored in storage.
122
- */
123
- clearStorage(): void {
124
- storage.removeItem(key);
125
- },
126
- /**
127
- * Reads item from storage and patches the state.
128
- */
129
- readFromStorage(): void {
130
- const stateString = storage.getItem(key);
131
- if (stateString) {
132
- patchState(store, parse(stateString));
133
- }
134
- },
135
- /**
136
- * Writes selected portion to storage.
137
- */
138
- writeToStorage(): void {
139
- const slicedState = select(getState(store) as State);
140
- storage.setItem(key, stringify(slicedState));
141
- },
142
- };
143
- }),
144
- withHooks({
145
- onInit(store, platformId = inject(PLATFORM_ID)) {
146
- if (isPlatformServer(platformId)) {
147
- return;
148
- }
149
-
150
- if (autoSync) {
151
- store.readFromStorage();
152
-
153
- effect(() => {
154
- store.writeToStorage();
155
- });
156
- }
157
- },
158
- })
159
- );
160
- }