import * as _ngrx_signals from '@ngrx/signals'; import { SignalStoreFeature, SignalStoreFeatureResult, Prettify, StateSignals, WritableStateSource, DeepSignal, EmptyFeatureResult } from '@ngrx/signals'; import * as _angular_core from '@angular/core'; import { Signal, OnDestroy, Provider } from '@angular/core'; import { SelectEntityId, EntityState, EntityProps, NamedEntityState, NamedEntityProps } from '@ngrx/signals/entities'; import { Observable, Subscription } from 'rxjs'; import { CollectionViewer } from '@angular/cdk/collections'; import { Params } from '@angular/router'; import * as _ngrx_traits_signals from '@ngrx-traits/signals'; type FeatureConfigFactory, FactoryConfig extends Record = Config> = Config | ((store: StoreSource) => FactoryConfig); type StoreSource = Prettify & Input['props'] & Input['methods'] & WritableStateSource>; declare function getFeatureConfig>(config: FeatureConfigFactory, store: StoreSource): Config; type ExtractStoreFeatureOutput SignalStoreFeature> = ReturnType extends SignalStoreFeature ? In & Out : never; type CallStatus$1 = 'init' | 'loading' | 'loaded' | { error: unknown; }; type CallStatusState = { callStatus: CallStatus$1; }; type CallStatusComputed = { isLoading: Signal; } & { isLoaded: Signal; } & { error: Signal; }; type CallStatusMethods = { setLoading: () => void; } & { setLoaded: () => void; } & { setError: (error?: Error) => void; }; type NamedCallStatusState = { [K in Prop as `${K}CallStatus`]: CallStatus$1; }; type NamedCallStatusComputed = { [K in Prop as `is${Capitalize}Loading`]: Signal; } & { [K in Prop as `is${Capitalize}Loaded`]: Signal; } & { [K in Prop as `${K}Error`]: Signal; }; type NamedCallStatusMethods = { [K in Prop as `set${Capitalize}Loading`]: () => void; } & { [K in Prop as `set${Capitalize}Loaded`]: () => void; } & { [K in Prop as `set${Capitalize}Error`]: (error?: Error) => void; }; /** * Generates necessary state, computed and methods for call progress status to the store * @param configFactory - The configuration object for the feature or a factory function that receives the store and returns the configuration object * @param configFactory.prop - The name of the property for which this represents the call status * @param configFactory.initialValue - The initial value of the call status * @param configFactory.collection - The name of the collection for which this represents the call status is an alias to prop param * @param configFactory.errorType - The type of the error * they do the same thing * * prop or collection is required * @example * const store = signalStore( * withCallStatus({ collection: 'user', }) * // other valid configurations * // withCallStatus() * // withCallStatus({ collection: 'user', initialValue: 'loading' , errorType: type()}) * ) * * // generates the following signals * store.userEntitiesCallStatus // 'init' | 'loading' | 'loaded' | { error: unknown } * // generates the following computed signals * store.isUserEntitiesLoading // boolean * store.isUserEntitiesLoaded // boolean * store.userEntitiesError // unknown | null * // generates the following methods * store.setUserEntitiesLoading // () => void * store.setUserEntitiesLoaded // () => void * store.setUserEntitiesError // (error?: unknown) => void */ declare function withCallStatus(configFactory: FeatureConfigFactory): SignalStoreFeature; props: NamedCallStatusComputed<`${Prop}Entities`, Error>; methods: NamedCallStatusMethods<`${Prop}Entities`, Error>; }>; declare function withCallStatus(configFactory: FeatureConfigFactory): SignalStoreFeature; props: NamedCallStatusComputed; methods: NamedCallStatusMethods; }>; declare function withCallStatus(configFactory?: FeatureConfigFactory): SignalStoreFeature; methods: CallStatusMethods; }>; type ObservableCall$1 = (() => Observable) | ((arg: Param) => Observable); type PromiseCall$1 = (() => Promise) | ((arg: Param) => Promise); type Call$1 = ObservableCall$1 | PromiseCall$1; type CallConfig = { /** * The main function to be called. */ call: Call$1; /** * The name of the property where the result of the call will be stored. */ resultProp: PropName; /** * Specifies how to map emissions of the call, using one of the following: * - 'switchMap': Cancels the previous call when a new one starts. * - 'concatMap': Queues calls and executes them sequentially. * - 'exhaustMap': Ignores new calls until the current one completes. * Default is exhaustMap */ mapPipe?: 'switchMap' | 'concatMap' | 'exhaustMap'; /** * default is true, if false disables automatically storing the result of the * function, and removes the generated types. */ storeResult?: boolean; /** * A default value for the result before the call is executed */ defaultResult?: NoInfer; /** * Callback function invoked on successful completion of the call. * Receives the result of the call and the parameter used. */ onSuccess?: (result: NoInfer, param: NoInfer, previousResult: NoInfer | undefined) => void; /** * A function to transform an error from the call into a custom `Error` type. * Receives the error and the parameter used. */ mapError?: (error: unknown, param: NoInfer) => Error; /** * Callback function invoked if the call encounters an error. * Receives the mapped error and the parameter used. */ onError?: (error: Error, param: NoInfer) => void; /** * A function with condition that determines whether the call should be skipped. * The function accepts the call parameter and must return a boolean | Observable. */ skipWhen?: (param: NoInfer, previousResult: NoInfer | undefined) => boolean | Promise | Observable; /** * Reactively execute the call with the provided params. * Supports the following: * - A direct parameter value. Which execute the call once on init. * - A function or `Observable` emitting the parameter of the call or undefined. * - A function returning the parameter or undefined. * * **Warning**: By default, when withCall is a function, signal * or observable that when returns a falsy value it will skip the call. * To override this behavior, define a skipWhen with your own rule or skipWhen: () => false * to always execute on any value. */ callWith?: Param extends undefined ? Observable | (() => boolean) | boolean : NoInfer | null | undefined | Observable> | (() => NoInfer | null | undefined); }; type ExtractCallResultPropName = T extends CallConfig ? T['storeResult'] extends false ? never : T['resultProp'] extends '' ? `${K & string}Result` : T['resultProp'] & string : `${K & string}Result`; type ExtractCallResultType = T extends Call$1 ? R | undefined : T extends CallConfig ? D extends undefined ? R | undefined : D : never; type ExtractErrorType = T extends CallConfig ? E : unknown; type NamedCallsStatusComputed> = { [K in keyof Calls as K extends `_${infer J}` ? `_is${Capitalize}Loading` : `is${Capitalize}Loading`]: Signal; } & { [K in keyof Calls as K extends `_${infer J}` ? `_is${Capitalize}Loaded` : `is${Capitalize}Loaded`]: Signal; } & { [K in keyof Calls as `${K & string}Error`]: Calls[K] extends CallConfig ? Signal : Signal; }; type RxMethodRef = { destroy: () => void; }; type EntitiesFilterState = { entitiesFilter: Filter; }; type EntitiesFilterComputed = { isEntitiesFilterChanged: Signal; }; type NamedEntitiesFilterState = { [K in Collection as `${K}EntitiesFilter`]: Filter; }; type NamedEntitiesFilterComputed = { [K in Collection as `is${Capitalize}EntitiesFilterChanged`]: Signal; }; type FilterOptions = Filter | { filter: Filter; debounce?: number; patch?: false | undefined; forceLoad?: boolean; } | { filter: Partial; debounce?: number; patch: true; forceLoad?: boolean; }; type EntitiesFilterMethods = { filterEntities: { (options?: (() => FilterOptions) | Observable>): RxMethodRef; (options?: FilterOptions): Promise<{ value: Signal; ok: true; } | { error: Signal; ok: false; }>; }; resetEntitiesFilter: (options?: { newDefaultFilter?: Filter; debounce?: number; forceLoad?: boolean; skipLoadingCall?: boolean; }) => void; }; type NamedEntitiesFilterMethods = { [K in Collection as `filter${Capitalize}Entities`]: { (options?: (() => FilterOptions) | Observable>): RxMethodRef; (options?: FilterOptions): Promise<{ value: Signal; ok: true; } | { error: Signal; ok: false; }>; }; } & { [K in Collection as `reset${Capitalize}EntitiesFilter`]: (options?: { newDefaultFilter?: Filter; debounce?: number; forceLoad?: boolean; skipLoadingCall?: boolean; }) => void; }; /** * Generates necessary state, computed and methods for locally filtering entities in the store, * the generated filter[Collection]Entities method will filter the entities based on the filter function * and is debounced by default. * * Requires withEntities to be used. * * @param configFactory - The configuration object for the feature or a factory function that receives the store and returns the configuration object * @param configFactory.filterFn - The function that will be used to filter the entities * @param configFactory.defaultFilter - The default filter to be used * @param configFactory.defaultDebounce - The default debounce time to be used, if not set it will default to 300ms * @param configFactory.entity - The entity type to be used * @param configFactory.collection - The optional collection name to be used * @param configFactory.selectId - The function to use to select the id of the entity * * @example * const entity = type(); * const collection = 'product'; * const store = signalStore( * { providedIn: 'root' }, * // requires withEntities to be used * withEntities({ entity, collection }), * * withEntitiesLocalFilter({ * entity, * collection, * defaultFilter: { search: '' }, * filterFn: (entity, filter) => * !filter?.search || // if there is no search term return all entities * entity?.name.toLowerCase().includes(filter?.search.toLowerCase()), * }), * ); * * // generates the following signals * store.productEntitiesFilter // { search: string } * // generates the following methods * store.filterProductEntities // (options: { filter: { search: string }, debounce?: number, patch?: boolean, forceLoad?: boolean }) => void * store.resetProductEntitiesFilter // (options?: { newDefaultFilter?: { search: string } }) => void — resets to defaultFilter or to newDefaultFilter if provided, updating the default for future resets */ declare function withEntitiesLocalFilter, Collection extends string = ''>(configFactory: FeatureConfigFactory boolean; defaultFilter: Filter; defaultDebounce?: number; entity: Entity; collection?: Collection; selectId?: SelectEntityId; }>): SignalStoreFeature; props: EntityProps; methods: {}; } : { state: NamedEntityState; props: NamedEntityProps; methods: {}; }), Collection extends '' ? { state: EntitiesFilterState; props: EntitiesFilterComputed; methods: EntitiesFilterMethods; } : { state: NamedEntitiesFilterState; props: NamedEntitiesFilterComputed; methods: NamedEntitiesFilterMethods; }>; type EntitiesRemoteFilterMethods = { filterEntities: { (options?: Observable & { skipLoadingCall?: boolean; }> | (() => FilterOptions)): RxMethodRef; (options?: FilterOptions & { skipLoadingCall?: boolean; }): Promise<{ value: Signal; ok: true; } | { error: Signal; ok: false; }>; }; resetEntitiesFilter: (options?: { newDefaultFilter?: Filter; debounce?: number; forceLoad?: boolean; skipLoadingCall?: boolean; }) => void; }; type NamedEntitiesRemoteFilterMethods = { [K in Collection as `filter${Capitalize}Entities`]: { (options?: Observable & { skipLoadingCall?: boolean; }> | (() => FilterOptions)): RxMethodRef; (options?: FilterOptions & { skipLoadingCall?: boolean; }): Promise<{ value: Signal; ok: true; } | { error: Signal; ok: false; }>; }; } & { [K in Collection as `reset${Capitalize}EntitiesFilter`]: (options?: { newDefaultFilter?: Filter; debounce?: number; forceLoad?: boolean; skipLoadingCall?: boolean; }) => void; }; /** * Generates necessary state, computed and methods for remotely filtering entities in the store, * the generated filter[Collection]Entities method will filter the entities by calling set[Collection]Loading() * and you should either create an effect that listens to [Collection]Loading can call the api with the [Collection]Filter params * or use withEntitiesLoadingCall to call the api with the [Collection]Filter params. * filter[Collection]Entities is debounced by default, you can change the debounce by using the debounce option filter[Collection]Entities or changing the defaultDebounce prop in the config. * * In case you dont want filter[Collection]Entities to call set[Collection]Loading() (which triggers a fetchEntities), you can pass skipLoadingCall: true to filter[Collection]Entities. * Useful in cases where you want to further change the state before manually calling set[Collection]Loading() to trigger a fetch of entities. * * Requires withEntities and withCallStatus to be present before this function. * @param configFactory - The configuration object for the feature or a factory function that receives the store and returns the configuration object * @param configFactory.defaultFilter - The default filter to be used * @param configFactory.defaultDebounce - The default debounce time to be used, if not set it will default to 300ms * @param configFactory.entity - The entity type to be used * @param configFactory.collection - The optional collection name to be used * * @example * const entity = type(); * const collection = 'product'; * export const store = signalStore( * // requires withEntities and withCallStatus to be used * withEntities({ entity, collection }), * withCallStatus({ collection, initialValue: 'loading' }), * * withEntitiesRemoteFilter({ * entity, * collection, * defaultFilter: { search: '' }, * }), * // after you can use withEntitiesLoadingCall to connect the filter to * // the api call, or do it manually as shown after * withEntitiesLoadingCall({ * collection, * fetchEntities: ({ productEntitiesFilter }) => { * return inject(ProductService) * .getProducts({ * search: productEntitiesFilter().search, * }) * }, * }), * // withEntitiesLoadingCall is the same as doing the following: * // withHooks(({ isProductEntitiesLoading, productEntitiesFilter, setProductEntitiesError, ...state }) => ({ * // onInit: async () => { * // effect(() => { * // if (isProductEntitiesLoading()) { * // inject(ProductService) * // .getProducts({ * // search: productEntitiesFilter().search, * // }) * // .pipe( * // takeUntilDestroyed(), * // tap((res) => * // patchState( * // state, * // setAllEntities(res.resultList, { collection: 'product' }), * // ), * // ), * // catchError((error) => { * // setProductEntitiesError(error); * // return EMPTY; * // }), * // ) * // .subscribe(); * // } * // }); * // }, * })), * // generates the following signals * store.productEntitiesFilter // { search: string } * // generates the following methods * store.filterProductEntities // (options: { filter: { search: string }, debounce?: number, patch?: boolean, forceLoad?: boolean, skipLoadingCall?:boolean }) => void * store.resetProductEntitiesFilter // (options?: { newDefaultFilter?: { search: string } }) => void — resets to defaultFilter or to newDefaultFilter if provided, updating the default for future resets */ declare function withEntitiesRemoteFilter, Collection extends string = ''>(configFactory: FeatureConfigFactory): SignalStoreFeature; props: EntityProps; methods: CallStatusMethods; } : { state: NamedEntityState; props: NamedEntityProps; methods: NamedCallStatusMethods<`${Collection}Entities`>; }), Collection extends '' ? { state: EntitiesFilterState; props: EntitiesFilterComputed; methods: EntitiesRemoteFilterMethods; } : { state: NamedEntitiesFilterState; props: NamedEntitiesFilterComputed; methods: NamedEntitiesRemoteFilterMethods; }>; /** * Generates necessary state and methods to do remote and local filtering of entities in the store, * the generated filter[Collection]Entities method will filter the entities by calling set[Collection]Loading() if the isRemoteFilter returns true * and if false will call the filterFn to filter the entities locally. * * For the remote case you should either create an effect that listens to [Collection]Loading can call the api with the [Collection]Filter params * or use withEntitiesLoadingCall to call the api with the [Collection]Filter params. filter[Collection]Entities * is debounced by default, you can change the debounce by using the debounce option filter[Collection]Entities or changing the defaultDebounce prop in the config. * * In case you dont want filter[Collection]Entities to call set[Collection]Loading() (which triggers a fetchEntities), you can pass skipLoadingCall: true to filter[Collection]Entities. * Useful in cases where you want to further change the state before manually calling set[Collection]Loading() to trigger a fetch of entities. * * Requires withEntities and withCallStatus to be present before this function. * @param configFactory - The configuration object for the feature or a factory function that receives the store and returns the configuration object * @param configFactory.defaultFilter - The default filter to be used * @param configFactory.defaultDebounce - The default debounce time to be used, if not set it will default to 300ms * @param configFactory.filterFn - The function to filter the entities * @param configFactory.isRemoteFilter - The function to determine if the filter is remote or local * @param configFactory.entity - The entity type to be used * @param configFactory.collection - The optional collection name to be used * @param configFactory.selectId - The optional function to select the id of the entity * * @example * const entity = type(); * const collection = 'product'; * export const store = signalStore( * { providedIn: 'root' }, * // requires withEntities and withCallStatus to be used * withEntities({ entity, collection }), * withCallStatus({ collection, initialValue: 'loading' }), * withEntitiesHybridFilter({ * entity, * collection, * defaultFilter: { search: '' , category: ''}, * filterFn: (entity, filter) => * (!filter.search || entity.name.toLowerCase().includes(filter.search.toLowerCase())) * // in this case the filter will call setProductEntitiesLoading() if the category changes, othewise * // it will filter the entities locally using filterFn * isRemoteFilter: (previous, current) => { * return previous.category !== current.category; * } * }), * // after you can use withEntitiesLoadingCall to connect the filter to * // the api call, or do it manually as shown after * withEntitiesLoadingCall({ * collection, * fetchEntities: ({ productEntitiesFilter }) => { * return inject(ProductService) * .getProducts({ * category: productEntitiesFilter().category, * }) * }, * }), * // withEntitiesLoadingCall is the same as doing the following: * // withHooks(({ productEntitiesCallStatus, setProductEntitiesError, ...state }) => ({ * // onInit: async () => { * // effect(() => { * // if (isProductEntitiesLoading()) { * // inject(ProductService) * // .getProducts({ * // category: productEntitiesFilter().category, * // }) * // .pipe( * // takeUntilDestroyed(), * // tap((res) => * // patchState( * // state, * // setAllEntities(res.resultList, { collection: 'product' }), * // ), * // ), * // catchError((error) => { * // setProductEntitiesError(error); * // return EMPTY; * // }), * // ) * // .subscribe(); * // } * // }); * // }, * })), * // generates the following signals * store.productEntitiesFilter // { search: string , category: string } * // generates the following methods * store.filterProductEntities // (options: { filter: { search: string, category: string }, debounce?: number, patch?: boolean, forceLoad?: boolean, skipLoadingCall?:boolean }) => void * store.resetProductEntitiesFilter // (options?: { newDefaultFilter?: { search: string, category: string } }) => void — resets to defaultFilter or to newDefaultFilter if provided, updating the default for future resets */ declare function withEntitiesHybridFilter, Collection extends string = ''>(configFactory: FeatureConfigFactory; filterFn: (entity: NoInfer, filter: NoInfer) => boolean; isRemoteFilter: (previous: NoInfer, current: NoInfer) => boolean; }>): SignalStoreFeature; props: EntityProps; methods: CallStatusMethods; } : { state: NamedEntityState; props: NamedEntityProps; methods: NamedCallStatusMethods<`${Collection}Entities`>; }), Collection extends '' ? { state: EntitiesFilterState; props: EntitiesFilterComputed; methods: EntitiesRemoteFilterMethods; } : { state: NamedEntitiesFilterState; props: NamedEntitiesFilterComputed; methods: NamedEntitiesRemoteFilterMethods; }>; type EntitiesPaginationLocalState = { entitiesPagination: { currentPage: number; pageSize: number; }; }; type NamedEntitiesPaginationLocalState = { [K in Collection as `${K}EntitiesPagination`]: { currentPage: number; pageSize: number; }; }; type EntitiesPaginationLocalComputed = { entitiesCurrentPage: DeepSignal<{ entities: Entity[]; pageIndex: number; total: number | undefined; pageSize: number; pagesCount: number | undefined; hasPrevious: boolean; hasNext: boolean; }>; }; type NamedEntitiesPaginationLocalComputed = { [K in Collection as `${K}EntitiesCurrentPage`]: DeepSignal<{ entities: Entity[]; pageIndex: number; total: number | undefined; pageSize: number; pagesCount: number | undefined; hasPrevious: boolean; hasNext: boolean; }>; }; type EntitiesPaginationLocalMethods = { loadEntitiesPage: (options: { pageIndex: number; pageSize?: number; }) => void; }; type NamedEntitiesPaginationLocalMethods = { [K in Collection as `load${Capitalize}EntitiesPage`]: (options: { pageIndex: number; pageSize?: number; }) => void; }; type SetEntitiesResult = { setEntitiesPagedResult: (result: ResultParam) => void; }; type NamedSetEntitiesResult = { [K in Collection as `set${Capitalize}EntitiesPagedResult`]: (result: ResultParam) => void; }; /** * Generates necessary state, computed and methods for local pagination of entities in the store. * * Requires withEntities to be present in the store. * @param configFactory - The configuration object for the feature or a factory function that receives the store and returns the configuration object * @param configFactory.pageSize - The number of entities to show per page * @param configFactory.currentPage - The current page to show * @param configFactory.entity - The entity type * @param configFactory.collection - The name of the collection * * @example * const entity = type(); * const collection = "product"; * export const ProductsLocalStore = signalStore( * { providedIn: 'root' }, * // required withEntities * withEntities({ entity, collection }), * withEntitiesLocalPagination({ * entity, * collection, * pageSize: 5, * }), * * // generates the following signals * store.productEntitiesPagination // { currentPage: 0, pageSize: 5 } * // generates the following computed signals * store.productEntitiesCurrentPage // { entities: Product[], pageIndex: 0, total: 10, pageSize: 5, pagesCount: 2, hasPrevious: false, hasNext: true } * // generates the following methods * store.loadProductEntitiesPage // ({ pageIndex: number }) => void */ declare function withEntitiesLocalPagination(configFactory: FeatureConfigFactory): SignalStoreFeature; props: EntityProps; methods: {}; } : { state: NamedEntityState; props: NamedEntityProps; methods: {}; }), Collection extends '' ? { state: EntitiesPaginationLocalState; props: EntitiesPaginationLocalComputed; methods: EntitiesPaginationLocalMethods; } : { state: NamedEntitiesPaginationLocalState; props: NamedEntitiesPaginationLocalComputed; methods: NamedEntitiesPaginationLocalMethods; }>; type PaginationState = { currentPage: number; requestPage: number; pageSize: number; total: number; pagesToCache: number; cache: { start: number; end: number; }; }; type EntitiesPaginationRemoteState = { entitiesPagination: PaginationState; }; type NamedEntitiesPaginationRemoteState = { [K in Collection as `${K}EntitiesPagination`]: PaginationState; }; type EntitiesPaginationRemoteComputed = { entitiesCurrentPage: DeepSignal<{ entities: Entity[]; pageIndex: number; total: number | undefined; pageSize: number; pagesCount: number | undefined; hasPrevious: boolean; hasNext: boolean; isLoading: boolean; }>; entitiesPagedRequest: DeepSignal<{ startIndex: number; size: number; page: number; }>; }; type NamedEntitiesPaginationRemoteComputed = { [K in Collection as `${K}EntitiesPagedRequest`]: DeepSignal<{ startIndex: number; size: number; page: number; }>; } & { [K in Collection as `${K}EntitiesCurrentPage`]: DeepSignal<{ entities: Entity[]; pageIndex: number; total: number | undefined; pageSize: number; pagesCount: number | undefined; hasPrevious: boolean; hasNext: boolean; isLoading: boolean; }>; }; type EntitiesPaginationRemoteMethods = { loadEntitiesPage: (options: { pageIndex: number; pageSize?: number; skipLoadingCall?: boolean; forceLoad?: boolean; }) => void; } & SetEntitiesResult<{ entities: Entity[]; total: number; }>; type NamedEntitiesPaginationRemoteMethods = { [K in Collection as `load${Capitalize}EntitiesPage`]: (options: { pageIndex: number; pageSize?: number; skipLoadingCall?: boolean; forceLoad?: boolean; }) => void; } & NamedSetEntitiesResult; /** * Generates necessary state, computed and methods for remote pagination of entities in the store. * Call load[Collection]Page to change the page, it will try to load the new page from cache if it's not present, * it will call set[Collection]Loading(), and you should either create an effect that listens to [Collection]Loading * and call the api with the [Collection]PagedRequest params and use set[Collection]Result to set the result * and changing the status errors manually, * or use withEntitiesLoadingCall to call the api with the [Collection]PagedRequest params which handles setting * the result and errors automatically. * * In case you dont want load[Collection]Page to call set[Collection]Loading() (which triggers a fetchEntities), you can pass skipLoadingCall: true to load[Collection]Page. * Useful in cases where you want to further change the state before manually calling set[Collection]Loading() to trigger a fetch of entities. * * This will keep at least the provided (pagesToCache) pages in memory, so previous pages could be removed from the cache. * If you need to keep all previous pages in memory, use withEntitiesRemoteScrollPagination instead. * * Requires withEntities and withCallStatus to be present in the store. * @param configFactory - The configuration object for the feature or a factory function that receives the store and returns the configuration object * @param configFactory.pageSize - The number of entities to show per page * @param configFactory.currentPage - The current page to show * @param configFactory.pagesToCache - The number of pages to cache * @param configFactory.entity - The entity type * @param configFactory.collection - The name of the collection * @param configFactory.selectId - The function to use to select the id of the entity * * @example * const entity = type(); * const collection = "product"; * export const store = signalStore( * { providedIn: 'root' }, * // required withEntities and withCallStatus * withEntities({ entity, collection }), * withCallStatus({ prop: collection, initialValue: 'loading' }), * * withEntitiesRemotePagination({ * entity, * collection, * pageSize: 5, * pagesToCache: 2, * }) * // after you can use withEntitiesLoadingCall to connect the filter to * // the api call, or do it manually as shown after * withEntitiesLoadingCall({ * collection, * fetchEntities: ({ productPagedRequest }) => { * return inject(ProductService) * .getProducts({ * take: productPagedRequest().size, * skip: productPagedRequest().startIndex, * }).pipe( * map((d) => ({ * entities: d.resultList, * total: d.total, * })), * ) * }, * }), * // withEntitiesLoadingCall is the same as doing the following: * // withHooks(({ productsLoading, setProductEntitiesError, setProductEntitiesPagedResult, ...state }) => ({ * // onInit: async () => { * // effect(() => { * // if (isProductEntitiesLoading()) { * // inject(ProductService) * // .getProducts({ * // take: productPagedRequest().size, * // skip: productPagedRequest().startIndex, * // }) * // .pipe( * // takeUntilDestroyed(), * // tap((res) => * // patchState( * // state, * // setProductEntitiesPagedResult({ entities: res.resultList, total: res.total } ), * // ), * // ), * // catchError((error) => { * // setProductEntitiesError(error); * // return EMPTY; * // }), * // ) * // .subscribe(); * // } * // }); * // }, * })), * // generates the following signals * store.productEntitiesPagination // { currentPage: number, requestPage: number, pageSize: 5, total: number, pagesToCache: number, cache: { start: number, end: number } } used internally * // generates the following computed signals * store.productEntitiesCurrentPage // { entities: Product[], pageIndex: number, total: number, pageSize: 5, pagesCount: number, hasPrevious: boolean, hasNext: boolean, isLoading: boolean } * store.productPagedRequest // { startIndex: number, size: number, page: number } * // generates the following methods * store.loadProductEntitiesPage({ pageIndex: number, forceLoad?: boolean, skipLoadingCall?:boolean }) // loads the page and sets the requestPage to the pageIndex * store.setProductEntitiesPagedResult(entities: Product[], total: number) // appends the entities to the cache of entities and total */ declare function withEntitiesRemotePagination(configFactory: FeatureConfigFactory; }>): SignalStoreFeature; props: EntityProps & CallStatusComputed; methods: CallStatusMethods; } : { state: NamedEntityState; props: NamedEntityProps & NamedCallStatusComputed<`${Collection}Entities`>; methods: NamedCallStatusMethods<`${Collection}Entities`>; }), Collection extends '' ? { state: EntitiesPaginationRemoteState; props: EntitiesPaginationRemoteComputed; methods: EntitiesPaginationRemoteMethods; } : { state: NamedEntitiesPaginationRemoteState; props: NamedEntitiesPaginationRemoteComputed; methods: NamedEntitiesPaginationRemoteMethods; }>; type ScrollPaginationState = { hasMore: boolean; pageSize: number; pagesToCache: number; currentPage: number; requestPage: number; }; type EntitiesScrollPaginationState = { pagination: ScrollPaginationState; }; type NamedEntitiesScrollPaginationState = { [K in Collection as `${K}EntitiesPagination`]: ScrollPaginationState; }; type EntitiesScrollPaginationComputed = { entitiesCurrentPage: DeepSignal<{ entities: Entity[]; pageIndex: number; pageSize: number; hasPrevious: boolean; hasNext: boolean; isLoading: boolean; }>; entitiesPagedRequest: DeepSignal<{ startIndex: number; size: number; }>; }; type NamedEntitiesScrollPaginationComputed = { [K in Collection as `${K}EntitiesPagedRequest`]: DeepSignal<{ startIndex: number; size: number; }>; } & { [K in Collection as `${K}EntitiesCurrentPage`]: DeepSignal<{ entities: Entity[]; pageIndex: number; pageSize: number; hasPrevious: boolean; hasNext: boolean; isLoading: boolean; }>; }; type EntitiesScrollPaginationMethods = SetEntitiesResult<{ entities: Entity[]; total: number; } | { entities: Entity[]; hasMore: boolean; } | { entities: Entity[]; }> & { loadMoreEntities: () => void; loadEntitiesNextPage: () => void; loadEntitiesPreviousPage: () => void; loadEntitiesFirstPage: () => void; }; type NamedEntitiesScrollPaginationMethods = NamedSetEntitiesResult & { [K in Collection as `loadMore${Capitalize}Entities`]: () => void; } & { [K in Collection as `load${Capitalize}EntitiesNextPage`]: () => void; } & { [K in Collection as `load${Capitalize}EntitiesPreviousPage`]: () => void; } & { [K in Collection as `load${Capitalize}EntitiesFirstPage`]: () => void; }; /** * Generates necessary state, computed and methods for remote infinite scroll pagination of entities in the store. * This is ideal for implementing infinite scroll where the entities cache keeps growing, or for a paginated list that only * allows going to the next and previous page because you dont know the total number of entities * probably because the data is top big and partitioned in multiple nodes. * * When the page changes, it will try to load the current page from cache if it's not present, * it will call set[Collection]Loading(), and you should either create an effect that listens to is[Collection]Loading * and call the api with the [Collection]PagedRequest params and use set[Collection]Result to set the result * and changing the status errors manually * or use withEntitiesLoadingCall to call the api with the [Collection]PagedRequest params which handles setting * the result and errors automatically. Requires withEntities and withCallStatus to be used. * * The generated set[Collection]Result method will append the entities to the cache of entities, * it requires either just set of requested entities set[Collection]Result({ entities }) in which case it will assume there is no more result if you set less entities * than the requested buffer size, or you can provide an extra param to the entities, total set[Collection]Result({ entities, total }) so it calculates if there is more * or a hasMore param set[Collection]Result({entities, hasMore}) that you can set to false to indicate the end of the entities. * * Requires withEntities and withCallStatus to be present in the store. * @param configFactory - The configuration object for the feature or a factory function that receives the store and returns the configuration object * @param configFactory.pageSize - The number of entities to show per page * @param configFactory.pagesToCache - The number of pages to cache * @param configFactory.entity - The entity type * @param configFactory.collection - The name of the collection * * @example * const entity = type(); * const collection = 'product'; * export const store = signalStore( * { providedIn: 'root' }, * // required withEntities and withCallStatus * withEntities({ entity, collection }), * withCallStatus({ collection, initialValue: 'loading' }), * * withEntitiesRemoteScrollPagination({ * entity, * collection, * pageSize: 5, * pagesToCache: 2, * }) * // after you can use withEntitiesLoadingCall to connect the filter to * // the api call, or do it manually as shown after * withEntitiesLoadingCall({ * collection, * fetchEntities: ({ productPagedRequest }) => { * return inject(ProductService) * .getProducts({ * take: productPagedRequest().size, * skip: productPagedRequest().startIndex, * }).pipe( * map((d) => ({ * entities: d.resultList, * total: d.total, * })), * ) * }, * }), * // withEntitiesLoadingCall is the same as doing the following: * // withHooks(({ productEntitiesCallStatus, setProductEntitiesError, setProductPagedResult, ...state }) => ({ * // onInit: async () => { * // effect(() => { * // if (isProductEntitiesLoading()) { * // inject(ProductService) * // .getProducts({ * // take: productPagedRequest().size, * // skip: productPagedRequest().startIndex, * // }) * // .pipe( * // takeUntilDestroyed(), * // tap((res) => * // // total is not required, you can use hasMore or none see docs * // setProductPagedResult({ entities: res.resultList, total: res.total } ) * // ), * // catchError((error) => { * // setProductEntitiesError(error); * // return EMPTY; * // }), * // ) * // .subscribe(); * // } * // }); * // }, * })), * * // in your component add * store = inject(ProductsRemoteStore); * dataSource = getInfiniteScrollDataSource(store, { collection: 'product' }) // pass this to your cdkVirtualFor see examples section * // generates the following signals * store.productEntitiesPagination // { currentPage: number, pageSize: number, pagesToCache: number, hasMore: boolean } used internally * // generates the following computed signals * store.productEntitiesCurrentPage // { entities: Entity[], pageIndex: number, total: number, pageSize: number, hasPrevious: boolean, hasNext: boolean, isLoading: boolean } * store.productEntitiesPagedRequest // { startIndex: number, size: number } * // generates the following methods * store.loadProductEntitiesNextPage() // loads next page * store.loadProductEntitiesPreviousPage() // loads previous page * store.loadProductEntitiesFirstPage() // loads first page * store.loadMoreProductEntities() // loads more entities (used for infinite scroll datasource) * store.setProductEntitiesPagedResult(entities: Product[], total: number) // appends the entities to the cache of entities and total */ declare function withEntitiesRemoteScrollPagination(configFactory: FeatureConfigFactory; }>): SignalStoreFeature; props: EntityProps & CallStatusComputed; methods: CallStatusMethods; } : { state: NamedEntityState; props: NamedEntityProps & NamedCallStatusComputed<`${Collection}Entities`>; methods: NamedCallStatusMethods<`${Collection}Entities`>; }), Collection extends '' ? { state: EntitiesScrollPaginationState; props: EntitiesScrollPaginationComputed; methods: EntitiesScrollPaginationMethods; } : { state: NamedEntitiesScrollPaginationState; props: NamedEntitiesScrollPaginationComputed; methods: NamedEntitiesScrollPaginationMethods; }>; declare function getInfiniteScrollDataSource(options: { store: EntityProps & EntitiesScrollPaginationMethods; debounceLoadMoreTime?: number; } | { collection: Collection; entity: Entity; store: NamedEntityProps & NamedEntitiesScrollPaginationMethods; debounceLoadMoreTime?: number; }): { subscription?: Subscription; entitiesList: Observable; connect(collectionViewer: CollectionViewer): Observable; disconnect(): void; }; type SortDirection = 'asc' | 'desc' | ''; type Sort = { /** The id of the column being sorted. */ field: keyof Entity | (string & {}); /** The sort direction. */ direction: SortDirection; }; type CdkSort = { /** The id of the column being sorted. */ active: keyof Entity | (string & {}); /** The sort direction. */ direction: SortDirection; }; type EntitiesSortState = { entitiesSort: Sort; }; type NamedEntitiesSortState = { [K in Collection as `${K}EntitiesSort`]: Sort; }; type EntitiesSortMethods = { sortEntities: (options?: Sort | CdkSort | { sort: Sort | CdkSort; } | Observable | CdkSort | { sort: Sort | CdkSort; }> | (() => Sort | CdkSort | { sort: Sort | CdkSort; })) => void; }; type NamedEntitiesSortMethods = { [K in Collection as `sort${Capitalize}Entities`]: (options?: Sort | CdkSort | { sort: Sort | CdkSort; } | Observable | CdkSort | { sort: Sort | CdkSort; }> | (() => Sort | CdkSort | { sort: Sort | CdkSort; })) => void; }; type QueryMapper = Record> = { /** * @param firstLoad true only for the first query params emission restored * into this store instance. Mappers should only read it, the caller resets * it once all mappers have run. */ queryParamsToState: (query: T, store: Store, firstLoad: boolean) => void; stateToQueryParams: (store: Store) => Signal | undefined | null; }; /** * @internal * @ignore * Gets a sorted copy of the data array based on the state of the Sort. * @param data The array of data that should be sorted. * @param sort The connected MatSort that holds the current sort state. */ declare function sortData(data: T[], sort: Sort): T[]; /** * Generates necessary state, computed and methods for sorting locally entities in the store. * * Requires withEntities to be present before this function * @param configFactory - The configuration object for the feature or a factory function that receives the store and returns the configuration object * @param configFactory.defaultSort - The default sort to be applied to the entities * @param configFactory.entity - The type entity to be used * @param configFactory.collection - The name of the collection for which will be sorted * @param configFactory.selectId - The function to use to select the id of the entity * @param configFactory.sortFunction - Optional custom function use to sort the entities * * @example * const entity = type(); * const collection = "product"; * export const store = signalStore( * { providedIn: 'root' }, * withEntities({ entity, collection }), * withEntitiesLocalSort({ * entity, * collection, * defaultSort: { field: 'name', direction: 'asc' }, * }), * ); * // generates the following signals * store.productEntitiesSort - the current sort applied to the products * // generates the following methods * store.sortProductEntities({ sort: { field: 'name', direction: 'asc' } }) - sorts the products entities */ declare function withEntitiesLocalSort(configFactory: FeatureConfigFactory>; entity: Entity; collection?: Collection; selectId?: SelectEntityId; sortFunction?: (entities: Entity[], sort: Sort) => Entity[]; }>): SignalStoreFeature; props: EntityProps; methods: {}; } : { state: NamedEntityState; props: NamedEntityProps; methods: {}; }), Collection extends '' ? { state: EntitiesSortState; props: {}; methods: EntitiesSortMethods; } : { state: NamedEntitiesSortState; props: {}; methods: NamedEntitiesSortMethods; }>; type EntitiesRemoteSortMethods = { sortEntities: (options?: Sort | CdkSort | { sort: Sort | CdkSort; skipLoadingCall?: boolean; } | Observable | CdkSort | { sort: Sort | CdkSort; skipLoadingCall?: boolean; }> | (() => Sort | CdkSort | { sort: Sort | CdkSort; skipLoadingCall?: boolean; })) => void; }; type NamedEntitiesRemoteSortMethods = { [K in Collection as `sort${Capitalize}Entities`]: (options?: Sort | CdkSort | { sort: Sort | CdkSort; skipLoadingCall?: boolean; } | Observable | CdkSort | { sort: Sort | CdkSort; skipLoadingCall?: boolean; }> | (() => Sort | CdkSort | { sort: Sort | CdkSort; skipLoadingCall?: boolean; })) => void; }; /** * Generates state, signals, and methods to sort entities remotely. When the sort method sort[Collection]Entities is called it will store the sort * and call set[Collection]Loading, and you should either create an effect that listens to [Collection]Loading * and call the api with the [Collection]Sort params and use wither setAllEntities if is not paginated or set[Collection]Result if is paginated * with the sorted result that come from the backend, plus changing the status and set errors is needed. * or use withEntitiesLoadingCall to call the api with the [Collection]Sort params which handles setting * the result and errors automatically. * * In case you dont want sort[Collection]Entities to call set[Collection]Loading() (which triggers a fetchEntities), you can pass skipLoadingCall: true to sort[Collection]Entities. * Useful in cases where you want to further change the state before manually calling set[Collection]Loading() to trigger a fetch of entities. * * Requires withEntities and withCallStatus to be present before this function. * * @param configFactory - The configuration object for the feature or a factory function that receives the store and returns the configuration object * @param configFactory.defaultSort - The default sort to use when the store is initialized * @param configFactory.entity - The entity type * @param configFactory.collection - The collection name * * @example * const entity = type(); * const collection = 'product'; * export const store = signalStore( * { providedIn: 'root' }, * // required withEntities and withCallStatus * withEntities({ entity, collection }), * withCallStatus({ collection, initialValue: 'loading' }), * * withEntitiesRemoteSort({ * entity, * collection, * defaultSort: { field: 'name', direction: 'asc' }, * }), * // after you can use withEntitiesLoadingCall to connect the filter to * // the api call, or do it manually as shown after * withEntitiesLoadingCall({ * collection, * fetchEntities: ({ productEntitiesSort }) => { * return inject(ProductService) * .getProducts({ * sortColumn: productEntitiesSort().field, * sortAscending: productEntitiesSort().direction === 'asc', * }) * }, * }), * // withEntitiesLoadingCall is the same as doing the following: * // withHooks(({ productEntitiesSort, isProductEntitiesLoading, setProductEntitiesError, ...state }) => ({ * // onInit: async () => { * // effect(() => { * // if (isProductEntitiesLoading()) { * // inject(ProductService) * // .getProducts({ * // sortColumn: productEntitiesSort().field, * // sortAscending: productEntitiesSort().direction === 'asc', * // }) * // .pipe( * // takeUntilDestroyed(), * // tap((res) => * // patchState( * // state, * // setAllEntities(res.resultList, { collection: 'product' }), * // ), * // ), * // catchError((error) => { * // setProductEntitiesError(error); * // return EMPTY; * // }), * // ) * // .subscribe(); * // } * // }); * // }, * })), * * // generate the following signals * store.productEntitiesSort // the current sort * // and the following methods * store.sortProductEntities // (options: { sort: Sort; , skipLoadingCall?:boolean}) => void; */ declare function withEntitiesRemoteSort(configFactory: FeatureConfigFactory; collection?: Collection; }>): SignalStoreFeature; props: EntityProps; methods: CallStatusMethods; } : { state: NamedEntityState; props: NamedEntityProps; methods: NamedCallStatusMethods<`${Collection}Entities`>; }), Collection extends '' ? { state: EntitiesSortState; props: {}; methods: EntitiesRemoteSortMethods; } : { state: NamedEntitiesSortState; props: {}; methods: NamedEntitiesRemoteSortMethods; }>; type EntitiesSingleSelectionState = { idSelected: string | number | undefined; }; type NamedEntitiesSingleSelectionState = { [K in Collection as `${K}IdSelected`]: string | number | undefined; }; type EntitiesSingleSelectionComputed = { entitySelected: Signal; }; type NamedEntitiesSingleSelectionComputed = { [K in Collection as `${K}EntitySelected`]: Signal; }; type EntitySelectOptions$1 = { id: string | number; } | undefined; type EntitiesSingleSelectionMethods = { selectEntity: (options: EntitySelectOptions$1 | Observable | (() => EntitySelectOptions$1)) => void; deselectEntity: () => void; toggleSelectEntity: (options: EntitySelectOptions$1 | Observable | (() => EntitySelectOptions$1)) => void; }; type NamedEntitiesSingleSelectionMethods = { [K in Collection as `select${Capitalize}Entity`]: (options: EntitySelectOptions$1 | Observable | (() => EntitySelectOptions$1)) => void; } & { [K in Collection as `deselect${Capitalize}Entity`]: () => void; } & { [K in Collection as `toggleSelect${Capitalize}Entity`]: (options: EntitySelectOptions$1 | Observable | (() => EntitySelectOptions$1)) => void; }; /** * Generates state, computed and methods for single selection of entities. * * Requires withEntities to be present before this function. * @param configFactory - The configuration object for the feature or a factory function that receives the store and returns the configuration object * @param configFactory.collection - The collection name * @param configFactory.entity - The entity type * @param configFactory.clearOnFilter - Clear the selected entity when the filter changes (default: true) * @param configFactory.clearOnRemoteSort - Clear the selected entity when the remote sort changes (default: true) * @example * const entity = type(); * const collection = "product"; * export const store = signalStore( * { providedIn: 'root' }, * // Required withEntities and withCallStatus * withEntities({ entity, collection }), * withCallStatus({ prop: collection, initialValue: 'loading' }), * * withEntitiesSingleSelection({ * entity, * collection, * }), * ); * * // generates the following signals * store.productIdSelected // string | number | undefined * // generates the following computed signals * store.productEntitySelected // Entity | undefined * // generates the following methods * store.selectProductEntity // (config: { id: string | number }) => void * store.deselectProductEntity // (config: { id: string | number }) => void * store.toggleProductEntity // (config: { id: string | number }) => void */ declare function withEntitiesSingleSelection(configFactory: FeatureConfigFactory): SignalStoreFeature; props: EntityProps; methods: {}; } : { state: NamedEntityState; props: NamedEntityProps; methods: {}; }), Collection extends '' ? { state: EntitiesSingleSelectionState; props: EntitiesSingleSelectionComputed; methods: EntitiesSingleSelectionMethods; } : { state: NamedEntitiesSingleSelectionState; props: NamedEntitiesSingleSelectionComputed; methods: NamedEntitiesSingleSelectionMethods; }>; type EntitiesMultiSelectionState = { idsSelectedMap: Record; }; type NamedEntitiesMultiSelectionState = { [K in Collection as `${K}IdsSelectedMap`]: Record; }; type EntitiesMultiSelectionComputed = { entitiesSelected: Signal; idsSelected: Signal<(string | number)[]>; isAllEntitiesSelected: Signal<'all' | 'none' | 'some'>; }; type NamedEntitiesMultiSelectionComputed = { [K in Collection as `${K}EntitiesSelected`]: Signal; } & { [K in Collection as `${K}IdsSelected`]: Signal<(string | number)[]>; } & { [K in Collection as `isAll${Capitalize}EntitiesSelected`]: Signal<'all' | 'none' | 'some'>; }; type EntitySelectOptions = { id: string | number; } | { ids: (string | number)[]; }; type EntitiesMultiSelectionMethods = { selectEntities: (options: (EntitySelectOptions & { clearSelectionBeforeSelect?: boolean; }) | Observable | (() => EntitySelectOptions & { clearSelectionBeforeSelect?: boolean; })) => void; deselectEntities: (options: EntitySelectOptions) => void; toggleSelectEntities: (options: EntitySelectOptions) => void; toggleSelectAllEntities: () => void; clearEntitiesSelection: () => void; }; type NamedEntitiesMultiSelectionMethods = { [K in Collection as `select${Capitalize}Entities`]: (options: (EntitySelectOptions & { clearSelectionBeforeSelect?: boolean; }) | Observable | (() => EntitySelectOptions & { clearSelectionBeforeSelect?: boolean; })) => void; } & { [K in Collection as `deselect${Capitalize}Entities`]: (options: EntitySelectOptions) => void; } & { [K in Collection as `toggleSelect${Capitalize}Entities`]: (options: EntitySelectOptions) => void; } & { [K in Collection as `toggleSelectAll${Capitalize}Entities`]: () => void; } & { [K in Collection as `clear${Capitalize}EntitiesSelection`]: () => void; }; /** * Generates state, signals and methods for multi selection of entities. * Warning: isAll[Collection]Selected and toggleSelectAll[Collection] wont work * correctly in using remote pagination, because they cant select all the data. * * Requires withEntities to be used before this feature. * @param configFactory - The configuration object for the feature or a factory function that receives the store and returns the configuration object * @param configFactory.entity - the entity type * @param configFactory.collection - the collection name * @param configFactory.clearOnFilter - Clear the selected entity when the filter changes (default: true) * @param configFactory.clearOnRemoteSort - Clear the selected entity when the remote sort changes (default: true) * * @example * const entity = type(); * const collection = "product"; * export const store = signalStore( * { providedIn: 'root' }, * withEntities({ entity, collection }), * withEntitiesMultiSelection({ entity, collection }), * ); * * // generates the following signals * store.productIdsSelectedMap // Record; * // generates the following computed signals * store.productEntitiesSelected // Entity[]; * store.isAllProductEntitiesSelected // 'all' | 'none' | 'some'; * // generates the following methods * store.selectProducts // (config: { id: string | number } | { ids: (string | number)[] }) => void; * store.deselectProducts // (config: { id: string | number } | { ids: (string | number)[] }) => void; * store.toggleSelectProducts // (config: { id: string | number } | { ids: (string | number)[] }) => void; * store.toggleSelectAllProducts // () => void; */ declare function withEntitiesMultiSelection(configFactory: FeatureConfigFactory; clearOnFilter?: boolean; clearOnRemoteSort?: boolean; defaultSelectedIds?: (string | number)[]; }>): SignalStoreFeature; props: EntityProps; methods: {}; } : { state: NamedEntityState; props: NamedEntityProps; methods: {}; }), Collection extends '' ? { state: EntitiesMultiSelectionState; props: EntitiesMultiSelectionComputed; methods: EntitiesMultiSelectionMethods; } : { state: NamedEntitiesMultiSelectionState; props: NamedEntitiesMultiSelectionComputed; methods: NamedEntitiesMultiSelectionMethods; }>; /** * Generates a onInit hook that fetches entities from a remote source * when the [Collection]Loading is true, by calling the fetchEntities function * and if successful, it will call set[Collection]Loaded and also set the entities * to the store using the setAllEntities method or the setEntitiesPagedResult method * if it exists (comes from withEntitiesRemotePagination), * if an error occurs it will set the error to the store using set[Collection]Error with the error. * * Requires withEntities and withCallStatus to be present in the store. * * @param config - Configuration object or factory function that returns the configuration object * @param config.fetchEntities - A function that fetches the entities from a remote source, the return type can be an array of entities or an object with entities and total * @param config.collection - The collection name * @param config.onSuccess - A function that is called when the fetchEntities is successful * @param config.mapError - A function to transform the error before setting it to the store, requires withCallStatus errorType to be set * @param config.onError - A function that is called when the fetchEntities fails * @param config.selectId - The function to use to select the id of the entity * @param config.storeResult - Whether to automatically store the fetched entities in the store (default: true). When false, entities are not stored, but setLoaded and onSuccess are still called, useful when you want to handle storing in onSuccess yourself * * * @example * export const ProductsRemoteStore = signalStore( * { providedIn: 'root' }, * // requires at least withEntities and withCallStatus * withEntities({ entity, collection }), * withCallStatus({ prop: collection, initialValue: 'loading' }), * // other features * withEntitiesRemoteFilter({ * entity, * collection, * defaultFilter: { name: '' }, * }), * withEntitiesRemotePagination({ * entity, * collection, * pageSize: 5, * pagesToCache: 2, * }), * withEntitiesRemoteSort({ * entity, * collection, * defaultSort: { field: 'name', direction: 'asc' }, * }), * // now we add the withEntitiesLoadingCall, in this case any time the filter, * // pagination or sort changes they call set[Collection]Loading() which then * // triggers the onInit effect that checks if [Collection]Loading(), if true * // then calls fetchEntities function * withEntitiesLoadingCall({ * collection, * fetchEntities: ({ productEntitiesFilter, productEntitiesPagedRequest, productEntitiesSort }) => { * return inject(ProductService) * .getProducts({ * search: productEntitiesFilter().name, * take: productEntitiesPagedRequest().size, * skip: productEntitiesPagedRequest().startIndex, * sortColumn: productEntitiesSort().field, * sortAscending: productEntitiesSort().direction === 'asc', * }) * .pipe( * map((d) => ({ * entities: d.resultList, * total: d.total, * })), * ); * }, * }), */ declare function withEntitiesLoadingCall(config: FeatureConfigFactory) => Observable ? ResultParam : Entity[] | { entities: Entity[]; }> | Promise ? ResultParam : Entity[] | { entities: Entity[]; }>; mapPipe?: 'switchMap' | 'concatMap' | 'exhaustMap'; onSuccess?: (result: Input['methods'] extends NamedSetEntitiesResult ? ResultParam : Entity[] | { entities: Entity[]; }) => void; mapError?: (error: unknown) => Error; onError?: (error: Error) => void; entity?: Entity; selectId?: SelectEntityId; storeResult?: boolean; }>): SignalStoreFeature & CallStatusState; props: EntityProps & CallStatusComputed; methods: CallStatusMethods; } : { state: NamedEntityState & NamedCallStatusState<`${Collection}Entities`>; props: NamedEntityProps & NamedCallStatusComputed<`${Collection}Entities`, Error>; methods: NamedCallStatusMethods<`${Collection}Entities`, Error>; }), EmptyFeatureResult>; /** * Log the state of the store on every change, optionally filter the signals to log * the filter prop can receive an array with the names of the props to filter, or you can provide a function * which receives the store as an argument and should return the object to log, if any of the props in the object is a signal * it will log the value of the signal. If showDiff is true it will log the diff of the state on every change. * * @param name - The name of the store to log * @param filter - optional filter function to filter the store signals or an array of keys to filter * @param showDiff - optional flag to log the diff of the state on every change * * @example * * const Store = signalStore( * withState(() => ({ prop1: 1, prop2: 2 })), * withComputed(({ prop1, prop2 }) => ({ * prop3: computed(() => prop1() + prop2()), * })), * withLogger({ * name: 'Store', * // by default it will log all state and computed signals * // or you can filter with an array of keys * // filter: ['prop1', 'prop2'], * // or you can filter with a function * // filter: ({ prop1, prop2 }) => ({ prop1, prop2 }), * // showDiff: true, * }), * ); */ declare function withLogger({ name, filter, showDiff, }: { name: string; filter?: ((store: StateSignals & Input['props']) => any) | readonly (keyof (StateSignals & Input['props']))[]; showDiff?: boolean; }): SignalStoreFeature; /** * Generates necessary state, computed and methods to track the progress of the * call and store the result of the call. The generated methods are rxMethods with * the same name as the original call, which accepts either the original parameters * or a Signal or Observable of the same type as the original parameters. * The original call can only have zero or one parameter, use an object with multiple * props as first param if you need more. * If the name start with an underscore, the call will be private and all generated methods * will also start with an underscore, making it only accessible inside the store. * @param {callsFactory} callsFactory - a factory function that receives the store and returns an object of type {Record} with the calls to be made * * @example * withCalls(({ productsSelectedEntity }) => ({ * loadProductDetail: callConfig({ * call: ({ id }: { id: string }) => * inject(ProductService).getProductDetail(id), * resultProp: 'productDetail', * // storeResult: false, // will omit storing the result, and remove the result prop from the store * mapPipe: 'switchMap', // default is 'exhaustMap' * onSuccess: (result, callParam) => { * // do something with the result * }, * mapError: (error, callParam) => { * return // transform the error before storing it * }, * onError: (error, callParam) => { * // do something with the error * }, * skipWhen: (callParam) => { * // if return true, the call will be skip, if false, the call will execute as usual * return // boolean | Promise | Observable * }, * callWith: () => * // reactively call with the selected product id, if undefined is return, the call is skip by default * productEntitySelected() * ? { id: productEntitySelected()!.id } * : undefined, * }), * checkout: () => * inject(OrderService).checkout({ * productId: productsSelectedEntity()!.id, * quantity: 1, * }), * })), * * // generates the following signals * store.loadProductDetailCallStatus // 'init' | 'loading' | 'loaded' | { error: unknown } * store.productDetail // the result of the call * store.checkoutCallStatus // 'init' | 'loading' | 'loaded' | { error: unknown } * store.checkoutResult // the result of the call * // generates the following computed signals * store.isLoadProductDetailLoading // boolean * store.isLoadProductDetailLoaded // boolean * store.loadProductDetailError // string | null * store.isCheckoutLoading // boolean * store.isCheckoutLoaded // boolean * store.checkoutError // unknown | null * // generates the following methods * store.loadProductDetail // ({id: string} | Signal<{id: string}> | Observable<{id: string}>) => void * store.checkout // () => void * * @warning The default mapPipe is {@link https://www.learnrxjs.io/learn-rxjs/operators/transformation/exhaustmap exhaustMap}. If your call returns an observable that does not complete after the first value is emitted, any changes to the input params will be ignored. Either specify {@link https://www.learnrxjs.io/learn-rxjs/operators/transformation/switchmap switchMap} as mapPipe, or use {@link https://www.learnrxjs.io/learn-rxjs/operators/filtering/take take(1)} or {@link https://www.learnrxjs.io/learn-rxjs/operators/filtering/first first()} as part of your call. */ declare function withCalls>(callsFactory: (store: StoreSource) => Calls): SignalStoreFeature & { [K in keyof Calls as ExtractCallResultPropName]: ExtractCallResultType; }; props: NamedCallsStatusComputed; methods: { [K in keyof Calls]: Calls[K] extends (...args: infer P) => any ? P extends [] ? () => void : { (param: P[0]): Promise<{ value: Signal>; ok: true; } | { error: Signal>; ok: false; }>; (param: Observable | (() => P[0])): RxMethodRef; } : Calls[K] extends CallConfig ? Parameters extends undefined[] ? () => void : { (param: Parameters[0]): Promise<{ value: Signal>; ok: true; } | { error: Signal>; ok: false; }>; (param: Observable[0]> | (() => Parameters[0])): RxMethodRef; } : never; }; }>; type NamedCallStatusMapState = { [K in Prop as `${K}CallStatus`]: Record; }; type NamedCallStatusMapComputed = { [K in Prop as `isAny${Capitalize}Loading`]: Signal; } & { [K in Prop as `areAll${Capitalize}Loaded`]: Signal; } & { [K in Prop as `${K}Errors`]: Signal; }; type NamedCallStatusMapMethods = { [K in Prop as `is${Capitalize}Loading`]: (id: string) => boolean; } & { [K in Prop as `is${Capitalize}Loaded`]: (id: string) => boolean; } & { [K in Prop as `${K}Error`]: (id: string) => Error | undefined; } & { [K in Prop as `set${Capitalize}Loading`]: (id: string) => void; } & { [K in Prop as `set${Capitalize}Loaded`]: (id: string) => void; } & { [K in Prop as `set${Capitalize}Error`]: (id: string, error: Error) => void; }; /** * Generates necessary state, computed and methods for call progress status but map by a key, allowing to implement * calls of the same type that run on parallel each with its own status. * @param configFactory - The configuration object for the feature or a factory function that receives the store and returns the configuration object * @param configFactory.prop - The name of the property for which this represents the call status * @param configFactory.initialValue - The initial value of the call status * @param configFactory.collection - The name of the collection for which this represents the call status is an alias to prop param * @param configFactory.errorType - The type of the error * they do the same thing * * prop or collection is required * @example * export const Store = signalStore( * { providedIn: 'root' }, * withEntities(orderEntity), * withCallStatusMap({ prop: 'loadDetails' }), * withMethods((store) => ({ * loadProducts: rxMethod<{ orderId: string }>( * pipe( * switchMap((params) => { * store.setLoadDetailsLoading(params.orderId); * return inject(OrderService) * .getOrderDetail(params.orderId) * .pipe( * tap((res) => * patchState( * store, * updateEntity( * { * id: params.orderId, * changes: { items: res.items }, * }, * orderEntity, * ), * ), * ), * catchError((error) => { * store.setLoadDetailsError(params.orderId, error); * return EMPTY; * }), * ); * }), * ), * ), * })), * ); * * // generates the following signals * store.loadDetailsCallStatus // '{[key:string]: init' | 'loading' | 'loaded' | { error: unknown }} * // generates the following computed signals * store.isAnyLoadDetailsLoading() // boolean * store.areAllLoadDetailsLoaded // boolean * store.loadDetailsErrors() // Errors[] | undefined * // generates the following methods * store.isLoadDetailsLoading(key: string) // boolean * store.isLoadDetailsLoaded(key: string) // boolean * store.loadDetailsError(key: string) // unknown | null * store.setLoadDetailsLoading(key: string) // () => void * store.setLoadDetailsLoaded(key: string) // () => void * store.setLoadDetailsError(key: string) // (error?: unknown) => void */ declare function withCallStatusMap(configFactory: FeatureConfigFactory; errorType?: Error; prop: Prop; }>): SignalStoreFeature; props: NamedCallStatusMapComputed; methods: NamedCallStatusMapMethods; }>; /** * Call configuration object for withCalls * @param config - the call configuration * @param config.call - required, the function that will be called * @param config.mapPipe - optional, default exhaustMap the pipe operator that will be used to map the call result * @param config.storeResult - optional, default true, if false, the result will not be stored in the store * @param config.resultProp - optional, default callName + 'Result', the name of the prop where the result will be stored * @param config.onSuccess - optional, a function that will be called when the call is successful * @param config.mapError - optional, a function that will be called to transform the error before storing it * @param config.onError - optional, a function that will be called when the call fails * @param config.skipWhen - optional, a function that will be called to determine if the call should be skipped * @param config.callWith - optional, reactively execute the call with the provided params return by a function or observable * @param config.defaultResult - optional, A default value for the result before the call is executed */ declare function callConfig = CallConfig, DefaultResult extends Result | undefined = undefined>(config: Omit, 'resultProp' | 'storeResult' | 'defaultResult'> & { resultProp?: PropName; defaultResult: NoInfer; }): C; /** * Call configuration object for withCalls * @param config - the call configuration * @param config.call - required, the function that will be called * @param config.mapPipe - optional, default exhaustMap the pipe operator that will be used to map the call result * @param config.storeResult - optional, default true, if false, the result will not be stored in the store * @param config.resultProp - optional, default callName + 'Result', the name of the prop where the result will be stored * @param config.onSuccess - optional, a function that will be called when the call is successful * @param config.mapError - optional, a function that will be called to transform the error before storing it * @param config.onError - optional, a function that will be called when the call fails * @param config.skipWhen - optional, a function that will be called to determine if the call should be skipped * @param config.callWith - optional, reactively execute the call with the provided params return by a function or observable * @param config.defaultResult - optional, A default value for the result before the call is executed */ declare function callConfig = CallConfig, DefaultResult extends Result | undefined = undefined>(config: Omit, 'resultProp' | 'storeResult' | 'defaultResult'> & { resultProp?: PropName; }): C; /** * Call configuration object for withCalls * @param config - the call configuration * @param config.call - required, the function that will be called * @param config.mapPipe - optional, default exhaustMap the pipe operator that will be used to map the call result * @param config.storeResult - optional, default true, if false, the result will not be stored in the store * @param config.resultProp - optional, default callName + 'Result', the name of the prop where the result will be stored * @param config.onSuccess - optional, a function that will be called when the call is successful * @param config.mapError - optional, a function that will be called to transform the error before storing it * @param config.onError - optional, a function that will be called when the call fails * @param config.skipWhen - optional, a function that will be called to determine if the call should be skipped * @param config.callWith - optional, reactively execute the call with the provided params return by a function or observable * @param config.defaultResult - optional, A default value for the result before the call is executed */ declare function callConfig, 'resultProp' | 'storeResult' | 'defaultResult'> & { storeResult: false; } = Omit, 'resultProp' | 'storeResult' | 'defaultResult'> & { storeResult: false; }>(config: Omit, 'resultProp' | 'storeResult' | 'defaultResult'> & { storeResult: false; }): C & { resultProp: ''; defaultResult: undefined; }; /** * Call configuration object for withCalls * @Deprecated renamed to callConfig() * @param config - the call configuration * @param config.call - required, the function that will be called * @param config.mapPipe - optional, default exhaustMap the pipe operator that will be used to map the call result * @param config.storeResult - optional, default true, if false, the result will not be stored in the store * @param config.resultProp - optional, default callName + 'Result', the name of the prop where the result will be stored * @param config.onSuccess - optional, a function that will be called when the call is successful * @param config.mapError - optional, a function that will be called to transform the error before storing it * @param config.onError - optional, a function that will be called when the call fails * @param config.skipWhen - optional, a function that will be called to determine if the call should be skipped * @param config.callWith - optional, reactively execute the call with the provided params return by a function or observable * @param config.defaultResult - optional, A default value for the result before the call is executed */ declare function typedCallConfig = CallConfig, DefaultResult extends Result | undefined = undefined>(config: Omit, 'resultProp' | 'storeResult' | 'defaultResult'> & { resultProp?: PropName; defaultResult: NoInfer; }): C; /** * Call configuration object for withCalls * @Deprecated renamed to callConfig() * @param config - the call configuration * @param config.call - required, the function that will be called * @param config.mapPipe - optional, default exhaustMap the pipe operator that will be used to map the call result * @param config.storeResult - optional, default true, if false, the result will not be stored in the store * @param config.resultProp - optional, default callName + 'Result', the name of the prop where the result will be stored * @param config.onSuccess - optional, a function that will be called when the call is successful * @param config.mapError - optional, a function that will be called to transform the error before storing it * @param config.onError - optional, a function that will be called when the call fails * @param config.skipWhen - optional, a function that will be called to determine if the call should be skipped * @param config.callWith - optional, reactively execute the call with the provided params return by a function or observable * @param config.defaultResult - optional, A default value for the result before the call is executed */ declare function typedCallConfig = CallConfig, DefaultResult extends Result | undefined = undefined>(config: Omit, 'resultProp' | 'storeResult' | 'defaultResult'> & { resultProp?: PropName; }): C; /** * Call configuration object for withCalls * @Deprecated renamed to callConfig() * @param config - the call configuration * @param config.call - required, the function that will be called * @param config.mapPipe - optional, default exhaustMap the pipe operator that will be used to map the call result * @param config.storeResult - optional, default true, if false, the result will not be stored in the store * @param config.resultProp - optional, default callName + 'Result', the name of the prop where the result will be stored * @param config.onSuccess - optional, a function that will be called when the call is successful * @param config.mapError - optional, a function that will be called to transform the error before storing it * @param config.onError - optional, a function that will be called when the call fails * @param config.skipWhen - optional, a function that will be called to determine if the call should be skipped * @param config.callWith - optional, reactively execute the call with the provided params return by a function or observable * @param config.defaultResult - optional, A default value for the result before the call is executed */ declare function typedCallConfig, 'resultProp' | 'storeResult' | 'defaultResult'> & { storeResult: false; } = Omit, 'resultProp' | 'storeResult' | 'defaultResult'> & { storeResult: false; }>(config: Omit, 'resultProp' | 'storeResult' | 'defaultResult'> & { storeResult: false; }): C & { resultProp: ''; defaultResult: undefined; }; type StorageValueMapper = Record> = (store: Store) => { storageValueToState: (value: T) => void; stateToStorageValue: () => T | undefined | null; }; /** * Sync the state of the store to the web storage * @param key - the key to use in the web storage * @param type - 'session' or 'local' storage * @param saveStateChangesAfterMs - save the state to the storage after this many milliseconds, 0 to disable * @param restoreOnInit - restore the state from the storage on init * @param filterState - filter the state before saving to the storage (mutually exclusive with valueMapper) * @param valueMapper - custom transformation between store state and storage value (mutually exclusive with filterState) * @param onRestore - callback after the state is restored from the storage * @param expires - storage will not be loaded if is older than this many milliseconds * * @example * // Example 1: Using filterState to save specific state properties * const store = signalStore( * withEntities({ entity, collection }), * withCallStatus({ prop: collection, initialValue: 'loading' }), * * withSyncToWebStorage({ * key: 'my-key', * type: 'session', * restoreOnInit: true, * saveStateChangesAfterMs: 300, * // optionally, filter the state before saving to the storage * filterState: ({ orderItemsEntityMap, orderItemsIds }) => ({ * orderItemsEntityMap, * orderItemsIds, * }), * }), * ); * * @example * // Example 2: Using valueMapper for custom transformation * const store = signalStore( * withState({ * userProfile: { * userName: '', * email: '', * preferences: { theme: 'light', notifications: true }, * tempData: null, * } * }), * * withSyncToWebStorage({ * key: 'user-form', * type: 'local', * restoreOnInit: true, * saveStateChangesAfterMs: 500, * // Custom mapper to store only userName and email * valueMapper: (store) => ({ * stateToStorageValue: () => ({ * userName: store.userProfile().userName, * email: store.userProfile().email, * }), * storageValueToState: (savedData) => { * patchState(store, { * userProfile: { * ...store.userProfile(), * userName: savedData.userName, * email: savedData.email, * } * }); * }, * }), * }), * ); * * // generates the following methods * store.saveToStorage(); * store.loadFromStorage(); * store.clearFromStore(); * */ declare function withSyncToWebStorage({ key, type: storageType, saveStateChangesAfterMs, restoreOnInit, onRestore, expires, ...rest }: { key: string; type: 'session' | 'local'; restoreOnInit?: boolean; saveStateChangesAfterMs?: number; expires?: number; onRestore?: (store: StoreSource) => void; } & ({ filterState: (state: Input['state']) => Partial; } | { valueMapper: StorageValueMapper>; } | {})): SignalStoreFeature void; loadFromStorage: () => void; clearFromStore: () => void; }; }>; type TransferValueMapper = Record> = (store: Store) => { transferValueToState: (value: T) => void; stateToTransferValue: () => T | undefined | null; }; /** * Sync the state of the store using Angular's TransferState API for SSR * @param key - the key to use in the TransferState * @param filterState - filter the state before saving to TransferState (mutually exclusive with valueMapper) * @param valueMapper - custom transformation between store state and transfer value (mutually exclusive with filterState) * @param onRestore - callback after the state is restored from TransferState * * @example * // Example 1: Using filterState to transfer specific state properties * const store = signalStore( * withEntities({ entity, collection }), * withCallStatus({ prop: collection, initialValue: 'loading' }), * * withServerStateTransfer({ * key: 'my-state', * // optionally, filter the state before transferring * filterState: ({ orderItemsEntityMap, orderItemsIds }) => ({ * orderItemsEntityMap, * orderItemsIds, * }), * }), * ); * * @example * // Example 2: Using valueMapper for custom transformation * const store = signalStore( * withState({ * userProfile: { * userName: '', * email: '', * preferences: { theme: 'light', notifications: true }, * tempData: null, * } * }), * * withServerStateTransfer({ * key: 'user-profile', * // Custom mapper to transfer only userName and email * valueMapper: (store) => ({ * stateToTransferValue: () => ({ * userName: store.userProfile().userName, * email: store.userProfile().email, * }), * transferValueToState: (savedData) => { * patchState(store, { * userProfile: { * ...store.userProfile(), * userName: savedData.userName, * email: savedData.email, * } * }); * }, * }), * }), * ); * */ declare function withServerStateTransfer({ key, onRestore, ...rest }: { key: string; onRestore?: (store: StoreSource) => void; } & ({ filterState: (state: Input['state']) => Partial; } | { valueMapper: TransferValueMapper>; } | {})): SignalStoreFeature; type FilterQueryMapper = { queryParamsToFilter: (query: T) => Filter; filterToQueryParams: (filter: Filter) => T | undefined | null; }; /** * Syncs entities filter, pagination, sort and single selection to route query params for local or remote entities store features. If a collection is provided, it will be used as a prefix (if non is provided) for the query params. * The prefix can be disabled by setting it to false, or changed by providing a string. The filterMapper can be used to customize how the filter object is map to a query params object, * when is not provided the filter will use JSON.stringify to serialize the filter object. * * Requires withEntities and withCallStatus to be present in the store. * * @param config.collection The collection name to use as a prefix for the query params. If not provided, the collection name will be used. * @param config.filterMapper A function to map the filter object to a query params object. * @param config.prefix The prefix to use for the query params. If set to false, the prefix will be disabled. * @param config.onQueryParamsLoaded A function to be called when the query params are loaded into the store, (only gets called once). * @param config.defaultDebounce The default debounce time to use sync the store changes back to the route query params. * @param config.skipLoadingCall When true, restoring state from query params will update the store state but will not trigger a backend call to fetch entities. Default is false. * * @example * export const ProductsRemoteStore = signalStore( * { providedIn: 'root' }, * // requires at least withEntities and withCallStatus * withEntities({ entity, collection }), * withCallStatus({ prop: collection, initialValue: 'loading' }), * withEntitiesRemoteFilter({ * entity, * collection, * }), * withEntitiesRemotePagination({ * entity, * collection, * }), * withEntitiesRemoteSort({ * entity, * collection, * defaultSort: { field: 'name', direction: 'asc' }, * }), * withEntitiesLoadingCall({ * collection, * fetchEntities: ({ productEntitiesFilter, productEntitiesPagedRequest, productEntitiesSort }) => { * return inject(ProductService) * .getProducts({ * search: productEntitiesFilter().name, * take: productEntitiesPagedRequest().size, * skip: productEntitiesPagedRequest().startIndex, * sortColumn: productEntitiesSort().field, * sortAscending: productEntitiesSort().direction === 'asc', * }) * .pipe( * map((d) => ({ * entities: d.resultList, * total: d.total, * })), * ); * }, * }), * // syncs the entities filter, pagination, sort and single selection to the route query params * withEntitiesSyncToRouteQueryParams({ * entity, * collection, * }) *); */ declare function withEntitiesSyncToRouteQueryParams(config: { entity: Entity; collection?: Collection; filterMapper?: FilterQueryMapper; prefix?: string | false; onQueryParamsLoaded?: (store: StoreSource) => void; defaultDebounce?: number; restoreOnInit?: boolean; skipLoadingCall?: boolean; syncFilter?: boolean; syncPagination?: boolean; syncSort?: boolean; syncSingleSelection?: boolean; syncMultiSelection?: boolean; }): SignalStoreFeature & CallStatusState; props: EntityProps & CallStatusComputed; methods: CallStatusMethods; } : { state: NamedEntityState & NamedCallStatusState<`${Collection}Entities`>; props: NamedEntityProps & NamedCallStatusComputed<`${Collection}Entities`>; methods: NamedCallStatusMethods<`${Collection}Entities`>; }), { state: {}; props: {}; methods: { loadFromQueryParams: () => void; }; }>; declare function getQueryMapperWithPrefix(config: { prefix: string; mapper: QueryMapper; }): QueryMapper; /** * Syncs the route query params with the store and back. On init it will load * the query params once and set them in the store using the mapper.queryParamsToState, after that * and change on the store will be reflected in the query params using the mapper.stateToQueryParams * @param config.mappers - The mappers to sync the query params with the store * @param config.defaultDebounce - The debounce time to wait before updating the query params from the store * * @example * const Store = signalStore( * withState({ * test: 'test', * foo: 'foo', * bar: false, * }), * withSyncToRouteQueryParams({ * mappers: [ * { * queryParamsToState: (query, store) => { * // set the query params in the store (only called once on init) * patchState(store, { * test: query.test, * foo: query.foo, * bar: query.bar === 'true', * }); * }, * stateToQueryParams: (store) => * // return the query params to be set in the route * computed(() => ({ * test: store.test(), * foo: store.foo(), * bar: store.bar().toString(), * })), * }, * ], * defaultDebounce: debounce, * }), * ); */ declare function withSyncToRouteQueryParams, Mappers extends ReadonlyArray>>>(config: { mappers: Mappers; defaultDebounce?: number; restoreOnInit?: boolean; onQueryParamsStored?: (store: StoreSource) => void; }): SignalStoreFeature void; }; }>; /** * Store feature that provides access to route params, query params, and route data. * Creates a computed signal for each property returned by the mapParams function. * * @param mapParams Function receiving `{ params, queryParams, data }` and returning an object. * * @example * // Combined params, queryParams and data * const Store = signalStore( * withRoute(({ params, queryParams, data }) => ({ * id: params['id'] as string, * tab: queryParams['tab'] as string, * title: data?.['title'] as string, * })), * withHooks(({ id, tab, title }) => ({ * onInit: () => console.log(`Product ID: ${id()}, tab: ${tab()}, title:${title()}` ), * })), * ); */ declare function withRoute>(mapParams: (options: { params: Params; queryParams: Params; data?: { [key: string | symbol]: any; }; }) => T): _ngrx_signals.SignalStoreFeature<_ngrx_signals.EmptyFeatureResult, { state: {}; props: { [P in keyof { [K in keyof T]: Signal; }]: { [K in keyof T]: Signal; }[P] extends Signal ? { [K in keyof T]: Signal; }[P] : { [K in keyof T]: Signal; }[P] extends () => infer V ? Signal : never; }; methods: {}; }>; /** * @deprecated use withRoute instead * This store feature provides access to the route params. The mapParams receives the route params object, use it to transform it * to an object, this will create a computed for each prop return by the mapParams function * @param mapParams A function to transform the params before they are stored. * * @example * * // example route /products/:id/ * const ProductDetailStore = signalStore( * withRouteParams(({ id }) => ({ id })), * withCalls(() => ({ * loadProductDetail: (id: string) => * inject(ProductService).getProductDetail(id), * })), * withHooks(({ loadProductDetail, id }) => ({ * onInit: () => { * loadProductDetail(id()); * }, * })), * ); */ declare function withRouteParams>(mapParams: (params: Params, data?: any) => T): _ngrx_signals.SignalStoreFeature<_ngrx_signals.EmptyFeatureResult, { state: {}; props: { [P in keyof { [K in keyof T]: Signal; }]: { [K in keyof T]: Signal; }[P] extends Signal ? { [K in keyof T]: Signal; }[P] : { [K in keyof T]: Signal; }[P] extends () => infer V ? Signal : never; }; methods: {}; }>; type RecordSignals = { [K in keyof T]: Signal; }; /** * Binds component inputs to the store, so that the store is updated with the latest values of the inputs. * @param inputs * * @example * * const Store = signalStore( * withInputBindings({ * pageIndex: 0, * length: 0, * pageSize: 10, * pageSizeOptions: [5, 10, 20], * }), * //... other features that use foo and bar * ); * // generates the signals * store.pageIndex(); // 0 * store.length(); // 0 * store.pageSize(); // 10 * store.pageSizeOptions(); // [5, 10, 20] * * generates the method * store.bindInputs({ pageIndex: Signal, length: Signal, pageSize: Signal, pageSizeOptions: Signal }); * * // use in a component * class PaginatorComponent { * readonly pageIndex = input.required; * readonly length = input.required; * readonly pageSize = input.required; * readonly pageSizeOptions = input.required; * readonly store = inject(Store); * constructor() { * this.store.bindInputs({ * pageIndex: this.pageIndex, * length: this.length, * pageSize: this.pageSize, * pageSizeOptions: this.pageSizeOptions, * }); * // if the inputs have the same name and type as the store, * // you can use bindInputs like * // this.store.bindInputs(this); * } * } * */ declare function withInputBindings = RecordSignals>(inputs: Object): _ngrx_signals.SignalStoreFeature<_ngrx_signals.EmptyFeatureResult, { state: { _inputsInitialized: boolean; } & Object extends infer T ? { [K in keyof T]: T[K]; } : never; props: {}; methods: { bindInputs: (inputs: Inputs) => { destroy: () => void; }; }; }>; /** * This store feature allows access to the store's state, methods, computed signals, to store features that don't have a config factory that * can access the store. This can be useful for creating store features that need to access the store's state, methods, computed signals, etc. or to wrap store * features that don't have a config factory that can access the store. * @param featureFactory * * @example * // Use case 1: allow a custome store feature that receives a plain config object to access the store's state, methods, computed signals. * function withCustomFeature(config: { fooValue: string }) { * ...// create a custom store feature * } * const Store = signalStore( * withState({ foo: 'foo' }), * // 👇use previous state to configure custom feature * withFeatureFactory(({ foo }) => withCustomFeature({ fooValue: foo() })), * // you can also use a signalStoreFeature inside withFeatureFactory * withFeatureFactory(({ foo }) => * signalStoreFeature( * withState({ foo2: foo() }), * // ... other store features, * ), * ), * ); * * // Use case 2: use withFeatureFactory inside a custom feature to create a store whose config can be a factory that receives the store * function withCustomFeature2( * configFactory: FeatureConfigFactory, * ): SignalStoreFeature< * Input, * { * state: { foo: string }; * computed: { bar: Signal }; * methods: { baz: () => number }; * } * > { * return withFeatureFactory((store: StoreSource) => { * const config = getFeatureConfig(configFactory, store); * return signalStoreFeature( * withState<{ foo: string }>({ foo: config.fooValue }), * withComputed(({ foo }) => ({ bar: computed(() => foo() + 1) })), * withMethods(({ foo, bar }) => ({ * baz: () => foo() + bar() + 2, * })), * ); * }) as any; * } * * // now withCustomFeature2 can be used like : * const Store = signalStore( * // withCustomFeature2({ fooValue: 'foo' }), // usual way with a plain object * withState({ fooValue: 'foo' }), * // or with a factory that receives the store * withCustomFeature2(({ fooValue }) => ({ fooValue: fooValue() })), * ); */ declare function withFeatureFactory>(featureFactory: (store: StoreSource) => Feature): SignalStoreFeature ? In : never), Feature extends SignalStoreFeature ? Out : never>; type CallStatus = { loading: Signal; error: Signal; }; /** * Adds methods to the store to track the status of all calls in the store * @example * export const ProductsLocalStore = signalStore( * withAllCallStatus(), // <-- add this line * withEntities({ entity, collection }), * withCallStatus({ collection, initialValue: 'loading' }), * withEntitiesLoadingCall({ * collection, * fetchEntities: () => { * return inject(ProductService) * .getProducts() * .pipe(map((d) => d.resultList)); * }, * }), * withCalls(() => ({ * loadProductDetail: callConfig({ * call: ({ id }: { id: string }) => * inject(ProductService).getProductDetail(id), * resultProp: 'productDetail', * }), * checkout: () => inject(OrderService).checkout(), * })), * ); * // generates the following methods * store.isAnyCallLoading() // Signal * store.callsErrors // () => Signals */ declare function withAllCallStatus(): _ngrx_signals.SignalStoreFeature<_ngrx_signals.EmptyFeatureResult, { state: { _allCallStatus: CallStatus[]; }; props: { isAnyCallLoading: _angular_core.Signal; callsErrors: _angular_core.Signal; }; methods: { _registerCallStatus: (callStatus: CallStatus) => void; }; }>; declare function registerCallState(store: Record, callStatus: CallStatus): void; type ObservableCall = (arg: Param) => Observable; type PromiseCall = (arg: Param) => Promise; type Call = ObservableCall | PromiseCall; type EntityCall) = string | number | Entity | ({ entity: Entity; } & Record), Result extends Partial | undefined = Partial | undefined> = Call; type EntityCallConfig = { /** * The main function to be called. */ call: Call; /** * function that returns the entity id in the params * @param param */ paramsSelectId?: (param: NoInfer) => string; /** * default is true, if false disables automatically storing the result of the * function, to allow you do your own implementation using onSuccess. */ storeResult?: boolean; /** * Callback function invoked on successful completion of the call. * Receives the result of the call and the parameter used. */ onSuccess?: (result: NoInfer, param: NoInfer, previousResult: NoInfer | undefined) => void; /** * A function to transform an error from the call into a custom `Error` type. * Receives the error and the parameter used. */ mapError?: (error: unknown, param: NoInfer) => Error; /** * Callback function invoked if the call encounters an error. * Receives the mapped error and the parameter used. */ onError?: (error: Error, param: NoInfer) => void; /** * A function with condition that determines whether the call should be skipped. * The function accepts the call parameter and must return a boolean | Observable. */ skipWhen?: Call, boolean> | (() => boolean) | ((param: NoInfer, previousResult: NoInfer | undefined) => boolean); /** * Reactively execute the call with the provided params. * Supports the following: * - A direct parameter value. Which execute the call once on init. * - A function or `Observable` emitting the parameter of the call or undefined. * - A function returning the parameter or undefined. * * **Warning**: By default, when withCall is a function, signal * or observable that when returns a falsy value it will skip the call. * To override this behavior, define a skipWhen with your own rule or skipWhen: () => false * to always execute on any value. */ callWith?: Param extends undefined ? Observable | (() => boolean) | boolean : NoInfer | null | undefined | Observable> | (() => NoInfer | null | undefined); }; type ExtractEntityCallErrorType | EntityCallConfig> = T extends EntityCallConfig ? E : unknown; type NamedEntitiesCallsStatusComputed | EntityCallConfig>> = { [K in keyof Calls as K extends `_${infer J}` ? `_isAny${Capitalize}Loading` : `isAny${Capitalize}Loading`]: Signal; } & { [K in keyof Calls as K extends `_${infer J}` ? `_areAll${Capitalize}Loaded` : `areAll${Capitalize}Loaded`]: Signal; } & { [K in keyof Calls as `${K & string}Errors`]: Calls[K] extends EntityCallConfig ? Signal : Signal; }; type NamedEntitiesCallsStatusMethods | EntityCallConfig>> = { [K in keyof Calls as K extends `_${infer J}` ? `_is${Capitalize}Loading` : `is${Capitalize}Loading`]: (entityOrId: Entity | string | number) => boolean; } & { [K in keyof Calls as K extends `_${infer J}` ? `_is${Capitalize}Loaded` : `is${Capitalize}Loaded`]: (entityOrId: Entity | string | number) => boolean; } & { [K in keyof Calls as `${K & string}Error`]: Calls[K] extends EntityCallConfig ? (entityOrId: Entity | string | number) => Error | undefined : (entityOrId: Entity | string | number) => unknown | undefined; }; /** * Generates necessary state, computed and methods to track the progress of * calls related to an entity and merges the result back to entities list. The generated methods are rxMethods with * the same name as the original call, which accepts either the original parameters * or a Signal or Observable of the same type as the original parameters. * The original call can only have zero or one parameter, use an object with multiple * props as first param if you need more. * *Important* The calls must have a parameter of type Entity {entity: Entity, ...extra params} or use entityCallConfig * and the paramsSelectId to return with param prop represents the entityId . * The call can be skipped based on the result of the previous call, to skip a call return undefined or false. * @param config.entity - The entity type to be used * @param config.collection - The optional collection name to be used * @param config.selectId - The function to use to select the id of the entity * @param config.callsFactory - a factory function that receives the store and returns an object of type {Record} with the calls to be made * * @example * const orderEntity = entityConfig({ * entity: type(), * collection: 'order', * }); * export const OrderStore = signalStore( * withEntities(orderEntity), * withEntitiesCalls({ * ...orderEntity, * calls: (store, orderService = inject(OrderService)) => ({ * loadOrderDetail: (entity) => orderService.getOrderDetail(entity.id), * // alternative way to define the call * // loadOrderDetail: entityCallConfig({ * // call: (entity: OrderSummary) => orderService.getOrderDetail(entity.id), * // // skip the call if result is already loaded * // skipWhen: (param, previousResult) => !!previousResult?.items, * // }), * changeOrderStatus: (option: { * entity: OrderSummary; * status: OrderSummary['status']; * }) => orderService.changeStatus(option.entity.id, option.status), * deleteOrder: (entity: OrderSummary) => { * return orderService.delete(entity.id).pipe( * map((deleted) => { * deleted ? undefined : entity; // returning undefined will remove the entity from the store * }), * ); * }, * }), * }), * ); * * // generates the following signals * store.loadOrderDetailCallStatus // a map { [id: string]:'init' | 'loading' | 'loaded' | { error: unknown }} * // similar for changeOrderStatus and deleteOrder * * // the calls updates the entities so results, which can be accessed with the usual entities list computed signals * // generates the following computed signals * store.isAnyLoadOrderDetailLoading: Signal * store.isAnyLoadOrderDetailLoaded: Signal * store.loadOrderDetailErrors: Signal * // same for changeOrderStatus and deleteOrder * // generates the following methods * store.isLoadOrderDetailLoading(id: string) => boolean * store.isLoadOrderDetailLoaded(id: string) => boolean * store.loadOrderDetailError(id: string) => string | null * store.loadOrderDetail ({id: string} | Signal<{id: string}> | Observable<{id: string}>) => void * // same for changeOrderStatus and deleteOrder * */ declare function withEntitiesCalls> | EntityCallConfig>>, Collection extends string = ''>(config: { entity: Entity; collection?: Collection; selectId?: SelectEntityId>; calls: (store: StoreSource) => Calls; }): SignalStoreFeature>; props: EntityProps>; methods: {}; } : { state: NamedEntityState, Collection>; props: NamedEntityProps, Collection>; methods: {}; }), { state: NamedCallStatusMapState; props: NamedEntitiesCallsStatusComputed; methods: NamedEntitiesCallsStatusMethods & { [K in keyof Calls]: Calls[K] extends (...args: infer P) => any ? { (param: P[0]): Promise<{ value: Signal; ok: true; } | { error: Signal>; ok: false; }>; (param: Observable | (() => P[0])): RxMethodRef; } : Calls[K] extends EntityCallConfig ? Parameters extends undefined[] ? () => void : { (...param: Parameters): Promise<{ value: Signal; ok: true; } | { error: Signal>; ok: false; }>; (param: Observable[0]> | (() => Parameters[0])): RxMethodRef; } : never; }; }>; /** * Call configuration object for withEntitiesCalls * @param config - the call configuration * @param config.call - required, the function that will be called * @param config.mapResult - required, a function to transform the result of the call to the entity * @param config.entityId - required, a function that returns the entity id in the params * @param config.onSuccess - optional, a function that will be called when the call is successful * @param config.mapError - optional, a function that will be called to transform the error before storing it * @param config.onError - optional, a function that will be called when the call fails * @param config.skipWhen - optional, a function that will be called to determine if the call should be skipped * @param config.callWith - optional, reactively execute the call with the provided params return by a function or observable * @param config.defaultResult - optional, A default value for the result before the call is executed */ declare function entityCallConfig | undefined, Error = unknown, C extends EntityCallConfig = EntityCallConfig>(config: Omit, 'storeResult' | 'paramsSelectId'> & { paramsSelectId: (param: NoInfer) => string; }): EntityCallConfig; declare function entityCallConfig = EntityCallConfig>(config: Omit, 'storeResult' | 'paramsSelectId'> & { paramsSelectId: (param: NoInfer) => string; storeResult: false; }): EntityCallConfig; declare function entityCallConfig), Result = Partial | undefined, Error = unknown, C extends EntityCallConfig = EntityCallConfig>(config: Omit, 'storeResult' | 'paramsSelectId'>): EntityCallConfig; type CacheKey = string | (string | object)[]; interface CacheData { value: any; date: number; expires?: number; invalid: boolean; hitCount: number; } interface CacheKeys { keys?: Map; data?: CacheData; } type CacheState = CacheKeys; type CacheValue = string | number | boolean | bigint | object | null | undefined; declare class CacheStore implements OnDestroy { cacheState: CacheState; skipAllCache: boolean; private intervalCancelKey; private isBrowser; constructor({ clearExpiredEvery }: { clearExpiredEvery: number; }); get({ key }: { key: CacheKey; }): _ngrx_traits_signals.CacheData | undefined; set({ key, value: valueOrFn, expires, maxCacheSize, }: { key: CacheKey; value: ((previousValue?: T) => T) | T; expires?: number; maxCacheSize?: number; }): void; invalidate({ key }: { key: CacheKey; }): void; delete({ key }: { key: CacheKey; }): void; setSkipCacheForAllCalls(skipAllCache: boolean): void; clear(): void; ngOnDestroy(): void; } declare function setGlobalCache(cache: CacheStore): void; declare function getGlobalCache(): CacheStore; /** * Return the cached results of the key if available, otherwise return the value of source and cache it * @param options */ declare function cacheCall({ key, call, expires, maxCacheSize, skip, cacheStore, }: { key: CacheKey; call: () => Promise; expires?: number; maxCacheSize?: number; skip?: boolean; cacheStore?: CacheStore; }): Promise; /** * Return the cached results of the key if available, otherwise return the value of source and cache it * @param options */ declare function cacheRxCall({ key, call, expires, maxCacheSize, skip, cacheStore, }: { key: CacheKey; call: Observable; expires?: number; maxCacheSize?: number; skip?: boolean; cacheStore?: CacheStore; }): Observable; declare function provideCacheStore(cacheStore: CacheStore): Provider[]; export { CacheStore, cacheCall, cacheRxCall, callConfig, entityCallConfig, getFeatureConfig, getGlobalCache, getInfiniteScrollDataSource, getQueryMapperWithPrefix, provideCacheStore, registerCallState, setGlobalCache, sortData, typedCallConfig, withAllCallStatus, withCallStatus, withCallStatusMap, withCalls, withEntitiesCalls, withEntitiesHybridFilter, withEntitiesLoadingCall, withEntitiesLocalFilter, withEntitiesLocalPagination, withEntitiesLocalSort, withEntitiesMultiSelection, withEntitiesRemoteFilter, withEntitiesRemotePagination, withEntitiesRemoteScrollPagination, withEntitiesRemoteSort, withEntitiesSingleSelection, withEntitiesSyncToRouteQueryParams, withFeatureFactory, withInputBindings, withLogger, withRoute, withRouteParams, withServerStateTransfer, withSyncToRouteQueryParams, withSyncToWebStorage }; export type { CacheData, CacheKey, CacheKeys, CacheState, CacheValue, Call$1 as Call, CallConfig, CallStatus$1 as CallStatus, CallStatusComputed, CallStatusMethods, CallStatusState, CdkSort, EntitiesFilterComputed, EntitiesFilterMethods, EntitiesFilterState, EntitiesMultiSelectionComputed, EntitiesMultiSelectionMethods, EntitiesMultiSelectionState, EntitiesPaginationLocalComputed, EntitiesPaginationLocalMethods, EntitiesPaginationLocalState, EntitiesPaginationRemoteComputed, EntitiesPaginationRemoteMethods, EntitiesPaginationRemoteState, EntitiesScrollPaginationComputed, EntitiesScrollPaginationMethods, EntitiesScrollPaginationState, EntitiesSingleSelectionComputed, EntitiesSingleSelectionMethods, EntitiesSingleSelectionState, EntitiesSortMethods, EntitiesSortState, EntityCall, EntityCallConfig, ExtractCallResultPropName, ExtractCallResultType, ExtractEntityCallErrorType, ExtractErrorType, ExtractStoreFeatureOutput, FeatureConfigFactory, FilterOptions, NamedCallStatusComputed, NamedCallStatusMapComputed, NamedCallStatusMapMethods, NamedCallStatusMapState, NamedCallStatusMethods, NamedCallStatusState, NamedCallsStatusComputed, NamedEntitiesCallsStatusComputed, NamedEntitiesCallsStatusMethods, NamedEntitiesFilterComputed, NamedEntitiesFilterMethods, NamedEntitiesFilterState, NamedEntitiesMultiSelectionComputed, NamedEntitiesMultiSelectionMethods, NamedEntitiesMultiSelectionState, NamedEntitiesPaginationLocalComputed, NamedEntitiesPaginationLocalMethods, NamedEntitiesPaginationLocalState, NamedEntitiesPaginationRemoteComputed, NamedEntitiesPaginationRemoteMethods, NamedEntitiesPaginationRemoteState, NamedEntitiesScrollPaginationComputed, NamedEntitiesScrollPaginationMethods, NamedEntitiesScrollPaginationState, NamedEntitiesSingleSelectionComputed, NamedEntitiesSingleSelectionMethods, NamedEntitiesSingleSelectionState, NamedEntitiesSortMethods, NamedEntitiesSortState, NamedSetEntitiesResult, ObservableCall$1 as ObservableCall, PaginationState, PromiseCall$1 as PromiseCall, QueryMapper, RxMethodRef, ScrollPaginationState, SetEntitiesResult, Sort, SortDirection, StoreSource, TransferValueMapper };