Permix

Template

Learn how to define permissions using templates

Overview

Permix provides a template method that allows you to define permissions in a separate location from where they are set up. This is useful for organizing permission definitions and reusing them across different parts of your application.

Templates are type-checked at compile time, ensuring your permission definitions match the instance definition.

Basic Usage

The simplest way to use templates is to define static permissions:

const adminPermissions = permix.template({
  post: {
    create: true,
    read: true
  }
})

// Later, use the template to setup permissions
permix.setup(adminPermissions())

Dynamic Templates

Templates can accept parameters to create dynamic permissions based on runtime values:

interface User {
  id: string
  role: string
}

const userPermissions = permix.template(({ id: userId }: User) => ({
  post: {
    create: true,
    read: true,
    update: post => post?.authorId === userId
  }
}))

// Use with specific user data
const user = await getUser()
permix.setup(userPermissions(user))

Type Safety

Templates maintain full type safety from your Permix instance definition:

import {  } from 'permix'

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

// This will cause a TypeScript error
const  = .({
  : {
    edit: true
Object literal may only specify known properties, and 'edit' does not exist in type '{ create: boolean | (() => boolean); }'.
} })

Role-Based Example

Templates are particularly useful for role-based permission systems:

const editorPermissions = permix.template({
  post: {
    create: true,
    read: true,
    update: post => !post?.published,
    delete: post => !post?.published
  }
})

const userPermissions = permix.template(({ id: userId }: User) => ({
  post: {
    create: false,
    read: true,
    update: post => post?.authorId === userId,
    delete: false
  }
}))

// Setup based on user role
async function setupPermissions() {
  const user = await getUser()
  const permissionsMap = {
    editor: () => editorPermissions(),
    user: () => userPermissions(user)
  }

  return permix.setup(permissionsMap[user.role]())
}

Standalone Templates

You can define permission templates outside of the Permix instance using the Rules type. This is useful when you want to organize your permission logic in separate files:

/lib/permix-template-standalone.ts
import type {  } from 'permix'
import {  } from 'permix'

type  = {
  : [
    { : 'create', : { : string; : string } },
    { : 'read', : { : string; : string } },
    { : 'update', : { : string; : string } },
    { : 'delete', : { : string; : string } },
  ]
}

// It can be in separate file and imported here
const  = <>()

// Create a standalone template function
function (: string, : 'admin' | 'user'): <> {
  return {
    : {
      :  === 'admin',
      : true,
      :  === 'admin' ? true : () => ?. === ,
      :  === 'admin'
    }
  }
}

// Later, use it with your Permix instance
const  = ('1', 'admin')

.()

This approach allows you to:

  • Keep permission logic separate from your Permix instance
  • Reuse permission templates across different parts of your application
  • Maintain full type safety with your Permix definition

On this page