permix
Version:
Permix is a lightweight, framework-agnostic, type-safe permissions management library for JavaScript applications on the client and server sides.
104 lines (103 loc) • 2.77 kB
JavaScript
import { PermixNotFoundError, createCheckContext, createHooks, createPermix as createPermix$1, createTemplate } from "../core/index.mjs";
//#region src/server/permix.ts
function buildPermix(resolveKey, options = {}) {
const onForbidden = options.onForbidden ?? (() => new Response(JSON.stringify({ error: "Forbidden" }), {
status: 403,
headers: { "Content-Type": "application/json" }
}));
const hooks = createHooks();
function get(req) {
return req[resolveKey()] ?? null;
}
function getOrThrow(req) {
const instance = get(req);
if (!instance) throw new PermixNotFoundError(resolveKey());
return instance;
}
function setupMiddleware(callbackOrRules) {
return async (req, next) => {
const instance = createPermix$1(typeof callbackOrRules === "function" ? await callbackOrRules({
req,
next
}) : callbackOrRules);
instance.hook("check", (context) => hooks.callHook("check", context));
req[resolveKey()] = instance;
return next();
};
}
const checkMiddleware = (...args) => {
return async (req, next) => {
const permix = get(req);
if (!permix) throw new PermixNotFoundError(resolveKey());
if (!permix.check(...args)) return await onForbidden({
req,
next,
...createCheckContext(...args)
});
return next();
};
};
function getRules(req) {
return get(req)?.getRules() ?? null;
}
function template(rules) {
return createTemplate(rules);
}
return {
setupMiddleware,
checkMiddleware,
template,
get,
getOrThrow,
getRules,
hook: hooks.hook,
hookOnce: hooks.hookOnce,
get key() {
return resolveKey();
},
$inferDefinition: void 0,
$inferPath: void 0
};
}
/**
* 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
*/
function createPermix(options = {}) {
let key = Symbol("permix");
const permix = buildPermix(() => key, options);
return Object.assign(permix, { contextKey(newKey) {
key = newKey;
return permix;
} });
}
//#endregion
export { createPermix };