drizzle-cube 0.1.11 → 0.1.13

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.
@@ -0,0 +1,89 @@
1
+ import { Router, Request, Response, Express } from 'express';
2
+ import { CorsOptions } from 'cors';
3
+ import { SemanticQuery, SecurityContext, DatabaseExecutor, DrizzleDatabase, Cube } from '../../server';
4
+ import { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
5
+ import { MySql2Database } from 'drizzle-orm/mysql2';
6
+ import { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
7
+ export interface ExpressAdapterOptions<TSchema extends Record<string, any> = Record<string, any>> {
8
+ /**
9
+ * Array of cube definitions to register
10
+ */
11
+ cubes: Cube<TSchema>[];
12
+ /**
13
+ * Drizzle database instance (REQUIRED)
14
+ * This is the core of drizzle-cube - Drizzle ORM integration
15
+ * Accepts PostgreSQL, MySQL, or SQLite database instances
16
+ */
17
+ drizzle: PostgresJsDatabase<TSchema> | MySql2Database<TSchema> | BetterSQLite3Database<TSchema> | DrizzleDatabase<TSchema>;
18
+ /**
19
+ * Database schema for type inference (RECOMMENDED)
20
+ * Provides full type safety for cube definitions
21
+ */
22
+ schema?: TSchema;
23
+ /**
24
+ * Extract security context from incoming HTTP request.
25
+ * Called for EVERY API request to determine user permissions and multi-tenant isolation.
26
+ *
27
+ * This is your security boundary - ensure proper authentication and authorization here.
28
+ *
29
+ * @param req - Express Request object containing the incoming HTTP request
30
+ * @param res - Express Response object
31
+ * @returns Security context with organisationId, userId, roles, etc.
32
+ *
33
+ * @example
34
+ * extractSecurityContext: async (req, res) => {
35
+ * // Extract JWT from Authorization header
36
+ * const token = req.headers.authorization?.replace('Bearer ', '')
37
+ * const decoded = await verifyJWT(token)
38
+ *
39
+ * // Return context that will be available in all cube SQL functions
40
+ * return {
41
+ * organisationId: decoded.orgId,
42
+ * userId: decoded.userId,
43
+ * roles: decoded.roles
44
+ * }
45
+ * }
46
+ */
47
+ extractSecurityContext: (req: Request, res: Response) => SecurityContext | Promise<SecurityContext>;
48
+ /**
49
+ * Database engine type (optional - auto-detected if not provided)
50
+ */
51
+ engineType?: 'postgres' | 'mysql' | 'sqlite';
52
+ /**
53
+ * CORS configuration (optional)
54
+ */
55
+ cors?: CorsOptions;
56
+ /**
57
+ * API base path (default: '/cubejs-api/v1')
58
+ */
59
+ basePath?: string;
60
+ /**
61
+ * JSON body parser limit (default: '10mb')
62
+ */
63
+ jsonLimit?: string;
64
+ }
65
+ /**
66
+ * Create Express router for Cube.js-compatible API
67
+ */
68
+ export declare function createCubeRouter<TSchema extends Record<string, any> = Record<string, any>>(options: ExpressAdapterOptions<TSchema>): Router;
69
+ /**
70
+ * Convenience function to mount Cube routes on an existing Express app
71
+ */
72
+ export declare function mountCubeRoutes<TSchema extends Record<string, any> = Record<string, any>>(app: Express, options: ExpressAdapterOptions<TSchema>): Express;
73
+ /**
74
+ * Create a complete Express app with Cube.js routes
75
+ *
76
+ * @example
77
+ * const app = createCubeApp({
78
+ * cubes: [salesCube, employeesCube],
79
+ * drizzle: db,
80
+ * schema,
81
+ * extractSecurityContext: async (req, res) => {
82
+ * const token = req.headers.authorization?.replace('Bearer ', '')
83
+ * const decoded = await verifyJWT(token)
84
+ * return { organisationId: decoded.orgId, userId: decoded.userId }
85
+ * }
86
+ * })
87
+ */
88
+ export declare function createCubeApp<TSchema extends Record<string, any> = Record<string, any>>(options: ExpressAdapterOptions<TSchema>): Express;
89
+ export type { SecurityContext, DatabaseExecutor, SemanticQuery, DrizzleDatabase, CorsOptions };
@@ -0,0 +1,177 @@
1
+ import g, { Router as $ } from "express";
2
+ import E from "cors";
3
+ import { S as R, c as a, f as v, a as L, b as x, h as C } from "../utils-C3A4JGFs.js";
4
+ function N(y) {
5
+ const {
6
+ cubes: c,
7
+ drizzle: p,
8
+ schema: w,
9
+ extractSecurityContext: d,
10
+ engineType: Q,
11
+ cors: h,
12
+ basePath: l = "/cubejs-api/v1",
13
+ jsonLimit: q = "10mb"
14
+ } = y;
15
+ if (!c || c.length === 0)
16
+ throw new Error("At least one cube must be provided in the cubes array");
17
+ const u = $();
18
+ h && u.use(E(h)), u.use(g.json({ limit: q })), u.use(g.urlencoded({ extended: !0, limit: q }));
19
+ const n = new R({
20
+ drizzle: p,
21
+ schema: w,
22
+ engineType: Q
23
+ });
24
+ return c.forEach((t) => {
25
+ n.registerCube(t);
26
+ }), console.log(`🚀 Drizzle Cube: Registered ${c.length} cube(s) with ${Q || "auto-detected"} engine`), u.post(`${l}/load`, async (t, r) => {
27
+ try {
28
+ const e = t.body.query || t.body, s = await d(t, r), o = n.validateQuery(e);
29
+ if (!o.isValid)
30
+ return r.status(400).json(a(
31
+ `Query validation failed: ${o.errors.join(", ")}`,
32
+ 400
33
+ ));
34
+ const i = await n.executeMultiCubeQuery(e, s);
35
+ r.json(v(e, i, n));
36
+ } catch (e) {
37
+ console.error("Query execution error:", e), r.status(500).json(a(
38
+ e instanceof Error ? e.message : "Query execution failed",
39
+ 500
40
+ ));
41
+ }
42
+ }), u.get(`${l}/load`, async (t, r) => {
43
+ try {
44
+ const e = t.query.query;
45
+ if (!e)
46
+ return r.status(400).json(a(
47
+ "Query parameter is required",
48
+ 400
49
+ ));
50
+ let s;
51
+ try {
52
+ s = JSON.parse(e);
53
+ } catch {
54
+ return r.status(400).json(a(
55
+ "Invalid JSON in query parameter",
56
+ 400
57
+ ));
58
+ }
59
+ const o = await d(t, r), i = n.validateQuery(s);
60
+ if (!i.isValid)
61
+ return r.status(400).json(a(
62
+ `Query validation failed: ${i.errors.join(", ")}`,
63
+ 400
64
+ ));
65
+ const f = await n.executeMultiCubeQuery(s, o);
66
+ r.json(v(s, f, n));
67
+ } catch (e) {
68
+ console.error("Query execution error:", e), r.status(500).json(a(
69
+ e instanceof Error ? e.message : "Query execution failed",
70
+ 500
71
+ ));
72
+ }
73
+ }), u.get(`${l}/meta`, (t, r) => {
74
+ try {
75
+ const e = n.getMetadata();
76
+ r.json(L(e));
77
+ } catch (e) {
78
+ console.error("Metadata error:", e), r.status(500).json(a(
79
+ e instanceof Error ? e.message : "Failed to fetch metadata",
80
+ 500
81
+ ));
82
+ }
83
+ }), u.post(`${l}/sql`, async (t, r) => {
84
+ var e, s;
85
+ try {
86
+ const o = t.body, i = await d(t, r), f = n.validateQuery(o);
87
+ if (!f.isValid)
88
+ return r.status(400).json(a(
89
+ `Query validation failed: ${f.errors.join(", ")}`,
90
+ 400
91
+ ));
92
+ const m = ((e = o.measures) == null ? void 0 : e[0]) || ((s = o.dimensions) == null ? void 0 : s[0]);
93
+ if (!m)
94
+ return r.status(400).json(a(
95
+ "No measures or dimensions specified",
96
+ 400
97
+ ));
98
+ const j = m.split(".")[0], b = await n.generateSQL(j, o, i);
99
+ r.json(x(o, b));
100
+ } catch (o) {
101
+ console.error("SQL generation error:", o), r.status(500).json(a(
102
+ o instanceof Error ? o.message : "SQL generation failed",
103
+ 500
104
+ ));
105
+ }
106
+ }), u.get(`${l}/sql`, async (t, r) => {
107
+ var e, s;
108
+ try {
109
+ const o = t.query.query;
110
+ if (!o)
111
+ return r.status(400).json(a(
112
+ "Query parameter is required",
113
+ 400
114
+ ));
115
+ const i = JSON.parse(o), f = await d(t, r), m = n.validateQuery(i);
116
+ if (!m.isValid)
117
+ return r.status(400).json(a(
118
+ `Query validation failed: ${m.errors.join(", ")}`,
119
+ 400
120
+ ));
121
+ const j = ((e = i.measures) == null ? void 0 : e[0]) || ((s = i.dimensions) == null ? void 0 : s[0]);
122
+ if (!j)
123
+ return r.status(400).json(a(
124
+ "No measures or dimensions specified",
125
+ 400
126
+ ));
127
+ const b = j.split(".")[0], S = await n.generateSQL(b, i, f);
128
+ r.json(x(i, S));
129
+ } catch (o) {
130
+ console.error("SQL generation error:", o), r.status(500).json(a(
131
+ o instanceof Error ? o.message : "SQL generation failed",
132
+ 500
133
+ ));
134
+ }
135
+ }), u.post(`${l}/dry-run`, async (t, r) => {
136
+ try {
137
+ const e = t.body.query || t.body, s = await d(t, r), o = await C(e, s, n);
138
+ r.json(o);
139
+ } catch (e) {
140
+ console.error("Dry-run error:", e), r.status(400).json({
141
+ error: e instanceof Error ? e.message : "Dry-run validation failed",
142
+ valid: !1
143
+ });
144
+ }
145
+ }), u.get(`${l}/dry-run`, async (t, r) => {
146
+ try {
147
+ const e = t.query.query;
148
+ if (!e)
149
+ return r.status(400).json({
150
+ error: "Query parameter is required",
151
+ valid: !1
152
+ });
153
+ const s = JSON.parse(e), o = await d(t, r), i = await C(s, o, n);
154
+ r.json(i);
155
+ } catch (e) {
156
+ console.error("Dry-run error:", e), r.status(400).json({
157
+ error: e instanceof Error ? e.message : "Dry-run validation failed",
158
+ valid: !1
159
+ });
160
+ }
161
+ }), u.use((t, r, e, s) => {
162
+ console.error("Express adapter error:", t), e.headersSent || e.status(500).json(a(t, 500));
163
+ }), u;
164
+ }
165
+ function M(y, c) {
166
+ const p = N(c);
167
+ return y.use("/", p), y;
168
+ }
169
+ function O(y) {
170
+ const c = g();
171
+ return M(c, y);
172
+ }
173
+ export {
174
+ O as createCubeApp,
175
+ N as createCubeRouter,
176
+ M as mountCubeRoutes
177
+ };
@@ -0,0 +1,88 @@
1
+ import { FastifyPluginCallback, FastifyRequest, FastifyInstance } from 'fastify';
2
+ import { FastifyCorsOptions } from '@fastify/cors';
3
+ import { SemanticQuery, SecurityContext, DatabaseExecutor, DrizzleDatabase, Cube } from '../../server';
4
+ import { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
5
+ import { MySql2Database } from 'drizzle-orm/mysql2';
6
+ import { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
7
+ export interface FastifyAdapterOptions<TSchema extends Record<string, any> = Record<string, any>> {
8
+ /**
9
+ * Array of cube definitions to register
10
+ */
11
+ cubes: Cube<TSchema>[];
12
+ /**
13
+ * Drizzle database instance (REQUIRED)
14
+ * This is the core of drizzle-cube - Drizzle ORM integration
15
+ * Accepts PostgreSQL, MySQL, or SQLite database instances
16
+ */
17
+ drizzle: PostgresJsDatabase<TSchema> | MySql2Database<TSchema> | BetterSQLite3Database<TSchema> | DrizzleDatabase<TSchema>;
18
+ /**
19
+ * Database schema for type inference (RECOMMENDED)
20
+ * Provides full type safety for cube definitions
21
+ */
22
+ schema?: TSchema;
23
+ /**
24
+ * Extract security context from incoming HTTP request.
25
+ * Called for EVERY API request to determine user permissions and multi-tenant isolation.
26
+ *
27
+ * This is your security boundary - ensure proper authentication and authorization here.
28
+ *
29
+ * @param request - Fastify Request object containing the incoming HTTP request
30
+ * @returns Security context with organisationId, userId, roles, etc.
31
+ *
32
+ * @example
33
+ * extractSecurityContext: async (request) => {
34
+ * // Extract JWT from Authorization header
35
+ * const token = request.headers.authorization?.replace('Bearer ', '')
36
+ * const decoded = await verifyJWT(token)
37
+ *
38
+ * // Return context that will be available in all cube SQL functions
39
+ * return {
40
+ * organisationId: decoded.orgId,
41
+ * userId: decoded.userId,
42
+ * roles: decoded.roles
43
+ * }
44
+ * }
45
+ */
46
+ extractSecurityContext: (request: FastifyRequest) => SecurityContext | Promise<SecurityContext>;
47
+ /**
48
+ * Database engine type (optional - auto-detected if not provided)
49
+ */
50
+ engineType?: 'postgres' | 'mysql' | 'sqlite';
51
+ /**
52
+ * CORS configuration (optional)
53
+ */
54
+ cors?: FastifyCorsOptions;
55
+ /**
56
+ * API base path (default: '/cubejs-api/v1')
57
+ */
58
+ basePath?: string;
59
+ /**
60
+ * JSON body parser limit (default: 10485760 - 10MB)
61
+ */
62
+ bodyLimit?: number;
63
+ }
64
+ /**
65
+ * Fastify plugin for Cube.js-compatible API
66
+ */
67
+ export declare const cubePlugin: FastifyPluginCallback<FastifyAdapterOptions>;
68
+ /**
69
+ * Helper function to register cube routes on an existing Fastify instance
70
+ */
71
+ export declare function registerCubeRoutes<TSchema extends Record<string, any> = Record<string, any>>(fastify: FastifyInstance, options: FastifyAdapterOptions<TSchema>): Promise<void>;
72
+ /**
73
+ * Create a complete Fastify instance with Cube.js routes
74
+ *
75
+ * @example
76
+ * const app = createCubeApp({
77
+ * cubes: [salesCube, employeesCube],
78
+ * drizzle: db,
79
+ * schema,
80
+ * extractSecurityContext: async (request) => {
81
+ * const token = request.headers.authorization?.replace('Bearer ', '')
82
+ * const decoded = await verifyJWT(token)
83
+ * return { organisationId: decoded.orgId, userId: decoded.userId }
84
+ * }
85
+ * })
86
+ */
87
+ export declare function createCubeApp<TSchema extends Record<string, any> = Record<string, any>>(options: FastifyAdapterOptions<TSchema>): FastifyInstance;
88
+ export type { SecurityContext, DatabaseExecutor, SemanticQuery, DrizzleDatabase, FastifyCorsOptions };
@@ -0,0 +1,213 @@
1
+ import { S as P, c as u, f as Q, a as R, b as C, h as w } from "../utils-C3A4JGFs.js";
2
+ const x = function(o, S, h) {
3
+ const {
4
+ cubes: m,
5
+ drizzle: $,
6
+ schema: E,
7
+ extractSecurityContext: y,
8
+ engineType: q,
9
+ cors: v,
10
+ basePath: d = "/cubejs-api/v1",
11
+ bodyLimit: p = 10485760
12
+ // 10MB
13
+ } = S;
14
+ if (!m || m.length === 0)
15
+ return h(new Error("At least one cube must be provided in the cubes array"));
16
+ v && o.register(import("@fastify/cors"), v), o.addHook("onRequest", async (r, t) => {
17
+ r.method === "POST" && (r.body = void 0);
18
+ });
19
+ const i = new P({
20
+ drizzle: $,
21
+ schema: E,
22
+ engineType: q
23
+ });
24
+ m.forEach((r) => {
25
+ i.registerCube(r);
26
+ }), console.log(`🚀 Drizzle Cube: Registered ${m.length} cube(s) with ${q || "auto-detected"} engine`), o.post(`${d}/load`, {
27
+ bodyLimit: p,
28
+ schema: {
29
+ body: {
30
+ type: "object",
31
+ additionalProperties: !0
32
+ }
33
+ }
34
+ }, async (r, t) => {
35
+ try {
36
+ const e = r.body, a = e.query || e, s = await y(r), n = i.validateQuery(a);
37
+ if (!n.isValid)
38
+ return t.status(400).send(u(
39
+ `Query validation failed: ${n.errors.join(", ")}`,
40
+ 400
41
+ ));
42
+ const c = await i.executeMultiCubeQuery(a, s);
43
+ return Q(a, c, i);
44
+ } catch (e) {
45
+ return r.log.error(e, "Query execution error"), t.status(500).send(u(
46
+ e instanceof Error ? e.message : "Query execution failed",
47
+ 500
48
+ ));
49
+ }
50
+ }), o.get(`${d}/load`, {
51
+ schema: {
52
+ querystring: {
53
+ type: "object",
54
+ properties: {
55
+ query: { type: "string" }
56
+ },
57
+ required: ["query"]
58
+ }
59
+ }
60
+ }, async (r, t) => {
61
+ try {
62
+ const { query: e } = r.query;
63
+ let a;
64
+ try {
65
+ a = JSON.parse(e);
66
+ } catch {
67
+ return t.status(400).send(u(
68
+ "Invalid JSON in query parameter",
69
+ 400
70
+ ));
71
+ }
72
+ const s = await y(r), n = i.validateQuery(a);
73
+ if (!n.isValid)
74
+ return t.status(400).send(u(
75
+ `Query validation failed: ${n.errors.join(", ")}`,
76
+ 400
77
+ ));
78
+ const c = await i.executeMultiCubeQuery(a, s);
79
+ return Q(a, c, i);
80
+ } catch (e) {
81
+ return r.log.error(e, "Query execution error"), t.status(500).send(u(
82
+ e instanceof Error ? e.message : "Query execution failed",
83
+ 500
84
+ ));
85
+ }
86
+ }), o.get(`${d}/meta`, async (r, t) => {
87
+ try {
88
+ const e = i.getMetadata();
89
+ return R(e);
90
+ } catch (e) {
91
+ return r.log.error(e, "Metadata error"), t.status(500).send(u(
92
+ e instanceof Error ? e.message : "Failed to fetch metadata",
93
+ 500
94
+ ));
95
+ }
96
+ }), o.post(`${d}/sql`, {
97
+ bodyLimit: p,
98
+ schema: {
99
+ body: {
100
+ type: "object",
101
+ additionalProperties: !0
102
+ }
103
+ }
104
+ }, async (r, t) => {
105
+ var e, a;
106
+ try {
107
+ const s = r.body, n = await y(r), c = i.validateQuery(s);
108
+ if (!c.isValid)
109
+ return t.status(400).send(u(
110
+ `Query validation failed: ${c.errors.join(", ")}`,
111
+ 400
112
+ ));
113
+ const l = ((e = s.measures) == null ? void 0 : e[0]) || ((a = s.dimensions) == null ? void 0 : a[0]);
114
+ if (!l)
115
+ return t.status(400).send(u(
116
+ "No measures or dimensions specified",
117
+ 400
118
+ ));
119
+ const b = l.split(".")[0], f = await i.generateSQL(b, s, n);
120
+ return C(s, f);
121
+ } catch (s) {
122
+ return r.log.error(s, "SQL generation error"), t.status(500).send(u(
123
+ s instanceof Error ? s.message : "SQL generation failed",
124
+ 500
125
+ ));
126
+ }
127
+ }), o.get(`${d}/sql`, {
128
+ schema: {
129
+ querystring: {
130
+ type: "object",
131
+ properties: {
132
+ query: { type: "string" }
133
+ },
134
+ required: ["query"]
135
+ }
136
+ }
137
+ }, async (r, t) => {
138
+ var e, a;
139
+ try {
140
+ const { query: s } = r.query, n = JSON.parse(s), c = await y(r), l = i.validateQuery(n);
141
+ if (!l.isValid)
142
+ return t.status(400).send(u(
143
+ `Query validation failed: ${l.errors.join(", ")}`,
144
+ 400
145
+ ));
146
+ const b = ((e = n.measures) == null ? void 0 : e[0]) || ((a = n.dimensions) == null ? void 0 : a[0]);
147
+ if (!b)
148
+ return t.status(400).send(u(
149
+ "No measures or dimensions specified",
150
+ 400
151
+ ));
152
+ const f = b.split(".")[0], j = await i.generateSQL(f, n, c);
153
+ return C(n, j);
154
+ } catch (s) {
155
+ return r.log.error(s, "SQL generation error"), t.status(500).send(u(
156
+ s instanceof Error ? s.message : "SQL generation failed",
157
+ 500
158
+ ));
159
+ }
160
+ }), o.post(`${d}/dry-run`, {
161
+ bodyLimit: p,
162
+ schema: {
163
+ body: {
164
+ type: "object",
165
+ additionalProperties: !0
166
+ }
167
+ }
168
+ }, async (r, t) => {
169
+ try {
170
+ const e = r.body, a = e.query || e, s = await y(r);
171
+ return await w(a, s, i);
172
+ } catch (e) {
173
+ return r.log.error(e, "Dry-run error"), t.status(400).send({
174
+ error: e instanceof Error ? e.message : "Dry-run validation failed",
175
+ valid: !1
176
+ });
177
+ }
178
+ }), o.get(`${d}/dry-run`, {
179
+ schema: {
180
+ querystring: {
181
+ type: "object",
182
+ properties: {
183
+ query: { type: "string" }
184
+ },
185
+ required: ["query"]
186
+ }
187
+ }
188
+ }, async (r, t) => {
189
+ try {
190
+ const { query: e } = r.query, a = JSON.parse(e), s = await y(r);
191
+ return await w(a, s, i);
192
+ } catch (e) {
193
+ return r.log.error(e, "Dry-run error"), t.status(400).send({
194
+ error: e instanceof Error ? e.message : "Dry-run validation failed",
195
+ valid: !1
196
+ });
197
+ }
198
+ }), o.setErrorHandler(async (r, t, e) => (t.log.error(r, "Fastify cube adapter error"), e.statusCode < 400 && e.status(500), u(r, e.statusCode))), h();
199
+ };
200
+ async function N(g, o) {
201
+ await g.register(x, o);
202
+ }
203
+ function M(g) {
204
+ const o = require("fastify")({
205
+ logger: !0
206
+ });
207
+ return o.register(x, g), o;
208
+ }
209
+ export {
210
+ M as createCubeApp,
211
+ x as cubePlugin,
212
+ N as registerCubeRoutes
213
+ };
@@ -1,13 +1,13 @@
1
1
  import { Hono } from 'hono';
2
- import { SemanticLayerCompiler, SemanticQuery, SecurityContext, DatabaseExecutor, DrizzleDatabase } from '../../server';
2
+ import { SemanticQuery, SecurityContext, DatabaseExecutor, DrizzleDatabase, Cube } from '../../server';
3
3
  import { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
4
4
  import { MySql2Database } from 'drizzle-orm/mysql2';
5
5
  import { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
6
6
  export interface HonoAdapterOptions<TSchema extends Record<string, any> = Record<string, any>> {
7
7
  /**
8
- * The semantic layer instance to use
8
+ * Array of cube definitions to register
9
9
  */
10
- semanticLayer: SemanticLayerCompiler<TSchema>;
10
+ cubes: Cube<TSchema>[];
11
11
  /**
12
12
  * Drizzle database instance (REQUIRED)
13
13
  * This is the core of drizzle-cube - Drizzle ORM integration
@@ -20,10 +20,33 @@ export interface HonoAdapterOptions<TSchema extends Record<string, any> = Record
20
20
  */
21
21
  schema?: TSchema;
22
22
  /**
23
- * Function to extract security context from Hono context
24
- * This is where you provide your app-specific context extraction logic
23
+ * Extract security context from incoming HTTP request.
24
+ * Called for EVERY API request to determine user permissions and multi-tenant isolation.
25
+ *
26
+ * This is your security boundary - ensure proper authentication and authorization here.
27
+ *
28
+ * @param c - Hono context containing the incoming HTTP request
29
+ * @returns Security context with organisationId, userId, roles, etc.
30
+ *
31
+ * @example
32
+ * extractSecurityContext: async (c) => {
33
+ * // Extract JWT from Authorization header
34
+ * const token = c.req.header('Authorization')?.replace('Bearer ', '')
35
+ * const decoded = await verifyJWT(token)
36
+ *
37
+ * // Return context that will be available in all cube SQL functions
38
+ * return {
39
+ * organisationId: decoded.orgId,
40
+ * userId: decoded.userId,
41
+ * roles: decoded.roles
42
+ * }
43
+ * }
25
44
  */
26
- getSecurityContext: (c: any) => SecurityContext | Promise<SecurityContext>;
45
+ extractSecurityContext: (c: any) => SecurityContext | Promise<SecurityContext>;
46
+ /**
47
+ * Database engine type (optional - auto-detected if not provided)
48
+ */
49
+ engineType?: 'postgres' | 'mysql' | 'sqlite';
27
50
  /**
28
51
  * CORS configuration (optional)
29
52
  */
@@ -48,6 +71,18 @@ export declare function createCubeRoutes<TSchema extends Record<string, any> = R
48
71
  export declare function mountCubeRoutes<TSchema extends Record<string, any> = Record<string, any>>(app: Hono, options: HonoAdapterOptions<TSchema>): Hono<import('hono/types').BlankEnv, import('hono/types').BlankSchema, "/">;
49
72
  /**
50
73
  * Create a complete Hono app with Cube.js routes
74
+ *
75
+ * @example
76
+ * const app = createCubeApp({
77
+ * cubes: [salesCube, employeesCube],
78
+ * drizzle: db,
79
+ * schema,
80
+ * extractSecurityContext: async (c) => {
81
+ * const token = c.req.header('Authorization')
82
+ * const decoded = await verifyJWT(token)
83
+ * return { organisationId: decoded.orgId, userId: decoded.userId }
84
+ * }
85
+ * })
51
86
  */
52
87
  export declare function createCubeApp<TSchema extends Record<string, any> = Record<string, any>>(options: HonoAdapterOptions<TSchema>): Hono<import('hono/types').BlankEnv, import('hono/types').BlankSchema, "/">;
53
88
  export type { SecurityContext, DatabaseExecutor, SemanticQuery, DrizzleDatabase };