https://github.com/falcondev-oss/caps
Simple, fully type-safe library to handle permissions/access control by defining capabilities with generators.
https://github.com/falcondev-oss/caps
access-control capabilities generator permissions typescript
Last synced: 7 months ago
JSON representation
Simple, fully type-safe library to handle permissions/access control by defining capabilities with generators.
- Host: GitHub
- URL: https://github.com/falcondev-oss/caps
- Owner: falcondev-oss
- License: apache-2.0
- Created: 2024-12-14T17:32:44.000Z (over 1 year ago)
- Default Branch: master
- Last Pushed: 2025-10-01T23:36:39.000Z (9 months ago)
- Last Synced: 2025-11-09T05:03:37.429Z (7 months ago)
- Topics: access-control, capabilities, generator, permissions, typescript
- Language: TypeScript
- Homepage:
- Size: 192 KB
- Stars: 2
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# @falcondev-oss/caps
Simple, **fully type-safe** library to handle permissions/access control by defining capabilities with generators.
## Installation
```bash
npm add @falcondev-oss/caps
```
## Example
```typescript
type User = { userId: string; role: 'user' | 'moderator' | 'admin'; isBanned: boolean }
type Post = { author: User }
const useActor = createActor().build((cap) => ({
social: {
posts: cap.subject().define(
function* ({ actor, subject, args }) {
// banned users can't do anything
if (actor.isBanned || subject.author.isBanned) return []
// everyone can read posts
yield ['read']
// users can update & delete posts themselves
if (actor.userId === subject.author.userId) yield ['update', 'delete']
// admins can delete any post & ban users
if (actor.role === 'admin') {
yield ['delete', 'ban']
}
// moderators can only delete posts from users
if (actor.role === 'moderator' && subject.author.role === 'user') {
yield ['delete']
// moderators can also ban users temporarily
if (args.ban?.temporary) yield ['ban']
}
return []
},
{
ban: arg<{ temporary: boolean }>,
},
),
},
}))
const Users = {
user1: { userId: '1', role: 'user', isBanned: false },
user2: { userId: '2', role: 'user', isBanned: false },
moderator: { userId: '3', role: 'moderator', isBanned: false },
admin: { userId: '4', role: 'admin', isBanned: false },
} as const
const user = useActor(Users.user1)
user.social.posts.subject({ author: Users.user2 }).can('read').check() // => true
user.social.posts.subject({ author: Users.user1 }).can('update').check() // => true
user.social.posts.subject({ author: Users.user2 }).can('delete').check() // => false
const moderator = useActor(Users.moderator)
moderator.social.posts.subject({ author: Users.user1 }).can('delete').check() // => true
moderator.social.posts.subject({ author: Users.user1 }).can('update').check() // => false
moderator.social.posts.subject({ author: Users.user1 }).can('ban', { temporary: false }).check() // => false
moderator.social.posts.subject({ author: Users.user1 }).can('ban', { temporary: true }).check() // => true
const admin = useActor(Users.admin)
admin.social.posts.subject({ author: Users.user1 }).can('ban', { temporary: false }).check() // => true
```