UNPKG

permix

Version:

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

103 lines (102 loc) 2.66 kB
import { PermixNotFoundError, createCheckContext, createHooks, createPermix as createPermix$1, createTemplate } from "../core/index.mjs"; //#region src/node/permix.ts function buildPermix(resolveKey, options = {}) { const onForbidden = options.onForbidden ?? (({ res }) => { res.statusCode = 403; res.setHeader("Content-Type", "application/json"); res.end(JSON.stringify({ error: "Forbidden" })); }); 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, res, next) => { const instance = createPermix$1(typeof callbackOrRules === "function" ? await callbackOrRules({ req, res, next }) : callbackOrRules); instance.hook("check", (context) => hooks.callHook("check", context)); req[resolveKey()] = instance; return next(); }; } const checkMiddleware = (...args) => { return async (req, res, next) => { const permix = get(req); if (!permix) return next(new PermixNotFoundError(resolveKey())); if (!permix.check(...args)) return await onForbidden({ req, res, 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 raw Node.js HTTP servers. * * Use `.contextKey('name')` to set a custom request key (defaults to a unique * `Symbol('permix')`). * * @example * ```ts * import http from 'node:http' * import { createPermix } from 'permix/node' * * const permix = createPermix<{ * post: ['create', 'read'] * }>() * * const setupPermix = permix.setupMiddleware(({ req }) => ({ * post: { create: true, read: true }, * })) * * http.createServer(async (req, res) => { * await setupPermix(req, res, () => {}) * permix.getOrThrow(req).check('post.read') // true * res.end('ok') * }).listen(3000) * ``` * * @link https://permix.letstri.dev/docs/integrations/node */ 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 };