{"_id":"@codylabs/casl-drizzle","_rev":"3-63e00986fc0ae0454f09349c60d6f57f","name":"@codylabs/casl-drizzle","dist-tags":{"latest":"0.1.0"},"versions":{"0.0.1":{"name":"@codylabs/casl-drizzle","version":"0.0.1","author":"Cody Nguyen","license":"MIT","_id":"@codylabs/casl-drizzle@0.0.1","maintainers":[{"name":"cuongnd1705","email":"cuongnd.work@gmail.com"}],"dist":{"shasum":"5a32621133d463bc2abd433df20f268cde9b9c09","tarball":"https://registry.npmjs.org/@codylabs/casl-drizzle/-/casl-drizzle-0.0.1.tgz","fileCount":6,"integrity":"sha512-8+/GFexQNIbwsPKhn7VvJwkYnJ3BxRkeNojENeLf9L6+Ro6CAVOw0WP9upXXivb/P9r4aJUKm2E15xiU2rtfAQ==","signatures":[{"sig":"MEUCIQDpt4W/9nJCx/u/fsrIG3zuEFjeWhkxkCHkmAbwJ/2GtAIgZc/LA4cLw+1G7S8UxGrIBHSsAnU3CgccuYySqCo2bAg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":33426},"main":"./dist/index.cjs","types":"./dist/index.d.cts","module":"./dist/index.mjs","exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"scripts":{"test":"vitest run","build":"tsdown src/index.ts --format cjs,esm --dts","clean":"rm -rf .turbo node_modules dist","prebuild":"rimraf dist","test:watch":"vitest"},"_npmUser":{"name":"cuongnd1705","email":"cuongnd.work@gmail.com"},"description":"CASL integration for Drizzle ORM — define and enforce permissions using Drizzle RQB v2 where syntax.","directories":{},"_nodeVersion":"24.16.0","dependencies":{"@ucast/js":"^4.0.1","@ucast/core":"^2.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsdown":"^0.22.0","vitest":"^4.1.7","typescript":"^6.0.3","drizzle-orm":"1.0.0-rc.4-5d5b77c","@casl/ability":"^7.0.0","@codylabs/typescript-configs":"0.0.8"},"peerDependencies":{"drizzle-orm":">=1.0.0-0","@casl/ability":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/casl-drizzle_0.0.1_1779982377370_0.2231735530477299","host":"s3://npm-registry-packages-npm-production"}},"0.0.2":{"name":"@codylabs/casl-drizzle","version":"0.0.2","author":"Cody Nguyen","license":"MIT","_id":"@codylabs/casl-drizzle@0.0.2","maintainers":[{"name":"cuongnd1705","email":"cuongnd.work@gmail.com"}],"homepage":"https://github.com/cuongnd1705/codylabs#readme","bugs":{"url":"https://github.com/cuongnd1705/codylabs/issues"},"dist":{"shasum":"60f7a07d1550d7f7586b46a54f7fb00c5748ec22","tarball":"https://registry.npmjs.org/@codylabs/casl-drizzle/-/casl-drizzle-0.0.2.tgz","fileCount":6,"integrity":"sha512-QsqS1UJS+9J+YTKEzdTqIse+WaOR5r4SabmEDzj+bixgGkqBXAbFsu/Lv4CPLCOlBaRX6zkcwtTIa/spwmgutQ==","signatures":[{"sig":"MEUCIQCGw8Nu3I9LUAGtOoI0gKy4f3uTAadbuDZj/DoMGY3yOgIgKvjXZdDG4fyNWhd0z0L3JXOTpPkPQOxtzJKDuuRM4Nk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":33670},"main":"./dist/index.cjs","types":"./dist/index.d.cts","module":"./dist/index.mjs","exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"scripts":{"test":"vitest run","build":"tsdown src/index.ts --format cjs,esm --dts","clean":"rm -rf .turbo node_modules dist","prebuild":"rimraf dist","test:watch":"vitest"},"_npmUser":{"name":"cuongnd1705","email":"cuongnd.work@gmail.com"},"repository":{"url":"git+https://github.com/cuongnd1705/codylabs.git","type":"git"},"description":"CASL integration for Drizzle ORM — define and enforce permissions using Drizzle RQB v2 where syntax.","directories":{},"_nodeVersion":"24.16.0","dependencies":{"@ucast/js":"^4.0.1","@ucast/core":"^2.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsdown":"^0.22.1","vitest":"^4.1.7","typescript":"^6.0.3","drizzle-orm":"1.0.0-rc.4-5d5b77c","@casl/ability":"^7.0.0","@codylabs/typescript-configs":"0.0.9"},"peerDependencies":{"drizzle-orm":">=1.0.0-0","@casl/ability":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/casl-drizzle_0.0.2_1780126504263_0.07811757130500685","host":"s3://npm-registry-packages-npm-production"}},"0.1.0":{"_id":"@codylabs/casl-drizzle@0.1.0","bugs":{"url":"https://github.com/cuongnd1705/codylabs/issues"},"dist":{"shasum":"2e32cf2ee75804eae3382e0a9b2bdb1b369fbc92","tarball":"https://registry.npmjs.org/@codylabs/casl-drizzle/-/casl-drizzle-0.1.0.tgz","fileCount":6,"integrity":"sha512-HxnQTD+P1IqEUoJ4CVL/SLcmp/Z/imhXKHIvjfqtpH8JkOrcRyJ101vzdm0Qk5LmS8y4lg70wdcG0h/krFo94Q==","signatures":[{"sig":"MEUCIDweuITnwG8fIUeRY+OQK/JQVqTaiVSOdPopYMNeC67rAiEAkUBsfwCOsHT/rQ0HRn/Ygia6pAWrZlMDsv4zJ8mq9zY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIGu0bQ/2kegh5hu4bXGx1BxISZDGoTpgb8kHsB8fc28MAiEAhVQI762iOAr7/fwHH1HXZ/Hr/9qxxfM07H1ydzgGe9c="}],"unpackedSize":33819},"main":"./dist/index.cjs","name":"@codylabs/casl-drizzle","types":"./dist/index.d.cts","author":"Cody Nguyen","module":"./dist/index.mjs","exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"license":"MIT","scripts":{"test":"vitest run","build":"tsdown src/index.ts --format cjs,esm --dts","clean":"rm -rf .turbo node_modules dist","prebuild":"rimraf dist","test:watch":"vitest"},"version":"0.1.0","_npmUser":{"name":"cuongnd1705","email":"cuongnd.work@gmail.com"},"homepage":"https://github.com/cuongnd1705/codylabs#readme","repository":{"url":"git+https://github.com/cuongnd1705/codylabs.git","type":"git"},"description":"CASL integration for Drizzle ORM — define and enforce permissions using Drizzle RQB v2 where syntax.","directories":{},"maintainers":[{"name":"cuongnd1705","email":"cuongnd.work@gmail.com"}],"_nodeVersion":"24.20.0","dependencies":{"@ucast/js":"^4.0.1","@ucast/core":"^2.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsdown":"^0.22.14","vitest":"^4.1.11","typescript":"^6.0.3","drizzle-orm":"1.0.0-rc.4-5d5b77c","@casl/ability":"^7.0.1","@codylabs/typescript-configs":"0.1.0"},"peerDependencies":{"drizzle-orm":">=1.0.0-0","@casl/ability":"^7.0.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/casl-drizzle_0.1.0_1788017286551_0.09671130186282806"}}},"time":{"created":"2026-05-28T15:32:57.247Z","modified":"2026-08-29T15:28:06.841Z","0.0.1":"2026-05-28T15:32:57.517Z","0.0.2":"2026-05-30T07:35:04.412Z","0.1.0":"2026-08-29T15:28:06.657Z"},"bugs":{"url":"https://github.com/cuongnd1705/codylabs/issues"},"author":"Cody Nguyen","license":"MIT","homepage":"https://github.com/cuongnd1705/codylabs#readme","repository":{"url":"git+https://github.com/cuongnd1705/codylabs.git","type":"git"},"description":"CASL integration for Drizzle ORM — define and enforce permissions using Drizzle RQB v2 where syntax.","maintainers":[{"name":"cuongnd1705","email":"cuongnd.work@gmail.com"}],"readme":"# @codylabs/casl-drizzle\n\nCASL integration for [Drizzle ORM](https://orm.drizzle.team/) — define and enforce permissions using Drizzle RQB v2 where syntax.\n\nSimilar to [`@casl/prisma`](https://github.com/stalniy/casl/tree/master/packages/casl-prisma) but for Drizzle ORM v1.\n\n## Installation\n\n```bash\npnpm add @codylabs/casl-drizzle @casl/ability drizzle-orm\n```\n\n## Usage\n\n### 1. Define your types\n\n```ts\nimport type { Ability } from '@casl/ability';\nimport type { DrizzleQuery, Subjects } from '@codylabs/casl-drizzle';\n\n// Your Drizzle table select types (from $inferSelect)\ninterface User {\n  id: number;\n  name: string;\n  role: string;\n}\n\ninterface Post {\n  id: number;\n  title: string;\n  authorId: number;\n  status: string;\n  private: boolean;\n}\n\ntype AppSubjects = Subjects<{ User: User; Post: Post }>;\ntype AppAbility = Ability<\n  ['create' | 'read' | 'update' | 'delete', 'all' | AppSubjects],\n  DrizzleQuery<{ User: User; Post: Post }>\n>;\n```\n\n### 2. Create abilities\n\n```ts\nimport { createDrizzleAbility } from '@codylabs/casl-drizzle';\nimport { subject } from '@casl/ability';\n\nconst ability = createDrizzleAbility<AppAbility>([\n  { action: 'read', subject: 'Post', conditions: { status: 'published' } },\n  { action: 'read', subject: 'Post', conditions: { authorId: userId } },\n  { action: 'read', subject: 'Post', conditions: { private: true }, inverted: true },\n  { action: 'update', subject: 'Post', conditions: { authorId: userId } },\n]);\n\n// Runtime checks work\nability.can('read', subject('Post', { id: 1, title: 'Hi', authorId: userId, status: 'published', private: false })); // true\nability.can('read', subject('Post', { id: 2, title: 'Secret', authorId: 999, status: 'draft', private: true })); // false\n```\n\n### 3. Query accessible records\n\n```ts\nimport { accessibleBy } from '@codylabs/casl-drizzle';\n\n// Get the where clause for Drizzle RQB v2\nconst where = accessibleBy(ability).ofType('Post');\n\n// Use with Drizzle relational query builder v2\nconst posts = await db.query.posts.findMany({ where });\n\n// Combine with your own conditions using AND\nconst posts = await db.query.posts.findMany({\n  where: {\n    AND: [accessibleBy(ability).ofType('Post'), { status: 'published' }],\n  },\n});\n```\n\n## Supported Operators\n\nAll Drizzle RQB v2 column-level filter operators are supported:\n\n| Operator               | Description                 | Example                                         |\n| ---------------------- | --------------------------- | ----------------------------------------------- |\n| `eq` (or direct value) | Equal                       | `{ id: 1 }` or `{ id: { eq: 1 } }`              |\n| `ne`                   | Not equal                   | `{ status: { ne: 'archived' } }`                |\n| `gt`                   | Greater than                | `{ age: { gt: 18 } }`                           |\n| `gte`                  | Greater than or equal       | `{ age: { gte: 18 } }`                          |\n| `lt`                   | Less than                   | `{ age: { lt: 65 } }`                           |\n| `lte`                  | Less than or equal          | `{ age: { lte: 65 } }`                          |\n| `in`                   | Value in array              | `{ status: { in: ['draft', 'published'] } }`    |\n| `notIn`                | Value not in array          | `{ id: { notIn: [1, 2] } }`                     |\n| `like`                 | SQL LIKE (case-sensitive)   | `{ title: { like: '%hello%' } }`                |\n| `ilike`                | SQL LIKE (case-insensitive) | `{ title: { ilike: '%hello%' } }`               |\n| `notLike`              | NOT LIKE                    | `{ title: { notLike: '%draft%' } }`             |\n| `notIlike`             | NOT ILIKE                   | `{ title: { notIlike: '%draft%' } }`            |\n| `isNull`               | Is null                     | `{ deletedAt: { isNull: true } }`               |\n| `isNotNull`            | Is not null                 | `{ name: { isNotNull: true } }`                 |\n| `arrayContains`        | Array contains all values   | `{ tags: { arrayContains: ['a', 'b'] } }`       |\n| `arrayContained`       | Array contained by values   | `{ tags: { arrayContained: ['a', 'b', 'c'] } }` |\n| `arrayOverlaps`        | Arrays overlap              | `{ tags: { arrayOverlaps: ['a', 'x'] } }`       |\n\n### Logical Operators\n\n| Operator | Level         | Description                       |\n| -------- | ------------- | --------------------------------- |\n| `AND`    | Table / Field | All conditions must match         |\n| `OR`     | Table / Field | At least one condition must match |\n| `NOT`    | Table / Field | Negate the condition              |\n\n## How It Works\n\nThis package follows the same architecture as `@casl/prisma`:\n\n1. **`drizzleQuery`** — A conditions matcher that parses Drizzle RQB v2 where objects into an AST (using `@ucast/core`) and interprets them at runtime (using `@ucast/js`). This powers `ability.can()` checks in memory.\n\n2. **`accessibleBy`** — Converts CASL ability rules into Drizzle RQB v2 where objects using `rulesToCondition` from `@casl/ability/extra`. Allowed rules are OR-ed, forbidden rules are wrapped in NOT and AND-ed with each allowed branch.\n\n3. **`createDrizzleAbility`** — Factory that creates a CASL `Ability` instance pre-configured with the Drizzle conditions matcher.\n\n## Empty Conditions\n\nWhen a user has no permissions for a given action/subject, `accessibleBy(...).ofType(...)` returns `{ OR: [] }`. In Drizzle RQB v2, an empty `OR` array means no records match — so the query returns an empty result set.\n\n## License\n\nMIT\n","readmeFilename":""}