Drizzle ORM-first semantic layer with Cube.js compatibility

Transform your Drizzle schema into a powerful, type-safe analytics platform with SQL injection protection and full TypeScript support.
π Documentation π Try the Sandbox
π SQL Injection Proof - All queries use Drizzle's parameterized SQL
π‘οΈ Type Safe - Full TypeScript inference from your database schema
β‘ Performance - Prepared statements and query optimization
π§© Cube.js Compatible - Works with existing Cube.js React components
π― Zero Config - Infer cube definitions from your Drizzle schema
npm install drizzle-cube drizzle-orm
// schema.ts
import { pgTable, text, integer, boolean } from 'drizzle-orm/pg-core'
export const employees = pgTable('employees', {
id: integer('id').primaryKey(),
name: text('name').notNull(),
email: text('email'),
active: boolean('active').default(true),
department: integer('department'),
organisation: integer('organisation').notNull()
})
export const departments = pgTable('departments', {
id: integer('id').primaryKey(),
name: text('name').notNull(),
organisation: integer('organisation').notNull()
})
export const schema = { employees, departments }
// cubes.ts
import { defineCube } from 'drizzle-cube/server'
import { eq } from 'drizzle-orm'
import { schema } from './schema'
export const employeesCube = defineCube('Employees', {
sql: (ctx) => ({
from: schema.employees,
where: eq(schema.employees.organisation, ctx.securityContext.organisationId)
}),
dimensions: {
name: {
name: 'name',
title: 'Employee Name',
type: 'string',
sql: schema.employees.name
},
email: {
name: 'email',
title: 'Email',
type: 'string',
sql: schema.employees.email
}
},
measures: {
count: {
name: 'count',
title: 'Total Employees',
type: 'count',
sql: schema.employees.id
}
}
})
// server.ts (Hono example)
import { Hono } from 'hono'
import { drizzle } from 'drizzle-orm/postgres-js'
import { createCubeApp } from 'drizzle-cube/adapters/hono'
import postgres from 'postgres'
import { schema } from './schema'
import { employeesCube } from './cubes'
const db = drizzle(postgres(process.env.DATABASE_URL!), { schema })
const app = createCubeApp({
cubes: [employeesCube],
drizzle: db,
schema,
getSecurityContext: async () => ({
organisationId: 1 // Your auth logic here
})
})
export default app
// Use built-in React components
import { QueryBuilder, AnalyticsDashboard } from 'drizzle-cube/client'
function App() {
return (
<div>
<QueryBuilder apiUrl="/cubejs-api/v1" />
<AnalyticsDashboard
config={dashboardConfig}
baseUrl="/cubejs-api/v1"
/>
</div>
)
}
π SQL Injection Proof - All queries use Drizzle's parameterized SQL
π‘οΈ Type Safe - Full TypeScript inference from your database schema
β‘ Performance - Prepared statements and query optimization
π§© Cube.js Compatible - Works with existing Cube.js React components
π― Zero Config - Infer cube definitions from your Drizzle schema
β
Multiple Database Types - PostgreSQL, MySQL
β
Framework Adapters - Hono, Express, Fastify, Next.js
β
Full Type Safety - Complete TypeScript inference
β
All SQL Features - Joins, CTEs, subqueries, window functions
β
Cube.js Compatibility - Drop-in replacement for existing apps
- π Full Documentation - Complete guides and API reference
- π Try the Sandbox - Working example version to experiment with
npm run dev
- Hono Example - Full-featured dashboard with Cloudflare Workers support
- Express Example - Simple Express.js server with React dashboard
- Fastify Example - High-performance Fastify server with React client
- Next.js Example - Full-stack Next.js app with API routes
We welcome contributions! Please see our Contributing Guide.
- π Pre-aggregations - Materialized view support
- π Real-time Updates - WebSocket support
- π Query Caching - Redis integration
MIT Β© Clifton Cunningham
Built with β€οΈ for the Drizzle ORM community