UNPKG

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
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 };