UNPKG

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