drizzle-cube
Version:
Drizzle ORM-first semantic layer with Cube.js compatibility. Type-safe analytics and dashboards with SQL injection protection.
247 lines (246 loc) • 6.61 kB
JavaScript
import { S as E, d as o, f, h as R, a as $, b as q, c as Q } from "../compiler-DdaSPwZs.js";
const v = function(a, x, p) {
const {
cubes: b,
drizzle: C,
schema: w,
extractSecurityContext: y,
engineType: S,
cors: h,
basePath: c = "/cubejs-api/v1",
bodyLimit: m = 10485760
// 10MB
} = x;
if (!b || b.length === 0)
return p(new Error("At least one cube must be provided in the cubes array"));
h && a.register(import("@fastify/cors"), h), a.addHook("onRequest", async (r, t) => {
r.method === "POST" && (r.body = void 0);
});
const n = new E({
drizzle: C,
schema: w,
engineType: S
});
b.forEach((r) => {
n.registerCube(r);
}), a.post(`${c}/load`, {
bodyLimit: m,
schema: {
body: {
type: "object",
additionalProperties: !0
}
}
}, async (r, t) => {
try {
const e = r.body, s = e.query || e, i = await y(r), u = n.validateQuery(s);
if (!u.isValid)
return t.status(400).send(o(
`Query validation failed: ${u.errors.join(", ")}`,
400
));
const d = await n.executeMultiCubeQuery(s, i);
return f(s, d, n);
} catch (e) {
return r.log.error(e, "Query execution error"), t.status(500).send(o(
e instanceof Error ? e.message : "Query execution failed",
500
));
}
}), a.get(`${c}/load`, {
schema: {
querystring: {
type: "object",
properties: {
query: { type: "string" }
},
required: ["query"]
}
}
}, async (r, t) => {
try {
const { query: e } = r.query;
let s;
try {
s = JSON.parse(e);
} catch {
return t.status(400).send(o(
"Invalid JSON in query parameter",
400
));
}
const i = await y(r), u = n.validateQuery(s);
if (!u.isValid)
return t.status(400).send(o(
`Query validation failed: ${u.errors.join(", ")}`,
400
));
const d = await n.executeMultiCubeQuery(s, i);
return f(s, d, n);
} catch (e) {
return r.log.error(e, "Query execution error"), t.status(500).send(o(
e instanceof Error ? e.message : "Query execution failed",
500
));
}
}), a.post(`${c}/batch`, {
bodyLimit: m,
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(o(
'Request body must contain a "queries" array',
400
));
if (e.length === 0)
return t.status(400).send(o(
"Queries array cannot be empty",
400
));
const s = await y(r);
return await R(e, s, n);
} catch (e) {
return r.log.error(e, "Batch execution error"), t.status(500).send(o(
e instanceof Error ? e.message : "Batch execution failed",
500
));
}
}), a.get(`${c}/meta`, async (r, t) => {
try {
const e = n.getMetadata();
return $(e);
} catch (e) {
return r.log.error(e, "Metadata error"), t.status(500).send(o(
e instanceof Error ? e.message : "Failed to fetch metadata",
500
));
}
}), a.post(`${c}/sql`, {
bodyLimit: m,
schema: {
body: {
type: "object",
additionalProperties: !0
}
}
}, async (r, t) => {
try {
const e = r.body, s = await y(r), i = n.validateQuery(e);
if (!i.isValid)
return t.status(400).send(o(
`Query validation failed: ${i.errors.join(", ")}`,
400
));
const u = e.measures?.[0] || e.dimensions?.[0];
if (!u)
return t.status(400).send(o(
"No measures or dimensions specified",
400
));
const d = u.split(".")[0], g = await n.generateSQL(d, e, s);
return q(e, g);
} catch (e) {
return r.log.error(e, "SQL generation error"), t.status(500).send(o(
e instanceof Error ? e.message : "SQL generation failed",
500
));
}
}), a.get(`${c}/sql`, {
schema: {
querystring: {
type: "object",
properties: {
query: { type: "string" }
},
required: ["query"]
}
}
}, async (r, t) => {
try {
const { query: e } = r.query, s = JSON.parse(e), i = await y(r), u = n.validateQuery(s);
if (!u.isValid)
return t.status(400).send(o(
`Query validation failed: ${u.errors.join(", ")}`,
400
));
const d = s.measures?.[0] || s.dimensions?.[0];
if (!d)
return t.status(400).send(o(
"No measures or dimensions specified",
400
));
const g = d.split(".")[0], j = await n.generateSQL(g, s, i);
return q(s, j);
} catch (e) {
return r.log.error(e, "SQL generation error"), t.status(500).send(o(
e instanceof Error ? e.message : "SQL generation failed",
500
));
}
}), a.post(`${c}/dry-run`, {
bodyLimit: m,
schema: {
body: {
type: "object",
additionalProperties: !0
}
}
}, async (r, t) => {
try {
const e = r.body, s = e.query || e, i = await y(r);
return await Q(s, i, n);
} 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
});
}
}), a.get(`${c}/dry-run`, {
schema: {
querystring: {
type: "object",
properties: {
query: { type: "string" }
},
required: ["query"]
}
}
}, async (r, t) => {
try {
const { query: e } = r.query, s = JSON.parse(e), i = await y(r);
return await Q(s, i, n);
} 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
});
}
}), a.setErrorHandler(async (r, t, e) => (t.log.error(r, "Fastify cube adapter error"), e.statusCode < 400 && e.status(500), o(r, e.statusCode))), p();
};
async function L(l, a) {
await l.register(v, a);
}
function N(l) {
const a = require("fastify")({
logger: !0
});
return a.register(v, l), a;
}
export {
N as createCubeApp,
v as cubePlugin,
L as registerCubeRoutes
};