npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

easy-permission-engine

v1.0.0

Published

A flexible and powerful permission management engine for TypeScript with RBAC, conditional permissions, role inheritance, and policy-based access control

Readme

Permission Engine

A flexible and powerful permission management system for TypeScript applications. This engine provides comprehensive role-based access control (RBAC) with support for conditional permissions, role inheritance, and policy-based access control.

Features

  • 🔐 Role-Based Access Control (RBAC): Define roles with specific permissions
  • 🎯 Conditional Permissions: Add conditions to permissions for fine-grained control
  • 🔗 Role Inheritance: Create role hierarchies with inherited permissions
  • 📜 Policy-Based Access Control: Define complex policies with custom logic
  • Performance: Efficient permission checking with minimal overhead
  • 🛡️ Type-Safe: Full TypeScript support with comprehensive type definitions
  • 🧪 Well-Tested: Designed with testability in mind

Installation

npm install

Architecture

This package provides two versions to fit different needs:

V1: PermissionEngine (In-Memory)

Simple, fast, in-memory storage. Great for getting started or small applications.

V2: PermissionEngineV2 (Repository-Based)

Scalable, stateless, database-backed. Recommended for production.

See ARCHITECTURE.md for detailed comparison.

Quick Start (V1 - Simple)

import { PermissionEngine, Role, User } from "./src";

// Create the engine
const engine = new PermissionEngine();

// Define a role
const editorRole: Role = {
  id: "editor",
  name: "Editor",
  permissions: [
    { resource: "post", action: "create" },
    { resource: "post", action: "read" },
    { resource: "post", action: "update" },
  ],
};

// Add role to engine
engine.roles.addRole(editorRole);

// Create a user with the role
const user: User = {
  id: "user-1",
  roles: ["editor"],
};

// Add user to engine
engine.addUser(user);

// Check permissions
const canUpdate = engine.checkPermission("user-1", "post", "update");
console.log(canUpdate.granted); // true

const canDelete = engine.checkPermission("user-1", "post", "delete");
console.log(canDelete.granted); // false

Quick Start (V2 - Scalable/Production)

import {
  PermissionEngineV2,
  InMemoryUserRepository, // Replace with your DB repository
  InMemoryRoleRepository,
  InMemoryPolicyRepository,
  User,
  Role,
} from "./src";

// Create repositories (implement these with your database)
const userRepo = new InMemoryUserRepository();
const roleRepo = new InMemoryRoleRepository();
const policyRepo = new InMemoryPolicyRepository();

// Create stateless engine
const engine = new PermissionEngineV2(userRepo, roleRepo, policyRepo);

// Set up a role in your database
const editorRole: Role = {
  id: "editor",
  name: "Editor",
  permissions: [
    { resource: "post", action: "create" },
    { resource: "post", action: "update" },
  ],
};
await roleRepo.saveRole(editorRole);

// User stored in your database
const user: User = {
  id: "user-1",
  roles: ["editor"],
};
await userRepo.saveUser(user);

// Check permissions (engine fetches from DB)
const result = await engine.checkPermission("user-1", "post", "update");
console.log(result.granted); // true

// 🎯 Engine is stateless - scales horizontally!
// 💾 All data in your database, not in memory
// ⚡ Add caching layer at repository level for performance

Core Concepts

Permissions

A permission defines access to a specific action on a resource:

{
  resource: 'post',    // The resource being accessed
  action: 'update',    // The action being performed
  conditions: []       // Optional conditions
}

Roles

Roles group permissions together and can be assigned to users:

const adminRole: Role = {
  id: "admin",
  name: "Administrator",
  description: "Full system access",
  permissions: [
    { resource: "*", action: "*" }, // Wildcard for all resources and actions
  ],
};

Users

Users are assigned roles and can have direct permissions:

const user: User = {
  id: "user-1",
  roles: ["editor", "reviewer"],
  permissions: [
    // Optional direct permissions
    { resource: "settings", action: "read" },
  ],
  attributes: {
    // Optional attributes for condition evaluation
    department: "engineering",
  },
};

Policies

Policies provide fine-grained access control with custom logic:

const policy: Policy = {
  id: "business-hours-only",
  name: "Business Hours Policy",
  effect: PolicyEffect.DENY,
  resources: ["sensitive-data"],
  actions: ["read", "update"],
  conditions: [
    {
      evaluate: (context) => {
        const hour = new Date().getHours();
        return hour < 9 || hour > 17; // Outside business hours
      },
      description: "Deny access outside business hours",
    },
  ],
};

engine.policies.addPolicy(policy);

Advanced Features

Conditional Permissions

Add conditions to permissions for context-aware access control:

const authorRole: Role = {
  id: "author",
  name: "Author",
  permissions: [
    {
      resource: "post",
      action: "update",
      conditions: [
        {
          field: "postAuthorId",
          operator: ConditionOperator.EQUALS,
          value: "userId",
        },
      ],
    },
  ],
};

// Check with context
const result = engine.checkPermission("author-1", "post", "update", {
  context: {
    postAuthorId: "userId",
    userId: "author-1",
  },
});

