A functional-first collection and data modeling layer built on Drizzle ORM.
- TypeScript 5.0+
- Drizzle ORM
# Install collections
npm install @deessejs/collections
# Or using pnpm
pnpm add @deessejs/collections
# Or using yarn
yarn add @deessejs/collectionsimport { defineConfig, collection, field, f, pgAdapter } from '@deessejs/collections'
// Define collections
const users = collection({
slug: 'users',
name: 'Users',
fields: {
name: field({ fieldType: f.text() }),
email: field({ fieldType: f.email(), unique: true }),
age: field({ fieldType: f.number() })
}
})
const posts = collection({
slug: 'posts',
name: 'Posts',
fields: {
title: field({ fieldType: f.text() }),
content: field({ fieldType: f.text() }),
published: field({ fieldType: f.boolean() })
}
})
// Create configuration
const config = defineConfig({
database: pgAdapter({ url: process.env.DATABASE_URL! }),
collections: [users, posts]
})
// Access metadata
console.log(config.collections.users.slug) // 'users'
// Access Drizzle db for operations
const { db } = config- Type-safe - Full TypeScript inference for collections and operations
- Functional - Clean, composable API
- Plugin system - Extend with hooks and custom collections
- Drizzle-based - Built on top of Drizzle ORM
- Schema generation - Auto-generate Drizzle schema from collections
Collections are inferred from your configuration, providing full autocompletion for metadata:
const config = defineConfig({
database: pgAdapter({ url: process.env.DATABASE_URL! }),
collections: [users, posts]
})
// Metadata access (autocomplete)
config.collections.users.slug // 'users'
config.collections.users.fields // { name, email, ... }
config.$meta.collections // ['users', 'posts']import { f } from '@deessejs/collections'
// Primitive types
f.text() // Text/string
f.email() // Email (with validation)
f.url() // URL (with validation)
f.number() // Number
f.boolean() // Boolean
f.date() // Date
f.timestamp() // Timestamp
f.json() // JSON
// Complex types
f.select(['draft', 'published']) // Enum
f.array(f.text()) // Array
f.relation({ collection: 'users' }) // RelationsExecute custom logic at each stage of database operations:
const users = collection({
slug: 'users',
fields: {
name: field({ fieldType: f.text() }),
email: field({ fieldType: f.text() })
},
hooks: {
beforeCreate: [async (context) => {
// Validate or transform data before creating
context.data.email = context.data.email.toLowerCase()
}],
afterCreate: [async (context) => {
// Handle post-creation logic
console.log(`Created user: ${context.result.id}`)
}]
}
})| Hook | Description |
|---|---|
beforeOperation |
Runs before any operation |
afterOperation |
Runs after any operation |
beforeCreate |
Runs before create operation |
afterCreate |
Runs after create operation |
beforeUpdate |
Runs before update operation |
afterUpdate |
Runs after update operation |
beforeDelete |
Runs before delete operation |
afterDelete |
Runs after delete operation |
beforeRead |
Runs before read operation |
afterRead |
Runs after read operation |
- Collection system - Implemented
- Field types - Implemented
- Hooks - Implemented
- Plugins - Implemented
- Schema generation - Implemented
- CRUD via db - Implemented
- Full CRUD via collections.* - In progress
Contributions are welcome! Please feel free to submit a Pull Request.
- Nesalia Inc.
If you discover any security vulnerabilities, please send an e-mail to security@nesalia.com.
MIT License - see the LICENSE file for details.