UNPKG

drizzle-cube

Version:

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

272 lines (271 loc) 7.32 kB
import { S as R, d as n, f, h as $, a as P, b as q, c as x } from "../compiler-Duyh6Jp-.js"; const Q = function(s, v, b) { const { cubes: p, drizzle: w, schema: C, extractSecurityContext: y, engineType: E, cors: h, basePath: d = "/cubejs-api/v1", bodyLimit: l = 10485760, // 10MB cache: S } = v; if (!p || p.length === 0) return b(new Error("At least one cube must be provided in the cubes array")); h && s.register(import("@fastify/cors"), h), s.addHook("onRequest", async (r, t) => { r.method === "POST" && (r.body = void 0); }); const o = new R({ drizzle: w, schema: C, engineType: E, cache: S }); p.forEach((r) => { o.registerCube(r); }), s.post(`${d}/load`, { bodyLimit: l, schema: { body: { type: "object", additionalProperties: !0 } } }, async (r, t) => { try { const e = r.body, a = e.query || e, i = await y(r), u = o.validateQuery(a); if (!u.isValid) return t.status(400).send(n( `Query validation failed: ${u.errors.join(", ")}`, 400 )); const c = await o.executeMultiCubeQuery(a, i); return f(a, c, o); } catch (e) { return r.log.error(e, "Query execution error"), t.status(500).send(n( e instanceof Error ? e.message : "Query execution failed", 500 )); } }), s.get(`${d}/load`, { schema: { querystring: { type: "object", properties: { query: { type: "string" } }, required: ["query"] } } }, async (r, t) => { try { const { query: e } = r.query; let a; try { a = JSON.parse(e); } catch { return t.status(400).send(n( "Invalid JSON in query parameter", 400 )); } const i = await y(r), u = o.validateQuery(a); if (!u.isValid) return t.status(400).send(n( `Query validation failed: ${u.errors.join(", ")}`, 400 )); const c = await o.executeMultiCubeQuery(a, i); return f(a, c, o); } catch (e) { return r.log.error(e, "Query execution error"), t.status(500).send(n( e instanceof Error ? e.message : "Query execution failed", 500 )); } }), s.post(`${d}/batch`, { bodyLimit: l, schema: { body: { type: "object", required: ["queries"], properties: { queries: { type: "array", items: { type: "object" } } } } } }, async (r, t) => { try { const { queries: e } = r.body; if (!e || !Array.isArray(e)) return t.status(400).send(n( 'Request body must contain a "queries" array', 400 )); if (e.length === 0) return t.status(400).send(n( "Queries array cannot be empty", 400 )); const a = await y(r); return await $(e, a, o); } catch (e) { return r.log.error(e, "Batch execution error"), t.status(500).send(n( e instanceof Error ? e.message : "Batch execution failed", 500 )); } }), s.get(`${d}/meta`, async (r, t) => { try { const e = o.getMetadata(); return P(e); } catch (e) { return r.log.error(e, "Metadata error"), t.status(500).send(n( e instanceof Error ? e.message : "Failed to fetch metadata", 500 )); } }), s.post(`${d}/sql`, { bodyLimit: l, schema: { body: { type: "object", additionalProperties: !0 } } }, async (r, t) => { try { const e = r.body, a = await y(r), i = o.validateQuery(e); if (!i.isValid) return t.status(400).send(n( `Query validation failed: ${i.errors.join(", ")}`, 400 )); const u = e.measures?.[0] || e.dimensions?.[0]; if (!u) return t.status(400).send(n( "No measures or dimensions specified", 400 )); const c = u.split(".")[0], g = await o.generateSQL(c, e, a); return q(e, g); } catch (e) { return r.log.error(e, "SQL generation error"), t.status(500).send(n( e instanceof Error ? e.message : "SQL generation failed", 500 )); } }), s.get(`${d}/sql`, { schema: { querystring: { type: "object", properties: { query: { type: "string" } }, required: ["query"] } } }, async (r, t) => { try { const { query: e } = r.query, a = JSON.parse(e), i = await y(r), u = o.validateQuery(a); if (!u.isValid) return t.status(400).send(n( `Query validation failed: ${u.errors.join(", ")}`, 400 )); const c = a.measures?.[0] || a.dimensions?.[0]; if (!c) return t.status(400).send(n( "No measures or dimensions specified", 400 )); const g = c.split(".")[0], j = await o.generateSQL(g, a, i); return q(a, j); } catch (e) { return r.log.error(e, "SQL generation error"), t.status(500).send(n( e instanceof Error ? e.message : "SQL generation failed", 500 )); } }), s.post(`${d}/dry-run`, { bodyLimit: l, schema: { body: { type: "object", additionalProperties: !0 } } }, async (r, t) => { try { const e = r.body, a = e.query || e, i = await y(r); return await x(a, i, o); } catch (e) { return r.log.error(e, "Dry-run error"), t.status(400).send({ error: e instanceof Error ? e.message : "Dry-run validation failed", valid: !1 }); } }), s.get(`${d}/dry-run`, { schema: { querystring: { type: "object", properties: { query: { type: "string" } }, required: ["query"] } } }, async (r, t) => { try { const { query: e } = r.query, a = JSON.parse(e), i = await y(r); return await x(a, i, o); } catch (e) { return r.log.error(e, "Dry-run error"), t.status(400).send({ error: e instanceof Error ? e.message : "Dry-run validation failed", valid: !1 }); } }), s.post(`${d}/explain`, { bodyLimit: l, schema: { body: { type: "object", additionalProperties: !0 } } }, async (r, t) => { try { const e = r.body, a = e.query || e, i = e.options || {}, u = await y(r), c = o.validateQuery(a); return c.isValid ? await o.explainQuery(a, u, i) : t.status(400).send({ error: `Query validation failed: ${c.errors.join(", ")}` }); } catch (e) { return r.log.error(e, "Explain error"), t.status(500).send({ error: e instanceof Error ? e.message : "Explain query failed" }); } }), s.setErrorHandler(async (r, t, e) => { t.log.error(r, "Fastify cube adapter error"), e.statusCode < 400 && e.status(500); const a = r instanceof Error ? r : String(r); return n(a, e.statusCode); }), b(); }; async function N(m, s) { await m.register(Q, s); } function M(m) { const s = require("fastify")({ logger: !0 }); return s.register(Q, m), s; } export { M as createCubeApp, Q as cubePlugin, N as registerCubeRoutes };