packages/casl-ability/src/types.ts
import type { Condition } from '@ucast/mongo2js';
import { Container, GenericFactory } from './hkt';
type Fn = (...args: any[]) => any;
export type AnyClass<ReturnType = any> = new (...args: any[]) => ReturnType;
type AnyRecord = Record<PropertyKey, any>;
export type AnyObject = Record<PropertyKey, unknown>;
export type SubjectClass<N extends string = string> = AnyClass & { modelName?: N };
export type SubjectType = string | SubjectClass;
export type Subject = AnyRecord | SubjectType;
export type AbilityTuple<X extends string = string, Y extends Subject = Subject> = [X, Y];
export type Abilities = AbilityTuple | string;
export type ToAbilityTypes<T extends Abilities> = T extends AbilityTuple
? AbilityTupleType<T[0], ExtractSubjectType<T[1]>>
: Extract<T, string>;
export type AbilityTupleType<
T extends string = string,
U extends SubjectType = SubjectType
> = [T, U];
export type AbilityTypes = string | AbilityTupleType;
export type Normalize<T extends Abilities> = T extends AbilityTuple ? T : [T, string];
export type IfString<T, U> = T extends string ? U : never;
export type AbilityParameters<
T extends Abilities,
TupleFunction extends Fn,
StringFunction extends Fn = () => 0,
Else = IfString<T, Parameters<StringFunction>>
> = T extends AbilityTuple ? Parameters<TupleFunction> : Else;
export type CanParameters<T extends Abilities, IncludeField extends boolean = true> =
AbilityParameters<
T,
T extends AbilityTuple
? IncludeField extends true
? (action: T[0], subject: T[1], field?: string) => 0
: (action: T[0], subject: T[1]) => 0
: never,
(action: Extract<T, string>) => 0
>;
export type ExtractSubjectType<S extends Subject> = Extract<S, SubjectType> | TagName<S>;
type SubjectClassWithCustomName<T> = AnyClass & { modelName: T };
export type InferSubjects<T, IncludeTagName extends boolean = false> =
T | (
T extends AnyClass<infer I>
? I | (
IncludeTagName extends true
? T extends SubjectClassWithCustomName<infer Name> ? Name : TagName<I>
: never
)
: TagName<T>
);
export interface ForcedSubject<T> {
readonly __caslSubjectType__: T;
}
export type TaggedInterface<T extends string> = ForcedSubject<T> |
{ readonly kind: T } |
{ readonly __typename: T };
type TagName<T> = T extends TaggedInterface<infer U> ? U : never;
interface MatchConditionsFactory extends GenericFactory<{}> {
produce: MatchConditions<this[0]>
}
export type MatchConditions<T extends {} = AnyRecord> = Container<MatchConditionsFactory> & {
(object: T): boolean
ast?: Condition
};
export type ConditionsMatcher<T> = (conditions: T) => MatchConditions;
export type MatchField<T extends string> = (field: T) => boolean;
export type FieldMatcher = <T extends string>(fields: T[]) => MatchField<T>;
export type AliasesMap = Record<string, string | string[]>;