JSPM

@noxify/casl-drizzle

0.0.1-beta.2
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 3
  • Score
    100M100P100Q32135F
  • License MIT

Drizzle-ORM adapter for CASL - generate Drizzle where inputs from CASL abilities

Package Exports

  • @noxify/casl-drizzle

Readme

work in progress :)

casl-drizzle

CASL integration for Drizzle ORM - Add type-safe authorization to your database queries

Install

npm install ucastle @casl/ability

Quick Start

Define your abilities using Drizzle's query types directly:

import type { QueryInput } from "ucastle"
import { integer, pgTable, text } from "drizzle-orm/pg-core"
import { accessibleBy, defineAbility } from "ucastle"

// Define your Drizzle schema
const users = pgTable("users", {
  id: integer().primaryKey(),
  name: text().notNull(),
  email: text().notNull(),
})

const schema = { users }

// Extract query types for your tables
type UserQuery = QueryInput<typeof schema, "users">

// Create abilities with subject-specific autocomplete
const ability = defineAbility<{ users: UserQuery }>((can, cannot) => {
  can("read", "users", { id: 1 }) // ✅ Autocomplete shows only user fields!
  can("update", "users", { id: 1 })
  cannot("delete", "users")
})

// Use with accessibleBy to get database filters
const filters = accessibleBy(ability, "read")
const readableUsers = await db.query.users.findMany({ where: filters.users })

Features

  • 🔒 Type-safe authorization - Full TypeScript support with Drizzle types
  • 🎯 CASL integration - Leverage CASL's powerful rule system
  • 🗄️ DB agnostic - Works with PostgreSQL, MySQL, SQLite, etc.
  • 🔗 Relation support - Filter by related table conditions
  • 📦 Zero overhead - Direct type composition, no runtime wrappers
  • 💡 Smart autocomplete - Subject-specific field suggestions with defineAbility()

With Relations

For schemas with relations, use RelationalQueryInput:

import type { RelationalQueryInput } from "ucastle"
import { defineRelations } from "drizzle-orm"

const posts = pgTable("posts", {
  id: integer().primaryKey(),
  title: text().notNull(),
  authorId: integer().notNull(),
})

const relations = defineRelations({ users, posts }, (r) => ({
  users: { posts: r.many(posts) },
  posts: { author: r.one(users, { fields: [posts.authorId], references: [users.id] }) },
}))

type PostQuery = RelationalQueryInput<typeof relations, "posts">

const ability = defineAbility<{ posts: PostQuery }>((can) => {
  can("read", "posts", { published: true })
  can("update", "posts", { authorId: 1 })
})

Alternative: AbilityBuilder

If you prefer the traditional AbilityBuilder pattern:

import type { DefineAbility } from "ucastle"
import { AbilityBuilder } from "@casl/ability"
import { createDrizzleAbilityFor } from "ucastle"

type AppAbility = DefineAbility<{ users: UserQuery }>

const { can, cannot, build } = new AbilityBuilder<AppAbility>(createDrizzleAbilityFor())

can("read", "users", { id: 1 })
cannot("delete", "users")

const ability = build()

Documentation

See SIMPLIFIED_API.md for detailed examples and patterns.

License

MIT