UNPKG

@falcondev-oss/caps

Version:

Simple, fully type-safe library to handle permissions/access control by defining capabilities with generators.

84 lines (80 loc) 5.36 kB
import { Exact, IfEmptyObject, TaggedUnion } from 'type-fest'; interface ContextOptions { createError?: (args: { capability: string; }) => unknown; } declare function createActor<Actor extends object>(): { build<D>(builder: (cap: ReturnType<typeof createCapability<Actor>>) => D): (actor: Actor, opts?: ContextOptions) => D; }; declare function createCapability<Actor>(actor: Actor, opts?: ContextOptions): { subject: <Subject>() => { define: <const Capability extends string, Args extends {} | Exact<Partial<Record<Capability, any>>, Args> = {}, ArgsType = { [K in keyof Args]: Args[K] extends (...args: any[]) => any ? ReturnType<Args[K]> : Args[K]; }>(resolver: (ctx: { actor: Actor; subject: Subject; args: Partial<ArgsType>; }) => Generator<Capability[], Capability[], any>, args?: Args | undefined) => Omit<{ subject: (subject: Subject) => { can: <Capability_1 extends Capability>(capability: Capability_1, ...args: Capability_1 extends keyof ArgsType ? ArgsType[Capability_1] extends undefined ? [] : [args: ArgsType[Capability_1]] : []) => { throw: () => void; check: () => boolean; }; list(args: IfEmptyObject<ArgsType, void, Partial<ArgsType>>): Capability[]; }; subjects: <const S>(subjects: S[], ...args: S extends Subject ? [] : [mapper: (s: S) => Subject]) => { canSome: <Capability_1 extends Capability>(capability: Capability_1, ...args: Capability_1 extends keyof ArgsType ? ArgsType[Capability_1] extends undefined ? [] : [args: ArgsType[Capability_1]] : []) => { check: () => boolean; throw: () => boolean; }; canEvery: <Capability_1 extends Capability>(capability: Capability_1, ...args: Capability_1 extends keyof ArgsType ? ArgsType[Capability_1] extends undefined ? [] : [args: ArgsType[Capability_1]] : []) => { check: () => boolean; throw: () => void; }; filter: <const FilterCaps extends Capability>(capabilities: FilterCaps[], args: IfEmptyObject<ArgsType, void, Partial<ArgsType>>) => S[]; }; can: <Capability_1 extends Capability>(capability: Capability_1, ...args: Capability_1 extends keyof ArgsType ? ArgsType[Capability_1] extends undefined ? [] : [args: ArgsType[Capability_1]] : []) => { throw: () => void; check: () => boolean; }; list(args: IfEmptyObject<ArgsType, void, Partial<ArgsType>>): Capability[]; }, Subject extends undefined ? "subject" | "subjects" : "can">; }; define: <const Capability extends string, Args extends {} | Exact<Partial<Record<Capability, any>>, Args> = {}, ArgsType = { [K in keyof Args]: Args[K] extends (...args: any[]) => any ? ReturnType<Args[K]> : Args[K]; }>(resolver: (ctx: { actor: Actor; subject: undefined; args: Partial<ArgsType>; }) => Generator<Capability[], Capability[], any>, args?: Args | undefined) => Omit<{ subject: (subject: undefined) => { can: <Capability_1 extends Capability>(capability: Capability_1, ...args: Capability_1 extends keyof ArgsType ? ArgsType[Capability_1] extends undefined ? [] : [args: ArgsType[Capability_1]] : []) => { throw: () => void; check: () => boolean; }; list(args: IfEmptyObject<ArgsType, void, Partial<ArgsType>>): Capability[]; }; subjects: <const S>(subjects: S[], ...args: S extends undefined ? [] : [mapper: (s: S) => undefined]) => { canSome: <Capability_1 extends Capability>(capability: Capability_1, ...args: Capability_1 extends keyof ArgsType ? ArgsType[Capability_1] extends undefined ? [] : [args: ArgsType[Capability_1]] : []) => { check: () => boolean; throw: () => boolean; }; canEvery: <Capability_1 extends Capability>(capability: Capability_1, ...args: Capability_1 extends keyof ArgsType ? ArgsType[Capability_1] extends undefined ? [] : [args: ArgsType[Capability_1]] : []) => { check: () => boolean; throw: () => void; }; filter: <const FilterCaps extends Capability>(capabilities: FilterCaps[], args: IfEmptyObject<ArgsType, void, Partial<ArgsType>>) => S[]; }; can: <Capability_1 extends Capability>(capability: Capability_1, ...args: Capability_1 extends keyof ArgsType ? ArgsType[Capability_1] extends undefined ? [] : [args: ArgsType[Capability_1]] : []) => { throw: () => void; check: () => boolean; }; list(args: IfEmptyObject<ArgsType, void, Partial<ArgsType>>): Capability[]; }, "subject" | "subjects">; }; declare class MissingCapabilityError extends Error { constructor(capability: string); } declare function arg<T extends object>(): T; type Modes<T extends Record<string, Record<string, unknown>>> = TaggedUnion<'__mode', T>; declare function mode<const K extends string, T extends Record<string, unknown>>(key: K, obj: T): { __mode: K; } & T; export { type ContextOptions, MissingCapabilityError, type Modes, arg, createActor, mode };