guantr
v2.0.0
Published
Flexible, type-safe JavaScript library for efficient authorization and permission checking
Readme
Guantr
A flexible, type-safe JavaScript library for authorization and permission checking. Define rules with a composable builder DSL, check permissions against resource instances, and leverage context-aware conditions — all with full TypeScript support.
Install
# ✨ Auto-detect
npx nypm install guantr
# npm
npm install guantr
# yarn
yarn add guantr
# pnpm
pnpm add guantr
# bun
bun install guantr
# deno
deno install npm:guantrESM (Node.js, Bun, Deno)
import { createGuantr } from 'guantr';CommonJS (Legacy Node.js)
const { createGuantr } = require('guantr');CDN (Deno and Browsers)
import { createGuantr } from 'https://esm.sh/guantr';Quick Start
import { createGuantr } from 'guantr';
import type { GuantrMeta } from 'guantr';
// 1. Define your resource map and context
type MyMeta = GuantrMeta<
{
post: {
action: 'read' | 'create' | 'update' | 'delete';
model: { id: number; title: string; published: boolean; authorId: number };
};
},
{ userId: number }
>;
// 2. Create an instance
const guantr = await createGuantr<MyMeta>({
context: () => ({ userId: 1 }),
});
// 3. Set rules with the builder DSL
await guantr.setRules((allow, deny) => {
allow('read', 'post');
deny('read', ['post', ({ eq, resource, literal }) => eq(resource('published'), literal(false))]);
allow('update', [
'post',
({ eq, resource, context }) => eq(resource('authorId'), context('userId')),
]);
});
// 4. Check permissions
const post = { id: 1, title: 'Hello', published: false, authorId: 1 };
await guantr.can.abstract('read', 'post'); // true — any allow rule exists?
await guantr.can('read', ['post', post]); // false — denied by condition
await guantr.can('update', ['post', post]); // true — author is owner
// Batch checks — context resolved once
await guantr.can.all([
['read', ['post', post]],
['update', ['post', post]],
]);Condition Builder DSL
Guantr v2 uses a type-safe builder DSL for conditions:
import type { MatchConditionFn } from 'guantr';
const condition: MatchConditionFn<Post, Context> = ({ and, eq, resource, literal }) =>
and(eq(resource('status'), literal('published')), eq(resource('deleted'), literal(false)));
// Use in rule objects or callbacks:
await guantr.setRules([
{
effect: 'allow',
action: 'read',
resource: 'post',
matchCondition: condition,
},
]);All conditions are serialized to a JSON-compatible AST at definition time, making them storable in any database.
API Overview
Permission Checks
| Method | Description |
| ----------------------------------------- | -------------------------------------------------- |
| can(action, [resourceKey, instance]) | Full evaluation against a specific instance |
| cannot(action, [resourceKey, instance]) | Negated can |
| can.abstract(action, resourceKey) | Any allow rule exists? (ignores conditions/denies) |
| cannot.abstract(action, resourceKey) | Negated can.abstract |
| can.all(checks) | All checks must pass |
| can.any(checks) | Any check must pass |
| cannot.all(checks) | All checks must be denied |
| cannot.any(checks) | Any check must be denied |
Rule Management
| Method | Description |
| ----------------------------------- | -------------------------------- |
| setRules((allow, deny) => {}) | Replace rules via callback |
| setRules([...]) | Replace rules via array |
| getRules() | Retrieve all stored rules |
| relatedRulesFor(action, resource) | Query rules by action + resource |
Storage & Context
await createGuantr<Meta>({
storage: new MyCustomStorage(), // default: InMemoryStorage
context: () => ({ userId: 1 }), // default: {}
maxRuleIterations: 500, // default: 1000
});Development
- Clone this repository
- Install latest LTS version of Node.js
- Enable Corepack using
corepack enable - Install dependencies using
pnpm install - Run playground using
pnpm play
License
Published under the MIT license. Made by community 💛
🤖 auto updated with automd
