Getting Started
Install
Section titled “Install”npm i accesscontrolAccessControl v3 is ESM and ships TypeScript types.
import { AccessControl } from 'accesscontrol';Other Runtimes
Section titled “Other Runtimes”Because v3 is pure ESM with no Node-only built-in dependencies, it runs beyond Node.js (≥ 20):
- Bun — works out of the box; install and import exactly as above:
Terminal window bun add accesscontrolimport { AccessControl } from 'accesscontrol'; - Deno — import via the
npm:specifier (no install step):or pin a version:import { AccessControl } from 'npm:accesscontrol';npm:accesscontrol@^3. If you keep an import map, add"accesscontrol": "npm:accesscontrol@^3"andimport { AccessControl } from 'accesscontrol'.
The API is identical across runtimes — only the install/import line differs.
Define Grants
Section titled “Define Grants”Create roles with grant() / deny(), chaining as you go. Roles inherit others
with extend(); grants are additive and an explicit deny always wins.
const ac = new AccessControl();
ac.grant('user') .createOwn('video') .deleteOwn('video') .readAny('video') .grant('admin') .extend('user') .updateAny('video', ['title']) // only the `title` attribute .deleteAny('video');Check Permissions
Section titled “Check Permissions”ac.can('user').createOwn('video').granted; // trueac.can('admin').updateAny('video').attributes; // ['title']Use filter() to strip a record down to the allowed attributes:
const perm = ac.can('user').readAny('video');perm.filter(videoRecord); // only the granted fieldsAdd a Condition
Section titled “Add a Condition”Constrain a grant with .where(), and supply per-check data via the context.
ac.grant('manager').where('$.order.value <= 100000').updateAny('order', ['*']);
ac.can('manager', { order: { value: 5000 } }).updateAny('order').granted; // trueEnforce Ownership
Section titled “Enforce Ownership”Tell the engine how ownership is determined and pass the record — own checks
are then enforced:
const ac = new AccessControl({}, { policy: { ownerField: 'ownerId' } });ac.grant('user').updateOwn('order', ['*']);
ac.can('user', { user: { id: 7 }, order: { ownerId: 7 } }).updateOwn('order').granted; // trueac.can('user', { user: { id: 7 }, order: { ownerId: 9 } }).updateOwn('order').granted; // falseNext Steps
Section titled “Next Steps”- Concepts (sidebar) — Conditions, Ownership, Require Gates, Groups & Categories, Events & Auditing, and more.
- Best Practices —
canvstryCan,wherevsrequire, modelling ownership, locking. - Security Considerations — what’s hardened and the choices left to you.
- What’s New in v3 · Migrating from v2 · FAQ
- API Reference (sidebar) — generated from the library’s types.