@snipsonian/observable-state
Version:
Observable-state snippets (redux-like)
172 lines (171 loc) • 9.37 kB
TypeScript
import { ITraceableApiErrorBase } from '@snipsonian/core/es/typings/apiErrors';
import { TNrOfParentNotificationLevelsToTrigger } from '../../observer/extendNotificationsToTrigger';
import { Dispatch } from '../types';
export declare type TEntityKey = string;
export interface IEntitiesStateBase {
[entityKey: string]: IAsyncEntity<any>;
}
export declare enum AsyncOperation {
fetch = "fetch",
create = "create",
update = "update",
remove = "remove"
}
export declare const ALL_ASYNC_OPERATIONS: AsyncOperation[];
export interface IAsyncEntity<Data, Error = ITraceableApiErrorBase<{}>> {
data: Data;
fetch?: IAsyncEntityOperation<Error>;
create?: IAsyncEntityOperation<Error>;
update?: IAsyncEntityOperation<Error>;
remove?: IAsyncEntityOperation<Error>;
}
export interface IAsyncEntityOperation<Error = ITraceableApiErrorBase<{}>> {
status: AsyncStatus;
error: Error;
}
export declare enum AsyncStatus {
Initial = "initial",
Busy = "busy",
Success = "success",
Error = "error"
}
export interface IAsyncEntityKeyConfigs<Error = ITraceableApiErrorBase<{}>> {
[asyncEntityKey: string]: IAsyncEntityKeyConfig<any, Error>;
}
export interface IAsyncEntityKeyConfig<Data, Error = ITraceableApiErrorBase<{}>> {
operations: AsyncOperation[];
initialState: IAsyncEntity<Data, Error>;
}
export interface IAsyncEntitiesManager<State, StateChangeNotificationKey, Error = ITraceableApiErrorBase<{}>> {
registerEntity<Data>(props: IRegisterEntityProps<Data, StateChangeNotificationKey>): IRegisteredEntity<State, Data, StateChangeNotificationKey, Error>;
getAsyncEntityConfig<Data = any>(props: {
asyncEntityKey: TEntityKey;
}): IAsyncEntityKeyConfig<Data, Error>;
getEntitiesInitialState(): IEntitiesInitialState;
}
export interface IRegisterEntityProps<Data, StateChangeNotificationKey> {
asyncEntityKey: TEntityKey;
operations: AsyncOperation[];
initialData?: Data;
includeUpdaters?: boolean;
notificationsToTrigger: StateChangeNotificationKey[];
nrOfParentNotificationLevelsToTrigger?: TNrOfParentNotificationLevelsToTrigger;
}
export interface IRegisteredEntity<State, Data, StateChangeNotificationKey, Error = ITraceableApiErrorBase<{}>> {
select: (state?: State) => IAsyncEntity<Data, Error>;
updaters?: IRegisteredEntityUpdaters<Data, StateChangeNotificationKey, Error>;
async: IRegisteredEntityAsyncTriggers<State, Data, StateChangeNotificationKey>;
}
export interface IRegisteredEntityUpdaters<Data, StateChangeNotificationKey, Error> {
fetch?: IRegisteredOperationUpdaters<Data, StateChangeNotificationKey, Error>;
create?: IRegisteredOperationUpdaters<Data, StateChangeNotificationKey, Error>;
update?: IRegisteredOperationUpdaters<Data, StateChangeNotificationKey, Error>;
remove?: IRegisteredOperationUpdaters<Data, StateChangeNotificationKey, Error>;
}
export interface IRegisteredOperationUpdaters<Data, StateChangeNotificationKey, Error> {
trigger(options?: IOperationUpdaterOptions<StateChangeNotificationKey>): void;
triggerWithoutDataReset(options?: IOperationUpdaterOptions<StateChangeNotificationKey>): void;
succeeded(data: Data, options?: IOperationUpdaterOptions<StateChangeNotificationKey>): void;
succeededWithoutDataSet(options?: IOperationUpdaterOptions<StateChangeNotificationKey>): void;
failed(error: Error, options?: IOperationUpdaterOptions<StateChangeNotificationKey>): void;
cancel(options?: IOperationUpdaterOptions<StateChangeNotificationKey>): void;
reset(options?: IOperationUpdaterOptions<StateChangeNotificationKey>): void;
resetWithoutDataReset(options?: IOperationUpdaterOptions<StateChangeNotificationKey>): void;
}
export interface IOperationUpdaterOptions<StateChangeNotificationKey> extends IAsyncEntityOperationNotificationProps<StateChangeNotificationKey> {
}
export interface IAsyncEntityUpdaters<Data, Error> {
trigger(entity: IAsyncEntity<Data, Error>, initialData: Data): IAsyncEntity<Data, Error>;
triggerWithoutDataReset(entity: IAsyncEntity<Data, Error>): IAsyncEntity<Data, Error>;
succeeded(entity: IAsyncEntity<Data, Error>, data: Data): IAsyncEntity<Data, Error>;
succeededWithoutDataSet(entity: IAsyncEntity<Data, Error>): IAsyncEntity<Data, Error>;
failed(entity: IAsyncEntity<Data, Error>, error: Error): IAsyncEntity<Data, Error>;
cancel(entity: IAsyncEntity<Data, Error>): IAsyncEntity<Data, Error>;
reset(entity: IAsyncEntity<Data, Error>, initialData: Data): IAsyncEntity<Data, Error>;
resetWithoutDataReset(entity: IAsyncEntity<Data, Error>): IAsyncEntity<Data, Error>;
}
export interface IAsyncEntityTriggerResolveValue<ApiResult> {
wasTriggered: boolean;
asyncResult: ApiResult | null;
}
export interface IRegisteredEntityAsyncTriggers<State, Data, StateChangeNotificationKey> {
fetch?: <ApiInput = unknown, ApiResult = Data, ApiResponse = ApiResult>(props: ITriggerAsyncEntityFetchProps<State, ApiInput, StateChangeNotificationKey, ApiResult, ApiResponse>) => Promise<IAsyncEntityTriggerResolveValue<ApiResult>>;
create?: <ApiInput = unknown, ApiResult = Data, ApiResponse = ApiResult>(props: ITriggerAsyncEntityCreateProps<State, ApiInput, StateChangeNotificationKey, ApiResult, ApiResponse>) => Promise<IAsyncEntityTriggerResolveValue<ApiResult>>;
update?: <ApiInput = unknown, ApiResult = Data, ApiResponse = ApiResult>(props: ITriggerAsyncEntityUpdateProps<State, ApiInput, StateChangeNotificationKey, ApiResult, ApiResponse>) => Promise<IAsyncEntityTriggerResolveValue<ApiResult>>;
remove?: <ApiInput = unknown, ApiResult = Data, ApiResponse = ApiResult>(props: ITriggerAsyncEntityRemoveProps<State, ApiInput, StateChangeNotificationKey, ApiResult, ApiResponse>) => Promise<IAsyncEntityTriggerResolveValue<ApiResult>>;
}
export interface ITriggerAsyncEntityFetchProps<State, ApiInput, StateChangeNotificationKey, ApiResult, ApiResponse> extends ITriggerAsyncEntityOperationBaseProps<State, ApiInput, StateChangeNotificationKey, ApiResult, ApiResponse>, IShouldFetchEntityProps<State>, IShouldResetEntityOnTrigger<State> {
}
export interface ITriggerAsyncEntityCreateProps<State, ApiInput, StateChangeNotificationKey, ApiResult, ApiResponse> extends ITriggerAsyncEntityOperationBaseProps<State, ApiInput, StateChangeNotificationKey, ApiResult, ApiResponse> {
updateDataOnSuccess?: boolean;
markAsFetchedOnSuccess?: boolean;
}
export interface ITriggerAsyncEntityUpdateProps<State, ApiInput, StateChangeNotificationKey, ApiResult, ApiResponse> extends ITriggerAsyncEntityOperationBaseProps<State, ApiInput, StateChangeNotificationKey, ApiResult, ApiResponse> {
updateDataOnSuccess?: boolean;
}
export interface ITriggerAsyncEntityRemoveProps<State, ApiInput, StateChangeNotificationKey, ApiResult, ApiResponse> extends ITriggerAsyncEntityOperationBaseProps<State, ApiInput, StateChangeNotificationKey, ApiResult, ApiResponse> {
markAsNotFetchedOnSuccess?: boolean;
}
export interface ITriggerAsyncEntityOperationBaseProps<State, ApiInput, StateChangeNotificationKey, ApiResult, ApiResponse> extends IAsyncEntityOperationHooks<State, ApiInput, ApiResult, ApiResponse>, IAsyncEntityOperationNotificationProps<StateChangeNotificationKey> {
api: (apiInput: ApiInput) => Promise<ApiResponse>;
apiInputSelector?: (props: {
state: State;
}) => ApiInput;
mapApiResponse?: (props: {
response: ApiResponse;
state: State;
}) => ApiResult;
}
export interface IAsyncEntityOperationNotificationProps<StateChangeNotificationKey> {
notificationsToTrigger?: StateChangeNotificationKey[];
nrOfParentNotificationLevelsToTrigger?: TNrOfParentNotificationLevelsToTrigger;
}
export interface IAsyncEntityOperationHooks<State, ApiInput, ApiResult, ApiResponse = ApiResult> {
onTrigger?: (props: {
state: State;
dispatch: Dispatch;
}) => void;
onPreSuccess?: (props: {
apiResponse: ApiResponse;
apiResult: ApiResult;
apiInput: ApiInput;
state: State;
dispatch: Dispatch;
}) => void;
onSuccess?: TOnAsyncEntityOperationSuccess<State, ApiInput, ApiResult, ApiResponse>;
onError?: <ApiError extends ITraceableApiErrorBase<any> = ITraceableApiErrorBase<{}>>(props: {
error: ApiError;
state: State;
dispatch: Dispatch;
}) => void;
}
export interface IShouldFetchEntityProps<State> {
shouldFetch?: (props: {
state: State;
}) => boolean;
refreshMode?: TRefreshMode<State>;
}
export interface IShouldResetEntityOnTrigger<State> {
resetDataOnTriggerMode?: TResetMode<State>;
}
export declare type TOnAsyncEntityOperationSuccess<State, ApiInput, ApiResult, ApiResponse = ApiResult> = (props: {
apiResponse: ApiResponse;
apiResult: ApiResult;
apiInput: ApiInput;
state: State;
dispatch: Dispatch;
}) => void;
export declare type TRefreshMode<State> = 'never' | 'always' | TOnlyRefreshIf<State>;
export declare type TResetMode<State> = 'never' | 'always' | TOnlyResetIf<State>;
export declare type TOnlyRefreshIf<State> = (props: {
state: State;
}) => boolean;
export declare type TOnlyResetIf<State> = (props: {
state: State;
}) => boolean;
export interface IEntitiesInitialState {
[key: string]: IAsyncEntity<any>;
}
export interface IWithKeyIndex {
[key: string]: any;
}