UNPKG

permix

Version:

Permix is a lightweight, framework-agnostic, type-safe permissions management library for JavaScript applications on the client and server sides.

110 lines 10.2 kB
import { A as Definition, C as Rules, D as Action, O as ActionName, S as DehydratedState, _ as PermixHooks, g as Permix, l as CheckArgs, u as CheckContext } from "../index-Ck271FWs.mjs"; import { t as MaybePromise } from "../utils-ReVRszGL.mjs"; import { FunctionMiddlewareServerNextFn, FunctionServerResultWithContext, createMiddleware } from "@tanstack/react-start"; //#region src/tanstack-start/permix.d.ts export interface SetupContext { request: Request; } /** * The subset of TanStack Start's request middleware server options that * {@link createSetupHandler} needs. Kept structural so the handler stays * assignable across TanStack Start versions (peer dependency is `>=1`). */ export interface SetupHandlerContext { request: Request; next: (options: { context: Record<string | symbol, unknown>; }) => any; } export interface MiddlewareContext { next: FunctionMiddlewareServerNextFn<{}, unknown, undefined>; } export interface PermixOptions<D extends Definition> { /** * Called when a `checkMiddleware` denies the request. By default a * `PermixError` is thrown, which surfaces as a server error to the caller. * * Throw a `redirect()` / `Response`, or your own error here to customise the * behaviour. */ onForbidden?: (params: CheckContext<D> & MiddlewareContext) => MaybePromise<FunctionServerResultWithContext<any, any, any, any, any>>; } /** * Create a per-request Permix helper for TanStack Start. * * Uses TanStack Start's per-request server context to share a single Permix * instance across global middleware, server routes, server functions, and the * router for the lifetime of each request. * * Use `.contextKey('name')` to set a custom context key (defaults to * `'__permix'`). * * @example * ```ts * // lib/permix.ts * import { createPermix } from 'permix/tanstack-start' * * export const permix = createPermix<{ * post: ['create', 'read', 'update', 'delete'] * }>() * ``` * * ```ts * // src/start.ts * import { createStart } from '@tanstack/react-start' * import { getSession } from './lib/auth' * import { permix } from './lib/permix' * * export const startInstance = createStart(() => ({ * requestMiddleware: [ * permix.setupMiddleware(async ({ request }) => { * const session = await getSession(request) * return { * post: { * create: !!session, * read: true, * update: session?.role === 'admin', * delete: session?.role === 'admin', * }, * } * }), * ], * })) * ``` * * @link https://permix.letstri.dev/docs/integrations/tanstack-start */ export declare function createPermix<D extends Definition>(options?: PermixOptions<D>): { setupMiddleware: (callbackOrRules: Rules<D> | ((context: SetupContext) => MaybePromise<Rules<D>>)) => import("@tanstack/react-start").RequestMiddlewareAfterServer<{}, undefined, undefined>; createSetupHandler: (callbackOrRules: Rules<D> | ((context: SetupContext) => MaybePromise<Rules<D>>)) => ({ next, request }: SetupHandlerContext) => Promise<any>; checkMiddleware: (...args: CheckArgs<D>) => ReturnType<typeof createMiddleware>; get: (context: Record<string | symbol, unknown> | null | undefined) => Permix<D> | null; getOrThrow: (context: Record<string | symbol, unknown> | null | undefined) => Permix<D>; dehydrate: (context: Record<string | symbol, unknown> | null | undefined) => DehydratedState<D>; getRules: (context: Record<string | symbol, unknown> | null | undefined) => Rules<D> | null; template: <T = void>(rules: Rules<D> | ((param: T) => Rules<D>)) => (param: T) => Rules<D>; 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): { setupMiddleware: (callbackOrRules: Rules<D> | ((context: SetupContext) => MaybePromise<Rules<D>>)) => import("@tanstack/react-start").RequestMiddlewareAfterServer<{}, undefined, undefined>; createSetupHandler: (callbackOrRules: Rules<D> | ((context: SetupContext) => MaybePromise<Rules<D>>)) => ({ next, request }: SetupHandlerContext) => Promise<any>; checkMiddleware: (...args: CheckArgs<D>) => ReturnType<typeof createMiddleware>; get: (context: Record<string | symbol, unknown> | null | undefined) => Permix<D> | null; getOrThrow: (context: Record<string | symbol, unknown> | null | undefined) => Permix<D>; dehydrate: (context: Record<string | symbol, unknown> | null | undefined) => DehydratedState<D>; getRules: (context: Record<string | symbol, unknown> | null | undefined) => Rules<D> | null; template: <T = void>(rules: Rules<D> | ((param: T) => Rules<D>)) => (param: T) => Rules<D>; 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]; } & /*elided*/ any; }; /** Return type of {@link createPermix}. */ export type TanStackStartPermix<D extends Definition> = ReturnType<typeof createPermix<D>>; //#endregion