@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
text/typescript
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 };