Drizzle Client
Database client for Entrolytics with Drizzle ORM
Drizzle Client
The @entro314labs/drizzle-client package provides a type-safe database client for Entrolytics built on Drizzle ORM.
Installation
pnpm add @entro314labs/drizzle-clientnpm install @entro314labs/drizzle-clientyarn add @entro314labs/drizzle-clientbun add @entro314labs/drizzle-clientQuick Start
import { createClient } from '@entro314labs/drizzle-client'
const db = createClient({
connectionString: process.env.DATABASE_URL,
})
// Query websites
const websites = await db.query.website.findMany()Configuration
import { createClient } from '@entro314labs/drizzle-client'
const db = createClient({
// Required
connectionString: process.env.DATABASE_URL,
// Optional
replicaConnectionString: process.env.DATABASE_REPLICA_URL,
type: 'neon', // 'neon' | 'pg'
maxConnections: 10,
idleTimeout: 30000,
connectionTimeout: 10000,
})Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
connectionString | string | - | Primary database connection URL (required) |
replicaConnectionString | string | - | Read replica connection URL |
type | string | 'neon' | Database type: 'neon' or 'pg' |
maxConnections | number | 10 | Maximum connection pool size |
idleTimeout | number | 30000 | Idle connection timeout (ms) |
connectionTimeout | number | 10000 | Connection timeout (ms) |
Database Schema
The client includes the complete Entrolytics schema:
Core Tables
| Table | Description |
|---|---|
user | User accounts (synced from Clerk) |
org | Organizations |
orgUser | Organization membership with roles |
website | Tracked websites |
session | Visitor sessions with device/geo data |
websiteEvent | Page views and custom events |
Feature Tables
| Table | Description |
|---|---|
board | Custom dashboards |
boardWidget | Dashboard widgets |
report | Saved reports |
segment | User segments |
link | Short links for campaigns |
pixel | Conversion tracking pixels |
revenue | Revenue tracking |
Data Tables
| Table | Description |
|---|---|
eventData | Custom event properties |
sessionData | Custom session properties |
API Reference
Client Methods
getReplica()
Get the replica client for read operations (falls back to primary if no replica).
const replica = db.getReplica()
const websites = await replica.query.website.findMany()getPrimary()
Get the primary client for write operations.
const primary = db.getPrimary()
await primary.insert(website).values({ name: 'My Site', domain: 'example.com' })execute(sql)
Execute raw SQL queries. Automatically routes SELECT to replica.
const result = await db.execute(sql`SELECT * FROM website WHERE domain = ${domain}`)transaction(callback, options?)
Execute queries in a transaction.
await db.transaction(async (tx) => {
await tx.insert(website).values({ name: 'My Site', domain: 'example.com' })
await tx.insert(orgWebsite).values({ orgId, websiteId })
}, { isolationLevel: 'read committed' })batch(queries)
Execute multiple queries in parallel.
const [users, websites, orgs] = await db.batch([
db.query.user.findMany(),
db.query.website.findMany(),
db.query.org.findMany(),
])healthCheck()
Check database connection health.
const { connected, latency } = await db.healthCheck()
console.log(`Database connected: ${connected}, latency: ${latency}ms`)close()
Close all database connections.
await db.close()Query Examples
Find Websites
import { eq, and, desc } from '@entro314labs/drizzle-client'
// Find all websites for an org
const websites = await db.query.website.findMany({
where: eq(website.orgId, orgId),
orderBy: desc(website.createdAt),
})
// Find website with related data
const site = await db.query.website.findFirst({
where: eq(website.id, websiteId),
with: {
org: true,
},
})Insert Data
import { website } from '@entro314labs/drizzle-client'
const newWebsite = await db.insert(website).values({
name: 'My Website',
domain: 'example.com',
orgId: 'org_123',
}).returning()Update Data
import { eq, website } from '@entro314labs/drizzle-client'
await db.update(website)
.set({ name: 'Updated Name' })
.where(eq(website.id, websiteId))Delete Data
import { eq, website } from '@entro314labs/drizzle-client'
await db.delete(website)
.where(eq(website.id, websiteId))Read Replicas
For high-traffic applications, use read replicas:
const db = createClient({
connectionString: process.env.DATABASE_URL,
replicaConnectionString: process.env.DATABASE_REPLICA_URL,
})
// Reads automatically go to replica
const websites = await db.query.website.findMany()
// Writes go to primary
await db.insert(website).values({ ... })Transactions
await db.transaction(async (tx) => {
// All operations in this callback are atomic
const org = await tx.insert(org).values({ name: 'New Org' }).returning()
await tx.insert(orgUser).values({
orgId: org[0].id,
userId: currentUserId,
role: 'org-owner',
})
})TypeScript Types
All schema types are exported:
import type {
User,
Org,
OrgUser,
Website,
Session,
WebsiteEvent,
Board,
BoardWidget,
Report,
Segment,
Link,
Pixel,
Revenue,
} from '@entro314labs/drizzle-client'Drizzle Operators
Re-exported for convenience:
import {
eq,
ne,
gt,
gte,
lt,
lte,
like,
ilike,
inArray,
notInArray,
isNull,
isNotNull,
and,
or,
not,
asc,
desc,
sql,
} from '@entro314labs/drizzle-client'Neon Postgres
The client is optimized for Neon serverless Postgres:
const db = createClient({
connectionString: process.env.NEON_DATABASE_URL,
type: 'neon',
})For standard PostgreSQL:
const db = createClient({
connectionString: process.env.DATABASE_URL,
type: 'pg',
})Requirements
- Node.js >= 22.x
- PostgreSQL 14+ (or Neon)
License
MIT