UNPKG

drizzle-cube

Version:

Drizzle ORM-first semantic layer with Cube.js compatibility. Type-safe analytics and dashboards with SQL injection protection.

176 lines (175 loc) 5.16 kB
import p, { Router as w } from "express"; import S from "cors"; import { S as E, c as s, f as g, a as R, b as q, h as v } from "../compiler-CVega_Gv.js"; function $(l) { const { cubes: c, drizzle: j, schema: x, extractSecurityContext: d, engineType: h, cors: b, basePath: y = "/cubejs-api/v1", jsonLimit: Q = "10mb" } = l; if (!c || c.length === 0) throw new Error("At least one cube must be provided in the cubes array"); const i = w(); b && i.use(S(b)), i.use(p.json({ limit: Q })), i.use(p.urlencoded({ extended: !0, limit: Q })); const a = new E({ drizzle: j, schema: x, engineType: h }); return c.forEach((t) => { a.registerCube(t); }), i.post(`${y}/load`, async (t, r) => { try { const e = t.body.query || t.body, o = await d(t, r), n = a.validateQuery(e); if (!n.isValid) return r.status(400).json(s( `Query validation failed: ${n.errors.join(", ")}`, 400 )); const u = await a.executeMultiCubeQuery(e, o); r.json(g(e, u, a)); } catch (e) { console.error("Query execution error:", e), r.status(500).json(s( e instanceof Error ? e.message : "Query execution failed", 500 )); } }), i.get(`${y}/load`, async (t, r) => { try { const e = t.query.query; if (!e) return r.status(400).json(s( "Query parameter is required", 400 )); let o; try { o = JSON.parse(e); } catch { return r.status(400).json(s( "Invalid JSON in query parameter", 400 )); } const n = await d(t, r), u = a.validateQuery(o); if (!u.isValid) return r.status(400).json(s( `Query validation failed: ${u.errors.join(", ")}`, 400 )); const f = await a.executeMultiCubeQuery(o, n); r.json(g(o, f, a)); } catch (e) { console.error("Query execution error:", e), r.status(500).json(s( e instanceof Error ? e.message : "Query execution failed", 500 )); } }), i.get(`${y}/meta`, (t, r) => { try { const e = a.getMetadata(); r.json(R(e)); } catch (e) { console.error("Metadata error:", e), r.status(500).json(s( e instanceof Error ? e.message : "Failed to fetch metadata", 500 )); } }), i.post(`${y}/sql`, async (t, r) => { try { const e = t.body, o = await d(t, r), n = a.validateQuery(e); if (!n.isValid) return r.status(400).json(s( `Query validation failed: ${n.errors.join(", ")}`, 400 )); const u = e.measures?.[0] || e.dimensions?.[0]; if (!u) return r.status(400).json(s( "No measures or dimensions specified", 400 )); const f = u.split(".")[0], m = await a.generateSQL(f, e, o); r.json(q(e, m)); } catch (e) { console.error("SQL generation error:", e), r.status(500).json(s( e instanceof Error ? e.message : "SQL generation failed", 500 )); } }), i.get(`${y}/sql`, async (t, r) => { try { const e = t.query.query; if (!e) return r.status(400).json(s( "Query parameter is required", 400 )); const o = JSON.parse(e), n = await d(t, r), u = a.validateQuery(o); if (!u.isValid) return r.status(400).json(s( `Query validation failed: ${u.errors.join(", ")}`, 400 )); const f = o.measures?.[0] || o.dimensions?.[0]; if (!f) return r.status(400).json(s( "No measures or dimensions specified", 400 )); const m = f.split(".")[0], C = await a.generateSQL(m, o, n); r.json(q(o, C)); } catch (e) { console.error("SQL generation error:", e), r.status(500).json(s( e instanceof Error ? e.message : "SQL generation failed", 500 )); } }), i.post(`${y}/dry-run`, async (t, r) => { try { const e = t.body.query || t.body, o = await d(t, r), n = await v(e, o, a); r.json(n); } catch (e) { console.error("Dry-run error:", e), r.status(400).json({ error: e instanceof Error ? e.message : "Dry-run validation failed", valid: !1 }); } }), i.get(`${y}/dry-run`, async (t, r) => { try { const e = t.query.query; if (!e) return r.status(400).json({ error: "Query parameter is required", valid: !1 }); const o = JSON.parse(e), n = await d(t, r), u = await v(o, n, a); r.json(u); } catch (e) { console.error("Dry-run error:", e), r.status(400).json({ error: e instanceof Error ? e.message : "Dry-run validation failed", valid: !1 }); } }), i.use((t, r, e, o) => { console.error("Express adapter error:", t), e.headersSent || e.status(500).json(s(t, 500)); }), i; } function L(l, c) { const j = $(c); return l.use("/", j), l; } function J(l) { const c = p(); return L(c, l); } export { J as createCubeApp, $ as createCubeRouter, L as mountCubeRoutes };