Permix

Check

Learn how to check permissions in your application

Overview

Permix provides the check method for verifying permissions. It returns a boolean indicating whether the action is allowed.

Dot paths

Check a single action using a dot-separated path:

permix.check('post.create') // returns true/false

Multiple actions

Combine multiple checks with a callback. All conditions must be truthy:

// Check if both create and read are allowed
permix.check(c => c('post.create') && c('post.read'))

All

Use the ~all special token to verify if all possible actions in a subtree are permitted:

// Check if all post actions are allowed
permix.check('post.~all')

// Check if all actions in the entire permission tree are allowed
permix.check('~all')

Any

Use the ~any special token to verify if any action in a subtree is permitted:

// Check if any post action is allowed
permix.check('post.~any')

// Check if any action in the entire permission tree is allowed
permix.check('~any')

Waiting for setup

When permissions might be set up asynchronously, wait for the instance to be ready before checking:

setTimeout(() => {
  permix.setup({
    post: { create: true }
  })
}, 1000)

await permix.isReadyAsync()
permix.check('post.create')

In most cases you should use check directly. Use isReadyAsync() when you need to ensure permissions are ready before checking, for example in route middleware.

Data-Based

You can define permissions that depend on the data being accessed:

permix.setup({
  post: {
    // Only allow updates if user is the author
    update: post => post.authorId === currentUserId,
    // Static permission
    read: true
  }
})

// Check with data
const post = { id: '1', authorId: 'user1' }

permix.check('post.update', post) // true if currentUserId === 'user1'

You can still check permissions without providing the data, but dynamic rules that require entity data will return false in that case.

Type Safety

Permix provides full type safety for your permissions:

import {  } from 'permix'

const  = <{
  : ['create', 'update']
}>()

.('post.invalid-action')
Argument of type '["post.invalid-action"]' is not assignable to parameter of type 'CheckArgs<{ post: ["create", "update"]; }>'. Type '["post.invalid-action"]' is not assignable to type '[callback: (c: CheckerFn<{ post: ["create", "update"]; }>) => boolean]'. Type 'string' is not assignable to type '(c: CheckerFn<{ post: ["create", "update"]; }>) => boolean'.
.('invalid-entity.create')
Argument of type '["invalid-entity.create"]' is not assignable to parameter of type 'CheckArgs<{ post: ["create", "update"]; }>'. Type '["invalid-entity.create"]' is not assignable to type '[callback: (c: CheckerFn<{ post: ["create", "update"]; }>) => boolean]'. Type 'string' is not assignable to type '(c: CheckerFn<{ post: ["create", "update"]; }>) => boolean'.

Invalid paths cause a TypeScript error at compile time. At runtime, checking an undefined path throws PermixRuleNotDefinedError.

Errors

Permix throws typed errors from permix when checks cannot run safely:

ErrorWhen
PermixNotReadyErrorcheck() or dehydrate() runs before any rules exist (no setup() and no initial rules).
PermixRuleNotDefinedErrorcheck() targets a path that is not present in the current rules object, or is deeper than the rules tree (for example rules { post: true } with check('post.create')).

After hydrate(), boolean rules are available immediately — check() works even while isReady() is still false. Function-based rules still need a follow-up setup() on the client. See Hydration and Ready State.

PermixNotFoundError is thrown by server integrations when middleware was not registered on the request — see Server and Node.js.

On this page