drizzle-cube
Version:
Drizzle ORM-first semantic layer with Cube.js compatibility. Type-safe analytics and dashboards with SQL injection protection.
212 lines (211 loc) • 5.62 kB
JavaScript
var R = Object.defineProperty;
var O = (a, e, r) => e in a ? R(a, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : a[e] = r;
var f = (a, e, r) => O(a, typeof e != "symbol" ? e + "" : e, r);
import { jsx as $ } from "react/jsx-runtime";
import { useState as p, useCallback as w, useEffect as x, useContext as j, createContext as T, useMemo as U } from "react";
class D {
constructor(e, r = {}) {
f(this, "apiUrl");
f(this, "headers");
this.apiUrl = r.apiUrl || "/cubejs-api/v1", this.headers = {
"Content-Type": "application/json",
...r.headers
}, e && (this.headers.Authorization = e);
}
async load(e) {
const r = encodeURIComponent(JSON.stringify(e)), t = `${this.apiUrl}/load?query=${r}`, s = await fetch(t, {
method: "GET",
headers: {
// Remove Content-Type for GET request
...Object.fromEntries(
Object.entries(this.headers).filter(([n]) => n !== "Content-Type")
)
},
credentials: "include"
// Include cookies for session auth
});
if (!s.ok) {
let n = `Cube query failed: ${s.status}`;
try {
const l = await s.text();
try {
const c = JSON.parse(l);
c.error ? n = c.error : n += ` ${l}`;
} catch {
n += ` ${l}`;
}
} catch {
}
throw new Error(n);
}
const i = await s.json();
return new S(i);
}
async meta() {
const e = `${this.apiUrl}/meta`, r = await fetch(e, {
method: "GET",
headers: this.headers,
credentials: "include"
});
if (!r.ok)
throw new Error(`Failed to fetch meta: ${r.status}`);
return r.json();
}
async sql(e) {
const r = encodeURIComponent(JSON.stringify(e)), t = `${this.apiUrl}/sql?query=${r}`, s = await fetch(t, {
method: "GET",
headers: {
// Remove Content-Type for GET request
...Object.fromEntries(
Object.entries(this.headers).filter(([i]) => i !== "Content-Type")
)
},
credentials: "include"
});
if (!s.ok)
throw new Error(`SQL generation failed: ${s.status}`);
return s.json();
}
async dryRun(e) {
const r = `${this.apiUrl}/dry-run`, t = await fetch(r, {
method: "POST",
headers: this.headers,
credentials: "include",
body: JSON.stringify({ query: e })
});
if (!t.ok) {
let s = `Dry run failed: ${t.status}`;
try {
const i = await t.text();
try {
const n = JSON.parse(i);
n.error ? s = n.error : s += ` ${i}`;
} catch {
s += ` ${i}`;
}
} catch {
}
throw new Error(s);
}
return t.json();
}
}
class S {
constructor(e) {
f(this, "loadResponse");
this.loadResponse = e;
}
rawData() {
return this.loadResponse.results && this.loadResponse.results[0] ? this.loadResponse.results[0].data || [] : this.loadResponse.data || [];
}
tablePivot() {
return this.rawData();
}
series() {
return this.rawData();
}
annotation() {
return this.loadResponse.results && this.loadResponse.results[0] ? this.loadResponse.results[0].annotation || {} : this.loadResponse.annotation || {};
}
}
function L(a, e = {}) {
return new D(a, e);
}
const k = 15 * 60 * 1e3;
let u = null;
function q(a) {
const e = {};
return a.cubes.forEach((r) => {
r.measures.forEach((t) => {
e[t.name] = t.title || t.shortTitle || t.name;
}), r.dimensions.forEach((t) => {
e[t.name] = t.title || t.shortTitle || t.name;
}), r.segments.forEach((t) => {
e[t.name] = t.title || t.shortTitle || t.name;
});
}), e;
}
function v() {
return u ? Date.now() - u.timestamp < k : !1;
}
function P(a) {
const [e, r] = p(null), [t, s] = p({}), [i, n] = p(!0), [l, c] = p(null), h = w(async () => {
if (v() && u) {
r(u.data), s(u.labelMap), n(!1), c(null);
return;
}
try {
n(!0), c(null);
const o = await a.meta(), d = q(o);
u = {
data: o,
labelMap: d,
timestamp: Date.now()
}, r(o), s(d);
} catch (o) {
const d = o instanceof Error ? o.message : "Failed to fetch metadata";
c(d), console.error("Failed to fetch cube metadata:", o);
} finally {
n(!1);
}
}, [a]);
x(() => {
h();
}, [h]);
const m = w((o) => t[o] || o, [t]), b = w(() => {
u = null, h();
}, [h]);
return {
meta: e,
labelMap: t,
loading: i,
error: l,
refetch: b,
getFieldLabel: m
};
}
const C = T(null);
function I({
cubeApi: a,
apiOptions: e,
token: r,
options: t = {},
features: s = { enableAI: !0, aiEndpoint: "/api/ai/generate" },
// Default to AI enabled for backward compatibility
children: i
}) {
const [n, l] = p({
apiOptions: e || { apiUrl: "/cubejs-api/v1" },
token: r
}), c = U(() => a && !e && !r ? a : L(n.token, n.apiOptions), [a, e, r, n.apiOptions, n.token]), { meta: h, labelMap: m, loading: b, error: o, getFieldLabel: d, refetch: y } = P(c), E = {
cubeApi: c,
options: t,
meta: h,
labelMap: m,
metaLoading: b,
metaError: o,
getFieldLabel: d,
refetchMeta: y,
updateApiConfig: (g, M) => {
l({
apiOptions: g,
token: M
});
},
features: s
};
return /* @__PURE__ */ $(C.Provider, { value: E, children: i });
}
function G() {
const a = j(C);
if (!a)
throw new Error("useCubeContext must be used within a CubeProvider");
return a;
}
export {
I as C,
P as a,
L as c,
G as u
};
//# sourceMappingURL=providers-DI5zeeEU.js.map