UNPKG

drizzle-cube

Version:

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

225 lines (224 loc) 7.67 kB
import { Hono as x } from "hono"; import { S as Q, f as p, h as v, a as b, b as w, c as g } from "../compiler-Duyh6Jp-.js"; var A = (q) => { const u = { ...{ origin: "*", allowMethods: ["GET", "HEAD", "PUT", "POST", "DELETE", "PATCH"], allowHeaders: [], exposeHeaders: [] }, ...q }, j = /* @__PURE__ */ ((i) => typeof i == "string" ? i === "*" ? () => i : (n) => i === n ? n : null : typeof i == "function" ? i : (n) => i.includes(n) ? n : null)(u.origin), y = ((i) => typeof i == "function" ? i : Array.isArray(i) ? () => i : () => [])(u.allowMethods); return async function(n, c) { function f(o, r) { n.res.headers.set(o, r); } const l = await j(n.req.header("origin") || "", n); if (l && f("Access-Control-Allow-Origin", l), u.credentials && f("Access-Control-Allow-Credentials", "true"), u.exposeHeaders?.length && f("Access-Control-Expose-Headers", u.exposeHeaders.join(",")), n.req.method === "OPTIONS") { u.origin !== "*" && f("Vary", "Origin"), u.maxAge != null && f("Access-Control-Max-Age", u.maxAge.toString()); const o = await y(n.req.header("origin") || "", n); o.length && f("Access-Control-Allow-Methods", o.join(",")); let r = u.allowHeaders; if (!r?.length) { const e = n.req.header("Access-Control-Request-Headers"); e && (r = e.split(/\s*,\s*/)); } return r?.length && (f("Access-Control-Allow-Headers", r.join(",")), n.res.headers.append("Vary", "Access-Control-Request-Headers")), n.res.headers.delete("Content-Length"), n.res.headers.delete("Content-Type"), new Response(null, { headers: n.res.headers, status: 204, statusText: "No Content" }); } await c(), u.origin !== "*" && n.header("Vary", "Origin", { append: !0 }); }; }; function E(q) { const { cubes: m, drizzle: u, schema: j, extractSecurityContext: y, engineType: i, cors: n, basePath: c = "/cubejs-api/v1", cache: f } = q; if (!m || m.length === 0) throw new Error("At least one cube must be provided in the cubes array"); const l = new x(); n && l.use("/*", A(n)); const o = new Q({ drizzle: u, schema: j, engineType: i, cache: f }); return m.forEach((r) => { o.registerCube(r); }), l.post(`${c}/load`, async (r) => { try { const e = await r.req.json(), t = e.query || e, a = await y(r), s = o.validateQuery(t); if (!s.isValid) return r.json({ error: `Query validation failed: ${s.errors.join(", ")}` }, 400); const d = await o.executeMultiCubeQuery(t, a); return r.json(p(t, d, o)); } 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 a = await y(r), s = o.validateQuery(t); if (!s.isValid) return r.json({ error: `Query validation failed: ${s.errors.join(", ")}` }, 400); const d = await o.executeMultiCubeQuery(t, a); return r.json(p(t, d, o)); } 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 a = await y(r), s = await v(t, a, o); 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 = o.getMetadata(); return r.json(b(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 y(r), a = o.validateQuery(e); if (!a.isValid) return r.json({ error: `Query validation failed: ${a.errors.join(", ")}` }, 400); const s = e.measures?.[0] || e.dimensions?.[0]; if (!s) return r.json({ error: "No measures or dimensions specified" }, 400); const d = s.split(".")[0], h = await o.generateSQL(d, e, t); return r.json(w(e, h)); } 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), a = await y(r), s = o.validateQuery(t); if (!s.isValid) return r.json({ error: `Query validation failed: ${s.errors.join(", ")}` }, 400); const d = t.measures?.[0] || t.dimensions?.[0]; if (!d) return r.json({ error: "No measures or dimensions specified" }, 400); const h = d.split(".")[0], C = await o.generateSQL(h, t, a); return r.json(w(t, C)); } 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, a = await y(r), s = await g(t, a, o); 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), a = await y(r), s = await g(t, a, o); 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.post(`${c}/explain`, async (r) => { try { const e = await r.req.json(), t = e.query || e, a = e.options || {}, s = await y(r), d = o.validateQuery(t); if (!d.isValid) return r.json({ error: `Query validation failed: ${d.errors.join(", ")}` }, 400); const h = await o.explainQuery(t, s, a); return r.json(h); } catch (e) { return console.error("Explain error:", e), r.json({ error: e instanceof Error ? e.message : "Explain query failed" }, 500); } }), l; } function S(q, m) { const u = E(m); return q.route("/", u), q; } function H(q) { const m = new x(); return S(m, q); } export { H as createCubeApp, E as createCubeRoutes, S as mountCubeRoutes };