drizzle-cube 0.1.1 → 0.1.2

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 +136 -51
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -54,29 +54,68 @@ export const schema = { employees, departments }
54
54
 
55
55
  ```typescript
56
56
  // cubes.ts
57
- import { defineCube, eq } from 'drizzle-cube/server'
57
+ import { defineCube } from 'drizzle-cube/server'
58
+ import { eq } from 'drizzle-orm'
58
59
  import { schema } from './schema'
59
60
 
60
- export const employeesCube = defineCube(schema, {
61
- name: 'Employees',
61
+ export const employeesCube = defineCube('Employees', {
62
+ title: 'Employee Analytics',
62
63
 
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)),
64
+ // Use Drizzle query structure for type safety
65
+ sql: (ctx) => ({
66
+ from: schema.employees,
67
+ joins: [
68
+ {
69
+ table: schema.departments,
70
+ on: eq(schema.employees.departmentId, schema.departments.id),
71
+ type: 'left'
72
+ }
73
+ ],
74
+ where: eq(schema.employees.organisationId, ctx.securityContext.organisationId)
75
+ }),
69
76
 
70
77
  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' }
78
+ name: {
79
+ name: 'name',
80
+ title: 'Employee Name',
81
+ sql: schema.employees.name,
82
+ type: 'string'
83
+ },
84
+ email: {
85
+ name: 'email',
86
+ title: 'Email Address',
87
+ sql: schema.employees.email,
88
+ type: 'string'
89
+ },
90
+ departmentName: {
91
+ name: 'departmentName',
92
+ title: 'Department',
93
+ sql: schema.departments.name,
94
+ type: 'string'
95
+ }
74
96
  },
75
97
 
76
98
  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' }
99
+ count: {
100
+ name: 'count',
101
+ title: 'Total Employees',
102
+ sql: schema.employees.id,
103
+ type: 'count'
104
+ },
105
+ totalSalary: {
106
+ name: 'totalSalary',
107
+ title: 'Total Salary',
108
+ sql: schema.employees.salary,
109
+ type: 'sum',
110
+ format: 'currency'
111
+ },
112
+ avgSalary: {
113
+ name: 'avgSalary',
114
+ title: 'Average Salary',
115
+ sql: schema.employees.salary,
116
+ type: 'avg',
117
+ format: 'currency'
118
+ }
80
119
  }
81
120
  })
82
121
  ```
@@ -89,13 +128,19 @@ import { drizzle } from 'drizzle-orm/postgres-js'
89
128
  import { createCubeApp } from 'drizzle-cube/adapters/hono'
90
129
  import { SemanticLayerCompiler } from 'drizzle-cube/server'
91
130
  import postgres from 'postgres'
131
+ import { schema } from './schema'
132
+ import { employeesCube } from './cubes'
92
133
 
93
134
  // Setup Drizzle
94
135
  const client = postgres(process.env.DATABASE_URL!)
95
136
  const db = drizzle(client, { schema })
96
137
 
97
138
  // Create semantic layer
98
- const semanticLayer = new SemanticLayerCompiler({ drizzle: db, schema })
139
+ const semanticLayer = new SemanticLayerCompiler({
140
+ drizzle: db,
141
+ schema,
142
+ engineType: 'postgres'
143
+ })
99
144
  semanticLayer.registerCube(employeesCube)
100
145
 
101
146
  // Create API server with Cube.js compatibility
@@ -161,10 +206,19 @@ const condition = eq(schema.employees.name, userInput)
161
206
  Get full TypeScript support from your database schema to your analytics:
162
207
 
163
208
  ```typescript
164
- const cube = defineCube(schema, {
209
+ const cube = defineCube('Employees', {
165
210
  dimensions: {
166
- name: { sql: schema.employees.name }, // ✅ Type-safe
167
- invalid: { sql: schema.employees.invalidCol } // ❌ TypeScript error
211
+ name: {
212
+ name: 'name',
213
+ title: 'Employee Name',
214
+ sql: schema.employees.name, // ✅ Type-safe
215
+ type: 'string'
216
+ },
217
+ invalid: {
218
+ name: 'invalid',
219
+ sql: schema.employees.invalidCol, // ❌ TypeScript error
220
+ type: 'string'
221
+ }
168
222
  }
169
223
  })
170
224
  ```
