@angular-architects/ngrx-toolkit 19.0.1 → 19.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/README.md +2 -2
- package/fesm2022/angular-architects-ngrx-toolkit-redux-connector.mjs +3 -3
- package/fesm2022/angular-architects-ngrx-toolkit.mjs +271 -67
- package/fesm2022/angular-architects-ngrx-toolkit.mjs.map +1 -1
- package/index.d.ts +4 -1
- package/lib/devtools/with-devtools.d.ts +0 -1
- package/lib/immutable-state/deep-freeze.d.ts +11 -0
- package/lib/immutable-state/is-dev-mode.d.ts +1 -0
- package/lib/immutable-state/with-immutable-state.d.ts +60 -0
- package/lib/with-conditional.d.ts +50 -0
- package/lib/with-feature-factory.d.ts +26 -0
- package/lib/with-pagination.d.ts +5 -31
- package/lib/with-redux.d.ts +88 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,6 +9,6 @@ NgRx Toolkit is a set of extensions to the NgRx Signals Store, like
|
|
|
9
9
|
- Storage Sync: Synchronize the Store with Web Storage
|
|
10
10
|
- Redux Connector: Map NgRx Store Actions to a present Signal Store
|
|
11
11
|
|
|
12
|
-
For a more detailed guide on installation, setup, and usage, head to the [**Documentation**](https://
|
|
12
|
+
For a more detailed guide on installation, setup, and usage, head to the [**Documentation**](https://ngrx-toolkit.angulararchitects.io//).
|
|
13
13
|
|
|
14
|
-
## https://
|
|
14
|
+
## https://ngrx-toolkit.angulararchitects.io/
|
|
@@ -42,10 +42,10 @@ class SignalReduxStore {
|
|
|
42
42
|
resultMethod: mapper.resultMethod
|
|
43
43
|
}));
|
|
44
44
|
}
|
|
45
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.
|
|
46
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.
|
|
45
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: SignalReduxStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
46
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: SignalReduxStore, providedIn: 'root' }); }
|
|
47
47
|
}
|
|
48
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.
|
|
48
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: SignalReduxStore, decorators: [{
|
|
49
49
|
type: Injectable,
|
|
50
50
|
args: [{
|
|
51
51
|
providedIn: 'root'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getState, signalStoreFeature, withMethods, withHooks, watchState, patchState as patchState$1, withState, withComputed, withProps } from '@ngrx/signals';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { inject, PLATFORM_ID, Injectable, signal, effect, computed, isSignal, untracked } from '@angular/core';
|
|
3
|
+
import { inject, PLATFORM_ID, Injectable, signal, effect, InjectionToken, computed, isSignal, untracked, isDevMode as isDevMode$1 } from '@angular/core';
|
|
4
4
|
import { isPlatformBrowser, isPlatformServer } from '@angular/common';
|
|
5
5
|
import { Subject } from 'rxjs';
|
|
6
6
|
import { setAllEntities, addEntity, updateEntity, removeEntity } from '@ngrx/signals/entities';
|
|
@@ -106,7 +106,9 @@ class DevtoolsSyncer {
|
|
|
106
106
|
let storeName = name;
|
|
107
107
|
const names = Object.values(this.#stores).map((store) => store.name);
|
|
108
108
|
if (names.includes(storeName)) {
|
|
109
|
-
const { options } = throwIfNull(
|
|
109
|
+
// const { options } = throwIfNull(
|
|
110
|
+
// Object.values(this.#stores).find((store) => store.name === storeName)
|
|
111
|
+
// );
|
|
110
112
|
if (!options.indexNames) {
|
|
111
113
|
throw new Error(`An instance of the store ${storeName} already exists. \
|
|
112
114
|
Enable automatic indexing via withDevTools('${storeName}', { indexNames: true }), or rename it upon instantiation.`);
|
|
@@ -166,10 +168,10 @@ Enable automatic indexing via withDevTools('${storeName}', { indexNames: true })
|
|
|
166
168
|
}, {});
|
|
167
169
|
this.#trackers.forEach((tracker) => tracker.notifyRenamedStore(id));
|
|
168
170
|
}
|
|
169
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.
|
|
170
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.
|
|
171
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: DevtoolsSyncer, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
172
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: DevtoolsSyncer, providedIn: 'root' }); }
|
|
171
173
|
}
|
|
172
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.
|
|
174
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: DevtoolsSyncer, decorators: [{
|
|
173
175
|
type: Injectable,
|
|
174
176
|
args: [{ providedIn: 'root' }]
|
|
175
177
|
}], ctorParameters: () => [] });
|
|
@@ -214,17 +216,17 @@ class DefaultTracker {
|
|
|
214
216
|
});
|
|
215
217
|
}
|
|
216
218
|
}
|
|
217
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.
|
|
218
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.
|
|
219
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: DefaultTracker, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
220
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: DefaultTracker, providedIn: 'root' }); }
|
|
219
221
|
}
|
|
220
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.
|
|
222
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: DefaultTracker, decorators: [{
|
|
221
223
|
type: Injectable,
|
|
222
224
|
args: [{ providedIn: 'root' }]
|
|
223
225
|
}] });
|
|
224
226
|
|
|
225
|
-
const existingNames = new Map();
|
|
226
227
|
const renameDevtoolsMethodName = '___renameDevtoolsName';
|
|
227
228
|
const uniqueDevtoolsId = '___uniqueDevtoolsId';
|
|
229
|
+
const EXISTING_NAMES = new InjectionToken('Array contain existing names for the signal stores', { factory: () => [], providedIn: 'root' });
|
|
228
230
|
/**
|
|
229
231
|
* Adds this store as a feature state to the Redux DevTools.
|
|
230
232
|
*
|
|
@@ -239,10 +241,6 @@ const uniqueDevtoolsId = '___uniqueDevtoolsId';
|
|
|
239
241
|
* @param features features to extend or modify the behavior of the Devtools
|
|
240
242
|
*/
|
|
241
243
|
function withDevtools(name, ...features) {
|
|
242
|
-
if (existingNames.has(name)) {
|
|
243
|
-
throw new Error(`The store "${name}" has already been registered in the DevTools. Duplicate registration is not allowed.`);
|
|
244
|
-
}
|
|
245
|
-
existingNames.set(name, true);
|
|
246
244
|
return signalStoreFeature(withMethods(() => {
|
|
247
245
|
const syncer = inject(DevtoolsSyncer);
|
|
248
246
|
const id = syncer.getNextId();
|
|
@@ -382,10 +380,10 @@ class GlitchTrackerService {
|
|
|
382
380
|
this.#callback({ [id]: getState(this.#stores[id].store) });
|
|
383
381
|
}
|
|
384
382
|
}
|
|
385
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.
|
|
386
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.
|
|
383
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: GlitchTrackerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
384
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: GlitchTrackerService, providedIn: 'root' }); }
|
|
387
385
|
}
|
|
388
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.
|
|
386
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: GlitchTrackerService, decorators: [{
|
|
389
387
|
type: Injectable,
|
|
390
388
|
args: [{ providedIn: 'root' }]
|
|
391
389
|
}] });
|
|
@@ -464,6 +462,98 @@ function payload() {
|
|
|
464
462
|
return {};
|
|
465
463
|
}
|
|
466
464
|
const noPayload = {};
|
|
465
|
+
/**
|
|
466
|
+
* Creates a reducer function to separate the reducer logic into another file.
|
|
467
|
+
*
|
|
468
|
+
* ```typescript
|
|
469
|
+
* interface FlightState {
|
|
470
|
+
* flights: Flight[];
|
|
471
|
+
* effect1: boolean;
|
|
472
|
+
* effect2: boolean;
|
|
473
|
+
* }
|
|
474
|
+
*
|
|
475
|
+
* const initialState: FlightState = {
|
|
476
|
+
* flights: [],
|
|
477
|
+
* effect1: false,
|
|
478
|
+
* effect2: false,
|
|
479
|
+
* };
|
|
480
|
+
*
|
|
481
|
+
* const actions = {
|
|
482
|
+
* init: noPayload,
|
|
483
|
+
* updateEffect1: payload<{ value: boolean }>(),
|
|
484
|
+
* updateEffect2: payload<{ value: boolean }>(),
|
|
485
|
+
* };
|
|
486
|
+
*
|
|
487
|
+
* const reducer = createReducer<FlightState, typeof actions>((actions, on) => {
|
|
488
|
+
* on(actions.updateEffect1, (state, { value }) => {
|
|
489
|
+
* patchState(state, { effect1: value });
|
|
490
|
+
* });
|
|
491
|
+
*
|
|
492
|
+
* on(actions.updateEffect2, (state, { value }) => {
|
|
493
|
+
* patchState(state, { effect2: value });
|
|
494
|
+
* });
|
|
495
|
+
* });
|
|
496
|
+
*
|
|
497
|
+
* signalStore(
|
|
498
|
+
* withState(initialState),
|
|
499
|
+
* withRedux({
|
|
500
|
+
* actions,
|
|
501
|
+
* reducer,
|
|
502
|
+
* })
|
|
503
|
+
* );
|
|
504
|
+
* ```
|
|
505
|
+
* @param reducerFactory
|
|
506
|
+
*/
|
|
507
|
+
function createReducer(reducerFactory) {
|
|
508
|
+
return reducerFactory;
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Creates the effects function to separate the effects logic into another file.
|
|
512
|
+
*
|
|
513
|
+
* ```typescript
|
|
514
|
+
* interface FlightState {
|
|
515
|
+
* flights: Flight[];
|
|
516
|
+
* effect1: boolean;
|
|
517
|
+
* effect2: boolean;
|
|
518
|
+
* }
|
|
519
|
+
*
|
|
520
|
+
* const initialState: FlightState = {
|
|
521
|
+
* flights: [],
|
|
522
|
+
* effect1: false,
|
|
523
|
+
* effect2: false,
|
|
524
|
+
* };
|
|
525
|
+
*
|
|
526
|
+
* const actions = {
|
|
527
|
+
* init: noPayload,
|
|
528
|
+
* updateEffect1: payload<{ value: boolean }>(),
|
|
529
|
+
* updateEffect2: payload<{ value: boolean }>(),
|
|
530
|
+
* };
|
|
531
|
+
*
|
|
532
|
+
* const effects = createEffects(actions, (actions, create) => {
|
|
533
|
+
* return {
|
|
534
|
+
* init1$: create(actions.init).pipe(
|
|
535
|
+
* map(() => actions.updateEffect1({ value: true }))
|
|
536
|
+
* ),
|
|
537
|
+
* init2$: create(actions.init).pipe(
|
|
538
|
+
* map(() => actions.updateEffect2({ value: true }))
|
|
539
|
+
* ),
|
|
540
|
+
* };
|
|
541
|
+
* });
|
|
542
|
+
*
|
|
543
|
+
* signalStore(
|
|
544
|
+
* withState(initialState),
|
|
545
|
+
* withRedux({
|
|
546
|
+
* actions,
|
|
547
|
+
* effects,
|
|
548
|
+
* })
|
|
549
|
+
* );
|
|
550
|
+
* ```
|
|
551
|
+
* @param actions
|
|
552
|
+
* @param effectsFactory
|
|
553
|
+
*/
|
|
554
|
+
function createEffects(actions, effectsFactory) {
|
|
555
|
+
return effectsFactory;
|
|
556
|
+
}
|
|
467
557
|
function createActionFns(actionFnSpecs, reducerRegistry, effectsRegistry, state) {
|
|
468
558
|
const actionFns = {};
|
|
469
559
|
for (const type in actionFnSpecs) {
|
|
@@ -553,7 +643,7 @@ function withRedux(redux) {
|
|
|
553
643
|
const { methods } = processRedux(redux.actions, redux.reducer, redux.effects, store);
|
|
554
644
|
return {
|
|
555
645
|
...store,
|
|
556
|
-
methods,
|
|
646
|
+
methods: { ...store.methods, ...methods },
|
|
557
647
|
};
|
|
558
648
|
};
|
|
559
649
|
}
|
|
@@ -995,7 +1085,7 @@ function withStorageSync(configOrKey) {
|
|
|
995
1085
|
* This feature implements the local pagination.
|
|
996
1086
|
*/
|
|
997
1087
|
function withPagination(options) {
|
|
998
|
-
const { pageKey, pageSizeKey, entitiesKey, selectedPageEntitiesKey, totalCountKey, pageCountKey, pageNavigationArrayMaxKey, pageNavigationArrayKey,
|
|
1088
|
+
const { pageKey, pageSizeKey, entitiesKey, selectedPageEntitiesKey, totalCountKey, pageCountKey, pageNavigationArrayMaxKey, pageNavigationArrayKey, hasNextPageKey, hasPreviousPageKey, } = createPaginationKeys(options);
|
|
999
1089
|
return signalStoreFeature(withState({
|
|
1000
1090
|
[pageKey]: 0,
|
|
1001
1091
|
[pageSizeKey]: 10,
|
|
@@ -1029,30 +1119,6 @@ function withPagination(options) {
|
|
|
1029
1119
|
return page() > 1;
|
|
1030
1120
|
}),
|
|
1031
1121
|
};
|
|
1032
|
-
}), withMethods((store) => {
|
|
1033
|
-
return {
|
|
1034
|
-
[setPageSizeKey]: (size) => {
|
|
1035
|
-
patchState$1(store, setPageSize(size, options));
|
|
1036
|
-
},
|
|
1037
|
-
[nextPageKey]: () => {
|
|
1038
|
-
patchState$1(store, nextPage(options));
|
|
1039
|
-
},
|
|
1040
|
-
[previousPageKey]: () => {
|
|
1041
|
-
patchState$1(store, previousPage(options));
|
|
1042
|
-
},
|
|
1043
|
-
[lastPageKey]: () => {
|
|
1044
|
-
const lastPage = store[pageCountKey]();
|
|
1045
|
-
if (lastPage === 0)
|
|
1046
|
-
return;
|
|
1047
|
-
patchState$1(store, gotoPage(lastPage - 1, options));
|
|
1048
|
-
},
|
|
1049
|
-
[firstPageKey]: () => {
|
|
1050
|
-
patchState$1(store, firstPage());
|
|
1051
|
-
},
|
|
1052
|
-
[gotoPageKey]: (page) => {
|
|
1053
|
-
patchState$1(store, gotoPage(page, options));
|
|
1054
|
-
},
|
|
1055
|
-
};
|
|
1056
1122
|
}));
|
|
1057
1123
|
}
|
|
1058
1124
|
function gotoPage(page, options) {
|
|
@@ -1116,24 +1182,6 @@ function createPaginationKeys(options) {
|
|
|
1116
1182
|
const pageNavigationArrayKey = options?.collection
|
|
1117
1183
|
? `${options.collection}PageNavigationArray`
|
|
1118
1184
|
: 'pageNavigationArray';
|
|
1119
|
-
const setPageSizeKey = options?.collection
|
|
1120
|
-
? `set${capitalize(options.collection)}PageSize`
|
|
1121
|
-
: 'setPageSize';
|
|
1122
|
-
const nextPageKey = options?.collection
|
|
1123
|
-
? `next${capitalize(options.collection)}Page`
|
|
1124
|
-
: 'nextPage';
|
|
1125
|
-
const previousPageKey = options?.collection
|
|
1126
|
-
? `previous${capitalize(options.collection)}Page`
|
|
1127
|
-
: 'previousPage';
|
|
1128
|
-
const lastPageKey = options?.collection
|
|
1129
|
-
? `last${capitalize(options.collection)}Page`
|
|
1130
|
-
: 'lastPage';
|
|
1131
|
-
const firstPageKey = options?.collection
|
|
1132
|
-
? `first${capitalize(options.collection)}Page`
|
|
1133
|
-
: 'firstPage';
|
|
1134
|
-
const gotoPageKey = options?.collection
|
|
1135
|
-
? `goto${capitalize(options.collection)}Page`
|
|
1136
|
-
: 'gotoPage';
|
|
1137
1185
|
const hasNextPageKey = options?.collection
|
|
1138
1186
|
? `hasNext${capitalize(options.collection)}Page`
|
|
1139
1187
|
: 'hasNextPage';
|
|
@@ -1149,12 +1197,6 @@ function createPaginationKeys(options) {
|
|
|
1149
1197
|
pageCountKey,
|
|
1150
1198
|
pageNavigationArrayKey,
|
|
1151
1199
|
pageNavigationArrayMaxKey,
|
|
1152
|
-
setPageSizeKey,
|
|
1153
|
-
nextPageKey,
|
|
1154
|
-
previousPageKey,
|
|
1155
|
-
lastPageKey,
|
|
1156
|
-
firstPageKey,
|
|
1157
|
-
gotoPageKey,
|
|
1158
1200
|
hasNextPageKey,
|
|
1159
1201
|
hasPreviousPageKey,
|
|
1160
1202
|
};
|
|
@@ -1231,9 +1273,171 @@ function setResetState(store, state) {
|
|
|
1231
1273
|
store.__setResetState__(state);
|
|
1232
1274
|
}
|
|
1233
1275
|
|
|
1276
|
+
/**
|
|
1277
|
+
* Deep freezes a state object along its properties with primitive values
|
|
1278
|
+
* on the first level.
|
|
1279
|
+
*
|
|
1280
|
+
* The reason for this is that the final state is a merge of all
|
|
1281
|
+
* root properties of all states, i.e. `withState`,....
|
|
1282
|
+
*
|
|
1283
|
+
* Since the root object will not be part of the state (shadow clone),
|
|
1284
|
+
* we are not freezing it.
|
|
1285
|
+
*/
|
|
1286
|
+
function deepFreeze(target,
|
|
1287
|
+
// if empty all properties will be frozen
|
|
1288
|
+
propertyNamesToBeFrozen,
|
|
1289
|
+
// also means that we are on the first level
|
|
1290
|
+
isRoot = true) {
|
|
1291
|
+
const runPropertyNameCheck = propertyNamesToBeFrozen.length > 0;
|
|
1292
|
+
for (const key of Reflect.ownKeys(target)) {
|
|
1293
|
+
if (runPropertyNameCheck && !propertyNamesToBeFrozen.includes(key)) {
|
|
1294
|
+
continue;
|
|
1295
|
+
}
|
|
1296
|
+
const propValue = target[key];
|
|
1297
|
+
if (isRecordLike(propValue) && !Object.isFrozen(propValue)) {
|
|
1298
|
+
Object.freeze(propValue);
|
|
1299
|
+
deepFreeze(propValue, [], false);
|
|
1300
|
+
}
|
|
1301
|
+
else if (isRoot) {
|
|
1302
|
+
Object.defineProperty(target, key, {
|
|
1303
|
+
value: propValue,
|
|
1304
|
+
writable: false,
|
|
1305
|
+
configurable: false,
|
|
1306
|
+
});
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
function isRecordLike(target) {
|
|
1311
|
+
return typeof target === 'object' && target !== null;
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
// necessary wrapper function to test prod mode
|
|
1315
|
+
function isDevMode() {
|
|
1316
|
+
return isDevMode$1();
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
function withImmutableState(stateOrFactory, options) {
|
|
1320
|
+
const immutableState = typeof stateOrFactory === 'function' ? stateOrFactory() : stateOrFactory;
|
|
1321
|
+
const stateKeys = Reflect.ownKeys(immutableState);
|
|
1322
|
+
const applyFreezing = isDevMode() || options?.enableInProduction === true;
|
|
1323
|
+
return signalStoreFeature(withState(immutableState), withHooks((store) => ({
|
|
1324
|
+
onInit() {
|
|
1325
|
+
if (!applyFreezing) {
|
|
1326
|
+
return;
|
|
1327
|
+
}
|
|
1328
|
+
/**
|
|
1329
|
+
* `immutableState` will be initially frozen. That is because
|
|
1330
|
+
* of potential mutations outside the SignalStore
|
|
1331
|
+
*
|
|
1332
|
+
* ```ts
|
|
1333
|
+
* const initialState = {id: 1};
|
|
1334
|
+
* signalStore(withImmutableState(initialState));
|
|
1335
|
+
*
|
|
1336
|
+
* initialState.id = 2; // must throw immutability
|
|
1337
|
+
* ```
|
|
1338
|
+
*/
|
|
1339
|
+
Object.freeze(immutableState);
|
|
1340
|
+
watchState(store, (state) => {
|
|
1341
|
+
deepFreeze(state, stateKeys);
|
|
1342
|
+
});
|
|
1343
|
+
},
|
|
1344
|
+
})));
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
/**
|
|
1348
|
+
* Allows to pass properties, methods, or signals from a SignalStore
|
|
1349
|
+
* to a feature.
|
|
1350
|
+
*
|
|
1351
|
+
* Typically, a `signalStoreFeature` can have input constraints on
|
|
1352
|
+
*
|
|
1353
|
+
* ```typescript
|
|
1354
|
+
* function withSum(a: Signal<number>, b: Signal<number>) {
|
|
1355
|
+
* return signalStoreFeature(
|
|
1356
|
+
* withComputed(() => ({
|
|
1357
|
+
* sum: computed(() => a() + b())
|
|
1358
|
+
* }))
|
|
1359
|
+
* );
|
|
1360
|
+
* }
|
|
1361
|
+
*
|
|
1362
|
+
* signalStore(
|
|
1363
|
+
* withState({ a: 1, b: 2 }),
|
|
1364
|
+
* withFeatureFactory((store) => withSum(store.a, store.b))
|
|
1365
|
+
* );
|
|
1366
|
+
* ```
|
|
1367
|
+
* @param factoryFn
|
|
1368
|
+
*/
|
|
1369
|
+
function withFeatureFactory(factoryFn) {
|
|
1370
|
+
return (store) => {
|
|
1371
|
+
const storeForFactory = {
|
|
1372
|
+
...store['stateSignals'],
|
|
1373
|
+
...store['props'],
|
|
1374
|
+
...store['methods'],
|
|
1375
|
+
};
|
|
1376
|
+
const feature = factoryFn(storeForFactory);
|
|
1377
|
+
return feature(store);
|
|
1378
|
+
};
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
/**
|
|
1382
|
+
* `withConditional` activates a feature based on a given condition.
|
|
1383
|
+
*
|
|
1384
|
+
* **Use Cases**
|
|
1385
|
+
* - Conditionally activate features based on the **store state** or other criteria.
|
|
1386
|
+
* - Choose between **two different implementations** of a feature.
|
|
1387
|
+
*
|
|
1388
|
+
* **Type Constraints**
|
|
1389
|
+
* Both features must have **exactly the same state, props, and methods**.
|
|
1390
|
+
* Otherwise, a type error will occur.
|
|
1391
|
+
*
|
|
1392
|
+
*
|
|
1393
|
+
* **Usage**
|
|
1394
|
+
*
|
|
1395
|
+
* ```typescript
|
|
1396
|
+
* const withUser = signalStoreFeature(
|
|
1397
|
+
* withState({ id: 1, name: 'Konrad' }),
|
|
1398
|
+
* withHooks(store => ({
|
|
1399
|
+
* onInit() {
|
|
1400
|
+
* // user loading logic
|
|
1401
|
+
* }
|
|
1402
|
+
* }))
|
|
1403
|
+
* );
|
|
1404
|
+
*
|
|
1405
|
+
* function withFakeUser() {
|
|
1406
|
+
* return signalStoreFeature(
|
|
1407
|
+
* withState({ id: 0, name: 'anonymous' })
|
|
1408
|
+
* );
|
|
1409
|
+
* }
|
|
1410
|
+
*
|
|
1411
|
+
* signalStore(
|
|
1412
|
+
* withMethods(() => ({
|
|
1413
|
+
* useRealUser: () => true
|
|
1414
|
+
* })),
|
|
1415
|
+
* withConditional((store) => store.useRealUser(), withUser, withFakeUser)
|
|
1416
|
+
* )
|
|
1417
|
+
* ```
|
|
1418
|
+
*
|
|
1419
|
+
* @param condition - A function that determines which feature to activate based on the store state.
|
|
1420
|
+
* @param featureIfTrue - The feature to activate if the condition evaluates to `true`.
|
|
1421
|
+
* @param featureIfFalse - The feature to activate if the condition evaluates to `false`.
|
|
1422
|
+
* @returns A `SignalStoreFeature` that applies the selected feature based on the condition.
|
|
1423
|
+
*/
|
|
1424
|
+
function withConditional(condition, featureIfTrue, featureIfFalse) {
|
|
1425
|
+
return (store) => {
|
|
1426
|
+
const conditionStore = {
|
|
1427
|
+
...store['stateSignals'],
|
|
1428
|
+
...store['props'],
|
|
1429
|
+
...store['methods'],
|
|
1430
|
+
};
|
|
1431
|
+
return condition(conditionStore)
|
|
1432
|
+
? featureIfTrue(store)
|
|
1433
|
+
: featureIfFalse(store);
|
|
1434
|
+
};
|
|
1435
|
+
}
|
|
1436
|
+
const emptyFeature = signalStoreFeature(withState({}));
|
|
1437
|
+
|
|
1234
1438
|
/**
|
|
1235
1439
|
* Generated bundle index. Do not edit.
|
|
1236
1440
|
*/
|
|
1237
1441
|
|
|
1238
|
-
export { capitalize, createPageArray, firstPage, getCallStateKeys, getDataServiceKeys, getUndoRedoKeys, gotoPage, nextPage, noPayload, patchState, payload, previousPage, renameDevtoolsName, setError, setLoaded, setLoading, setMaxPageNavigationArrayItems, setPageSize, setResetState, updateState, withCallState, withDataService, withDevToolsStub, withDevtools, withDisabledNameIndices, withGlitchTracking, withMapper, withPagination, withRedux, withReset, withStorageSync, withUndoRedo };
|
|
1442
|
+
export { capitalize, createEffects, createPageArray, createReducer, emptyFeature, firstPage, getCallStateKeys, getDataServiceKeys, getUndoRedoKeys, gotoPage, nextPage, noPayload, patchState, payload, previousPage, renameDevtoolsName, setError, setLoaded, setLoading, setMaxPageNavigationArrayItems, setPageSize, setResetState, updateState, withCallState, withConditional, withDataService, withDevToolsStub, withDevtools, withDisabledNameIndices, withFeatureFactory, withGlitchTracking, withImmutableState, withMapper, withPagination, withRedux, withReset, withStorageSync, withUndoRedo };
|
|
1239
1443
|
//# sourceMappingURL=angular-architects-ngrx-toolkit.mjs.map
|