drizzle-cube 0.1.2 → 0.1.4
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/README.md +28 -67
- package/dist/adapters/hono/index.d.ts +5 -1
- package/dist/adapters/hono/index.js +187 -93
- package/dist/client/client/CubeClient.d.ts +14 -0
- package/dist/client/components/AnalyticsDashboard.d.ts +2 -0
- package/dist/client/components/AnalyticsPage.d.ts +1 -0
- package/dist/client/components/AnalyticsPortlet.d.ts +6 -0
- package/dist/client/components/ChartConfigEditor.d.ts +8 -0
- package/dist/client/components/ChartErrorBoundary.d.ts +21 -0
- package/dist/client/components/DashboardEditModal.d.ts +14 -0
- package/dist/client/components/DashboardGrid.d.ts +11 -0
- package/dist/client/components/Modal.d.ts +15 -0
- package/dist/client/components/PortletContainer.d.ts +10 -0
- package/dist/client/components/PortletEditModal.d.ts +12 -0
- package/dist/client/components/charts/AreaChart.d.ts +2 -0
- package/dist/client/components/charts/BarChart.d.ts +2 -0
- package/dist/client/components/charts/ChartContainer.d.ts +7 -0
- package/dist/client/components/charts/ChartLegend.d.ts +7 -0
- package/dist/client/components/charts/ChartTooltip.d.ts +7 -0
- package/dist/client/components/charts/DataTable.d.ts +2 -0
- package/dist/client/components/charts/LineChart.d.ts +2 -0
- package/dist/client/components/charts/PieChart.d.ts +2 -0
- package/dist/client/components/charts/RadarChart.d.ts +2 -0
- package/dist/client/components/charts/RadialBarChart.d.ts +2 -0
- package/dist/client/components/charts/ScatterChart.d.ts +2 -0
- package/dist/client/components/charts/TreeMapChart.d.ts +2 -0
- package/dist/client/components/charts/index.d.ts +13 -0
- package/dist/client/hooks/useCubeQuery.d.ts +8 -0
- package/dist/client/index.d.ts +14 -0
- package/dist/client/index.js +23813 -4
- package/dist/client/providers/CubeProvider.d.ts +15 -0
- package/dist/client/styles.css +1 -0
- package/dist/client/types.d.ts +111 -0
- package/dist/client/utils/chartConstants.d.ts +15 -0
- package/dist/client/utils/chartUtils.d.ts +9 -0
- package/dist/client/utils/index.d.ts +87 -0
- package/dist/server/index.d.ts +74 -1155
- package/dist/server/index.js +1036 -2842
- package/package.json +10 -3
package/README.md
CHANGED
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
Transform your Drizzle schema into a powerful, type-safe analytics platform with SQL injection protection and full TypeScript support.
|
|
6
6
|
|
|
7
|
+
📖 **[Documentation](https://www.drizzle-cube.dev/)** • 🚀 **[Try the Sandbox](https://try.drizzle-cube.dev/)**
|
|
8
|
+
|
|
9
|
+
> **⚠️ DEVELOPMENT WARNING**
|
|
10
|
+
> **This project is under active development and is not yet fully functional. I will update here when we reach an alpha/working version!**
|
|
11
|
+
> Feel free to star ⭐ the repo to stay updated on progress.
|
|
12
|
+
|
|
7
13
|
[](https://www.npmjs.com/package/drizzle-cube)
|
|
8
14
|
[](https://www.typescriptlang.org/)
|
|
9
15
|
[](https://orm.drizzle.team/)
|
|
@@ -240,56 +246,6 @@ Works with multiple frameworks via adapter pattern:
|
|
|
240
246
|
|
|
241
247
|
## Advanced Usage
|
|
242
248
|
|
|
243
|
-
### Complex Queries with CTEs
|
|
244
|
-
|
|
245
|
-
```typescript
|
|
246
|
-
import { sql } from 'drizzle-orm'
|
|
247
|
-
|
|
248
|
-
const advancedCube = defineCube('DepartmentAnalytics', {
|
|
249
|
-
title: 'Department Analytics',
|
|
250
|
-
|
|
251
|
-
// For complex queries, you can use raw SQL
|
|
252
|
-
sql: (ctx) => sql`
|
|
253
|
-
WITH department_stats AS (
|
|
254
|
-
SELECT
|
|
255
|
-
d.id,
|
|
256
|
-
d.name,
|
|
257
|
-
COUNT(e.id) as employee_count,
|
|
258
|
-
AVG(e.salary) as avg_salary
|
|
259
|
-
FROM ${schema.departments} d
|
|
260
|
-
LEFT JOIN ${schema.employees} e ON d.id = e.department_id
|
|
261
|
-
WHERE d.organisation_id = ${ctx.securityContext.organisationId}
|
|
262
|
-
GROUP BY d.id, d.name
|
|
263
|
-
)
|
|
264
|
-
SELECT * FROM department_stats
|
|
265
|
-
`,
|
|
266
|
-
|
|
267
|
-
dimensions: {
|
|
268
|
-
name: {
|
|
269
|
-
name: 'name',
|
|
270
|
-
title: 'Department Name',
|
|
271
|
-
sql: sql`name`,
|
|
272
|
-
type: 'string'
|
|
273
|
-
}
|
|
274
|
-
},
|
|
275
|
-
|
|
276
|
-
measures: {
|
|
277
|
-
employeeCount: {
|
|
278
|
-
name: 'employeeCount',
|
|
279
|
-
title: 'Employee Count',
|
|
280
|
-
sql: sql`employee_count`,
|
|
281
|
-
type: 'number'
|
|
282
|
-
},
|
|
283
|
-
avgSalary: {
|
|
284
|
-
name: 'avgSalary',
|
|
285
|
-
title: 'Average Salary',
|
|
286
|
-
sql: sql`avg_salary`,
|
|
287
|
-
type: 'number',
|
|
288
|
-
format: 'currency'
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
})
|
|
292
|
-
```
|
|
293
249
|
|
|
294
250
|
### Advanced Security with Row-Level Security
|
|
295
251
|
|
|
@@ -330,21 +286,6 @@ const secureCube = defineCube('SecureEmployees', {
|
|
|
330
286
|
})
|
|
331
287
|
```
|
|
332
288
|
|
|
333
|
-
### Multiple Database Support
|
|
334
|
-
|
|
335
|
-
```typescript
|
|
336
|
-
// PostgreSQL
|
|
337
|
-
import { drizzle } from 'drizzle-orm/postgres-js'
|
|
338
|
-
import postgres from 'postgres'
|
|
339
|
-
|
|
340
|
-
// MySQL
|
|
341
|
-
import { drizzle } from 'drizzle-orm/mysql2'
|
|
342
|
-
import mysql from 'mysql2/promise'
|
|
343
|
-
|
|
344
|
-
// SQLite
|
|
345
|
-
import { drizzle } from 'drizzle-orm/better-sqlite3'
|
|
346
|
-
import Database from 'better-sqlite3'
|
|
347
|
-
```
|
|
348
289
|
|
|
349
290
|
## API Reference
|
|
350
291
|
|
|
@@ -379,11 +320,31 @@ Supports all Cube.js filter operators with Drizzle safety:
|
|
|
379
320
|
|
|
380
321
|
## Documentation
|
|
381
322
|
|
|
382
|
-
|
|
323
|
+
📚 **[Full Documentation](https://drizzle-cube.dev/help)** - Complete guides and API reference
|
|
324
|
+
|
|
325
|
+
### Quick Links
|
|
326
|
+
- [Getting Started](https://drizzle-cube.dev/help/getting-started) - Installation and first steps
|
|
327
|
+
- [Core Concepts](https://drizzle-cube.dev/help/getting-started/concepts) - Cubes, dimensions, and measures
|
|
328
|
+
- [Semantic Layer](https://drizzle-cube.dev/help/semantic-layer) - Advanced semantic layer features
|
|
329
|
+
- [React Client](https://drizzle-cube.dev/help/client) - Dashboard and chart components
|
|
330
|
+
- [Hono Adapter](https://drizzle-cube.dev/help/adapters/hono) - Web framework integration
|
|
331
|
+
- [Security](https://drizzle-cube.dev/help/semantic-layer/security) - Multi-tenant security patterns
|
|
332
|
+
|
|
333
|
+
### Local Development
|
|
334
|
+
```bash
|
|
335
|
+
# Run documentation site locally
|
|
336
|
+
npm run dev:help
|
|
337
|
+
|
|
338
|
+
# Build documentation site
|
|
339
|
+
npm run build:help
|
|
340
|
+
```
|
|
383
341
|
|
|
384
342
|
## Examples
|
|
385
343
|
|
|
386
|
-
|
|
344
|
+
🚀 **[Live Examples](https://github.com/cliftonc/drizzle-cube/tree/main/examples)**
|
|
345
|
+
|
|
346
|
+
- **[Basic Example](https://github.com/cliftonc/drizzle-cube/tree/main/examples/basic)** - Simple semantic layer setup
|
|
347
|
+
- **[Hono Example](https://github.com/cliftonc/drizzle-cube/tree/main/examples/hono)** - Full-featured dashboard with Cloudflare Workers
|
|
387
348
|
|
|
388
349
|
## Contributing
|
|
389
350
|
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
2
|
import { SemanticLayerCompiler, SemanticQuery, SecurityContext, DatabaseExecutor, DrizzleDatabase } from '../../server';
|
|
3
|
+
import { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
|
|
4
|
+
import { MySql2Database } from 'drizzle-orm/mysql2';
|
|
5
|
+
import { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
|
|
3
6
|
export interface HonoAdapterOptions<TSchema extends Record<string, any> = Record<string, any>> {
|
|
4
7
|
/**
|
|
5
8
|
* The semantic layer instance to use
|
|
@@ -8,8 +11,9 @@ export interface HonoAdapterOptions<TSchema extends Record<string, any> = Record
|
|
|
8
11
|
/**
|
|
9
12
|
* Drizzle database instance (REQUIRED)
|
|
10
13
|
* This is the core of drizzle-cube - Drizzle ORM integration
|
|
14
|
+
* Accepts PostgreSQL, MySQL, or SQLite database instances
|
|
11
15
|
*/
|
|
12
|
-
drizzle: DrizzleDatabase<TSchema>;
|
|
16
|
+
drizzle: PostgresJsDatabase<TSchema> | MySql2Database<TSchema> | BetterSQLite3Database<TSchema> | DrizzleDatabase<TSchema>;
|
|
13
17
|
/**
|
|
14
18
|
* Database schema for type inference (RECOMMENDED)
|
|
15
19
|
* Provides full type safety for cube definitions
|
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
import { Hono as
|
|
2
|
-
var
|
|
3
|
-
const
|
|
1
|
+
import { Hono as v } from "hono";
|
|
2
|
+
var A = (y) => {
|
|
3
|
+
const c = {
|
|
4
4
|
...{
|
|
5
5
|
origin: "*",
|
|
6
6
|
allowMethods: ["GET", "HEAD", "PUT", "POST", "DELETE", "PATCH"],
|
|
7
7
|
allowHeaders: [],
|
|
8
8
|
exposeHeaders: []
|
|
9
9
|
},
|
|
10
|
-
...
|
|
11
|
-
}, q = /* @__PURE__ */ ((
|
|
12
|
-
return async function(
|
|
13
|
-
var
|
|
14
|
-
function
|
|
15
|
-
|
|
10
|
+
...y
|
|
11
|
+
}, q = /* @__PURE__ */ ((u) => typeof u == "string" ? u === "*" ? () => u : (n) => u === n ? n : null : typeof u == "function" ? u : (n) => u.includes(n) ? n : null)(c.origin), g = ((u) => typeof u == "function" ? u : Array.isArray(u) ? () => u : () => [])(c.allowMethods);
|
|
12
|
+
return async function(n, d) {
|
|
13
|
+
var e;
|
|
14
|
+
function f(r, s) {
|
|
15
|
+
n.res.headers.set(r, s);
|
|
16
16
|
}
|
|
17
|
-
const
|
|
18
|
-
if (
|
|
19
|
-
const r =
|
|
20
|
-
r ?
|
|
17
|
+
const w = q(n.req.header("origin") || "", n);
|
|
18
|
+
if (w && f("Access-Control-Allow-Origin", w), c.origin !== "*") {
|
|
19
|
+
const r = n.req.header("Vary");
|
|
20
|
+
r ? f("Vary", r) : f("Vary", "Origin");
|
|
21
21
|
}
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
const r =
|
|
25
|
-
r.length &&
|
|
26
|
-
let
|
|
27
|
-
if (!(
|
|
28
|
-
const
|
|
29
|
-
|
|
22
|
+
if (c.credentials && f("Access-Control-Allow-Credentials", "true"), (e = c.exposeHeaders) != null && e.length && f("Access-Control-Expose-Headers", c.exposeHeaders.join(",")), n.req.method === "OPTIONS") {
|
|
23
|
+
c.maxAge != null && f("Access-Control-Max-Age", c.maxAge.toString());
|
|
24
|
+
const r = g(n.req.header("origin") || "", n);
|
|
25
|
+
r.length && f("Access-Control-Allow-Methods", r.join(","));
|
|
26
|
+
let s = c.allowHeaders;
|
|
27
|
+
if (!(s != null && s.length)) {
|
|
28
|
+
const t = n.req.header("Access-Control-Request-Headers");
|
|
29
|
+
t && (s = t.split(/\s*,\s*/));
|
|
30
30
|
}
|
|
31
|
-
return
|
|
32
|
-
headers:
|
|
31
|
+
return s != null && s.length && (f("Access-Control-Allow-Headers", s.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
|
+
headers: n.res.headers,
|
|
33
33
|
status: 204,
|
|
34
34
|
statusText: "No Content"
|
|
35
35
|
});
|
|
@@ -37,28 +37,27 @@ var j = (f) => {
|
|
|
37
37
|
await d();
|
|
38
38
|
};
|
|
39
39
|
};
|
|
40
|
-
function
|
|
40
|
+
function E(y) {
|
|
41
41
|
const {
|
|
42
|
-
semanticLayer:
|
|
43
|
-
drizzle:
|
|
42
|
+
semanticLayer: a,
|
|
43
|
+
drizzle: c,
|
|
44
44
|
schema: q,
|
|
45
|
-
getSecurityContext:
|
|
46
|
-
cors:
|
|
47
|
-
basePath:
|
|
48
|
-
} =
|
|
49
|
-
|
|
50
|
-
var o, i;
|
|
45
|
+
getSecurityContext: g,
|
|
46
|
+
cors: u,
|
|
47
|
+
basePath: n = "/cubejs-api/v1"
|
|
48
|
+
} = y, d = new v();
|
|
49
|
+
u && d.use("/*", A(u)), a.hasExecutor() || a.setDrizzle(c, q), d.post(`${n}/load`, async (e) => {
|
|
51
50
|
try {
|
|
52
|
-
const r = await e.req.json(),
|
|
53
|
-
if (!
|
|
51
|
+
const r = await e.req.json(), s = r.query || r, t = await g(e), o = a.validateQuery(s);
|
|
52
|
+
if (!o.isValid)
|
|
54
53
|
return e.json({
|
|
55
|
-
error:
|
|
54
|
+
error: `Query validation failed: ${o.errors.join(", ")}`
|
|
56
55
|
}, 400);
|
|
57
|
-
const
|
|
56
|
+
const i = await a.executeMultiCubeQuery(s, t);
|
|
58
57
|
return e.json({
|
|
59
|
-
data:
|
|
60
|
-
annotation:
|
|
61
|
-
query:
|
|
58
|
+
data: i.data,
|
|
59
|
+
annotation: i.annotation,
|
|
60
|
+
query: s,
|
|
62
61
|
slowQuery: !1
|
|
63
62
|
});
|
|
64
63
|
} catch (r) {
|
|
@@ -66,24 +65,23 @@ function C(f) {
|
|
|
66
65
|
error: r instanceof Error ? r.message : "Query execution failed"
|
|
67
66
|
}, 500);
|
|
68
67
|
}
|
|
69
|
-
}), d.get(`${
|
|
70
|
-
var o, i;
|
|
68
|
+
}), d.get(`${n}/load`, async (e) => {
|
|
71
69
|
try {
|
|
72
70
|
const r = e.req.query("query");
|
|
73
71
|
if (!r)
|
|
74
72
|
return e.json({
|
|
75
73
|
error: "Query parameter is required"
|
|
76
74
|
}, 400);
|
|
77
|
-
const
|
|
78
|
-
if (!
|
|
75
|
+
const s = JSON.parse(r), t = await g(e), o = a.validateQuery(s);
|
|
76
|
+
if (!o.isValid)
|
|
79
77
|
return e.json({
|
|
80
|
-
error:
|
|
78
|
+
error: `Query validation failed: ${o.errors.join(", ")}`
|
|
81
79
|
}, 400);
|
|
82
|
-
const
|
|
80
|
+
const i = await a.executeMultiCubeQuery(s, t);
|
|
83
81
|
return e.json({
|
|
84
|
-
data:
|
|
85
|
-
annotation:
|
|
86
|
-
query:
|
|
82
|
+
data: i.data,
|
|
83
|
+
annotation: i.annotation,
|
|
84
|
+
query: s,
|
|
87
85
|
slowQuery: !1
|
|
88
86
|
});
|
|
89
87
|
} catch (r) {
|
|
@@ -91,82 +89,178 @@ function C(f) {
|
|
|
91
89
|
error: r instanceof Error ? r.message : "Query execution failed"
|
|
92
90
|
}, 500);
|
|
93
91
|
}
|
|
94
|
-
}), d.get(`${
|
|
92
|
+
}), d.get(`${n}/meta`, async (e) => {
|
|
95
93
|
try {
|
|
96
|
-
const
|
|
94
|
+
const r = a.getMetadata();
|
|
97
95
|
return e.json({
|
|
98
|
-
cubes:
|
|
96
|
+
cubes: r
|
|
99
97
|
});
|
|
100
|
-
} catch (
|
|
101
|
-
return console.error("Metadata error:",
|
|
102
|
-
error:
|
|
98
|
+
} catch (r) {
|
|
99
|
+
return console.error("Metadata error:", r), e.json({
|
|
100
|
+
error: r instanceof Error ? r.message : "Failed to fetch metadata"
|
|
103
101
|
}, 500);
|
|
104
102
|
}
|
|
105
|
-
}), d.post(`${
|
|
106
|
-
var
|
|
103
|
+
}), d.post(`${n}/sql`, async (e) => {
|
|
104
|
+
var r, s;
|
|
107
105
|
try {
|
|
108
|
-
const
|
|
109
|
-
if (!
|
|
106
|
+
const t = await e.req.json(), o = await g(e), i = a.validateQuery(t);
|
|
107
|
+
if (!i.isValid)
|
|
110
108
|
return e.json({
|
|
111
|
-
error:
|
|
109
|
+
error: `Query validation failed: ${i.errors.join(", ")}`
|
|
112
110
|
}, 400);
|
|
113
|
-
const
|
|
114
|
-
if (!
|
|
111
|
+
const p = ((r = t.measures) == null ? void 0 : r[0]) || ((s = t.dimensions) == null ? void 0 : s[0]);
|
|
112
|
+
if (!p)
|
|
115
113
|
return e.json({
|
|
116
114
|
error: "No measures or dimensions specified"
|
|
117
115
|
}, 400);
|
|
118
|
-
const
|
|
116
|
+
const h = p.split(".")[0], j = await a.generateSQL(h, t, o);
|
|
119
117
|
return e.json({
|
|
120
|
-
sql:
|
|
121
|
-
params:
|
|
122
|
-
query:
|
|
118
|
+
sql: j.sql,
|
|
119
|
+
params: j.params || [],
|
|
120
|
+
query: t
|
|
123
121
|
});
|
|
124
|
-
} catch (
|
|
125
|
-
return console.error("SQL generation error:",
|
|
126
|
-
error:
|
|
122
|
+
} catch (t) {
|
|
123
|
+
return console.error("SQL generation error:", t), e.json({
|
|
124
|
+
error: t instanceof Error ? t.message : "SQL generation failed"
|
|
127
125
|
}, 500);
|
|
128
126
|
}
|
|
129
|
-
}), d.get(`${
|
|
130
|
-
var
|
|
127
|
+
}), d.get(`${n}/sql`, async (e) => {
|
|
128
|
+
var r, s;
|
|
131
129
|
try {
|
|
132
|
-
const
|
|
133
|
-
if (!
|
|
130
|
+
const t = e.req.query("query");
|
|
131
|
+
if (!t)
|
|
134
132
|
return e.json({
|
|
135
133
|
error: "Query parameter is required"
|
|
136
134
|
}, 400);
|
|
137
|
-
const
|
|
138
|
-
if (!
|
|
135
|
+
const o = JSON.parse(t), i = await g(e), p = a.validateQuery(o);
|
|
136
|
+
if (!p.isValid)
|
|
139
137
|
return e.json({
|
|
140
|
-
error:
|
|
138
|
+
error: `Query validation failed: ${p.errors.join(", ")}`
|
|
141
139
|
}, 400);
|
|
142
|
-
const
|
|
143
|
-
if (!
|
|
140
|
+
const h = ((r = o.measures) == null ? void 0 : r[0]) || ((s = o.dimensions) == null ? void 0 : s[0]);
|
|
141
|
+
if (!h)
|
|
144
142
|
return e.json({
|
|
145
143
|
error: "No measures or dimensions specified"
|
|
146
144
|
}, 400);
|
|
147
|
-
const
|
|
145
|
+
const j = h.split(".")[0], Q = await a.generateSQL(j, o, i);
|
|
148
146
|
return e.json({
|
|
149
|
-
sql:
|
|
150
|
-
params:
|
|
151
|
-
query:
|
|
147
|
+
sql: Q.sql,
|
|
148
|
+
params: Q.params || [],
|
|
149
|
+
query: o
|
|
152
150
|
});
|
|
153
|
-
} catch (
|
|
154
|
-
return console.error("SQL generation error:",
|
|
155
|
-
error:
|
|
151
|
+
} catch (t) {
|
|
152
|
+
return console.error("SQL generation error:", t), e.json({
|
|
153
|
+
error: t instanceof Error ? t.message : "SQL generation failed"
|
|
156
154
|
}, 500);
|
|
157
155
|
}
|
|
156
|
+
});
|
|
157
|
+
function f(e) {
|
|
158
|
+
var s, t, o, i;
|
|
159
|
+
let r = 0;
|
|
160
|
+
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
|
+
}
|
|
162
|
+
async function w(e, r) {
|
|
163
|
+
var h, j, Q, b;
|
|
164
|
+
const s = a.validateQuery(e);
|
|
165
|
+
if (!s.isValid)
|
|
166
|
+
throw new Error(`Query validation failed: ${s.errors.join(", ")}`);
|
|
167
|
+
const t = /* @__PURE__ */ new Set();
|
|
168
|
+
(h = e.measures) == null || h.forEach((l) => {
|
|
169
|
+
const m = l.split(".")[0];
|
|
170
|
+
t.add(m);
|
|
171
|
+
}), (j = e.dimensions) == null || j.forEach((l) => {
|
|
172
|
+
const m = l.split(".")[0];
|
|
173
|
+
t.add(m);
|
|
174
|
+
}), (Q = e.timeDimensions) == null || Q.forEach((l) => {
|
|
175
|
+
const m = l.dimension.split(".")[0];
|
|
176
|
+
t.add(m);
|
|
177
|
+
}), (b = e.filters) == null || b.forEach((l) => {
|
|
178
|
+
if ("member" in l) {
|
|
179
|
+
const m = l.member.split(".")[0];
|
|
180
|
+
t.add(m);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
const o = t.size > 1;
|
|
184
|
+
let i;
|
|
185
|
+
if (o)
|
|
186
|
+
i = await a.generateMultiCubeSQL(e, r);
|
|
187
|
+
else {
|
|
188
|
+
const l = Array.from(t)[0];
|
|
189
|
+
i = await a.generateSQL(l, e, r);
|
|
190
|
+
}
|
|
191
|
+
const p = Array.from(t).map((l) => {
|
|
192
|
+
var m, x;
|
|
193
|
+
return {
|
|
194
|
+
cube: l,
|
|
195
|
+
query: {
|
|
196
|
+
measures: ((m = e.measures) == null ? void 0 : m.filter((C) => C.startsWith(l + "."))) || [],
|
|
197
|
+
dimensions: ((x = e.dimensions) == null ? void 0 : x.filter((C) => C.startsWith(l + "."))) || [],
|
|
198
|
+
filters: e.filters || [],
|
|
199
|
+
timeDimensions: e.timeDimensions || [],
|
|
200
|
+
order: e.order || {},
|
|
201
|
+
limit: e.limit,
|
|
202
|
+
offset: e.offset
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
});
|
|
206
|
+
return {
|
|
207
|
+
queryType: "regularQuery",
|
|
208
|
+
normalizedQueries: p,
|
|
209
|
+
queryOrder: Array.from(t),
|
|
210
|
+
transformedQueries: p,
|
|
211
|
+
pivotQuery: {
|
|
212
|
+
query: e,
|
|
213
|
+
cubes: Array.from(t)
|
|
214
|
+
},
|
|
215
|
+
sql: {
|
|
216
|
+
sql: [i.sql],
|
|
217
|
+
params: i.params || []
|
|
218
|
+
},
|
|
219
|
+
complexity: f(e),
|
|
220
|
+
valid: !0,
|
|
221
|
+
cubesUsed: Array.from(t),
|
|
222
|
+
joinType: o ? "multi_cube_join" : "single_cube",
|
|
223
|
+
query: e
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
return d.post(`${n}/dry-run`, async (e) => {
|
|
227
|
+
try {
|
|
228
|
+
const r = await e.req.json(), s = r.query || r, t = await g(e), o = await w(s, t);
|
|
229
|
+
return e.json(o);
|
|
230
|
+
} catch (r) {
|
|
231
|
+
return console.error("Dry-run error:", r), e.json({
|
|
232
|
+
error: r instanceof Error ? r.message : "Dry-run validation failed",
|
|
233
|
+
valid: !1
|
|
234
|
+
}, 400);
|
|
235
|
+
}
|
|
236
|
+
}), d.get(`${n}/dry-run`, async (e) => {
|
|
237
|
+
try {
|
|
238
|
+
const r = e.req.query("query");
|
|
239
|
+
if (!r)
|
|
240
|
+
return e.json({
|
|
241
|
+
error: "Query parameter is required",
|
|
242
|
+
valid: !1
|
|
243
|
+
}, 400);
|
|
244
|
+
const s = JSON.parse(r), t = await g(e), o = await w(s, t);
|
|
245
|
+
return e.json(o);
|
|
246
|
+
} catch (r) {
|
|
247
|
+
return console.error("Dry-run error:", r), e.json({
|
|
248
|
+
error: r instanceof Error ? r.message : "Dry-run validation failed",
|
|
249
|
+
valid: !1
|
|
250
|
+
}, 400);
|
|
251
|
+
}
|
|
158
252
|
}), d;
|
|
159
253
|
}
|
|
160
|
-
function
|
|
161
|
-
const
|
|
162
|
-
return
|
|
254
|
+
function S(y, a) {
|
|
255
|
+
const c = E(a);
|
|
256
|
+
return y.route("/", c), y;
|
|
163
257
|
}
|
|
164
|
-
function
|
|
165
|
-
const
|
|
166
|
-
return
|
|
258
|
+
function D(y) {
|
|
259
|
+
const a = new v();
|
|
260
|
+
return S(a, y);
|
|
167
261
|
}
|
|
168
262
|
export {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
263
|
+
D as createCubeApp,
|
|
264
|
+
E as createCubeRoutes,
|
|
265
|
+
S as mountCubeRoutes
|
|
172
266
|
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { CubeQuery, CubeApiOptions, CubeResultSet } from '../types';
|
|
2
|
+
export declare class CubeClient {
|
|
3
|
+
private apiUrl;
|
|
4
|
+
private headers;
|
|
5
|
+
constructor(token?: string, options?: CubeApiOptions);
|
|
6
|
+
load(query: CubeQuery): Promise<CubeResultSet>;
|
|
7
|
+
meta(): Promise<any>;
|
|
8
|
+
sql(query: CubeQuery): Promise<any>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Factory function to create a cube client
|
|
12
|
+
*/
|
|
13
|
+
export declare function createCubeClient(token?: string, options?: CubeApiOptions): CubeClient;
|
|
14
|
+
export declare function cube(token?: string, options?: CubeApiOptions): CubeClient;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function AnalyticsPage(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { AnalyticsPortletProps } from '../types';
|
|
2
|
+
interface AnalyticsPortletRef {
|
|
3
|
+
refresh: () => void;
|
|
4
|
+
}
|
|
5
|
+
declare const AnalyticsPortlet: import('react').ForwardRefExoticComponent<AnalyticsPortletProps & import('react').RefAttributes<AnalyticsPortletRef>>;
|
|
6
|
+
export default AnalyticsPortlet;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ChartAxisConfig, ChartDisplayConfig } from '../types';
|
|
2
|
+
interface ChartConfigEditorProps {
|
|
3
|
+
chartConfig: ChartAxisConfig;
|
|
4
|
+
displayConfig?: ChartDisplayConfig;
|
|
5
|
+
onConfigChange: (chartConfig: ChartAxisConfig, displayConfig: ChartDisplayConfig) => void;
|
|
6
|
+
}
|
|
7
|
+
export default function ChartConfigEditor({ chartConfig, displayConfig, onConfigChange }: ChartConfigEditorProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { default as React, Component, ReactNode } from 'react';
|
|
2
|
+
interface Props {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
fallback?: ReactNode;
|
|
5
|
+
portletTitle?: string;
|
|
6
|
+
portletConfig?: any;
|
|
7
|
+
cubeQuery?: string;
|
|
8
|
+
}
|
|
9
|
+
interface State {
|
|
10
|
+
hasError: boolean;
|
|
11
|
+
error: Error | null;
|
|
12
|
+
errorInfo: string | null;
|
|
13
|
+
}
|
|
14
|
+
export default class ChartErrorBoundary extends Component<Props, State> {
|
|
15
|
+
constructor(props: Props);
|
|
16
|
+
static getDerivedStateFromError(error: Error): State;
|
|
17
|
+
componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void;
|
|
18
|
+
handleReset: () => void;
|
|
19
|
+
render(): string | number | boolean | Iterable<React.ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
|
|
20
|
+
}
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface DashboardEditModalProps {
|
|
2
|
+
isOpen: boolean;
|
|
3
|
+
onClose: () => void;
|
|
4
|
+
onSave: (data: {
|
|
5
|
+
name: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
}) => Promise<void> | void;
|
|
8
|
+
title: string;
|
|
9
|
+
submitText: string;
|
|
10
|
+
initialName?: string;
|
|
11
|
+
initialDescription?: string;
|
|
12
|
+
}
|
|
13
|
+
export default function DashboardEditModal({ isOpen, onClose, onSave, title, submitText, initialName, initialDescription }: DashboardEditModalProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { DashboardConfig } from '../types';
|
|
2
|
+
interface DashboardGridProps {
|
|
3
|
+
config: DashboardConfig;
|
|
4
|
+
editable?: boolean;
|
|
5
|
+
onConfigChange?: (config: DashboardConfig) => void;
|
|
6
|
+
onPortletRefresh?: (portletId: string) => void;
|
|
7
|
+
onSave?: (config: DashboardConfig) => Promise<void> | void;
|
|
8
|
+
apiUrl?: string;
|
|
9
|
+
}
|
|
10
|
+
export default function DashboardGrid({ config, editable, onConfigChange, onPortletRefresh, onSave, apiUrl }: DashboardGridProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
export interface ModalProps {
|
|
3
|
+
isOpen: boolean;
|
|
4
|
+
onClose: () => void;
|
|
5
|
+
title?: string;
|
|
6
|
+
size?: 'sm' | 'md' | 'lg' | 'xl' | 'full';
|
|
7
|
+
closeOnBackdropClick?: boolean;
|
|
8
|
+
closeOnEscape?: boolean;
|
|
9
|
+
showCloseButton?: boolean;
|
|
10
|
+
className?: string;
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
footer?: React.ReactNode;
|
|
13
|
+
}
|
|
14
|
+
declare const Modal: React.FC<ModalProps>;
|
|
15
|
+
export default Modal;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PortletConfig } from '../types';
|
|
2
|
+
interface PortletContainerProps {
|
|
3
|
+
portlet: PortletConfig;
|
|
4
|
+
editable?: boolean;
|
|
5
|
+
onEdit?: (portlet: PortletConfig) => void;
|
|
6
|
+
onDelete?: (portletId: string) => void;
|
|
7
|
+
onRefresh?: (portletId: string) => void;
|
|
8
|
+
}
|
|
9
|
+
export default function PortletContainer({ portlet, editable, onEdit, onDelete, onRefresh }: PortletContainerProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { PortletConfig } from '../types';
|
|
2
|
+
interface PortletEditModalProps {
|
|
3
|
+
isOpen: boolean;
|
|
4
|
+
onClose: () => void;
|
|
5
|
+
onSave: (portlet: PortletConfig | Omit<PortletConfig, 'id' | 'x' | 'y'>) => void;
|
|
6
|
+
portlet?: PortletConfig | null;
|
|
7
|
+
title: string;
|
|
8
|
+
submitText: string;
|
|
9
|
+
apiUrl?: string;
|
|
10
|
+
}
|
|
11
|
+
export default function PortletEditModal({ isOpen, onClose, onSave, portlet, title, submitText, apiUrl }: PortletEditModalProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
2
|
+
interface ChartContainerProps {
|
|
3
|
+
children: ReactElement;
|
|
4
|
+
height?: string | number;
|
|
5
|
+
}
|
|
6
|
+
export default function ChartContainer({ children, height }: ChartContainerProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export {};
|