Supported Condition Operators

  • EQUALS: Exact match
  • NOT_EQUALS: Not equal
  • IN: Value in array
  • NOT_IN: Value not in array
  • GREATER_THAN: Numeric comparison
  • LESS_THAN: Numeric comparison
  • GREATER_THAN_OR_EQUAL: Numeric comparison
  • LESS_THAN_OR_EQUAL: Numeric comparison
  • CONTAINS: String contains substring
  • NOT_CONTAINS: String doesn't contain substring
  • STARTS_WITH: String starts with
  • ENDS_WITH: String ends with
  • MATCHES: Regular expression match

Role Inheritance

Create role hierarchies where child roles inherit parent permissions:

const userRole: Role = {
  id: "user",
  name: "User",
  permissions: [
    { resource: "profile", action: "read" },
    { resource: "profile", action: "update" },
  ],
};

const moderatorRole: Role = {
  id: "moderator",
  name: "Moderator",
  permissions: [{ resource: "comment", action: "delete" }],
  inherits: ["user"], // Inherits all user permissions
};

engine.roles.addRole(userRole);
engine.roles.addRole(moderatorRole);

Multiple Permission Checks

Check multiple permissions at once:

// Check if user has ALL permissions
const hasAll = engine.checkAllPermissions("user-1", [
  { resource: "post", action: "create" },
  { resource: "post", action: "publish" },
]);

// Check if user has ANY permission
const hasAny = engine.checkAnyPermission("user-1", [
  { resource: "post", action: "delete" },
  { resource: "post", action: "publish" },
]);

Direct Permission Management

Grant or revoke permissions directly to users:

// Grant permission
engine.grantPermission("user-1", {
  resource: "admin-panel",
  action: "access",
});

// Revoke permission
engine.revokePermission("user-1", "admin-panel", "access");

API Reference

PermissionEngine

Main class for managing users, roles, and permissions.

Methods

  • addUser(user: User): void - Add a user
  • getUser(userId: string): User | undefined - Get a user
  • removeUser(userId: string): boolean - Remove a user
  • assignRole(userId: string, roleId: string): boolean - Assign role to user
  • removeRole(userId: string, roleId: string): boolean - Remove role from user
  • checkPermission(userId: string, resource: string, action: string, options?: CheckOptions): PermissionCheckResult - Check permission
  • checkAllPermissions(userId: string, checks: Array<{resource: string, action: string}>, options?: CheckOptions): PermissionCheckResult - Check multiple permissions (AND)
  • checkAnyPermission(userId: string, checks: Array<{resource: string, action: string}>, options?: CheckOptions): PermissionCheckResult - Check multiple permissions (OR)
  • grantPermission(userId: string, permission: Permission): boolean - Grant direct permission
  • revokePermission(userId: string, resource: string, action: string): boolean - Revoke direct permission

RoleManager

Accessed via engine.roles

Methods

  • addRole(role: Role): void - Add a role
  • getRole(roleId: string): Role | undefined - Get a role
  • getAllRoles(): Role[] - Get all roles
  • removeRole(roleId: string): boolean - Remove a role
  • updateRole(roleId: string, updates: Partial<Role>): boolean - Update a role
  • getRolePermissions(roleId: string): Permission[] - Get all permissions (including inherited)
  • addPermissionToRole(roleId: string, permission: Permission): boolean - Add permission to role
  • removePermissionFromRole(roleId: string, resource: string, action: string): boolean - Remove permission from role

PolicyManager

Accessed via engine.policies

Methods

  • addPolicy(policy: Policy): void - Add a policy
  • getPolicy(policyId: string): Policy | undefined - Get a policy
  • getAllPolicies(): Policy[] - Get all policies
  • removePolicy(policyId: string): boolean - Remove a policy

Examples

See the examples directory for comprehensive examples:

npm run example

Building

npm run build

The compiled JavaScript will be in the dist/ directory.

Which Version Should I Use?

Use V1 (PermissionEngine) if:

  • ✅ Getting started or prototyping
  • ✅ Small application (< 1,000 users)
  • ✅ Single server deployment
  • ✅ All permission data fits in memory
  • ✅ You want the simplest setup

Use V2 (PermissionEngineV2) if:

  • Production application (recommended)
  • ✅ Large user base (1,000s - millions)
  • ✅ Multi-server / microservices deployment
  • ✅ Need data persistence
  • ✅ Want horizontal scalability
  • ✅ Need caching strategies

See ARCHITECTURE.md and docs/DATABASE_INTEGRATION.md for details.

Use Cases

  • Web Applications: Control access to routes, API endpoints, and resources
  • Content Management Systems: Manage user roles and content permissions
  • Multi-Tenant Applications: Isolate permissions between tenants
  • API Services: Protect API endpoints with fine-grained access control
  • Admin Panels: Control access to administrative features
  • Microservices: Centralized permission service with database backend

Best Practices

  1. Use Roles for Common Permissions: Group common permissions into roles
  2. Use Policies for Complex Logic: Implement business rules with policies
  3. Use Conditions for Context-Aware Access: Add conditions when access depends on context
  4. Keep Permissions Granular: Define specific resources and actions
  5. Test Permission Logic: Thoroughly test your permission rules
  6. Document Roles and Policies: Maintain clear documentation of your access control model

License

MIT

Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.