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