@@ -189,10 +243,13 @@ Works with multiple frameworks via adapter pattern:
189
243
  ### Complex Queries with CTEs
190
244
 
191
245
  ```typescript
192
- const advancedCube = defineCube(schema, {
193
- name: 'DepartmentAnalytics',
246
+ import { sql } from 'drizzle-orm'
247
+
248
+ const advancedCube = defineCube('DepartmentAnalytics', {
249
+ title: 'Department Analytics',
194
250
 
195
- sql: ({ db, securityContext }) => sql`
251
+ // For complex queries, you can use raw SQL
252
+ sql: (ctx) => sql`
196
253
  WITH department_stats AS (
197
254
  SELECT
198
255
  d.id,
@@ -201,19 +258,35 @@ const advancedCube = defineCube(schema, {
201
258
  AVG(e.salary) as avg_salary
202
259
  FROM ${schema.departments} d
203
260
  LEFT JOIN ${schema.employees} e ON d.id = e.department_id
204
- WHERE d.organisation_id = ${securityContext.organisationId}
261
+ WHERE d.organisation_id = ${ctx.securityContext.organisationId}
205
262
  GROUP BY d.id, d.name
206
263
  )
207
264
  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: 'Department Name',
271
+ sql: sql`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
+ employeeCount: {
278
+ name: 'employeeCount',
279
+ title: 'Employee Count',
280
+ sql: sql`employee_count`,
281
+ type: 'number'
282
+ },
283
+ avgSalary: {
284
+ name: 'avgSalary',
285
+ title: 'Average Salary',
286
+ sql: sql`avg_salary`,
287
+ type: 'number',
288
+ format: 'currency'
289
+ }
217
290
  }
218
291
  })
219
292
  ```
@@ -221,21 +294,39 @@ const advancedCube = defineCube(schema, {
221
294
  ### Advanced Security with Row-Level Security
222
295
 
223
296
  ```typescript
224
- const secureCube = defineCube(schema, {
225
- name: 'SecureEmployees',
297
+ import { and, sql } from 'drizzle-orm'
298
+
299
+ const secureCube = defineCube('SecureEmployees', {
300
+ title: 'Secure Employee Data',
226
301
 
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
- )
302
+ sql: (ctx) => ({
303
+ from: schema.employees,
304
+ where: and(
305
+ eq(schema.employees.organisationId, ctx.securityContext.organisationId),
306
+ // Only show employees user has permission to see
307
+ ctx.securityContext.role === 'admin'
308
+ ? sql`true`
309
+ : eq(schema.employees.managerId, ctx.securityContext.userId)
310
+ )
311
+ }),
312
+
313
+ dimensions: {
314
+ name: {
315
+ name: 'name',
316
+ title: 'Employee Name',
317
+ sql: schema.employees.name,
318
+ type: 'string'
319
+ }
320
+ },
321
+
322
+ measures: {
323
+ count: {
324
+ name: 'count',
325
+ title: 'Employee Count',
326
+ sql: schema.employees.id,
327
+ type: 'count'
328
+ }
329
+ }
239
330
  })
240
331
  ```
241
332
 
@@ -259,9 +350,9 @@ import Database from 'better-sqlite3'
259
350
 
260
351
  ### Core Functions
261
352
 
262
- - `defineCube(schema, definition)` - Create type-safe cube
263
- - `createSemanticLayer({ drizzle, schema })` - Setup semantic layer
264
- - `createCubeApp(options)` - Create Cube.js API server
353
+ - `defineCube(name, definition)` - Create type-safe cube with name and configuration
354
+ - `SemanticLayerCompiler({ drizzle, schema, engineType })` - Setup semantic layer compiler
355
+ - `createCubeApp(options)` - Create Cube.js-compatible API server
265
356
 
266
357
  ### Supported Drizzle Features
267
358
 
@@ -288,17 +379,11 @@ Supports all Cube.js filter operators with Drizzle safety:
288
379
 
289
380
  ## Documentation
290
381
 
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)**
382
+ Coming soon! 📚
295
383
 
296
384
  ## Examples
297
385
 
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/)**
386
+ Coming soon! Check the test files for usage patterns in the meantime.
302
387
 
303
388
  ## Contributing
304
389
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drizzle-cube",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
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",