drizzle-cube
Version:
Drizzle ORM-first semantic layer with Cube.js compatibility. Type-safe analytics and dashboards with SQL injection protection.
178 lines (177 loc) • 5.29 kB
JavaScript
import Q, { Router as E } from "express";
import R from "cors";
import { S as $, c as a, f as v, a as L, b as x, h } from "../compiler-Dec55JjO.js";
function N(l) {
const {
cubes: c,
drizzle: p,
schema: C,
extractSecurityContext: d,
engineType: w,
cors: g,
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 u = E();
g && u.use(R(g)), u.use(Q.json({ limit: q })), u.use(Q.urlencoded({ extended: !0, limit: q }));
const n = new $({
drizzle: p,
schema: C,
engineType: w
});
return c.forEach((t) => {
n.registerCube(t);
}), u.post(`${y}/load`, async (t, r) => {
try {
const e = t.body.query || t.body, s = await d(t, r), o = n.validateQuery(e);
if (!o.isValid)
return r.status(400).json(a(
`Query validation failed: ${o.errors.join(", ")}`,
400
));
const i = await n.executeMultiCubeQuery(e, s);
r.json(v(e, i, n));
} catch (e) {
console.error("Query execution error:", e), r.status(500).json(a(
e instanceof Error ? e.message : "Query execution failed",
500
));
}
}), u.get(`${y}/load`, async (t, r) => {
try {
const e = t.query.query;
if (!e)
return r.status(400).json(a(
"Query parameter is required",
400
));
let s;
try {
s = JSON.parse(e);
} catch {
return r.status(400).json(a(
"Invalid JSON in query parameter",
400
));
}
const o = await d(t, r), i = n.validateQuery(s);
if (!i.isValid)
return r.status(400).json(a(
`Query validation failed: ${i.errors.join(", ")}`,
400
));
const f = await n.executeMultiCubeQuery(s, o);
r.json(v(s, f, n));
} catch (e) {
console.error("Query execution error:", e), r.status(500).json(a(
e instanceof Error ? e.message : "Query execution failed",
500
));
}
}), u.get(`${y}/meta`, (t, r) => {
try {
const e = n.getMetadata();
r.json(L(e));
} catch (e) {
console.error("Metadata error:", e), r.status(500).json(a(
e instanceof Error ? e.message : "Failed to fetch metadata",
500
));
}
}), u.post(`${y}/sql`, async (t, r) => {
var e, s;
try {
const o = t.body, i = await d(t, r), f = n.validateQuery(o);
if (!f.isValid)
return r.status(400).json(a(
`Query validation failed: ${f.errors.join(", ")}`,
400
));
const m = ((e = o.measures) == null ? void 0 : e[0]) || ((s = o.dimensions) == null ? void 0 : s[0]);
if (!m)
return r.status(400).json(a(
"No measures or dimensions specified",
400
));
const j = m.split(".")[0], b = await n.generateSQL(j, o, i);
r.json(x(o, b));
} catch (o) {
console.error("SQL generation error:", o), r.status(500).json(a(
o instanceof Error ? o.message : "SQL generation failed",
500
));
}
}), u.get(`${y}/sql`, async (t, r) => {
var e, s;
try {
const o = t.query.query;
if (!o)
return r.status(400).json(a(
"Query parameter is required",
400
));
const i = JSON.parse(o), f = await d(t, r), m = n.validateQuery(i);
if (!m.isValid)
return r.status(400).json(a(
`Query validation failed: ${m.errors.join(", ")}`,
400
));
const j = ((e = i.measures) == null ? void 0 : e[0]) || ((s = i.dimensions) == null ? void 0 : s[0]);
if (!j)
return r.status(400).json(a(
"No measures or dimensions specified",
400
));
const b = j.split(".")[0], S = await n.generateSQL(b, i, f);
r.json(x(i, S));
} catch (o) {
console.error("SQL generation error:", o), r.status(500).json(a(
o instanceof Error ? o.message : "SQL generation failed",
500
));
}
}), u.post(`${y}/dry-run`, async (t, r) => {
try {
const e = t.body.query || t.body, s = await d(t, r), o = await h(e, s, n);
r.json(o);
} catch (e) {
console.error("Dry-run error:", e), r.status(400).json({
error: e instanceof Error ? e.message : "Dry-run validation failed",
valid: !1
});
}
}), u.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 s = JSON.parse(e), o = await d(t, r), i = await h(s, o, n);
r.json(i);
} catch (e) {
console.error("Dry-run error:", e), r.status(400).json({
error: e instanceof Error ? e.message : "Dry-run validation failed",
valid: !1
});
}
}), u.use((t, r, e, s) => {
console.error("Express adapter error:", t), e.headersSent || e.status(500).json(a(t, 500));
}), u;
}
function M(l, c) {
const p = N(c);
return l.use("/", p), l;
}
function P(l) {
const c = Q();
return M(c, l);
}
export {
P as createCubeApp,
N as createCubeRouter,
M as mountCubeRoutes
};