drizzle-cube
Version:
Drizzle ORM-first semantic layer with Cube.js compatibility. Type-safe analytics and dashboards with SQL injection protection.
211 lines (210 loc) • 7.13 kB
JavaScript
import { Hono as C } from "hono";
import { S as Q, f as g, h as b, a as A, b as p, c as w } from "../compiler-Ddwn99Ja.js";
var v = (f) => {
const i = {
...{
origin: "*",
allowMethods: ["GET", "HEAD", "PUT", "POST", "DELETE", "PATCH"],
allowHeaders: [],
exposeHeaders: []
},
...f
}, h = /* @__PURE__ */ ((a) => typeof a == "string" ? a === "*" ? () => a : (o) => a === o ? o : null : typeof a == "function" ? a : (o) => a.includes(o) ? o : null)(i.origin), d = ((a) => typeof a == "function" ? a : Array.isArray(a) ? () => a : () => [])(i.allowMethods);
return async function(o, c) {
function y(n, r) {
o.res.headers.set(n, r);
}
const l = await h(o.req.header("origin") || "", o);
if (l && y("Access-Control-Allow-Origin", l), i.credentials && y("Access-Control-Allow-Credentials", "true"), i.exposeHeaders?.length && y("Access-Control-Expose-Headers", i.exposeHeaders.join(",")), o.req.method === "OPTIONS") {
i.origin !== "*" && y("Vary", "Origin"), i.maxAge != null && y("Access-Control-Max-Age", i.maxAge.toString());
const n = await d(o.req.header("origin") || "", o);
n.length && y("Access-Control-Allow-Methods", n.join(","));
let r = i.allowHeaders;
if (!r?.length) {
const e = o.req.header("Access-Control-Request-Headers");
e && (r = e.split(/\s*,\s*/));
}
return r?.length && (y("Access-Control-Allow-Headers", r.join(",")), o.res.headers.append("Vary", "Access-Control-Request-Headers")), o.res.headers.delete("Content-Length"), o.res.headers.delete("Content-Type"), new Response(null, {
headers: o.res.headers,
status: 204,
statusText: "No Content"
});
}
await c(), i.origin !== "*" && o.header("Vary", "Origin", { append: !0 });
};
};
function S(f) {
const {
cubes: m,
drizzle: i,
schema: h,
extractSecurityContext: d,
engineType: a,
cors: o,
basePath: c = "/cubejs-api/v1",
cache: y
} = f;
if (!m || m.length === 0)
throw new Error("At least one cube must be provided in the cubes array");
const l = new C();
o && l.use("/*", v(o));
const n = new Q({
drizzle: i,
schema: h,
engineType: a,
cache: y
});
return m.forEach((r) => {
n.registerCube(r);
}), l.post(`${c}/load`, async (r) => {
try {
const e = await r.req.json(), t = e.query || e, u = await d(r), s = n.validateQuery(t);
if (!s.isValid)
return r.json({
error: `Query validation failed: ${s.errors.join(", ")}`
}, 400);
const q = await n.executeMultiCubeQuery(t, u);
return r.json(g(t, q, n));
} catch (e) {
return console.error("Query execution error:", e), r.json({
error: e instanceof Error ? e.message : "Query execution failed"
}, 500);
}
}), l.get(`${c}/load`, async (r) => {
try {
const e = r.req.query("query");
if (!e)
return r.json({
error: "Query parameter is required"
}, 400);
let t;
try {
t = JSON.parse(e);
} catch {
return r.json({
error: "Invalid JSON in query parameter"
}, 400);
}
const u = await d(r), s = n.validateQuery(t);
if (!s.isValid)
return r.json({
error: `Query validation failed: ${s.errors.join(", ")}`
}, 400);
const q = await n.executeMultiCubeQuery(t, u);
return r.json(g(t, q, n));
} catch (e) {
return console.error("Query execution error:", e), r.json({
error: e instanceof Error ? e.message : "Query execution failed"
}, 500);
}
}), l.post(`${c}/batch`, async (r) => {
try {
const e = await r.req.json(), { queries: t } = e;
if (!t || !Array.isArray(t))
return r.json({
error: 'Request body must contain a "queries" array'
}, 400);
if (t.length === 0)
return r.json({
error: "Queries array cannot be empty"
}, 400);
const u = await d(r), s = await b(t, u, n);
return r.json(s);
} catch (e) {
return console.error("Batch execution error:", e), r.json({
error: e instanceof Error ? e.message : "Batch execution failed"
}, 500);
}
}), l.get(`${c}/meta`, (r) => {
try {
const e = n.getMetadata();
return r.json(A(e));
} catch (e) {
return console.error("Metadata error:", e), r.json({
error: e instanceof Error ? e.message : "Failed to fetch metadata"
}, 500);
}
}), l.post(`${c}/sql`, async (r) => {
try {
const e = await r.req.json(), t = await d(r), u = n.validateQuery(e);
if (!u.isValid)
return r.json({
error: `Query validation failed: ${u.errors.join(", ")}`
}, 400);
const s = e.measures?.[0] || e.dimensions?.[0];
if (!s)
return r.json({
error: "No measures or dimensions specified"
}, 400);
const q = s.split(".")[0], j = await n.generateSQL(q, e, t);
return r.json(p(e, j));
} catch (e) {
return console.error("SQL generation error:", e), r.json({
error: e instanceof Error ? e.message : "SQL generation failed"
}, 500);
}
}), l.get(`${c}/sql`, async (r) => {
try {
const e = r.req.query("query");
if (!e)
return r.json({
error: "Query parameter is required"
}, 400);
const t = JSON.parse(e), u = await d(r), s = n.validateQuery(t);
if (!s.isValid)
return r.json({
error: `Query validation failed: ${s.errors.join(", ")}`
}, 400);
const q = t.measures?.[0] || t.dimensions?.[0];
if (!q)
return r.json({
error: "No measures or dimensions specified"
}, 400);
const j = q.split(".")[0], x = await n.generateSQL(j, t, u);
return r.json(p(t, x));
} catch (e) {
return console.error("SQL generation error:", e), r.json({
error: e instanceof Error ? e.message : "SQL generation failed"
}, 500);
}
}), l.post(`${c}/dry-run`, async (r) => {
try {
const e = await r.req.json(), t = e.query || e, u = await d(r), s = await w(t, u, n);
return r.json(s);
} catch (e) {
return console.error("Dry-run error:", e), r.json({
error: e instanceof Error ? e.message : "Dry-run validation failed",
valid: !1
}, 400);
}
}), l.get(`${c}/dry-run`, async (r) => {
try {
const e = r.req.query("query");
if (!e)
return r.json({
error: "Query parameter is required",
valid: !1
}, 400);
const t = JSON.parse(e), u = await d(r), s = await w(t, u, n);
return r.json(s);
} catch (e) {
return console.error("Dry-run error:", e), r.json({
error: e instanceof Error ? e.message : "Dry-run validation failed",
valid: !1
}, 400);
}
}), l;
}
function E(f, m) {
const i = S(m);
return f.route("/", i), f;
}
function $(f) {
const m = new C();
return E(m, f);
}
export {
$ as createCubeApp,
S as createCubeRoutes,
E as mountCubeRoutes
};