@angular-architects/ngrx-toolkit 20.0.3 → 20.3.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/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as _ngrx_signals from '@ngrx/signals';
2
2
  import { StateSource, patchState as patchState$1, WritableStateSource, PartialStateUpdater, SignalStoreFeature, EmptyFeatureResult, SignalStoreFeatureResult, StateSignals } from '@ngrx/signals';
3
- import { ValueProvider, Signal, ProviderToken, WritableSignal } from '@angular/core';
4
- import { Observable } from 'rxjs';
3
+ import { ValueProvider, Signal, ProviderToken, WritableSignal, Injector, ResourceStatus, Resource, ResourceRef } from '@angular/core';
4
+ import { Observable, ObservableInput, OperatorFunction, ObservedValueOf } from 'rxjs';
5
5
  import { EntityId, NamedEntityState } from '@ngrx/signals/entities';
6
6
 
7
7
  /**
@@ -941,5 +941,277 @@ type StoreForFactory<Input extends SignalStoreFeatureResult> = StateSignals<Inpu
941
941
  */
942
942
  declare function withFeatureFactory<Input extends SignalStoreFeatureResult, Output extends SignalStoreFeatureResult>(factoryFn: (store: StoreForFactory<Input>) => SignalStoreFeature<Input, Output>): SignalStoreFeature<Input, Output>;
943
943
 
