UNPKG

@gjv/redux-slice-factory

Version:

Generic factory functions for common slice data structures

345 lines (319 loc) 14.8 kB
import { CaseReducer } from '@reduxjs/toolkit'; import { CaseReducerActions } from '@reduxjs/toolkit'; import { Comparer } from '@reduxjs/toolkit'; import { Draft } from '@reduxjs/toolkit'; import { EntityId } from '@reduxjs/toolkit'; import { EntitySelectors } from '@reduxjs/toolkit'; import { EntityState } from '@reduxjs/toolkit'; import { OutputSelector } from '@reduxjs/toolkit'; import { PayloadAction } from '@reduxjs/toolkit'; import { Reducer } from '@reduxjs/toolkit'; import { Selector } from '@reduxjs/toolkit'; import { SerializedError } from '@reduxjs/toolkit'; import { SliceCaseReducers } from '@reduxjs/toolkit'; import { Update } from '@reduxjs/toolkit'; /** * @public */ export declare function createEntitySlice<TGlobalState, TEntity, TStatusEnum extends keyof typeof StatusEnum | string = keyof typeof StatusEnum, TError extends SerializedError = SerializedError>(options: ICreateEntitySliceOptions<TGlobalState, TEntity, TStatusEnum, TError>): IEntitySlice<TGlobalState, TEntity, TStatusEnum, TError>; /** * @public */ export declare function createModelSlice<TGlobalState, TModel, TStatusEnum extends keyof typeof StatusEnum | string = keyof typeof StatusEnum, TError extends SerializedError = SerializedError>(options: ICreateModelSliceOptions<TGlobalState, TModel, TStatusEnum, TError>): IModelSlice<TGlobalState, TModel, TStatusEnum, TError>; /** * @public */ export declare interface ICreateEntitySliceOptions<TGlobalState, TEntity, TStatusEnum extends keyof typeof StatusEnum | string = keyof typeof StatusEnum, TError extends SerializedError = SerializedError> extends ISliceOptions<TGlobalState, IEntityState<TEntity, TStatusEnum, TError>> { selectId: (o: TEntity) => EntityId; sortComparer: false | Comparer<TEntity>; } /** * @public */ export declare interface ICreateModelSliceOptions<TGlobalState, TModel, TStatusEnum extends keyof typeof StatusEnum | string = keyof typeof StatusEnum, TError extends SerializedError = SerializedError> extends ISliceOptions<TGlobalState, IModelState<TModel, TStatusEnum, TError>> { /** * This is how the slice will merge the current model and the update model during an update action * @defaultValue `merge` from {@link https://www.npmjs.com/package/ts-deepmerge} */ handleUpdate?: (current: Draft<TModel>, update: Partial<TModel>) => TModel; } /** * @public */ export declare type IEntitySlice<TGlobalState, TEntity, TStatusEnum extends keyof typeof StatusEnum | string = keyof typeof StatusEnum, TError extends SerializedError = SerializedError> = ISlice<TGlobalState, IEntityState<TEntity, TStatusEnum, TError>, IEntitySliceReducers<IEntityState<TEntity, TStatusEnum, TError>, TEntity, TStatusEnum, TError>, IEntitySliceSelectors<TGlobalState, TEntity, TStatusEnum, TError>>; /** * @public */ export declare interface IEntitySliceReducers<TSliceState, TEntity, TStatusEnum extends keyof typeof StatusEnum | string = keyof typeof StatusEnum, TError extends SerializedError = SerializedError> extends IMetaSliceReducers<TSliceState, TStatusEnum, TError> { /** * This will modify the slice. This adds one entity to the slice and sets lastModified. * @see {@link @reduxjs/toolkit#EntityStateAdapter} */ addOne: CaseReducer<TSliceState, PayloadAction<TEntity>>; /** * This will modify the slice. This adds many entities to the slice and sets lastModified. * @see {@link @reduxjs/toolkit#EntityStateAdapter} */ addMany: CaseReducer<TSliceState, PayloadAction<Array<TEntity> | Record<EntityId, TEntity>>>; /** * This will hydrate the slice. This sets one entity of the slice and lastHydrated, and resets lastModified. * @see {@link @reduxjs/toolkit#EntityStateAdapter.setOne} */ hydrateOne: CaseReducer<TSliceState, PayloadAction<TEntity>>; /** * This will hydrate the slice. This sets many entities of the slice and lastHydrated, and resets lastModified. * @see {@link @reduxjs/toolkit#EntityStateAdapter.setMany} */ hydrateMany: CaseReducer<TSliceState, PayloadAction<Array<TEntity> | Record<EntityId, TEntity>>>; /** * This will hydrate the slice. This sets all entities of the slice and lastHydrated, and resets lastModified. * @see {@link @reduxjs/toolkit#EntityStateAdapter.setAll} */ hydrateAll: CaseReducer<TSliceState, PayloadAction<Array<TEntity> | Record<EntityId, TEntity>>>; /** * This will modify the slice. This updates one entity of the slice and sets lastModified. * @see {@link @reduxjs/toolkit#EntityStateAdapter.updateOne} */ updateOne: CaseReducer<TSliceState, PayloadAction<Update<TEntity>>>; /** * This will modify the slice. This updates many entities of the slice and sets lastModified. * @see {@link @reduxjs/toolkit#EntityStateAdapter.updateMany} */ updateMany: CaseReducer<TSliceState, PayloadAction<Array<Update<TEntity>>>>; /** * This will modify the slice. This updates or inserts one entity of the slice and sets lastModified. * @see {@link @reduxjs/toolkit#EntityStateAdapter.upsertOne} */ upsertOne: CaseReducer<TSliceState, PayloadAction<TEntity>>; /** * This will modify the slice. This updates or inserts many entities of the slice and sets lastModified. * @see {@link @reduxjs/toolkit#EntityStateAdapter.upsertMany} */ upsertMany: CaseReducer<TSliceState, PayloadAction<Array<TEntity> | Record<EntityId, TEntity>>>; /** * This will modify the slice. This removes one entity of the slice and sets lastModified. * @see {@link @reduxjs/toolkit#EntityStateAdapter.removeOne} */ removeOne: CaseReducer<TSliceState, PayloadAction<EntityId>>; /** * This will modify the slice. This removes many entities of the slice and sets lastModified. * @see {@link @reduxjs/toolkit#EntityStateAdapter.removeMany} */ removeMany: CaseReducer<TSliceState, PayloadAction<Array<EntityId>>>; /** * This will modify the slice. This removes all entities of the slice and sets lastModified. * @see {@link @reduxjs/toolkit#EntityStateAdapter.removeAll} */ removeAll: CaseReducer<TSliceState, PayloadAction>; /** * This will reset the slice to its initial state. */ reset: CaseReducer<TSliceState, PayloadAction>; /** * This will modify the slice. This sets all entities of the slice and sets lastModified. * @see {@link @reduxjs/toolkit#EntityStateAdapter.setAll} */ setAll: CaseReducer<TSliceState, PayloadAction<Array<TEntity> | Record<EntityId, TEntity>>>; } /** * @public */ export declare interface IEntitySliceSelectors<TGlobalState, TEntity, TStatusEnum extends keyof typeof StatusEnum | string = keyof typeof StatusEnum, TError extends SerializedError = SerializedError> extends EntitySelectors<TEntity, TGlobalState>, ISliceSelectors<TGlobalState, IEntityState<TEntity, TStatusEnum, TError>>, IMetaSliceSelectors<TGlobalState, IEntityState<TEntity, TStatusEnum, TError>, TStatusEnum, TError> { } /** * @public */ export declare interface IEntityState<T, TStatusEnum extends keyof typeof StatusEnum | string = keyof typeof StatusEnum, TError extends SerializedError = SerializedError> extends EntityState<T>, IMetaState<TStatusEnum, TError> { } declare interface IMetaSliceReducers<TSliceState, TStatusEnum extends keyof typeof StatusEnum | string = keyof typeof StatusEnum, TError extends SerializedError = SerializedError> extends SliceCaseReducers<TSliceState> { /** * This will set the status of the slice. */ setStatus: CaseReducer<TSliceState, PayloadAction<TStatusEnum>>; /** * This will set the error of the slice. */ setError: CaseReducer<TSliceState, PayloadAction<TError | null>>; /** * This will set any meta state properties that are defined */ setMetaState: CaseReducer<TSliceState, PayloadAction<Partial<Pick<IMetaState<TStatusEnum, TError>, 'error' | 'status'>>>>; } /** * @public * @see IMetaState */ export declare interface IMetaSliceSelectors<TGlobalState, TSliceState, TStatusEnum extends keyof typeof StatusEnum | string = keyof typeof StatusEnum, TError extends SerializedError = SerializedError> { /** * This selects the status of the slice. * @see {@link IMetaState.status} */ selectStatus: IOutputSelector<TGlobalState, TSliceState, TStatusEnum>; /** * This selects the error of the slice. * @see {@link IMetaState.error} */ selectError: IOutputSelector<TGlobalState, TSliceState, TError | null>; /** * This selects the lastModified of the slice. * @see {@link IMetaState.lastModified} */ selectLastModified: IOutputSelector<TGlobalState, TSliceState, string | null>; /** * This selects the status of the slice. * @see {@link IMetaState.lastHydrated} */ selectLastHydrated: IOutputSelector<TGlobalState, TSliceState, string | null>; } /** * @public */ export declare interface IMetaState<TStatusEnum extends keyof typeof StatusEnum | string = keyof typeof StatusEnum, TError extends SerializedError = SerializedError> { /** * The status of the slice. * @defaultValue `StatusEnum` */ status: TStatusEnum; /** * The status of the slice. * @defaultValue `SerializedError` */ error: TError | null; /** * The timestamp of the last time the slice was modified. */ lastModified: string | null; /** * The timestamp of the last time the slice was hydrated. */ lastHydrated: string | null; } /** * @public */ export declare type IModelSlice<TGlobalState, TModel, TStatusEnum extends keyof typeof StatusEnum | string = keyof typeof StatusEnum, TError extends SerializedError = SerializedError> = ISlice<TGlobalState, IModelState<TModel, TStatusEnum, TError>, IModelSliceReducers<IModelState<TModel, TStatusEnum, TError>, TModel, TStatusEnum, TError>, IModelSliceSelectors<TGlobalState, TModel, TStatusEnum, TError>>; /** * @public */ export declare interface IModelSliceReducers<TSliceState, TModel, TStatusEnum extends keyof typeof StatusEnum | string = keyof typeof StatusEnum, TError extends SerializedError = SerializedError> extends IMetaSliceReducers<TSliceState, TStatusEnum, TError> { /** * This will hydrate the slice. This sets the model and lastHydrated, and resets lastModified. */ hydrate: CaseReducer<TSliceState, PayloadAction<TModel>>; /** * This will modify the slice. This updates the model and sets lastModified. */ update: CaseReducer<TSliceState, PayloadAction<Partial<TModel>>>; /** * This will modify the slice. This sets the model and sets lastModified. */ set: CaseReducer<TSliceState, PayloadAction<TModel>>; /** * This will reset the slice to its initial state. */ reset: CaseReducer<TSliceState, PayloadAction>; } /** * @public */ export declare interface IModelSliceSelectors<TGlobalState, TModel, TStatusEnum extends keyof typeof StatusEnum | string = keyof typeof StatusEnum, TError extends SerializedError = SerializedError> extends ISliceSelectors<TGlobalState, IModelState<TModel, TStatusEnum, TError>>, IMetaSliceSelectors<TGlobalState, IModelState<TModel, TStatusEnum, TError>, TStatusEnum, TError> { /** * This selects the slice model. */ selectModel: IOutputSelector<TGlobalState, IModelState<TModel, TStatusEnum, TError>, TModel>; } /** * @public */ export declare interface IModelState<T, TStatusEnum extends keyof typeof StatusEnum | string = keyof typeof StatusEnum, TError extends SerializedError = SerializedError> extends IMetaState<TStatusEnum, TError> { /** * The model of the slice. */ model: T; } /** * @public */ declare type IOutputSelector<TGlobalState, TSliceState, TResult> = OutputSelector<[Selector<TGlobalState, TSliceState>], TResult, (sliceState: TSliceState) => TResult>; /** * @public */ declare type ISelectCanRequest<TSliceState> = (sliceState: TSliceState) => boolean; /** * @public */ declare type ISelectShouldRequest<TSliceState> = (sliceState: TSliceState, canRequest: ReturnType<ISelectCanRequest<TSliceState>>) => boolean; /** * @public */ declare type ISelectSliceState<TGlobalState, TSliceState> = (globalState: TGlobalState) => TSliceState; /** * @public */ export declare interface ISlice<TGlobalState, TSliceState, TCaseReducers extends SliceCaseReducers<TSliceState>, TSliceSelectors extends ISliceSelectors<TGlobalState, TSliceState>> { name: ISliceName<TGlobalState>; reducer: Reducer<TSliceState>; actions: CaseReducerActions<TCaseReducers>; selectors: TSliceSelectors; } /** * @internal */ declare type ISliceName<TGlobalState> = keyof TGlobalState & string; /** * @public */ declare interface ISliceOptions<TGlobalState, TSliceState> { /** * The name of the slice in the redux store. */ name: ISliceName<TGlobalState>; /** * @see {@link ISliceSelectors.selectSliceState} */ selectSliceState: ISelectSliceState<TGlobalState, TSliceState>; /** * @see {@link ISliceSelectors.selectCanRequest} */ selectCanRequest?: ISelectCanRequest<TSliceState>; /** * @see {@link ISliceSelectors.selectShouldRequest} */ selectShouldRequest?: ISelectShouldRequest<TSliceState>; /** * The initial state of the slice. */ initialState?: Partial<TSliceState>; /** * The function for mapping a `Date` to a timestamp. */ createTimestamp?: (datetime?: Date) => string; } /** * @public */ export declare interface ISliceSelectors<TGlobalState, TSliceState> { /** * @public * Selects the entire slice state. */ selectSliceState: IOutputSelector<TGlobalState, TSliceState, TSliceState>; /** * @defaultValue (overrideable) The slice can request if it is not requesting, error is empty, and the slice has not been modified */ selectCanRequest: IOutputSelector<TGlobalState, TSliceState, boolean>; /** * @defaultValue (overrideable) The slice should request if it can request and it has not been hydrated * @see {@link ISliceSelectors.selectCanRequest} */ selectShouldRequest: IOutputSelector<TGlobalState, TSliceState, boolean>; } /** * @public */ export declare enum StatusEnum { Settled = "Settled", Requesting = "Requesting", Failed = "Failed" } export { }