Last active
May 4, 2023 09:04
-
-
Save realiarthur/a16d993ed352c7c8d2fc95deb07c0b60 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { merge as dotPropMerge, set as setPropMerge } from 'dot-prop-immutable' | |
import { CaseReducer, PayloadAction } from '@reduxjs/toolkit' | |
type PropsNames<T> = Exclude<keyof T, symbol> | |
type DotPrefix<T extends string> = T extends '' ? '' : `.${T}` | |
type RecursivePropsNames<T> = { | |
[K in PropsNames<T>]: `${K}${DotPrefix<DotNestedKeys<T[K]>>}` | `${K}` | |
}[PropsNames<T>] | |
type DotNestedKeys<T> = (T extends object ? RecursivePropsNames<T> : '') extends infer D | |
? Extract<D, string> | |
: never | |
export const merge = <S>(object: S, value: any, path?: DotNestedKeys<S>) => | |
path | |
? dotPropMerge<S, S>(object, path, value) | |
: ({ | |
...object, | |
...value, | |
} as S) | |
export const set = <S>(object: S, value: any, path?: DotNestedKeys<S>) => | |
path ? setPropMerge<S, S>(object, path, value) : (value as S) | |
// forward payload reducer | |
export function forwardSetReducer<S, P>(path?: DotNestedKeys<S>): CaseReducer<S, PayloadAction<P>> { | |
return (state, { payload }) => set(state, payload, path) | |
} | |
export function forwardMergeReducer<S, P>( | |
path?: DotNestedKeys<S>, | |
): CaseReducer<S, PayloadAction<P>> { | |
return (state, { payload }) => merge(state, payload, path) | |
} | |
// default init | |
const fetchInitMeta: FetchMeta = { | |
loading: false, | |
loaded: false, | |
error: false, | |
errorCode: undefined, | |
} | |
export function getMetaInitialState<S>(initialState: S, loading?: boolean): WithFetchMeta<S> | |
export function getMetaInitialState(): FetchMeta | |
export function getMetaInitialState( | |
initialState?: any, | |
loading = false, | |
): WithFetchMeta | FetchMeta { | |
return initialState !== undefined | |
? { | |
...fetchInitMeta, | |
data: initialState, | |
loading, | |
} | |
: { ...fetchInitMeta, loading } | |
} | |
// default start | |
export const fetchStartMeta: Partial<FetchMeta> = { | |
loading: true, | |
error: false, | |
} | |
export const startReducer: <S, P = void>( | |
path?: DotNestedKeys<S>, | |
) => CaseReducer<S, PayloadAction<P>> = path => state => merge(state, { ...fetchStartMeta }, path) | |
// default success | |
export const fetchSuccessMeta: FetchMeta = { | |
loading: false, | |
loaded: true, | |
error: false, | |
errorCode: undefined, | |
} | |
export function successReducer<S, P = void>( | |
path?: DotNestedKeys<S>, | |
): CaseReducer<S, PayloadAction<P>> { | |
return (state, { payload }) => | |
payload !== undefined | |
? set( | |
state, | |
{ | |
...fetchSuccessMeta, | |
data: payload, | |
}, | |
path, | |
) | |
: set( | |
state, | |
{ | |
...fetchSuccessMeta, | |
}, | |
path, | |
) | |
} | |
// default error | |
export const fetchErrorMeta: Partial<FetchMeta> = { | |
loading: false, | |
error: true, | |
} | |
export const errorReducer: <S>( | |
path?: DotNestedKeys<S>, | |
) => CaseReducer<S, PayloadAction<ErrorPayload>> = | |
path => | |
(state, { payload }) => | |
merge(state, { ...fetchErrorMeta, ...payload }, path) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type ErrorPayload = { | |
errorCode?: import('core/errors').ERROR_CODE | |
} | |
type FetchMeta = ErrorPayload & { | |
loading: boolean | |
loaded: boolean | |
error: boolean | |
} | |
type WithFetchMeta<TStateSlice = void> = FetchMeta & { | |
data: TStateSlice | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment