permission-js-core
Version:
46 lines (42 loc) • 2.55 kB
TypeScript
type TupleToUnionTuple<T extends any[], R extends any[] = [], U = T[number]> = T extends [infer I, ...infer Rest] ? TupleToUnionTuple<Rest, [...R, U], U> | R : R;
type UniqueTuple<T extends any[], Seen extends any[] = []> = T extends [
infer First,
...infer Rest
] ? First extends Seen[number] ? never : UniqueTuple<Rest, [...Seen, First]> : Seen extends [infer I, ...infer Rest] ? Seen : never;
type Mode = 'some' | 'every';
type AnyRecord = Record<string, any>;
type AnyFunction = (...args: any[]) => any;
type ConvertRecordValue<T extends AnyRecord> = T[string] extends [...T[string]] ? {
[key in keyof T]: T[key];
} : {
[key in keyof T]: T[key][];
};
type Tuple = [string, ...string[]];
type BaseActions<K extends string> = Record<K, Tuple>;
type BaseConditions<K extends string> = Record<K, AnyRecord>;
type Rules<K extends string, A extends BaseActions<K>, C extends BaseConditions<K>> = {
[key in K]: {
[action in A[key][number]]: C[key] extends never ? boolean : C[key] | boolean;
};
};
type CheckPermissions<Subject extends string, Action extends BaseActions<Subject>[Subject], Conditions extends BaseConditions<Subject>, FunctionMode extends Mode = 'some'> = {
subject: Subject | UniqueTuple<Subject[]>;
action: Action[number] | UniqueTuple<TupleToUnionTuple<Action>>;
conditions?: Conditions[Subject] | ConvertRecordValue<Conditions[Subject]>;
mode?: FunctionMode;
};
type Signal = {
signal: () => void;
};
type SubscribedCheckPermissions<Subjects extends string, Action extends BaseActions<Subjects>[Subjects], Conditions extends BaseConditions<Subjects>> = CheckPermissions<Subjects, Action, Conditions> & Signal;
type SubscriberMap<S extends string, A extends string> = {
[key in S]: {
[action in A]: Set<Signal['signal']>;
};
};
declare const factoryPermission: <S extends string, A extends BaseActions<S>, C extends BaseConditions<S>>() => {
can: ({ subject, action, conditions, mode }: CheckPermissions<S, A[S], C>) => boolean;
subscribe: () => <Subjects extends S, Action extends A[Subjects]>(props: SubscribedCheckPermissions<Subjects, Action, C>) => boolean;
update: <Subject extends S>(subject: Subject, action: A[Subject][number], value: Rules<S, A, C>[Subject][A[Subject][number]]) => void;
};
export { type AnyFunction, type AnyRecord, type BaseActions, type BaseConditions, type CheckPermissions, type ConvertRecordValue, type Mode, type Rules, type Signal, type SubscribedCheckPermissions, type SubscriberMap, type Tuple, factoryPermission };