stalniy/casl

View on GitHub
packages/casl-ability/src/types.ts

Summary

Maintainability
A
0 mins
Test Coverage
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[]>;