permix
Version:
Permix is a lightweight, framework-agnostic, type-safe permissions management library for JavaScript applications on the client and server sides.
94 lines (93 loc) • 2.46 kB
JavaScript
import { PermixNotFoundError, createCheckContext, createHooks, createPermix as createPermix$1, createTemplate } from "../core/index.mjs";
import { TRPCError, initTRPC } from "@trpc/server";
//#region src/trpc/permix.ts
function buildPermix(resolveKey, options = {}) {
const forbiddenHandler = options.onForbidden ?? (() => {
throw new TRPCError({
code: "FORBIDDEN",
message: "You do not have permission to perform this action"
});
});
const hooks = createHooks();
const t = initTRPC.context().create();
function setupContext(rules) {
const instance = createPermix$1(rules);
instance.hook("check", (context) => hooks.callHook("check", context));
return { [resolveKey()]: instance };
}
function checkMiddleware(...args) {
return t.middleware(async (opts) => {
const instance = opts.ctx[resolveKey()];
if (!instance) throw new PermixNotFoundError(resolveKey());
if (instance.check(...args)) return opts.next();
return forbiddenHandler({
...opts,
...createCheckContext(...args)
});
});
}
function getRules(ctx) {
return ctx[resolveKey()]?.getRules() ?? null;
}
function template(rules) {
return createTemplate(rules);
}
return {
setupContext,
checkMiddleware,
getRules,
template,
hook: hooks.hook,
hookOnce: hooks.hookOnce,
get key() {
return resolveKey();
},
$inferDefinition: void 0,
$inferPath: void 0
};
}
/**
* Create a middleware factory that wires Permix into tRPC procedures.
*
* Use `.contextKey('name')` to set a custom context key (its literal type is
* inferred automatically). Defaults to `'permix'`.
*
* @example
* ```ts
* import { initTRPC } from '@trpc/server'
* import { createPermix } from 'permix/trpc'
*
* const permix = createPermix<{
* post: ['create', 'read']
* }>()
*
* const t = initTRPC.context<Context>().create()
*
* const trpc = t.procedure
* .use(({ next }) => {
* return next({
* ctx: permix.setupContext({
* post: { create: true },
* }),
* })
* })
*
* export const router = trpc.router({
* createPost: trpc
* .use(permix.checkMiddleware('post.create'))
* .mutation(({ ctx }) => { ... }),
* })
* ```
*
* @link https://permix.letstri.dev/docs/integrations/trpc
*/
function createPermix(options = {}) {
let key = "permix";
const permix = buildPermix(() => key, options);
return Object.assign(permix, { contextKey(newKey) {
key = newKey;
return permix;
} });
}
//#endregion
export { createPermix };