Quick Start
This guide will walk you through the initial steps to get up and running with Guantr in your project. Guantr provides a flexible, type-safe way to handle permissions and access control, making it a great choice for modern JavaScript and TypeScript applications.
Installation
First, you'll need to install the Guantr package. Depending on your package manager of choice, you can use one of the following commands:
# ✨ Auto-detect
npx nypm install guantr
# npm
npm install guantr
# yarn
yarn add guantr
# pnpm
pnpm install guantr
# bun
bun install guantr
This command adds Guantr to your project's dependencies.
Importing Guantr
Once installed, import the necessary functions from Guantr:
ESM (Node.js, Bun)
import { createGuantr } from "guantr";
// For defining typed rules (optional but recommended with TypeScript)
// import type { GuantrRule, GuantrMeta } from "guantr";
CommonJS (Legacy Node.js)
const { createGuantr } = require("guantr");
CDN (Deno, Bun and Browsers)
import { createGuantr } from "https://esm.sh/guantr";
Initializing Guantr
Create an instance using the createGuantr
function. createGuantr
is asynchronous as it might interact with storage or asynchronous context.
Basic Initialization
const guantr = await createGuantr();
With TypeScript (Using GuantrMeta for Type Safety)
Define your resources, actions, and context shape using GuantrMeta
for enhanced type checking when defining and checking rules.
import type { GuantrMeta, GuantrRule } from 'guantr';
// Define your application's specific actions, resources, models, and context
type MyMeta = GuantrMeta<
{ // ResourceMap
post: { action: 'read' | 'edit', model: { id: number, archived: boolean, ownerId: string } },
comment: { action: 'read' | 'create', model: { id: number, postId: number } }
},
{ // Context
userId: string | null
}
>;
const typedGuantr = await createGuantr<MyMeta>();
With Context
Provide a getContext
function during initialization if your rules need dynamic data (like the current user ID).
const contextualGuantr = await createGuantr({
// This function will be called whenever context is needed for rule evaluation
getContext: async () => {
// In a real app, fetch user data, session info, etc.
const currentUser = await getCurrentUser();
return {
userId: currentUser?.id || null
};
}
});
Setting Rules
Define permissions using the setRules
method. You can provide rules via a callback function or an array of rule objects.
Using the Callback Function
Pass an asynchronous function that receives allow
and deny
helpers.
await guantr.setRules(async (allow, deny) => {
// Allow reading any post
allow('read', 'post');
// Deny reading posts that are archived
// Conditions use the format: { field: [operator, value] }
deny('read', ['post', { archived: ['eq', true] }]);
// Example using context (if contextualGuantr was initialized with getContext)
// Allow editing a post only if the user is the owner
// allow('edit', ['post', { ownerId: ['eq', '$ctx.userId'] }]);
});
Using a Direct Array of Rule Objects
You can also pass an array of rule objects. Remember that the effect
property should be 'allow'
or 'deny'
, and conditions follow the [operator, value]
format.
import type { GuantrRule } from 'guantr'; // Or GuantrAnyRule if not using Meta
// Define types if using TypeScript without Meta for clarity in this example
type Action = 'read' | 'edit';
type ResourceKey = 'post';
type Post = { archived: boolean };
type Context = {}; // Empty if not needed for these rules
const rules: GuantrRule<{ ResourceMap: { post: { action: Action, model: Post }}, Context: Context}>[] = [
{
effect: 'allow',
action: 'read',
resource: 'post',
condition: null // No condition for general read access
},
{
effect: 'deny', // Use 'deny', not 'cannot'
action: 'read',
resource: 'post',
// Condition format: { field: [operator, value] }
condition: { archived: ['eq', true] }
}
];
await guantr.setRules(rules);
Checking Permissions
Use the can
(or cannot
) method to check if an action is permitted. Pass the specific resource object when checking rules that involve conditions.
// Check general permission to read posts
const canReadAnyPost = await guantr.can('read', 'post');
console.log('Can read any post?', canReadAnyPost); // Likely true based on rules above
// Check permission to read a specific archived post
const archivedPost = { id: 1, archived: true, ownerId: 'user-abc' };
const canReadArchived = await guantr.can('read', ['post', archivedPost]);
console.log('Can read the archived post?', canReadArchived); // Expected: false (due to the 'deny' rule)
// Check permission to read a specific non-archived post
const activePost = { id: 2, archived: false, ownerId: 'user-xyz' };
const canReadActive = await guantr.can('read', ['post', activePost]);
console.log('Can read the active post?', canReadActive); // Expected: true (allowed by general 'read', not blocked by 'deny')
Next Steps
You've now installed, initialized, set rules for, and checked permissions with Guantr! Explore further topics:
- Guides: Dive deeper into Defining Rules, Basic RBAC, and Basic ABAC.
- Advanced Usage: Learn about Caching and creating a custom Storage Adapter.
- API Reference: Consult the detailed API documentation.
- GitHub: Explore the source code and contribute.
- Discussions: Ask questions and share ideas in the community forums.
Happy coding!