permix
Version:
Permix is a lightweight, framework-agnostic, type-safe permissions management library for JavaScript applications on the client and server sides.
83 lines (82 loc) • 8.26 kB
text/typescript
import { A as Definition, C as Rules, D as Action, O as ActionName, _ as PermixHooks, g as Permix, l as CheckArgs, u as CheckContext } from "../index-BYcbfVQ7.mjs";
import { t as MaybePromise } from "../utils-ReVRszGL.mjs";
//#region src/server/permix.d.ts
type NextFunction = () => MaybePromise<Response>;
/**
* Fetch middleware compatible with [srvx](https://srvx.h3.dev/guide/middleware)
* and other web-standard server handlers.
*/
type Middleware = (req: Request, next: NextFunction) => MaybePromise<Response>;
interface MiddlewareContext {
req: Request;
next: NextFunction;
}
interface PermixOptions<D extends Definition> {
/**
* Called when a `checkMiddleware` denies the request. Defaults to a 403 JSON
* response of `{ error: 'Forbidden' }`.
*/
onForbidden?: (params: CheckContext<D> & MiddlewareContext) => MaybePromise<Response>;
}
/**
* Create a middleware factory that wires Permix into fetch-style request handlers.
*
* Middleware follows the web-standard `(req, next) => Response` pattern used by
* [srvx](https://github.com/h3js/srvx) and similar runtimes.
*
* Call `.contextKey('name')` to set a custom request key. Omit it to use a
* fresh `Symbol('permix')` as the default key.
*
* @example
* ```ts
* import { serve } from 'srvx'
* import { createPermix } from 'permix/server'
*
* const permix = createPermix<Def>()
*
* serve({
* middleware: [
* permix.setupMiddleware(({ req }) => ({
* post: { create: true, read: true, update: false, delete: false },
* })),
* ],
* fetch(req) {
* return permix.checkMiddleware('post.create')(req, () =>
* Response.json({ ok: true }),
* )
* },
* })
* ```
*
* @link https://permix.letstri.dev/docs/integrations/server
*/
declare function createPermix<D extends Definition>(options?: PermixOptions<D>): {
setupMiddleware: (callbackOrRules: Rules<D> | ((context: MiddlewareContext) => MaybePromise<Rules<D>>)) => Middleware;
checkMiddleware: (...args: CheckArgs<D>) => Middleware;
template: <T = void>(rules: Rules<D> | ((param: T) => Rules<D>)) => (param: T) => Rules<D>;
get: (req: Request) => Permix<D> | null;
getOrThrow: (req: Request) => Permix<D>;
getRules: (req: Request) => Rules<D> | null;
hook: <K extends keyof PermixHooks<D>>(name: K, fn: PermixHooks<D>[K]) => () => void;
hookOnce: <K extends keyof PermixHooks<D>>(name: K, fn: PermixHooks<D>[K]) => void;
readonly key: string | symbol;
$inferDefinition: D;
$inferPath: D extends readonly Action[] ? `${ActionName<D[number]>}` : { [K in keyof D & string]: D[K] extends Definition ? D[K] extends infer T ? T extends D[K] ? T extends readonly Action[] ? `${K}.${ActionName<T[number]>}` : { [K_2 in keyof T & string]: T[K_2] extends Definition ? T[K_2] extends infer T_1 ? T_1 extends T[K_2] ? T_1 extends readonly Action[] ? `${K}.${K_2}.${ActionName<T_1[number]>}` : { [K_3 in keyof T_1 & string]: T_1[K_3] extends Definition ? T_1[K_3] extends infer T_2 ? T_2 extends T_1[K_3] ? T_2 extends readonly Action[] ? `${K}.${K_2}.${K_3}.${ActionName<T_2[number]>}` : { [K_4 in keyof T_2 & string]: T_2[K_4] extends Definition ? T_2[K_4] extends infer T_3 ? T_3 extends T_2[K_4] ? T_3 extends readonly Action[] ? `${K}.${K_2}.${K_3}.${K_4}.${ActionName<T_3[number]>}` : { [K_5 in keyof T_3 & string]: T_3[K_5] extends Definition ? T_3[K_5] extends infer T_4 ? T_4 extends T_3[K_5] ? T_4 extends readonly Action[] ? `${K}.${K_2}.${K_3}.${K_4}.${K_5}.${ActionName<T_4[number]>}` : { [K_6 in keyof T_4 & string]: T_4[K_6] extends Definition ? T_4[K_6] extends infer T_5 ? T_5 extends T_4[K_6] ? T_5 extends readonly Action[] ? `${K}.${K_2}.${K_3}.${K_4}.${K_5}.${K_6}.${ActionName<T_5[number]>}` : { [K_7 in keyof T_5 & string]: T_5[K_7] extends Definition ? T_5[K_7] extends infer T_6 ? T_6 extends T_5[K_7] ? T_6 extends readonly Action[] ? `${K}.${K_2}.${K_3}.${K_4}.${K_5}.${K_6}.${K_7}.${ActionName<T_6[number]>}` : { [K_8 in keyof T_6 & string]: T_6[K_8] extends Definition ? T_6[K_8] extends infer T_7 ? T_7 extends T_6[K_8] ? T_7 extends readonly Action[] ? `${K}.${K_2}.${K_3}.${K_4}.${K_5}.${K_6}.${K_7}.${K_8}.${ActionName<T_7[number]>}` : { [K_9 in keyof T_7 & string]: T_7[K_9] extends Definition ? T_7[K_9] extends infer T_8 ? T_8 extends T_7[K_9] ? T_8 extends readonly Action[] ? `${K}.${K_2}.${K_3}.${K_4}.${K_5}.${K_6}.${K_7}.${K_8}.${K_9}.${ActionName<T_8[number]>}` : { [K_10 in keyof T_8 & string]: T_8[K_10] extends Definition ? never : never }[keyof T_8 & string] : never : never : never }[keyof T_7 & string] : never : never : never }[keyof T_6 & string] : never : never : never }[keyof T_5 & string] : never : never : never }[keyof T_4 & string] : never : never : never }[keyof T_3 & string] : never : never : never }[keyof T_2 & string] : never : never : never }[keyof T_1 & string] : never : never : never }[keyof T & string] : never : never : never }[keyof D & string];
} & {
contextKey(newKey: string | symbol): {
setupMiddleware: (callbackOrRules: Rules<D> | ((context: MiddlewareContext) => MaybePromise<Rules<D>>)) => Middleware;
checkMiddleware: (...args: CheckArgs<D>) => Middleware;
template: <T = void>(rules: Rules<D> | ((param: T) => Rules<D>)) => (param: T) => Rules<D>;
get: (req: Request) => Permix<D> | null;
getOrThrow: (req: Request) => Permix<D>;
getRules: (req: Request) => Rules<D> | null;
hook: <K_1 extends keyof PermixHooks<D>>(name: K_1, fn: PermixHooks<D>[K_1]) => () => void;
hookOnce: <K_1 extends keyof PermixHooks<D>>(name: K_1, fn: PermixHooks<D>[K_1]) => void;
readonly key: string | symbol;
$inferDefinition: D;
$inferPath: D extends readonly Action[] ? `${ActionName<D[number]>}` : { [K in keyof D & string]: D[K] extends Definition ? D[K] extends infer T ? T extends D[K] ? T extends readonly Action[] ? `${K}.${ActionName<T[number]>}` : { [K_2 in keyof T & string]: T[K_2] extends Definition ? T[K_2] extends infer T_1 ? T_1 extends T[K_2] ? T_1 extends readonly Action[] ? `${K}.${K_2}.${ActionName<T_1[number]>}` : { [K_3 in keyof T_1 & string]: T_1[K_3] extends Definition ? T_1[K_3] extends infer T_2 ? T_2 extends T_1[K_3] ? T_2 extends readonly Action[] ? `${K}.${K_2}.${K_3}.${ActionName<T_2[number]>}` : { [K_4 in keyof T_2 & string]: T_2[K_4] extends Definition ? T_2[K_4] extends infer T_3 ? T_3 extends T_2[K_4] ? T_3 extends readonly Action[] ? `${K}.${K_2}.${K_3}.${K_4}.${ActionName<T_3[number]>}` : { [K_5 in keyof T_3 & string]: T_3[K_5] extends Definition ? T_3[K_5] extends infer T_4 ? T_4 extends T_3[K_5] ? T_4 extends readonly Action[] ? `${K}.${K_2}.${K_3}.${K_4}.${K_5}.${ActionName<T_4[number]>}` : { [K_6 in keyof T_4 & string]: T_4[K_6] extends Definition ? T_4[K_6] extends infer T_5 ? T_5 extends T_4[K_6] ? T_5 extends readonly Action[] ? `${K}.${K_2}.${K_3}.${K_4}.${K_5}.${K_6}.${ActionName<T_5[number]>}` : { [K_7 in keyof T_5 & string]: T_5[K_7] extends Definition ? T_5[K_7] extends infer T_6 ? T_6 extends T_5[K_7] ? T_6 extends readonly Action[] ? `${K}.${K_2}.${K_3}.${K_4}.${K_5}.${K_6}.${K_7}.${ActionName<T_6[number]>}` : { [K_8 in keyof T_6 & string]: T_6[K_8] extends Definition ? T_6[K_8] extends infer T_7 ? T_7 extends T_6[K_8] ? T_7 extends readonly Action[] ? `${K}.${K_2}.${K_3}.${K_4}.${K_5}.${K_6}.${K_7}.${K_8}.${ActionName<T_7[number]>}` : { [K_9 in keyof T_7 & string]: T_7[K_9] extends Definition ? T_7[K_9] extends infer T_8 ? T_8 extends T_7[K_9] ? T_8 extends readonly Action[] ? `${K}.${K_2}.${K_3}.${K_4}.${K_5}.${K_6}.${K_7}.${K_8}.${K_9}.${ActionName<T_8[number]>}` : { [K_10 in keyof T_8 & string]: T_8[K_10] extends Definition ? never : never }[keyof T_8 & string] : never : never : never }[keyof T_7 & string] : never : never : never }[keyof T_6 & string] : never : never : never }[keyof T_5 & string] : never : never : never }[keyof T_4 & string] : never : never : never }[keyof T_3 & string] : never : never : never }[keyof T_2 & string] : never : never : never }[keyof T_1 & string] : never : never : never }[keyof T & string] : never : never : never }[keyof D & string];
};
};
type ServerPermix<D extends Definition> = ReturnType<typeof createPermix<D>>;
//#endregion
export { Middleware, MiddlewareContext, NextFunction, PermixOptions, ServerPermix, createPermix };