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

abilitee

v1.2.0

Published

Simple ability definition library.

Readme

Abilitee

A simple ability definition library that allows for complex rules to be expressed simply. Inspired by CanCan (which was in turn inspired by the Rub Gem with the same name).

Installation

npm install abilitee

Usage

import { Ability, Or } from "abilitee";

// --- Define types ---

class User {
  constructor(public name: string, public type: UserType = "user") {}
}

class Product {
  constructor(public seller: User, public isPublic: boolean = true) {}
}

// --- Subjects and actions that are available (for intellisense) ---

type Subjects =
  | User
  | Product
;

type Actions = "read" | "create" |  "update" | "delete";

type Scopes = "role";


// --- Ability factory function ---

const createAbilityForUser = (user: User) => {
  const ability = new Ability<Subjects, Actions, Scopes>();

  // Users can view users
  ability.allow(User, "read", User);

  // Users can only update and delete themselves
  ability.allow(User, ["update", "delete"], User, { name: user.name });
  // Note: this is equivalent to
  // ability.allow(User, ["update", "delete"], User, (performer, target) => {
  //   return performer.name === target.name;
  // });

  // Users cannot update their role
  ability.disallow(User, "update", User, "role");

  // Users can create new products
  ability.allow(User, "create", Product);

  // Users can view public products or products that they are selling
  ability.allow(
    User, 
    "read", 
    Product, 
    Or<User, Product>(
      { isPublic: true }, 
      (user, product) => user.name === product.seller.name
    )
  );

  // Users can update and delete their own products
  ability.allow(User, ["update", "delete"], Product, (user, product) => {
    return user.name === product.seller.name;
  });

  // Admin can manage everything
  if (user.type === "admin") {
    ability.allow(User, "$manage", "$all");
  }

  // Manager can manage everything with products
  if (user.type === "manager") {
    ability.allow(User, "$manage", Product);
  }

  return ability;
};


// --- Instantiate data ----

const admin = new User("Admin", "admin");
const manager = new User("Manager", "manager");
const userA = new User("A");
const userB = new User("B");

const product1 = new Product(userA);
const product2 = new Product(userB);
const product3 = new Product(userB, false);

// Ability instance specifically for each user
const adminAbility = createAbilityForUser(admin);
const managerAbility = createAbilityForUser(manager);
const userAAbility = createAbilityForUser(userA);
const userBAbility = createAbilityForUser(userB);

// --- Check some abilities ---

// User A can view any user
userAAbility.can(userA, "read", User); // => true

// User A can view user B
userAAbility.can(userA, "read", userB); // => true

// User A can update self
userAAbility.can(userA, "update", userA); // => true

// User A cannot update others
userAAbility.can(userA, "update", userB); // => true

// Throws error because a custom condition is defined
userAAbility.can(userA, "update", User) // error

// User A can view product 2, which is public
userAAbility.can(userA, "read", product2); // => true

// User A cannot view product 3 because it is private and they do not sell it
userAAbility.can(userA, "read", product3); // => false

// User B can view product 3 because they sell it
userBAbility.can(userB, "read", product3); // => false

// Admin and manager can view product 3 as well because they manage products
adminAbility.can(admin, "read", product3); // => true
managerAbility.can(manager, "read", product3) // => true

// However, only admin can delete user A
adminAbility.can(admin, "delete", userA); // => true
managerAbility.can(manager, "delete", userA) // => false

// User A tries to promote themself
userAAbility.can(userA, "update", userA, "role"); // => false

// User B tries to promote user A
userBAbility.can(userB, "update", userA, "role"); // => false

// Admin promotes user A
adminAbility.can(admin, "update", userA, "role"); // => true

API

Ability class:

  • constructor(options?)
    • options (optional):
    • allow(model, action, target, condition?): void
    • allow(model, action, target, scopes, condition?): void
      • Description: Sets up an allow relation between model, action, and target. You can think of it as "<model> can <action> <target>"
      • Parameters:
        • model: Class
        • action: string | string[]
        • target: Class
        • scope: string | string[] = "$global
        • condition: ConditionFunction or DeepPartial<target>
    • disallow(model, action, target, condition?): void
    • disallow(model, action, target, scopes, condition?): void
      • Description: Sets up a disallow relation between model, action, and target. You can think of it as "<model> cannot <action> <target>"
      • Parameters:
        • model: Class
        • action: string | string[]
        • target: Class
        • scope: string | string[] = "$global
        • condition: ConditionFunction or DeepPartial<target>
    • can(performer, action, target, scope?): boolean
      • Description: Returns true if the given relation between model, action and target is allowed.
      • Parameters:
        • performer: Class instance
        • action: string
        • target: Class or class instance
        • scope: string = "$global"
    • cannot(performer, action, target, scope?): boolean
      • Description: Returns true if the given relation between model, action and target is not allowed.
      • Parameters:
        • performer: Class instance
        • action: string
        • target: Class or class instance
        • scope: string = "$global"

Ability options:

  • instanceOf: (performer, model) => boolean: overrides the default instanceOf function used.

ConditionFunction = (performer, target) => boolean:

  • Description: a function that takes in a performer (instance of the model class) and a target (instance of the target class) and returns true if the allow passes.

Predicate Composition Functions

Or(...conditions): ConditionFunction

  • Description: returns a condition function that evaluates true if some of the given conditions return true.

And(...conditions): ConditionFunction

  • Description: returns a condition function that evaluates true if all of the given conditions return true.

Or(condition): ConditionFunction

  • Description: returns a condition function that negates the result of the given condition.