36 lines
1.0 KiB
TypeScript
36 lines
1.0 KiB
TypeScript
|
import * as R from 'remeda';
|
||
|
import { DuxState, UnionToIntersection } from './types.js';
|
||
|
|
||
|
type RebaseSelectors<SLICE, DUX> = DUX extends { selectors: infer S }
|
||
|
? {
|
||
|
[key in keyof S]: RebaseSelector<SLICE, S[key]>;
|
||
|
}
|
||
|
: never;
|
||
|
|
||
|
type RebaseSelector<SLICE, S> = SLICE extends string
|
||
|
? S extends (state: infer STATE) => infer R
|
||
|
? (state: Record<SLICE, STATE>) => R
|
||
|
: never
|
||
|
: never;
|
||
|
|
||
|
type Values<X> = X[keyof X];
|
||
|
|
||
|
export type DuxSelectors<D> = (D extends { selectors: infer S } ? S : {}) &
|
||
|
(D extends { subduxes: infer SUB }
|
||
|
? Values<{
|
||
|
[key in keyof SUB]: RebaseSelectors<key, SUB[key]>;
|
||
|
}>
|
||
|
: {});
|
||
|
|
||
|
export function buildSelectors(localSelectors = {}, subduxes = {}) {
|
||
|
const subSelectors = (Object.entries(subduxes) as any).map(
|
||
|
([slice, { selectors }]) =>
|
||
|
R.mapValues(
|
||
|
selectors,
|
||
|
(subSelect) => (state) => subSelect(state[slice]),
|
||
|
),
|
||
|
);
|
||
|
|
||
|
return R.mergeAll([localSelectors, ...subSelectors]);
|
||
|
}
|