drizzle-cube 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +109 -85
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -4,6 +4,10 @@
4
4
 
5
5
  Transform your Drizzle schema into a powerful, type-safe analytics platform with SQL injection protection and full TypeScript support.
6
6
 
7
+ > **⚠️ DEVELOPMENT WARNING**
8
+ > **This project is under active development and is not yet fully functional. I will update here when we reach an alpha/working version!**
9
+ > Feel free to star ⭐ the repo to stay updated on progress.
10
+
7
11
  [![NPM Version](https://img.shields.io/npm/v/drizzle-cube)](https://www.npmjs.com/package/drizzle-cube)
8
12
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue)](https://www.typescriptlang.org/)
9
13
  [![Drizzle ORM](https://img.shields.io/badge/Drizzle%20ORM-0.33+-green)](https://orm.drizzle.team/)
@@ -54,29 +58,68 @@ export const schema = { employees, departments }
54
58
 
55
59
  ```typescript
56
60
  // cubes.ts
57
- import { defineCube, eq } from 'drizzle-cube/server'
61
+ import { defineCube } from 'drizzle-cube/server'
62
+ import { eq } from 'drizzle-orm'
58
63
  import { schema } from './schema'
59
64
 
60
- export const employeesCube = defineCube(schema, {
61
- name: 'Employees',
65
+ export const employeesCube = defineCube('Employees', {
66
+ title: 'Employee Analytics',
62
67
 
63
- // Use Drizzle query builder for type safety
64
- sql: ({ db, securityContext }) =>
65
- db.select()
66
- .from(schema.employees)
67
- .leftJoin(schema.departments, eq(schema.employees.departmentId, schema.departments.id))
68
- .where(eq(schema.employees.organisationId, securityContext.organisationId)),
68
+ // Use Drizzle query structure for type safety
69
+ sql: (ctx) => ({
70
+ from: schema.employees,
71
+ joins: [
72
+ {
73
+ table: schema.departments,
74
+ on: eq(schema.employees.departmentId, schema.departments.id),
75
+ type: 'left'
76
+ }
77
+ ],
78
+ where: eq(schema.employees.organisationId, ctx.securityContext.organisationId)
79
+ }),
69
80
 
70
81
  dimensions: {
71
- name: { sql: schema.employees.name, type: 'string' },
72
- email: { sql: schema.employees.email, type: 'string' },
73
- departmentName: { sql: schema.departments.name, type: 'string' }
82
+ name: {
83
+ name: 'name',
84
+ title: 'Employee Name',
85
+ sql: schema.employees.name,
86
+ type: 'string'
87
+ },
88
+ email: {
89
+ name: 'email',
90
+ title: 'Email Address',
91
+ sql: schema.employees.email,
92
+ type: 'string'
93
+ },
94
+ departmentName: {
95
+ name: 'departmentName',
96
+ title: 'Department',
97
+ sql: schema.departments.name,
98
+ type: 'string'
99
+ }
74
100
  },
75
101
 
76
102
  measures: {
77
- count: { sql: schema.employees.id, type: 'count' },
78
- totalSalary: { sql: schema.employees.salary, type: 'sum', format: 'currency' },
79
- avgSalary: { sql: schema.employees.salary, type: 'avg', format: 'currency' }
103
+ count: {
104
+ name: 'count',
105
+ title: 'Total Employees',
106
+ sql: schema.employees.id,
107
+ type: 'count'
108
+ },
109
+ totalSalary: {
110
+ name: 'totalSalary',
111
+ title: 'Total Salary',
112
+ sql: schema.employees.salary,
113
+ type: 'sum',
114
+ format: 'currency'
115
+ },
116
+ avgSalary: {
117
+ name: 'avgSalary',
118
+ title: 'Average Salary',
119
+ sql: schema.employees.salary,
120
+ type: 'avg',
121
+ format: 'currency'
122
+ }
80
123
  }
81
124
  })
82
125
  ```
@@ -89,13 +132,19 @@ import { drizzle } from 'drizzle-orm/postgres-js'
89
132
  import { createCubeApp } from 'drizzle-cube/adapters/hono'
90
133
  import { SemanticLayerCompiler } from 'drizzle-cube/server'
91
134
  import postgres from 'postgres'
135
+ import { schema } from './schema'
136
+ import { employeesCube } from './cubes'
92
137
 
93
138
  // Setup Drizzle
94
139
  const client = postgres(process.env.DATABASE_URL!)
95
140
  const db = drizzle(client, { schema })
96
141
 
97
142
  // Create semantic layer
98
- const semanticLayer = new SemanticLayerCompiler({ drizzle: db, schema })
143
+ const semanticLayer = new SemanticLayerCompiler({
144
+ drizzle: db,
145
+ schema,
146
+ engineType: 'postgres'
147
+ })
99
148
  semanticLayer.registerCube(employeesCube)
100
149
 
101
150
  // Create API server with Cube.js compatibility
@@ -161,10 +210,19 @@ const condition = eq(schema.employees.name, userInput)
161
210
  Get full TypeScript support from your database schema to your analytics:
162
211
 
163
212
  ```typescript
164
- const cube = defineCube(schema, {
213
+ const cube = defineCube('Employees', {
165
214
  dimensions: {
166
- name: { sql: schema.employees.name }, // ✅ Type-safe
167
- invalid: { sql: schema.employees.invalidCol } // ❌ TypeScript error
215
+ name: {
216
+ name: 'name',
217
+ title: 'Employee Name',
218
+ sql: schema.employees.name, // ✅ Type-safe
219
+ type: 'string'
220
+ },
221
+ invalid: {
222
+ name: 'invalid',
223
+ sql: schema.employees.invalidCol, // ❌ TypeScript error
224
+ type: 'string'
225
+ }
168
226
  }
169
227
  })
170
228
  ```
@@ -186,82 +244,54 @@ Works with multiple frameworks via adapter pattern:
186
244
 
187
245
  ## Advanced Usage
188
246
 
189
- ### Complex Queries with CTEs
247
+
248
+ ### Advanced Security with Row-Level Security
190
249
 
191
250
  ```typescript
192
- const advancedCube = defineCube(schema, {
193
- name: 'DepartmentAnalytics',
251
+ import { and, sql } from 'drizzle-orm'
252
+
253
+ const secureCube = defineCube('SecureEmployees', {
254
+ title: 'Secure Employee Data',
194
255
 
195
- sql: ({ db, securityContext }) => sql`
196
- WITH department_stats AS (
197
- SELECT
198
- d.id,
199
- d.name,
200
- COUNT(e.id) as employee_count,
201
- AVG(e.salary) as avg_salary
202
- FROM ${schema.departments} d
203
- LEFT JOIN ${schema.employees} e ON d.id = e.department_id
204
- WHERE d.organisation_id = ${securityContext.organisationId}
205
- GROUP BY d.id, d.name
256
+ sql: (ctx) => ({
257
+ from: schema.employees,
258
+ where: and(
259
+ eq(schema.employees.organisationId, ctx.securityContext.organisationId),
260
+ // Only show employees user has permission to see
261
+ ctx.securityContext.role === 'admin'
262
+ ? sql`true`
263
+ : eq(schema.employees.managerId, ctx.securityContext.userId)
206
264
  )
207
- SELECT * FROM department_stats
208
- `,
265
+ }),
209
266
 
210
267
  dimensions: {
211
- name: { sql: sql`name`, type: 'string' }
268
+ name: {
269
+ name: 'name',
270
+ title: 'Employee Name',
271
+ sql: schema.employees.name,
272
+ type: 'string'
273
+ }
212
274
  },
213
275
 
214
276
  measures: {
215
- employeeCount: { sql: sql`employee_count`, type: 'number' },
216
- avgSalary: { sql: sql`avg_salary`, type: 'number', format: 'currency' }
277
+ count: {
278
+ name: 'count',
279
+ title: 'Employee Count',
280
+ sql: schema.employees.id,
281
+ type: 'count'
282
+ }
217
283
  }
218
284
  })
219
285
  ```
220
286
 
221
- ### Advanced Security with Row-Level Security
222
-
223
- ```typescript
224
- const secureCube = defineCube(schema, {
225
- name: 'SecureEmployees',
226
-
227
- sql: ({ db, securityContext }) =>
228
- db.select()
229
- .from(schema.employees)
230
- .where(
231
- and(
232
- eq(schema.employees.organisationId, securityContext.organisationId),
233
- // Only show employees user has permission to see
234
- securityContext.role === 'admin'
235
- ? sql`true`
236
- : eq(schema.employees.managerId, securityContext.userId)
237
- )
238
- )
239
- })
240
- ```
241
-
242
- ### Multiple Database Support
243
-
244
- ```typescript
245
- // PostgreSQL
246
- import { drizzle } from 'drizzle-orm/postgres-js'
247
- import postgres from 'postgres'
248
-
249
- // MySQL
250
- import { drizzle } from 'drizzle-orm/mysql2'
251
- import mysql from 'mysql2/promise'
252
-
253
- // SQLite
254
- import { drizzle } from 'drizzle-orm/better-sqlite3'
255
- import Database from 'better-sqlite3'
256
- ```
257
287
 
258
288
  ## API Reference
259
289
 
260
290
  ### Core Functions
261
291
 
262
- - `defineCube(schema, definition)` - Create type-safe cube
263
- - `createSemanticLayer({ drizzle, schema })` - Setup semantic layer
264
- - `createCubeApp(options)` - Create Cube.js API server
292
+ - `defineCube(name, definition)` - Create type-safe cube with name and configuration
293
+ - `SemanticLayerCompiler({ drizzle, schema, engineType })` - Setup semantic layer compiler
294
+ - `createCubeApp(options)` - Create Cube.js-compatible API server
265
295
 
266
296
  ### Supported Drizzle Features
267
297
 
@@ -288,17 +318,11 @@ Supports all Cube.js filter operators with Drizzle safety:
288
318
 
289
319
  ## Documentation
290
320
 
291
- 📚 **[Complete Documentation](https://drizzle-cube.dev)**
292
- 🏗️ **[API Reference](https://drizzle-cube.dev/api)**
293
- 🎯 **[Drizzle Integration Guide](./docs/drizzle-integration.md)**
294
- 🚀 **[Migration Guide](https://drizzle-cube.dev/migration)**
321
+ Coming soon! 📚
295
322
 
296
323
  ## Examples
297
324
 
298
- - **[Basic Hono App](./examples/hono-basic/)**
299
- - **[Advanced Security](./examples/hono-security/)**
300
- - **[Multi-tenant SaaS](./examples/multi-tenant/)**
301
- - **[Real-time Dashboard](./examples/dashboard/)**
325
+ Coming soon! Check the test files for usage patterns in the meantime.
302
326
 
303
327
  ## Contributing
304
328
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drizzle-cube",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Drizzle ORM-first semantic layer with Cube.js compatibility. Type-safe analytics and dashboards with SQL injection protection.",
5
5
  "main": "./dist/server/index.js",
6
6
  "types": "./dist/server/index.d.ts",