Drizzleasy is a library to make CRUD operations and database management ridiculously easy. 100% typesafe with full LSP support in your editor due to the chainable syntax.
type TUser = { id: string; email: string; isPremium: boolean }
const read = readFn<TUser>()
const create = createFn<TUser>()
// Create new user
const { data: newUser } = await create('users')({
email: formData.get('email'),
isPremium: formData.get('premium') === 'true'
})
// Query premium users
const { data: premiumUsers } = await read('users').where({ isPremium: true })()
return { newUser, premiumUsers }- Full Documentation - Complete guides and API reference
- Quickstart - Get started in 5 minutes
- API Reference - Detailed function documentation
- FAQ - Common questions and answers
- One-liner setup -
initializeConnection(url)replaces complex Drizzle setup - Auto-detection - Reads your drizzle.config.ts automatically
- Multi-database - PostgreSQL (Neon, Vercel, Docker), SQLite, Turso
- Simple syntax - Natural operators like
age: '>18'andname: '*john*' - 100% type-safe - Full TypeScript support with IntelliSense
- Optimistic updates - Built-in React hooks for smooth UX
- Environment switching - Development/production database configs
- Connection caching - Automatic connection reuse for performance
- Dual module support - Works with both ESM and CommonJS
- Zero dependencies - Only peer dependencies for database drivers
bun add @remcostoeten/drizzleasy drizzle-orm
# Add database driver (choose one)
bun add @neondatabase/serverless # Neon PostgreSQL
bun add @libsql/client # Turso
bun add better-sqlite3 # SQLite
bun add pg # Local PostgreSQL💡 Not sure which driver? See the installation guide
Before:
import { drizzle } from 'drizzle-orm/neon-http'
import { neon } from '@neondatabase/serverless'
import * as schema from './schema'
const sql = neon(process.env.DATABASE_URL!)
export const db = drizzle(sql, { schema, logger: true })After:
import { initializeConnection } from '@remcostoeten/drizzleasy'
export const db = await initializeConnection(process.env.DATABASE_URL!)// PostgreSQL (Neon, Vercel, Supabase)
const db = await initializeConnection('postgresql://neon.tech/db')
// Local PostgreSQL (Docker)
const db = await initializeConnection('postgresql://localhost:5432/mydb')
// SQLite (Local file)
const db = await initializeConnection('file:./dev.db')
// Turso (with auth token)
const db = await initializeConnection('libsql://my-db.turso.io', {
authToken: process.env.TURSO_AUTH_TOKEN
})
// Environment switching
const db = await initializeConnection({
development: 'file:./dev.db',
production: process.env.DATABASE_URL!
})
// Multiple databases
const dbs = await initializeConnection({
main: process.env.DATABASE_URL!,
analytics: process.env.ANALYTICS_URL!,
cache: 'file:./cache.db'
})import { readFn, createFn, updateFn, destroyFn } from '@remcostoeten/drizzleasy'
type User = {
id: string
name: string
email: string
age: number
status: 'active' | 'inactive'
}
// Create factory functions
const read = readFn<User>()
const create = createFn<User>()
const update = updateFn<User>()
const destroy = destroyFn<User>()
// Read all records
const { data: users } = await read('users')()
// Read with natural WHERE syntax
const { data: activeUsers } = await read('users')
.where({ status: 'active' })
.where({ age: '>18' })
.where({ name: '*john*' })()
// Create
const { data, error } = await create('users')({
name: 'John',
email: 'john@example.com',
age: 25,
status: 'active'
})
// Update
await update('users')('user-123', { status: 'inactive' })
// Delete
await destroy('users')('user-123')// PostgreSQL (Neon, Vercel, Docker)
const db = initializeConnection('postgresql://...')
// SQLite (Local file)
const db = initializeConnection('file:./dev.db')
// Turso (with auth token)
const db = initializeConnection('libsql://...', {
authToken: process.env.TURSO_AUTH_TOKEN
})// Automatic environment detection
const db = initializeConnection({
development: 'file:./dev.db',
production: process.env.DATABASE_URL!
})
// Multiple databases
const dbs = initializeConnection({
main: process.env.DATABASE_URL!,
analytics: process.env.ANALYTICS_URL!,
cache: 'file:./cache.db'
})// Comparison
{
age: '>18'
} // Greater than
{
price: '<=100'
} // Less than or equal
{
status: '!inactive'
} // Not equal
// String patterns
{
name: '*john*'
} // Contains
{
name: 'john*'
} // Starts with
{
email: '*@gmail.com'
} // Ends with
// Arrays (IN)
{
role: ['admin', 'user']
}
// Direct equality
{
status: 'active'
}Works with both ESM and CommonJS:
// ESM (recommended)
import {
readFn,
createFn,
updateFn,
destroyFn,
initializeConnection
} from '@remcostoeten/drizzleasy'
// CommonJS
const {
readFn,
createFn,
updateFn,
destroyFn,
initializeConnection
} = require('@remcostoeten/drizzleasy')All operations return a consistent result format:
const create = createFn<User>()
const { data, error } = await create('users')({ name: 'John' })
if (error) {
console.error('Operation failed:', error.message)
return
}
console.log('Success:', data)Contributions are welcome! Please feel free to submit a Pull Request.
MIT © Remco Stoeten
