Permix

Instance

Learn how to create a new Permix instance

Overview

Instance is the main entry point for Permix that will check permissions in every returned method. To create an instance, you need to use the createPermix function.

TypeScript

Permix is built with TypeScript, providing type safety and validation. Using TypeScript enables autocompletion and compile-time checks for your permission definitions.

/lib/permix.ts
import { createPermix } from 'permix'

const permix = createPermix<{
  post: {
    action: 'create' | 'edit'
  }
}>()

Generic type

Permix instance accepts a generic type to define permissions.

action

Union type of all actions you want to check on the entity.

/lib/permix.ts
import { createPermix } from 'permix'

const permix = createPermix<{
  post: {
    action: 'create' | 'edit'
//  ^^^^^^
  }
}>()

dataType

Not required, but recommended.

To define a type of your entities, you can pass the dataType property to a generic type. This is useful if you want to check permissions on a specific entity otherwise the type will be unknown.

/lib/permix.ts
import { createPermix } from 'permix'

interface Post {
  id: string
  author: string
  content: string
}

const permix = createPermix<{
  post: {
    dataType: Post
//  ^^^^^^^^
    action: 'create' | 'edit'
  }
}>()

permix.setup({
  post: {
    create: true,
    edit: post => post?.author === 'John Doe'
//        ^?
  }
})

const somePost: Post = {
  id: '1',
  author: 'John Doe',
  content: 'Hello World'
}

const canEdit = permix.check('post', 'edit') // false
const canEditWithPost = permix.check('post', 'edit', somePost) // true

dataRequired

Not required, defaults to false.

By default, when you define a dataType, the data parameter in permission checks is optional. You can make it required by setting dataRequired: true. This ensures that permission checks for that entity must always include the data parameter.

/lib/permix.ts
import { createPermix } from 'permix'

interface Post {
  id: string
  author: string
  content: string
}

const permix = createPermix<{
  post: {
    dataType: Post
    dataRequired: true
//  ^^^^^^^^^^^^
    action: 'create' | 'edit'
  }
}>()

permix.setup({
  post: {
    create: true,
    edit: post => post.author === 'John Doe'
//        ^?
  }
})

const somePost: Post = {
  id: '1',
  author: 'John Doe',
  content: 'Hello World'
}

// @errors: 2554
const canCreate = permix.check('post', 'create')
const canEdit = permix.check('post', 'edit', somePost) // ✅ Valid

When dataRequired is true, TypeScript will enforce that you must pass the data parameter when checking permissions for that entity. This is useful when your permission logic always depends on the entity data and you want to prevent accidental calls without the required data.

PermixDefinition

You can use PermixDefinition type to define your permissions separately from the instance.

/lib/permix.ts
import type { PermixDefinition, PermixRules } from 'permix'
import { createPermix } from 'permix'

type PermissionsDefinition = PermixDefinition<{
  post: {
    action: 'create' | 'edit'
  }
}>

async function getRules(): Promise<PermixRules<PermissionsDefinition>> {
  // get user or something like that
  return {
    post: {
      create: true,
      edit: false
    }
  }
}

const permix = createPermix<PermissionsDefinition>()

permix.setup(await getRules())

Return type

Each Permix instance provides a list of methods to manage and check permissions. These methods are documented in detail on their separate pages.

/lib/permix.ts
import { createPermix } from 'permix'

const permix = createPermix()

// @noErrors
permix.
//     ^|

JavaScript

Not using TypeScript? Permix works perfectly fine even with plain JavaScript.

/lib/permix.js
const permix = createPermix()

Initial Rules

You can provide initial rules when creating a Permix instance. This allows you to set up permissions immediately without calling setup separately.

/lib/permix.ts
import { createPermix } from 'permix'

const permix = createPermix<{
  post: {
    action: 'create' | 'edit'
  }
}>({
  post: {
    create: true,
    edit: false
  }
})

// Permissions are immediately available
console.log(permix.check('post', 'create')) // true
console.log(permix.isReady()) // true

This is equivalent to:

/lib/permix.ts
import { createPermix } from 'permix'

const permix = createPermix<{
  post: {
    action: 'create' | 'edit'
  }
}>()

permix.setup({
  post: {
    create: true,
    edit: false
  }
})

Initial rules are useful when you have permissions that are known at initialization time and don't need to be loaded asynchronously.

You still should pass generic type to createPermix even if you provide initial rules. Otherwise, Permix will not be able to validate your permissions.