944
- export { capitalize, createEffects, createPageArray, createReducer, deriveCallStateKeys, emptyFeature, firstPage, getCallStateKeys, getCollectionArray, getDataServiceKeys, getUndoRedoKeys, gotoPage, nextPage, noPayload, patchState, payload, previousPage, provideDevtoolsConfig, renameDevtoolsName, setError, setLoaded, setLoading, setMaxPageNavigationArrayItems, setPageSize, setResetState, updateState, withCallState, withConditional, withDataService, withDevToolsStub, withDevtools, withDisabledNameIndices, withFeatureFactory, withGlitchTracking, withImmutableState, withIndexedDB, withIndexedDB as withIndexeddb, withLocalStorage, withMapper, withPagination, withRedux, withReset, withSessionStorage, withStorageSync, withUndoRedo };
945
- export type { CallState, CallStateSignals, CallStateSlice, DataService, DataServiceComputed, DataServiceMethods, DataServiceState, Entity, Filter, NamedCallStateSignals, NamedCallStateSlice, NamedDataServiceComputed, NamedDataServiceMethods, NamedDataServiceState, NamedPaginationServiceSignals, NamedPaginationServiceState, NormalizedUndoRedoOptions, Page, PaginationServiceSignals, PaginationServiceState, ReduxDevtoolsConfig, SetCallState, SetPaginationState, StackItem, SyncConfig };
944
+ type RxJsFlatteningOperator = <T, O extends ObservableInput<unknown>>(project: (value: T, index: number) => O) => OperatorFunction<T, ObservedValueOf<O>>;
945
+ /**
946
+ * A wrapper for an RxJS flattening operator.
947
+ * This wrapper informs about whether the operator has exhaust semantics or not.
948
+ */
949
+ type FlatteningOperator = {
950
+ rxJsOperator: RxJsFlatteningOperator;
951
+ exhaustSemantics: boolean;
952
+ };
953
+ declare const switchOp: FlatteningOperator;
954
+ declare const mergeOp: FlatteningOperator;
955
+ declare const concatOp: FlatteningOperator;
956
+ declare const exhaustOp: FlatteningOperator;
957
+
958
+ type Mutation<P, R> = {
959
+ (params: P): Promise<MutationResult<R>>;
960
+ status: Signal<MutationStatus>;
961
+ isPending: Signal<boolean>;
962
+ error: Signal<unknown>;
963
+ };
964
+ type MutationsDictionary = Record<string, Mutation<any, any>>;
965
+ type MutationResult<T> = {
966
+ status: 'success';
967
+ value: T;
968
+ } | {
969
+ status: 'error';
970
+ error: unknown;
971
+ } | {
972
+ status: 'aborted';
973
+ };
974
+ type MutationStatus = 'idle' | 'pending' | 'error' | 'success';
975
+ type MethodsDictionary = Record<string, Function>;
976
+ type NamedMutationProps<T extends MutationsDictionary> = {
977
+ [Prop in keyof T as `${Prop & string}IsPending`]: Signal<boolean>;
978
+ } & {
979
+ [Prop in keyof T as `${Prop & string}Status`]: Signal<MutationStatus>;
980
+ } & {
981
+ [Prop in keyof T as `${Prop & string}Error`]: Signal<Error | undefined>;
982
+ };
983
+ type NamedMutationMethods<T extends MutationsDictionary> = {
984
+ [Prop in keyof T as `${Prop & string}`]: T[Prop] extends Mutation<infer P, infer R> ? Mutation<P, R> : never;
985
+ };
986
+ type NamedMutationResult<T extends MutationsDictionary> = EmptyFeatureResult & {
987
+ props: NamedMutationProps<T>;
988
+ methods: NamedMutationMethods<T>;
989
+ };
990
+ /**
991
+ * Adds mutation methods to the store. Also, for each mutation method, several
992
+ * Signals are added informing about the mutation's status and errors.
993
+ *
994
+ * ```typescript
995
+ * export type Params = {
996
+ * value: number;
997
+ * };
998
+ *
999
+ * export const CounterStore = signalStore(
1000
+ * { providedIn: 'root' },
1001
+ * withState({ counter: 0 }),
1002
+ * withMutations((store) => ({
1003
+ * increment: rxMutation({ ... }),
1004
+ * })),
1005
+ * );
1006
+ * ```
1007
+ *
1008
+ * There are several types of mutations. In the example shown, an {@link module:rx-mutation.rxMutation | rxMutation}
1009
+ * leveraging RxJS is used
1010
+ *
1011
+ * For the defined `increment` mutation, several the following properties and
1012
+ * methods are added to the store:
1013
+ * - `increment(params: Params): Promise<MutationResult<number>>`: The mutation method.
1014
+ * - `incrementIsPending`: A signal indicating if the mutation is in progress.
1015
+ * - `incrementStatus`: A signal representing the current status of the mutation.
1016
+ * - `incrementError`: A signal containing any error that occurred during the mutation.
1017
+ *
1018
+ * @param mutationsFactory
1019
+ */
1020
+ declare function withMutations<Input extends SignalStoreFeatureResult, Result extends MutationsDictionary>(mutationsFactory: (store: Input['props'] & Input['methods'] & WritableStateSource<Input['state']> & StateSignals<Input['state']>) => Result): SignalStoreFeature<Input, NamedMutationResult<Result>>;
1021
+
1022
+ type Func<P, R> = (params: P) => R;
1023
+ interface RxMutationOptions<P, R> {
1024
+ operation: Func<P, Observable<R>>;
1025
+ onSuccess?: (result: R, params: P) => void;
1026
+ onError?: (error: unknown, params: P) => void;
1027
+ operator?: FlatteningOperator;
1028
+ injector?: Injector;
1029
+ }
1030
+ /**
1031
+ * Creates a mutation that leverages RxJS.
1032
+ *
1033
+ * For each mutation the following options can be defined:
1034
+ * - `operation`: A function that defines the mutation logic. It returns an Observable.
1035
+ * - `onSuccess`: A callback that is called when the mutation is successful.
1036
+ * - `onError`: A callback that is called when the mutation fails.
1037
+ * - `operator`: An optional wrapper of an RxJS flattening operator. By default `concat` sematics are used.
1038
+ * - `injector`: An optional Angular injector to use for dependency injection.
1039
+ *
1040
+ * The `operation` is the only mandatory option.
1041
+ *
1042
+ * ```typescript
1043
+ * export type Params = {
1044
+ * value: number;
1045
+ * };
1046
+ *
1047
+ * export const CounterStore = signalStore(
1048
+ * { providedIn: 'root' },
1049
+ * withState({ counter: 0 }),
1050
+ * withMutations((store) => ({
1051
+ * increment: rxMutation({
1052
+ * operation: (params: Params) => {
1053
+ * return calcSum(store.counter(), params.value);
1054
+ * },
1055
+ * operator: concatOp,
1056
+ * onSuccess: (result) => {
1057
+ * console.log('result', result);
1058
+ * patchState(store, { counter: result });
1059
+ * },
1060
+ * onError: (error) => {
1061
+ * console.error('Error occurred:', error);
1062
+ * },
1063
+ * }),
1064
+ * })),
1065
+ * );
1066
+ *
1067
+ * function calcSum(a: number, b: number): Observable<number> {
1068
+ * return of(a + b);
1069
+ * }
1070
+ * ```
1071
+ *
1072
+ * @param options
1073
+ * @returns
1074
+ */
1075
+ declare function rxMutation<P, R>(options: RxMutationOptions<P, R>): Mutation<P, R>;
1076
+
1077
+ type ResourceResult<T> = {
1078
+ state: {
1079
+ value: T;
1080
+ };
1081
+ props: {
1082
+ status: Signal<ResourceStatus>;
1083
+ error: Signal<Error | undefined>;
1084
+ isLoading: Signal<boolean>;
1085
+ };
1086
+ methods: {
1087
+ hasValue(): this is Resource<Exclude<T, undefined>>;
1088
+ _reload(): boolean;
1089
+ };
1090
+ };
1091
+ type ResourceDictionary = Record<string, ResourceRef<unknown>>;
1092
+ type NamedResourceResult<T extends ResourceDictionary> = {
1093
+ state: {
1094
+ [Prop in keyof T as `${Prop & string}Value`]: T[Prop]['value'] extends Signal<infer S> ? S : never;
1095
+ };
1096
+ props: {
1097
+ [Prop in keyof T as `${Prop & string}Status`]: Signal<ResourceStatus>;
1098
+ } & {
1099
+ [Prop in keyof T as `${Prop & string}Error`]: Signal<Error | undefined>;
1100
+ } & {
1101
+ [Prop in keyof T as `${Prop & string}IsLoading`]: Signal<boolean>;
1102
+ };
1103
+ methods: {
1104
+ [Prop in keyof T as `${Prop & string}HasValue`]: () => this is Resource<Exclude<T[Prop]['value'], undefined>>;
1105
+ } & {
1106
+ [Prop in keyof T as `_${Prop & string}Reload`]: () => boolean;
1107
+ };
1108
+ };
1109
+ /**
1110
+ * @experimental
1111
+ * @description
1112
+ *
1113
+ * Integrates a `Resource` into the SignalStore and makes the store instance
1114
+ * implement the `Resource` interface.
1115
+ *
1116
+ * The resource’s value is stored under the `value` key in the state
1117
+ * and is exposed as a `DeepSignal`.
1118
+ *
1119
+ * It can also be updated via `patchState`.
1120
+ *
1121
+ * @usageNotes
1122
+ *
1123
+ * ```ts
1124
+ * const UserStore = signalStore(
1125
+ * withState({ userId: undefined as number | undefined }),
1126
+ * withResource(({ userId }) =>
1127
+ * httpResource<User>(() =>
1128
+ * userId === undefined ? undefined : `/users/${userId}`
1129
+ * )
1130
+ * )
1131
+ * );
1132
+ *
1133
+ * const userStore = new UserStore();
1134
+ * userStore.value(); // User | undefined
1135
+ * ```
1136
+ *
1137
+ * @param resourceFactory A factory function that receives the store's state signals,
1138
+ * methods, and props. Needs to return a `ResourceRef`.
1139
+ */
1140
+ declare function withResource<Input extends SignalStoreFeatureResult, ResourceValue>(resourceFactory: (store: Input['props'] & Input['methods'] & StateSignals<Input['state']>) => ResourceRef<ResourceValue>): SignalStoreFeature<Input, ResourceResult<ResourceValue>>;
1141
+ /**
1142
+ * @experimental
1143
+ * @description
1144
+ *
1145
+ * Integrates multiple resources into the SignalStore. Each resource is
1146
+ * registered by name, which is used as a prefix when spreading the members
1147
+ * of `Resource` onto the store.
1148
+ *
1149
+ * Each resource’s value is part of the state, stored under the `value` key
1150
+ * with the resource name as prefix. Values are exposed as `DeepSignal`s and
1151
+ * can be updated via `patchState`.
1152
+ *
1153
+ * @usageNotes
1154
+ *
1155
+ * ```ts
1156
+ * const UserStore = signalStore(
1157
+ * withState({ userId: undefined as number | undefined }),
1158
+ * withResource(({ userId }) => ({
1159
+ * list: httpResource<User[]>(() => '/users', { defaultValue: [] }),
1160
+ * detail: httpResource<User>(() =>
1161
+ * userId === undefined ? undefined : `/users/${userId}`
1162
+ * ),
1163
+ * }))
1164
+ * );
1165
+ *
1166
+ * const userStore = new UserStore();
1167
+ * userStore.listValue(); // []
1168
+ * userStore.detailValue(); // User | undefined
1169
+ * ```
1170
+ *
1171
+ * @param resourceFactory A factory function that receives the store's props,
1172
+ * methods, and state signals. It must return a `Record<string, ResourceRef>`.
1173
+ */
1174
+ declare function withResource<Input extends SignalStoreFeatureResult, Dictionary extends ResourceDictionary>(resourceFactory: (store: Input['props'] & Input['methods'] & StateSignals<Input['state']>) => Dictionary): SignalStoreFeature<Input, NamedResourceResult<Dictionary>>;
1175
+ type NamedResource<Name extends string, T> = {
1176
+ [Prop in `${Name}Value`]: Signal<T>;
1177
+ } & {
1178
+ [Prop in `${Name}Status`]: Signal<ResourceStatus>;
1179
+ } & {
1180
+ [Prop in `${Name}Error`]: Signal<Error | undefined>;
1181
+ } & {
1182
+ [Prop in `${Name}IsLoading`]: Signal<boolean>;
1183
+ } & {
1184
+ [Prop in `${Name}HasValue`]: () => boolean;
1185
+ };
1186
+ type IsValidResourceName<Name extends string, Store extends Record<string, unknown>> = Store[`${Name}Value`] extends Signal<infer S> ? Store extends NamedResource<Name, S> ? true : false : false;
1187
+ type ResourceNames<Store extends Record<string, unknown>> = keyof {
1188
+ [Prop in keyof Store as Prop extends `${infer Name}Value` ? IsValidResourceName<Name, Store> extends true ? Name : never : never]: Store[Prop] extends Signal<infer S> ? S : never;
1189
+ };
1190
+ type MappedResource<Store extends Record<string, unknown>, Name extends string> = Resource<Store[`${Name}Value`] extends Signal<infer S> ? S : never>;
1191
+ /**
1192
+ * @experimental
1193
+ * @description
1194
+ *
1195
+ * Maps a named resource to type `Resource<T>`.
1196
+ *
1197
+ * @usageNotes
1198
+ *
1199
+ * ```ts
1200
+ * const store = signalStore(
1201
+ * withState({ userId: undefined as number | undefined }),
1202
+ * withResource(({ userId }) => ({
1203
+ * user: httpResource<User[]>(() => '/users', { defaultValue: [] }),
1204
+ * }))
1205
+ * );
1206
+ * const userResource = mapToResource(store, 'user');
1207
+ * userResource satisfies Resource<User[]>;
1208
+ * ```
1209
+ *
1210
+ * @param store The store instance to map the resource to.
1211
+ * @param name The name of the resource to map.
1212
+ * @returns `ResourceRef<T>`
1213
+ */
1214
+ declare function mapToResource<Name extends ResourceNames<Store>, Store extends Record<string, unknown>>(store: Store, name: Name): MappedResource<Store, Name>;
1215
+
1216
+ export { capitalize, concatOp, createEffects, createPageArray, createReducer, deriveCallStateKeys, emptyFeature, exhaustOp, firstPage, getCallStateKeys, getCollectionArray, getDataServiceKeys, getUndoRedoKeys, gotoPage, mapToResource, mergeOp, nextPage, noPayload, patchState, payload, previousPage, provideDevtoolsConfig, renameDevtoolsName, rxMutation, setError, setLoaded, setLoading, setMaxPageNavigationArrayItems, setPageSize, setResetState, switchOp, updateState, withCallState, withConditional, withDataService, withDevToolsStub, withDevtools, withDisabledNameIndices, withFeatureFactory, withGlitchTracking, withImmutableState, withIndexedDB, withIndexedDB as withIndexeddb, withLocalStorage, withMapper, withMutations, withPagination, withRedux, withReset, withResource, withSessionStorage, withStorageSync, withUndoRedo };
1217
+ export type { CallState, CallStateSignals, CallStateSlice, DataService, DataServiceComputed, DataServiceMethods, DataServiceState, Entity, Filter, Func, MethodsDictionary, Mutation, MutationResult, MutationStatus, NamedCallStateSignals, NamedCallStateSlice, NamedDataServiceComputed, NamedDataServiceMethods, NamedDataServiceState, NamedMutationResult, NamedPaginationServiceSignals, NamedPaginationServiceState, NormalizedUndoRedoOptions, Page, PaginationServiceSignals, PaginationServiceState, ReduxDevtoolsConfig, RxMutationOptions, SetCallState, SetPaginationState, StackItem, SyncConfig };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angular-architects/ngrx-toolkit",
3
- "version": "20.0.3",
3
+ "version": "20.3.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "GitHub",