drizzle-cube 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/hono/index.js +163 -94
- package/dist/client/client/CubeClient.d.ts +1 -0
- package/dist/client/components/Modal.d.ts +2 -1
- package/dist/client/components/QueryBuilder/CubeMetaExplorer.d.ts +4 -0
- package/dist/client/components/QueryBuilder/QueryPanel.d.ts +4 -0
- package/dist/client/components/QueryBuilder/ResultsPanel.d.ts +4 -0
- package/dist/client/components/QueryBuilder/SetupPanel.d.ts +11 -0
- package/dist/client/components/QueryBuilder/index.d.ts +3 -0
- package/dist/client/components/QueryBuilder/types.d.ts +132 -0
- package/dist/client/components/QueryBuilder/utils.d.ts +42 -0
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.js +11606 -9980
- package/dist/client/styles.css +1 -1
- package/dist/server/index.d.ts +10 -0
- package/dist/server/index.js +339 -313
- package/package.json +5 -1
|
@@ -1,63 +1,79 @@
|
|
|
1
|
-
import { Hono as
|
|
2
|
-
var
|
|
3
|
-
const
|
|
1
|
+
import { Hono as D } from "hono";
|
|
2
|
+
var S = (q) => {
|
|
3
|
+
const d = {
|
|
4
4
|
...{
|
|
5
5
|
origin: "*",
|
|
6
6
|
allowMethods: ["GET", "HEAD", "PUT", "POST", "DELETE", "PATCH"],
|
|
7
7
|
allowHeaders: [],
|
|
8
8
|
exposeHeaders: []
|
|
9
9
|
},
|
|
10
|
-
...
|
|
11
|
-
},
|
|
12
|
-
return async function(n,
|
|
13
|
-
var
|
|
14
|
-
function
|
|
15
|
-
n.res.headers.set(
|
|
10
|
+
...q
|
|
11
|
+
}, A = /* @__PURE__ */ ((u) => typeof u == "string" ? u === "*" ? () => u : (n) => u === n ? n : null : typeof u == "function" ? u : (n) => u.includes(n) ? n : null)(d.origin), j = ((u) => typeof u == "function" ? u : Array.isArray(u) ? () => u : () => [])(d.allowMethods);
|
|
12
|
+
return async function(n, m) {
|
|
13
|
+
var x;
|
|
14
|
+
function p(h, f) {
|
|
15
|
+
n.res.headers.set(h, f);
|
|
16
16
|
}
|
|
17
|
-
const
|
|
18
|
-
if (
|
|
19
|
-
const
|
|
20
|
-
|
|
17
|
+
const b = A(n.req.header("origin") || "", n);
|
|
18
|
+
if (b && p("Access-Control-Allow-Origin", b), d.origin !== "*") {
|
|
19
|
+
const h = n.req.header("Vary");
|
|
20
|
+
h ? p("Vary", h) : p("Vary", "Origin");
|
|
21
21
|
}
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
let
|
|
27
|
-
if (!(
|
|
28
|
-
const
|
|
29
|
-
|
|
22
|
+
if (d.credentials && p("Access-Control-Allow-Credentials", "true"), (x = d.exposeHeaders) != null && x.length && p("Access-Control-Expose-Headers", d.exposeHeaders.join(",")), n.req.method === "OPTIONS") {
|
|
23
|
+
d.maxAge != null && p("Access-Control-Max-Age", d.maxAge.toString());
|
|
24
|
+
const h = j(n.req.header("origin") || "", n);
|
|
25
|
+
h.length && p("Access-Control-Allow-Methods", h.join(","));
|
|
26
|
+
let f = d.allowHeaders;
|
|
27
|
+
if (!(f != null && f.length)) {
|
|
28
|
+
const e = n.req.header("Access-Control-Request-Headers");
|
|
29
|
+
e && (f = e.split(/\s*,\s*/));
|
|
30
30
|
}
|
|
31
|
-
return
|
|
31
|
+
return f != null && f.length && (p("Access-Control-Allow-Headers", f.join(",")), n.res.headers.append("Vary", "Access-Control-Request-Headers")), n.res.headers.delete("Content-Length"), n.res.headers.delete("Content-Type"), new Response(null, {
|
|
32
32
|
headers: n.res.headers,
|
|
33
33
|
status: 204,
|
|
34
34
|
statusText: "No Content"
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
|
-
await
|
|
37
|
+
await m();
|
|
38
38
|
};
|
|
39
39
|
};
|
|
40
|
-
function E(
|
|
40
|
+
function E(q) {
|
|
41
41
|
const {
|
|
42
42
|
semanticLayer: a,
|
|
43
|
-
drizzle:
|
|
44
|
-
schema:
|
|
45
|
-
getSecurityContext:
|
|
43
|
+
drizzle: d,
|
|
44
|
+
schema: A,
|
|
45
|
+
getSecurityContext: j,
|
|
46
46
|
cors: u,
|
|
47
47
|
basePath: n = "/cubejs-api/v1"
|
|
48
|
-
} =
|
|
49
|
-
u &&
|
|
48
|
+
} = q, m = new D();
|
|
49
|
+
u && m.use("/*", S(u)), a.hasExecutor() || a.setDrizzle(d, A), m.post(`${n}/load`, async (e) => {
|
|
50
50
|
try {
|
|
51
|
-
const r = await e.req.json(), s = r.query || r, t = await
|
|
51
|
+
const r = await e.req.json(), s = r.query || r, t = await j(e), o = a.validateQuery(s);
|
|
52
52
|
if (!o.isValid)
|
|
53
53
|
return e.json({
|
|
54
54
|
error: `Query validation failed: ${o.errors.join(", ")}`
|
|
55
55
|
}, 400);
|
|
56
|
-
const i = await a.executeMultiCubeQuery(s, t);
|
|
56
|
+
const i = await a.executeMultiCubeQuery(s, t), l = h(a), y = b(), g = (/* @__PURE__ */ new Date()).toISOString(), Q = x(s);
|
|
57
57
|
return e.json({
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
queryType: "regularQuery",
|
|
59
|
+
results: [{
|
|
60
|
+
query: s,
|
|
61
|
+
lastRefreshTime: g,
|
|
62
|
+
usedPreAggregations: {},
|
|
63
|
+
transformedQuery: Q,
|
|
64
|
+
requestId: y,
|
|
65
|
+
annotation: i.annotation,
|
|
66
|
+
dataSource: "default",
|
|
67
|
+
dbType: l,
|
|
68
|
+
extDbType: l,
|
|
69
|
+
external: !1,
|
|
70
|
+
slowQuery: !1,
|
|
71
|
+
data: i.data
|
|
72
|
+
}],
|
|
73
|
+
pivotQuery: {
|
|
74
|
+
...s,
|
|
75
|
+
queryType: "regularQuery"
|
|
76
|
+
},
|
|
61
77
|
slowQuery: !1
|
|
62
78
|
});
|
|
63
79
|
} catch (r) {
|
|
@@ -65,23 +81,39 @@ function E(y) {
|
|
|
65
81
|
error: r instanceof Error ? r.message : "Query execution failed"
|
|
66
82
|
}, 500);
|
|
67
83
|
}
|
|
68
|
-
}),
|
|
84
|
+
}), m.get(`${n}/load`, async (e) => {
|
|
69
85
|
try {
|
|
70
86
|
const r = e.req.query("query");
|
|
71
87
|
if (!r)
|
|
72
88
|
return e.json({
|
|
73
89
|
error: "Query parameter is required"
|
|
74
90
|
}, 400);
|
|
75
|
-
const s = JSON.parse(r), t = await
|
|
91
|
+
const s = JSON.parse(r), t = await j(e), o = a.validateQuery(s);
|
|
76
92
|
if (!o.isValid)
|
|
77
93
|
return e.json({
|
|
78
94
|
error: `Query validation failed: ${o.errors.join(", ")}`
|
|
79
95
|
}, 400);
|
|
80
|
-
const i = await a.executeMultiCubeQuery(s, t);
|
|
96
|
+
const i = await a.executeMultiCubeQuery(s, t), l = h(a), y = b(), g = (/* @__PURE__ */ new Date()).toISOString(), Q = x(s);
|
|
81
97
|
return e.json({
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
98
|
+
queryType: "regularQuery",
|
|
99
|
+
results: [{
|
|
100
|
+
query: s,
|
|
101
|
+
lastRefreshTime: g,
|
|
102
|
+
usedPreAggregations: {},
|
|
103
|
+
transformedQuery: Q,
|
|
104
|
+
requestId: y,
|
|
105
|
+
annotation: i.annotation,
|
|
106
|
+
dataSource: "default",
|
|
107
|
+
dbType: l,
|
|
108
|
+
extDbType: l,
|
|
109
|
+
external: !1,
|
|
110
|
+
slowQuery: !1,
|
|
111
|
+
data: i.data
|
|
112
|
+
}],
|
|
113
|
+
pivotQuery: {
|
|
114
|
+
...s,
|
|
115
|
+
queryType: "regularQuery"
|
|
116
|
+
},
|
|
85
117
|
slowQuery: !1
|
|
86
118
|
});
|
|
87
119
|
} catch (r) {
|
|
@@ -89,7 +121,7 @@ function E(y) {
|
|
|
89
121
|
error: r instanceof Error ? r.message : "Query execution failed"
|
|
90
122
|
}, 500);
|
|
91
123
|
}
|
|
92
|
-
}),
|
|
124
|
+
}), m.get(`${n}/meta`, (e) => {
|
|
93
125
|
try {
|
|
94
126
|
const r = a.getMetadata();
|
|
95
127
|
return e.json({
|
|
@@ -100,23 +132,23 @@ function E(y) {
|
|
|
100
132
|
error: r instanceof Error ? r.message : "Failed to fetch metadata"
|
|
101
133
|
}, 500);
|
|
102
134
|
}
|
|
103
|
-
}),
|
|
135
|
+
}), m.post(`${n}/sql`, async (e) => {
|
|
104
136
|
var r, s;
|
|
105
137
|
try {
|
|
106
|
-
const t = await e.req.json(), o = await
|
|
138
|
+
const t = await e.req.json(), o = await j(e), i = a.validateQuery(t);
|
|
107
139
|
if (!i.isValid)
|
|
108
140
|
return e.json({
|
|
109
141
|
error: `Query validation failed: ${i.errors.join(", ")}`
|
|
110
142
|
}, 400);
|
|
111
|
-
const
|
|
112
|
-
if (!
|
|
143
|
+
const l = ((r = t.measures) == null ? void 0 : r[0]) || ((s = t.dimensions) == null ? void 0 : s[0]);
|
|
144
|
+
if (!l)
|
|
113
145
|
return e.json({
|
|
114
146
|
error: "No measures or dimensions specified"
|
|
115
147
|
}, 400);
|
|
116
|
-
const
|
|
148
|
+
const y = l.split(".")[0], g = await a.generateSQL(y, t, o);
|
|
117
149
|
return e.json({
|
|
118
|
-
sql:
|
|
119
|
-
params:
|
|
150
|
+
sql: g.sql,
|
|
151
|
+
params: g.params || [],
|
|
120
152
|
query: t
|
|
121
153
|
});
|
|
122
154
|
} catch (t) {
|
|
@@ -124,7 +156,7 @@ function E(y) {
|
|
|
124
156
|
error: t instanceof Error ? t.message : "SQL generation failed"
|
|
125
157
|
}, 500);
|
|
126
158
|
}
|
|
127
|
-
}),
|
|
159
|
+
}), m.get(`${n}/sql`, async (e) => {
|
|
128
160
|
var r, s;
|
|
129
161
|
try {
|
|
130
162
|
const t = e.req.query("query");
|
|
@@ -132,17 +164,17 @@ function E(y) {
|
|
|
132
164
|
return e.json({
|
|
133
165
|
error: "Query parameter is required"
|
|
134
166
|
}, 400);
|
|
135
|
-
const o = JSON.parse(t), i = await
|
|
136
|
-
if (!
|
|
167
|
+
const o = JSON.parse(t), i = await j(e), l = a.validateQuery(o);
|
|
168
|
+
if (!l.isValid)
|
|
137
169
|
return e.json({
|
|
138
|
-
error: `Query validation failed: ${
|
|
170
|
+
error: `Query validation failed: ${l.errors.join(", ")}`
|
|
139
171
|
}, 400);
|
|
140
|
-
const
|
|
141
|
-
if (!
|
|
172
|
+
const y = ((r = o.measures) == null ? void 0 : r[0]) || ((s = o.dimensions) == null ? void 0 : s[0]);
|
|
173
|
+
if (!y)
|
|
142
174
|
return e.json({
|
|
143
175
|
error: "No measures or dimensions specified"
|
|
144
176
|
}, 400);
|
|
145
|
-
const
|
|
177
|
+
const g = y.split(".")[0], Q = await a.generateSQL(g, o, i);
|
|
146
178
|
return e.json({
|
|
147
179
|
sql: Q.sql,
|
|
148
180
|
params: Q.params || [],
|
|
@@ -154,30 +186,67 @@ function E(y) {
|
|
|
154
186
|
}, 500);
|
|
155
187
|
}
|
|
156
188
|
});
|
|
157
|
-
function
|
|
189
|
+
function p(e) {
|
|
158
190
|
var s, t, o, i;
|
|
159
191
|
let r = 0;
|
|
160
192
|
return r += (((s = e.measures) == null ? void 0 : s.length) || 0) * 1, r += (((t = e.dimensions) == null ? void 0 : t.length) || 0) * 1, r += (((o = e.filters) == null ? void 0 : o.length) || 0) * 2, r += (((i = e.timeDimensions) == null ? void 0 : i.length) || 0) * 3, r <= 5 ? "low" : r <= 15 ? "medium" : "high";
|
|
161
193
|
}
|
|
162
|
-
|
|
163
|
-
|
|
194
|
+
function b() {
|
|
195
|
+
const e = Date.now(), r = Math.random().toString(36).substring(2, 9);
|
|
196
|
+
return `${e}-${r}`;
|
|
197
|
+
}
|
|
198
|
+
function x(e) {
|
|
199
|
+
const r = e.dimensions || [], s = e.timeDimensions || [], t = e.measures || [];
|
|
200
|
+
return {
|
|
201
|
+
sortedDimensions: r,
|
|
202
|
+
sortedTimeDimensions: s,
|
|
203
|
+
timeDimensions: s,
|
|
204
|
+
measures: t,
|
|
205
|
+
leafMeasureAdditive: !0,
|
|
206
|
+
leafMeasures: t,
|
|
207
|
+
measureToLeafMeasures: {},
|
|
208
|
+
hasNoTimeDimensionsWithoutGranularity: !0,
|
|
209
|
+
allFiltersWithinSelectedDimensions: !0,
|
|
210
|
+
isAdditive: !0,
|
|
211
|
+
granularityHierarchies: {},
|
|
212
|
+
hasMultipliedMeasures: !1,
|
|
213
|
+
hasCumulativeMeasures: !1,
|
|
214
|
+
windowGranularity: null,
|
|
215
|
+
filterDimensionsSingleValueEqual: {},
|
|
216
|
+
ownedDimensions: r,
|
|
217
|
+
ownedTimeDimensionsWithRollupGranularity: [],
|
|
218
|
+
ownedTimeDimensionsAsIs: [],
|
|
219
|
+
allBackAliasMembers: {},
|
|
220
|
+
hasMultiStage: !1
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
function h(e) {
|
|
224
|
+
if (e.hasExecutor()) {
|
|
225
|
+
const r = e.databaseExecutor;
|
|
226
|
+
if (r != null && r.engineType)
|
|
227
|
+
return r.engineType;
|
|
228
|
+
}
|
|
229
|
+
return "postgres";
|
|
230
|
+
}
|
|
231
|
+
async function f(e, r) {
|
|
232
|
+
var y, g, Q, v;
|
|
164
233
|
const s = a.validateQuery(e);
|
|
165
234
|
if (!s.isValid)
|
|
166
235
|
throw new Error(`Query validation failed: ${s.errors.join(", ")}`);
|
|
167
236
|
const t = /* @__PURE__ */ new Set();
|
|
168
|
-
(
|
|
169
|
-
const
|
|
170
|
-
t.add(
|
|
171
|
-
}), (
|
|
172
|
-
const
|
|
173
|
-
t.add(
|
|
174
|
-
}), (Q = e.timeDimensions) == null || Q.forEach((
|
|
175
|
-
const
|
|
176
|
-
t.add(
|
|
177
|
-
}), (
|
|
178
|
-
if ("member" in
|
|
179
|
-
const
|
|
180
|
-
t.add(
|
|
237
|
+
(y = e.measures) == null || y.forEach((c) => {
|
|
238
|
+
const w = c.split(".")[0];
|
|
239
|
+
t.add(w);
|
|
240
|
+
}), (g = e.dimensions) == null || g.forEach((c) => {
|
|
241
|
+
const w = c.split(".")[0];
|
|
242
|
+
t.add(w);
|
|
243
|
+
}), (Q = e.timeDimensions) == null || Q.forEach((c) => {
|
|
244
|
+
const w = c.dimension.split(".")[0];
|
|
245
|
+
t.add(w);
|
|
246
|
+
}), (v = e.filters) == null || v.forEach((c) => {
|
|
247
|
+
if ("member" in c) {
|
|
248
|
+
const w = c.member.split(".")[0];
|
|
249
|
+
t.add(w);
|
|
181
250
|
}
|
|
182
251
|
});
|
|
183
252
|
const o = t.size > 1;
|
|
@@ -185,16 +254,16 @@ function E(y) {
|
|
|
185
254
|
if (o)
|
|
186
255
|
i = await a.generateMultiCubeSQL(e, r);
|
|
187
256
|
else {
|
|
188
|
-
const
|
|
189
|
-
i = await a.generateSQL(
|
|
257
|
+
const c = Array.from(t)[0];
|
|
258
|
+
i = await a.generateSQL(c, e, r);
|
|
190
259
|
}
|
|
191
|
-
const
|
|
192
|
-
var
|
|
260
|
+
const l = Array.from(t).map((c) => {
|
|
261
|
+
var w, T;
|
|
193
262
|
return {
|
|
194
|
-
cube:
|
|
263
|
+
cube: c,
|
|
195
264
|
query: {
|
|
196
|
-
measures: ((
|
|
197
|
-
dimensions: ((
|
|
265
|
+
measures: ((w = e.measures) == null ? void 0 : w.filter((C) => C.startsWith(c + "."))) || [],
|
|
266
|
+
dimensions: ((T = e.dimensions) == null ? void 0 : T.filter((C) => C.startsWith(c + "."))) || [],
|
|
198
267
|
filters: e.filters || [],
|
|
199
268
|
timeDimensions: e.timeDimensions || [],
|
|
200
269
|
order: e.order || {},
|
|
@@ -205,9 +274,9 @@ function E(y) {
|
|
|
205
274
|
});
|
|
206
275
|
return {
|
|
207
276
|
queryType: "regularQuery",
|
|
208
|
-
normalizedQueries:
|
|
277
|
+
normalizedQueries: l,
|
|
209
278
|
queryOrder: Array.from(t),
|
|
210
|
-
transformedQueries:
|
|
279
|
+
transformedQueries: l,
|
|
211
280
|
pivotQuery: {
|
|
212
281
|
query: e,
|
|
213
282
|
cubes: Array.from(t)
|
|
@@ -216,16 +285,16 @@ function E(y) {
|
|
|
216
285
|
sql: [i.sql],
|
|
217
286
|
params: i.params || []
|
|
218
287
|
},
|
|
219
|
-
complexity:
|
|
288
|
+
complexity: p(e),
|
|
220
289
|
valid: !0,
|
|
221
290
|
cubesUsed: Array.from(t),
|
|
222
291
|
joinType: o ? "multi_cube_join" : "single_cube",
|
|
223
292
|
query: e
|
|
224
293
|
};
|
|
225
294
|
}
|
|
226
|
-
return
|
|
295
|
+
return m.post(`${n}/dry-run`, async (e) => {
|
|
227
296
|
try {
|
|
228
|
-
const r = await e.req.json(), s = r.query || r, t = await
|
|
297
|
+
const r = await e.req.json(), s = r.query || r, t = await j(e), o = await f(s, t);
|
|
229
298
|
return e.json(o);
|
|
230
299
|
} catch (r) {
|
|
231
300
|
return console.error("Dry-run error:", r), e.json({
|
|
@@ -233,7 +302,7 @@ function E(y) {
|
|
|
233
302
|
valid: !1
|
|
234
303
|
}, 400);
|
|
235
304
|
}
|
|
236
|
-
}),
|
|
305
|
+
}), m.get(`${n}/dry-run`, async (e) => {
|
|
237
306
|
try {
|
|
238
307
|
const r = e.req.query("query");
|
|
239
308
|
if (!r)
|
|
@@ -241,7 +310,7 @@ function E(y) {
|
|
|
241
310
|
error: "Query parameter is required",
|
|
242
311
|
valid: !1
|
|
243
312
|
}, 400);
|
|
244
|
-
const s = JSON.parse(r), t = await
|
|
313
|
+
const s = JSON.parse(r), t = await j(e), o = await f(s, t);
|
|
245
314
|
return e.json(o);
|
|
246
315
|
} catch (r) {
|
|
247
316
|
return console.error("Dry-run error:", r), e.json({
|
|
@@ -249,18 +318,18 @@ function E(y) {
|
|
|
249
318
|
valid: !1
|
|
250
319
|
}, 400);
|
|
251
320
|
}
|
|
252
|
-
}),
|
|
321
|
+
}), m;
|
|
253
322
|
}
|
|
254
|
-
function
|
|
255
|
-
const
|
|
256
|
-
return
|
|
323
|
+
function M(q, a) {
|
|
324
|
+
const d = E(a);
|
|
325
|
+
return q.route("/", d), q;
|
|
257
326
|
}
|
|
258
|
-
function
|
|
259
|
-
const a = new
|
|
260
|
-
return
|
|
327
|
+
function R(q) {
|
|
328
|
+
const a = new D();
|
|
329
|
+
return M(a, q);
|
|
261
330
|
}
|
|
262
331
|
export {
|
|
263
|
-
|
|
332
|
+
R as createCubeApp,
|
|
264
333
|
E as createCubeRoutes,
|
|
265
|
-
|
|
334
|
+
M as mountCubeRoutes
|
|
266
335
|
};
|
|
@@ -3,13 +3,14 @@ export interface ModalProps {
|
|
|
3
3
|
isOpen: boolean;
|
|
4
4
|
onClose: () => void;
|
|
5
5
|
title?: string;
|
|
6
|
-
size?: 'sm' | 'md' | 'lg' | 'xl' | 'full';
|
|
6
|
+
size?: 'sm' | 'md' | 'lg' | 'xl' | 'full' | 'fullscreen';
|
|
7
7
|
closeOnBackdropClick?: boolean;
|
|
8
8
|
closeOnEscape?: boolean;
|
|
9
9
|
showCloseButton?: boolean;
|
|
10
10
|
className?: string;
|
|
11
11
|
children: React.ReactNode;
|
|
12
12
|
footer?: React.ReactNode;
|
|
13
|
+
noPadding?: boolean;
|
|
13
14
|
}
|
|
14
15
|
declare const Modal: React.FC<ModalProps>;
|
|
15
16
|
export default Modal;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { ApiConfig } from './types';
|
|
3
|
+
interface SetupPanelProps {
|
|
4
|
+
isOpen: boolean;
|
|
5
|
+
onToggle: () => void;
|
|
6
|
+
config: ApiConfig;
|
|
7
|
+
onConfigChange: (config: ApiConfig) => void;
|
|
8
|
+
onReset: () => void;
|
|
9
|
+
}
|
|
10
|
+
declare const SetupPanel: React.FC<SetupPanelProps>;
|
|
11
|
+
export default SetupPanel;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { CubeQuery } from '../../types';
|
|
2
|
+
export interface MetaField {
|
|
3
|
+
name: string;
|
|
4
|
+
title: string;
|
|
5
|
+
shortTitle: string;
|
|
6
|
+
type: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface MetaCube {
|
|
10
|
+
name: string;
|
|
11
|
+
title: string;
|
|
12
|
+
description: string;
|
|
13
|
+
measures: MetaField[];
|
|
14
|
+
dimensions: MetaField[];
|
|
15
|
+
segments: MetaField[];
|
|
16
|
+
}
|
|
17
|
+
export interface MetaResponse {
|
|
18
|
+
cubes: MetaCube[];
|
|
19
|
+
}
|
|
20
|
+
export type ValidationStatus = 'idle' | 'validating' | 'valid' | 'invalid';
|
|
21
|
+
export type ExecutionStatus = 'idle' | 'loading' | 'success' | 'error';
|
|
22
|
+
export type SchemaStatus = 'idle' | 'loading' | 'success' | 'error';
|
|
23
|
+
export interface QueryBuilderState {
|
|
24
|
+
query: CubeQuery;
|
|
25
|
+
schema: MetaResponse | null;
|
|
26
|
+
schemaStatus: SchemaStatus;
|
|
27
|
+
schemaError: string | null;
|
|
28
|
+
validationStatus: ValidationStatus;
|
|
29
|
+
validationError: string | null;
|
|
30
|
+
validationSql: {
|
|
31
|
+
sql: string[];
|
|
32
|
+
params: any[];
|
|
33
|
+
} | null;
|
|
34
|
+
executionStatus: ExecutionStatus;
|
|
35
|
+
executionResults: any[] | null;
|
|
36
|
+
executionError: string | null;
|
|
37
|
+
totalRowCount: number | null;
|
|
38
|
+
totalRowCountStatus: 'idle' | 'loading' | 'success' | 'error';
|
|
39
|
+
}
|
|
40
|
+
export interface ValidationResult {
|
|
41
|
+
valid?: boolean;
|
|
42
|
+
error?: string;
|
|
43
|
+
query?: CubeQuery;
|
|
44
|
+
sql?: {
|
|
45
|
+
sql: string[];
|
|
46
|
+
params: any[];
|
|
47
|
+
};
|
|
48
|
+
queryType?: string;
|
|
49
|
+
normalizedQueries?: any[];
|
|
50
|
+
queryOrder?: string[];
|
|
51
|
+
transformedQueries?: any[];
|
|
52
|
+
pivotQuery?: any;
|
|
53
|
+
complexity?: string;
|
|
54
|
+
cubesUsed?: string[];
|
|
55
|
+
joinType?: string;
|
|
56
|
+
}
|
|
57
|
+
export interface ApiConfig {
|
|
58
|
+
baseApiUrl: string;
|
|
59
|
+
apiToken: string;
|
|
60
|
+
}
|
|
61
|
+
export interface QueryBuilderProps {
|
|
62
|
+
baseUrl: string;
|
|
63
|
+
className?: string;
|
|
64
|
+
initialQuery?: CubeQuery;
|
|
65
|
+
disableLocalStorage?: boolean;
|
|
66
|
+
hideSettings?: boolean;
|
|
67
|
+
}
|
|
68
|
+
export interface QueryBuilderRef {
|
|
69
|
+
getCurrentQuery: () => CubeQuery;
|
|
70
|
+
getValidationState: () => {
|
|
71
|
+
status: ValidationStatus;
|
|
72
|
+
result?: ValidationResult;
|
|
73
|
+
};
|
|
74
|
+
getValidationResult: () => ValidationResult | null;
|
|
75
|
+
}
|
|
76
|
+
export interface CubeMetaExplorerProps {
|
|
77
|
+
schema: MetaResponse | null;
|
|
78
|
+
schemaStatus: SchemaStatus;
|
|
79
|
+
schemaError: string | null;
|
|
80
|
+
selectedFields: {
|
|
81
|
+
measures: string[];
|
|
82
|
+
dimensions: string[];
|
|
83
|
+
timeDimensions: string[];
|
|
84
|
+
};
|
|
85
|
+
onFieldSelect: (fieldName: string, fieldType: 'measures' | 'dimensions' | 'timeDimensions') => void;
|
|
86
|
+
onFieldDeselect: (fieldName: string, fieldType: 'measures' | 'dimensions' | 'timeDimensions') => void;
|
|
87
|
+
onRetrySchema?: () => void;
|
|
88
|
+
onOpenSettings?: () => void;
|
|
89
|
+
}
|
|
90
|
+
export interface QueryPanelProps {
|
|
91
|
+
query: CubeQuery;
|
|
92
|
+
validationStatus: ValidationStatus;
|
|
93
|
+
validationError: string | null;
|
|
94
|
+
validationSql: {
|
|
95
|
+
sql: string[];
|
|
96
|
+
params: any[];
|
|
97
|
+
} | null;
|
|
98
|
+
onValidate: () => void;
|
|
99
|
+
onExecute: () => void;
|
|
100
|
+
onRemoveField: (fieldName: string, fieldType: 'measures' | 'dimensions' | 'timeDimensions') => void;
|
|
101
|
+
onTimeDimensionGranularityChange: (dimensionName: string, granularity: string) => void;
|
|
102
|
+
onClearQuery?: () => void;
|
|
103
|
+
showSettings?: boolean;
|
|
104
|
+
onSettingsClick?: () => void;
|
|
105
|
+
}
|
|
106
|
+
export interface ResultsPanelProps {
|
|
107
|
+
executionStatus: ExecutionStatus;
|
|
108
|
+
executionResults: any[] | null;
|
|
109
|
+
executionError: string | null;
|
|
110
|
+
query: CubeQuery;
|
|
111
|
+
displayLimit?: number;
|
|
112
|
+
onDisplayLimitChange?: (limit: number) => void;
|
|
113
|
+
totalRowCount?: number | null;
|
|
114
|
+
totalRowCountStatus?: 'idle' | 'loading' | 'success' | 'error';
|
|
115
|
+
}
|
|
116
|
+
export declare const TIME_GRANULARITIES: readonly [{
|
|
117
|
+
readonly value: "day";
|
|
118
|
+
readonly label: "Day";
|
|
119
|
+
}, {
|
|
120
|
+
readonly value: "week";
|
|
121
|
+
readonly label: "Week";
|
|
122
|
+
}, {
|
|
123
|
+
readonly value: "month";
|
|
124
|
+
readonly label: "Month";
|
|
125
|
+
}, {
|
|
126
|
+
readonly value: "quarter";
|
|
127
|
+
readonly label: "Quarter";
|
|
128
|
+
}, {
|
|
129
|
+
readonly value: "year";
|
|
130
|
+
readonly label: "Year";
|
|
131
|
+
}];
|
|
132
|
+
export type TimeGranularity = typeof TIME_GRANULARITIES[number]['value'];
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { CubeQuery } from '../../types';
|
|
2
|
+
import { MetaField, MetaResponse } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Check if a field is selected in the current query
|
|
5
|
+
*/
|
|
6
|
+
export declare function isFieldSelected(fieldName: string, fieldType: 'measures' | 'dimensions' | 'timeDimensions', query: CubeQuery): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Get all time dimension fields from schema
|
|
9
|
+
*/
|
|
10
|
+
export declare function getTimeDimensionFields(schema: MetaResponse): MetaField[];
|
|
11
|
+
/**
|
|
12
|
+
* Get all non-time dimension fields from schema
|
|
13
|
+
*/
|
|
14
|
+
export declare function getRegularDimensionFields(schema: MetaResponse): MetaField[];
|
|
15
|
+
/**
|
|
16
|
+
* Get all measure fields from schema
|
|
17
|
+
*/
|
|
18
|
+
export declare function getMeasureFields(schema: MetaResponse): MetaField[];
|
|
19
|
+
/**
|
|
20
|
+
* Check if query has any content (measures, dimensions, or timeDimensions)
|
|
21
|
+
*/
|
|
22
|
+
export declare function hasQueryContent(query: CubeQuery): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Get count of selected fields across all types
|
|
25
|
+
*/
|
|
26
|
+
export declare function getSelectedFieldsCount(query: CubeQuery): number;
|
|
27
|
+
/**
|
|
28
|
+
* Get cube name from field name (e.g., "Employees.count" -> "Employees")
|
|
29
|
+
*/
|
|
30
|
+
export declare function getCubeNameFromField(fieldName: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Group fields by cube name
|
|
33
|
+
*/
|
|
34
|
+
export declare function groupFieldsByCube(fields: MetaField[]): Record<string, MetaField[]>;
|
|
35
|
+
/**
|
|
36
|
+
* Clean query object by removing empty arrays
|
|
37
|
+
*/
|
|
38
|
+
export declare function cleanQuery(query: CubeQuery): CubeQuery;
|
|
39
|
+
/**
|
|
40
|
+
* Create an empty query object
|
|
41
|
+
*/
|
|
42
|
+
export declare function createEmptyQuery(): CubeQuery;
|
package/dist/client/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export { default as PortletEditModal } from './components/PortletEditModal';
|
|
|
7
7
|
export { default as DashboardEditModal } from './components/DashboardEditModal';
|
|
8
8
|
export { default as Modal } from './components/Modal';
|
|
9
9
|
export { default as ChartConfigEditor } from './components/ChartConfigEditor';
|
|
10
|
+
export { default as QueryBuilder } from './components/QueryBuilder';
|
|
10
11
|
export { CubeProvider } from './providers/CubeProvider';
|
|
11
12
|
export { useCubeQuery } from './hooks/useCubeQuery';
|
|
12
13
|
export { createCubeClient } from './client/CubeClient';
|