Permix

Setup

Learn how to setup permissions in your project

Overview

After creating Permix instance, you need to define permissions with setup method. You can call setup in any time with any permissions and Permix will replace the previous permissions.

You always should describe all permissions in the setup method that was defined in the Permix generic type.

For role separation, you can use the template method.

Object definition

const permix = createPermix<{
  post: ['create']
  comment: ['create', 'update']
}>()

permix.setup({
  post: {
    create: true,
  },
  comment: {
    create: true,
    update: true,
  }
})

You can also use enum based permissions. See Enum-based for more information.

Initial

You can set up initial rules directly when creating a Permix instance by passing them as the first parameter to createPermix.

import {  } from 'permix'

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

// The instance is immediately ready to use
.('post.create') // true

.() // true

When using initial rules, the Permix instance is immediately ready to use without calling setup first.

Type-Based

When creating a Permix instance, you can attach a type to actions that need entity data in rule callbacks. This allows you to check permissions for specific data entities. So instead of boolean you can use functions to check permissions.

import {  } from 'permix'

interface Post {
  : string
  : string
}

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

.({
  : {
    :  => .
  • authorId
  • id
} : { : comment => c
comment: any
} })

Required

By default, a type on an action makes the data argument optional in check. Set required: true to require it.

import {  } from 'permix'

interface Post {
  : string
  : string
}

interface Comment {
  : string
  : string
}

const  = <{
  : [{ : 'update', : Post, : true }]
  : [{ : 'update', : Comment }]
}>()

.({
  : {
    : post => !!.
post: Post
} : { : comment => !!.
comment: Comment | undefined
} })

unknown

If you cannot define entity types in the Permix instance, callback data is unknown by default, but you can still narrow it in the setup method.

This approach is not recommended as it reduces type safety and IDE support.

import {  } from 'permix'

const  = { : 'user-1' }

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

.({
  : {
    : (: { : string }) => . === .
  }
})

Dynamic

You can use async functions to fetch permissions from external sources and then set them up.

See the template for more examples and patterns.

import { createPermix } from 'permix'

const permix = createPermix<{
  post: ['create', 'read', 'update', 'delete']
  comment: ['create', 'read', 'update', 'delete']
}>()

// Fetch permissions from API
async function loadUserPermissions(userId: string) {
  const permissions = await getPermissionsFromAnyPlace()

  permix.setup({
    post: {
      create: permissions.includes('post:create'),
      read: permissions.includes('post:read'),
      update: permissions.includes('post:update'),
      delete: permissions.includes('post:delete'),
    },
    comment: {
      create: permissions.includes('comment:create'),
      read: permissions.includes('comment:read'),
      update: permissions.includes('comment:update'),
      delete: permissions.includes('comment:delete'),
    },
  })
}

// Usage
await loadUserPermissions('user-123')

Typed rules factory

Use createRules when rules live in a separate module but must stay aligned with your schema:

/lib/rules.ts
import { ,  } from 'permix'

type  = {
  : ['create', 'read']
}

export const  = <>({
  : {
    : true,
    : true,
  },
})

export const  = <>()

.()

Getting Rules

You can get the current rules from an existing Permix instance using the getRules method:

// Get current rules
const rules = permix.getRules()

The getRules method returns the exact rules object that was set using setup, including any permission functions.

On this page