drizzle-cube 0.1.12 → 0.1.14
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 +48 -213
- package/dist/adapters/express/index.d.ts +89 -0
- package/dist/adapters/express/index.js +177 -0
- package/dist/adapters/fastify/index.d.ts +88 -0
- package/dist/adapters/fastify/index.js +213 -0
- package/dist/adapters/hono/index.d.ts +41 -6
- package/dist/adapters/hono/index.js +102 -248
- package/dist/adapters/nextjs/index.d.ts +129 -0
- package/dist/adapters/nextjs/index.js +211 -0
- package/dist/adapters/utils-C3A4JGFs.js +3779 -0
- package/dist/adapters/utils.d.ts +119 -0
- package/dist/client/components/AnalyticsDashboard.d.ts +1 -1
- package/dist/client/components/AxisDropZone.d.ts +2 -1
- package/dist/client/components/DashboardGrid.d.ts +1 -2
- package/dist/client/components/PortletEditModal.d.ts +1 -2
- package/dist/client/components/QueryBuilder/types.d.ts +0 -1
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.js +7626 -7542
- package/dist/client/providers/CubeProvider.d.ts +6 -3
- package/dist/client/styles.css +1 -1
- package/dist/client/types.d.ts +0 -2
- package/dist/express/index.d.ts +2 -0
- package/dist/fastify/index.d.ts +2 -0
- package/dist/hono/index.d.ts +2 -0
- package/dist/nextjs/index.d.ts +2 -0
- package/package.json +37 -1
|
@@ -1,316 +1,170 @@
|
|
|
1
|
-
import { Hono as
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { Hono as x } from "hono";
|
|
2
|
+
import { S as b, f as p, a as v, b as w, h as C } from "../utils-C3A4JGFs.js";
|
|
3
|
+
var A = (y) => {
|
|
4
|
+
const l = {
|
|
4
5
|
...{
|
|
5
6
|
origin: "*",
|
|
6
7
|
allowMethods: ["GET", "HEAD", "PUT", "POST", "DELETE", "PATCH"],
|
|
7
8
|
allowHeaders: [],
|
|
8
9
|
exposeHeaders: []
|
|
9
10
|
},
|
|
10
|
-
...
|
|
11
|
-
},
|
|
12
|
-
return async function(n,
|
|
13
|
-
var
|
|
14
|
-
function
|
|
15
|
-
n.res.headers.set(
|
|
11
|
+
...y
|
|
12
|
+
}, j = /* @__PURE__ */ ((u) => typeof u == "string" ? u === "*" ? () => u : (n) => u === n ? n : null : typeof u == "function" ? u : (n) => u.includes(n) ? n : null)(l.origin), f = ((u) => typeof u == "function" ? u : Array.isArray(u) ? () => u : () => [])(l.allowMethods);
|
|
13
|
+
return async function(n, d) {
|
|
14
|
+
var e;
|
|
15
|
+
function s(r, t) {
|
|
16
|
+
n.res.headers.set(r, t);
|
|
16
17
|
}
|
|
17
|
-
const
|
|
18
|
-
if (
|
|
19
|
-
const
|
|
20
|
-
|
|
18
|
+
const a = j(n.req.header("origin") || "", n);
|
|
19
|
+
if (a && s("Access-Control-Allow-Origin", a), l.origin !== "*") {
|
|
20
|
+
const r = n.req.header("Vary");
|
|
21
|
+
r ? s("Vary", r) : s("Vary", "Origin");
|
|
21
22
|
}
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
let
|
|
27
|
-
if (!(
|
|
28
|
-
const
|
|
29
|
-
|
|
23
|
+
if (l.credentials && s("Access-Control-Allow-Credentials", "true"), (e = l.exposeHeaders) != null && e.length && s("Access-Control-Expose-Headers", l.exposeHeaders.join(",")), n.req.method === "OPTIONS") {
|
|
24
|
+
l.maxAge != null && s("Access-Control-Max-Age", l.maxAge.toString());
|
|
25
|
+
const r = f(n.req.header("origin") || "", n);
|
|
26
|
+
r.length && s("Access-Control-Allow-Methods", r.join(","));
|
|
27
|
+
let t = l.allowHeaders;
|
|
28
|
+
if (!(t != null && t.length)) {
|
|
29
|
+
const o = n.req.header("Access-Control-Request-Headers");
|
|
30
|
+
o && (t = o.split(/\s*,\s*/));
|
|
30
31
|
}
|
|
31
|
-
return
|
|
32
|
+
return t != null && t.length && (s("Access-Control-Allow-Headers", t.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
33
|
headers: n.res.headers,
|
|
33
34
|
status: 204,
|
|
34
35
|
statusText: "No Content"
|
|
35
36
|
});
|
|
36
37
|
}
|
|
37
|
-
await
|
|
38
|
+
await d();
|
|
38
39
|
};
|
|
39
40
|
};
|
|
40
|
-
function
|
|
41
|
+
function S(y) {
|
|
41
42
|
const {
|
|
42
|
-
|
|
43
|
-
drizzle:
|
|
44
|
-
schema:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
cubes: c,
|
|
44
|
+
drizzle: l,
|
|
45
|
+
schema: j,
|
|
46
|
+
extractSecurityContext: f,
|
|
47
|
+
engineType: u,
|
|
48
|
+
cors: n,
|
|
49
|
+
basePath: d = "/cubejs-api/v1"
|
|
50
|
+
} = y;
|
|
51
|
+
if (!c || c.length === 0)
|
|
52
|
+
throw new Error("At least one cube must be provided in the cubes array");
|
|
53
|
+
const s = new x();
|
|
54
|
+
n && s.use("/*", A(n));
|
|
55
|
+
const a = new b({
|
|
56
|
+
drizzle: l,
|
|
57
|
+
schema: j,
|
|
58
|
+
engineType: u
|
|
59
|
+
});
|
|
60
|
+
return c.forEach((e) => {
|
|
61
|
+
a.registerCube(e);
|
|
62
|
+
}), console.log(`🚀 Drizzle Cube: Registered ${c.length} cube(s) with ${u || "auto-detected"} engine`), s.post(`${d}/load`, async (e) => {
|
|
50
63
|
try {
|
|
51
|
-
const r = await e.req.json(),
|
|
52
|
-
if (!
|
|
64
|
+
const r = await e.req.json(), t = r.query || r, o = await f(e), i = a.validateQuery(t);
|
|
65
|
+
if (!i.isValid)
|
|
53
66
|
return e.json({
|
|
54
|
-
error: `Query validation failed: ${
|
|
67
|
+
error: `Query validation failed: ${i.errors.join(", ")}`
|
|
55
68
|
}, 400);
|
|
56
|
-
const
|
|
57
|
-
return e.json(
|
|
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
|
-
},
|
|
77
|
-
slowQuery: !1
|
|
78
|
-
});
|
|
69
|
+
const m = await a.executeMultiCubeQuery(t, o);
|
|
70
|
+
return e.json(p(t, m, a));
|
|
79
71
|
} catch (r) {
|
|
80
72
|
return console.error("Query execution error:", r), e.json({
|
|
81
73
|
error: r instanceof Error ? r.message : "Query execution failed"
|
|
82
74
|
}, 500);
|
|
83
75
|
}
|
|
84
|
-
}),
|
|
76
|
+
}), s.get(`${d}/load`, async (e) => {
|
|
85
77
|
try {
|
|
86
78
|
const r = e.req.query("query");
|
|
87
79
|
if (!r)
|
|
88
80
|
return e.json({
|
|
89
81
|
error: "Query parameter is required"
|
|
90
82
|
}, 400);
|
|
91
|
-
let
|
|
83
|
+
let t;
|
|
92
84
|
try {
|
|
93
|
-
|
|
85
|
+
t = JSON.parse(r);
|
|
94
86
|
} catch {
|
|
95
87
|
return e.json({
|
|
96
88
|
error: "Invalid JSON in query parameter"
|
|
97
89
|
}, 400);
|
|
98
90
|
}
|
|
99
|
-
const
|
|
100
|
-
if (!
|
|
91
|
+
const o = await f(e), i = a.validateQuery(t);
|
|
92
|
+
if (!i.isValid)
|
|
101
93
|
return e.json({
|
|
102
|
-
error: `Query validation failed: ${
|
|
94
|
+
error: `Query validation failed: ${i.errors.join(", ")}`
|
|
103
95
|
}, 400);
|
|
104
|
-
const
|
|
105
|
-
return e.json(
|
|
106
|
-
queryType: "regularQuery",
|
|
107
|
-
results: [{
|
|
108
|
-
query: s,
|
|
109
|
-
lastRefreshTime: g,
|
|
110
|
-
usedPreAggregations: {},
|
|
111
|
-
transformedQuery: Q,
|
|
112
|
-
requestId: y,
|
|
113
|
-
annotation: i.annotation,
|
|
114
|
-
dataSource: "default",
|
|
115
|
-
dbType: l,
|
|
116
|
-
extDbType: l,
|
|
117
|
-
external: !1,
|
|
118
|
-
slowQuery: !1,
|
|
119
|
-
data: i.data
|
|
120
|
-
}],
|
|
121
|
-
pivotQuery: {
|
|
122
|
-
...s,
|
|
123
|
-
queryType: "regularQuery"
|
|
124
|
-
},
|
|
125
|
-
slowQuery: !1
|
|
126
|
-
});
|
|
96
|
+
const m = await a.executeMultiCubeQuery(t, o);
|
|
97
|
+
return e.json(p(t, m, a));
|
|
127
98
|
} catch (r) {
|
|
128
99
|
return console.error("Query execution error:", r), e.json({
|
|
129
100
|
error: r instanceof Error ? r.message : "Query execution failed"
|
|
130
101
|
}, 500);
|
|
131
102
|
}
|
|
132
|
-
}),
|
|
103
|
+
}), s.get(`${d}/meta`, (e) => {
|
|
133
104
|
try {
|
|
134
105
|
const r = a.getMetadata();
|
|
135
|
-
return e.json(
|
|
136
|
-
cubes: r
|
|
137
|
-
});
|
|
106
|
+
return e.json(v(r));
|
|
138
107
|
} catch (r) {
|
|
139
108
|
return console.error("Metadata error:", r), e.json({
|
|
140
109
|
error: r instanceof Error ? r.message : "Failed to fetch metadata"
|
|
141
110
|
}, 500);
|
|
142
111
|
}
|
|
143
|
-
}),
|
|
144
|
-
var r,
|
|
112
|
+
}), s.post(`${d}/sql`, async (e) => {
|
|
113
|
+
var r, t;
|
|
145
114
|
try {
|
|
146
|
-
const
|
|
147
|
-
if (!
|
|
115
|
+
const o = await e.req.json(), i = await f(e), m = a.validateQuery(o);
|
|
116
|
+
if (!m.isValid)
|
|
148
117
|
return e.json({
|
|
149
|
-
error: `Query validation failed: ${
|
|
118
|
+
error: `Query validation failed: ${m.errors.join(", ")}`
|
|
150
119
|
}, 400);
|
|
151
|
-
const
|
|
152
|
-
if (!
|
|
120
|
+
const q = ((r = o.measures) == null ? void 0 : r[0]) || ((t = o.dimensions) == null ? void 0 : t[0]);
|
|
121
|
+
if (!q)
|
|
153
122
|
return e.json({
|
|
154
123
|
error: "No measures or dimensions specified"
|
|
155
124
|
}, 400);
|
|
156
|
-
const
|
|
157
|
-
return e.json(
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
});
|
|
162
|
-
} catch (t) {
|
|
163
|
-
return console.error("SQL generation error:", t), e.json({
|
|
164
|
-
error: t instanceof Error ? t.message : "SQL generation failed"
|
|
125
|
+
const g = q.split(".")[0], h = await a.generateSQL(g, o, i);
|
|
126
|
+
return e.json(w(o, h));
|
|
127
|
+
} catch (o) {
|
|
128
|
+
return console.error("SQL generation error:", o), e.json({
|
|
129
|
+
error: o instanceof Error ? o.message : "SQL generation failed"
|
|
165
130
|
}, 500);
|
|
166
131
|
}
|
|
167
|
-
}),
|
|
168
|
-
var r,
|
|
132
|
+
}), s.get(`${d}/sql`, async (e) => {
|
|
133
|
+
var r, t;
|
|
169
134
|
try {
|
|
170
|
-
const
|
|
171
|
-
if (!
|
|
135
|
+
const o = e.req.query("query");
|
|
136
|
+
if (!o)
|
|
172
137
|
return e.json({
|
|
173
138
|
error: "Query parameter is required"
|
|
174
139
|
}, 400);
|
|
175
|
-
const
|
|
176
|
-
if (!
|
|
140
|
+
const i = JSON.parse(o), m = await f(e), q = a.validateQuery(i);
|
|
141
|
+
if (!q.isValid)
|
|
177
142
|
return e.json({
|
|
178
|
-
error: `Query validation failed: ${
|
|
143
|
+
error: `Query validation failed: ${q.errors.join(", ")}`
|
|
179
144
|
}, 400);
|
|
180
|
-
const
|
|
181
|
-
if (!
|
|
145
|
+
const g = ((r = i.measures) == null ? void 0 : r[0]) || ((t = i.dimensions) == null ? void 0 : t[0]);
|
|
146
|
+
if (!g)
|
|
182
147
|
return e.json({
|
|
183
148
|
error: "No measures or dimensions specified"
|
|
184
149
|
}, 400);
|
|
185
|
-
const
|
|
186
|
-
return e.json(
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
});
|
|
191
|
-
} catch (t) {
|
|
192
|
-
return console.error("SQL generation error:", t), e.json({
|
|
193
|
-
error: t instanceof Error ? t.message : "SQL generation failed"
|
|
150
|
+
const h = g.split(".")[0], Q = await a.generateSQL(h, i, m);
|
|
151
|
+
return e.json(w(i, Q));
|
|
152
|
+
} catch (o) {
|
|
153
|
+
return console.error("SQL generation error:", o), e.json({
|
|
154
|
+
error: o instanceof Error ? o.message : "SQL generation failed"
|
|
194
155
|
}, 500);
|
|
195
156
|
}
|
|
196
|
-
})
|
|
197
|
-
function p(e) {
|
|
198
|
-
var s, t, o, i;
|
|
199
|
-
let r = 0;
|
|
200
|
-
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";
|
|
201
|
-
}
|
|
202
|
-
function b() {
|
|
203
|
-
const e = Date.now(), r = Math.random().toString(36).substring(2, 9);
|
|
204
|
-
return `${e}-${r}`;
|
|
205
|
-
}
|
|
206
|
-
function x(e) {
|
|
207
|
-
const r = e.dimensions || [], s = e.timeDimensions || [], t = e.measures || [];
|
|
208
|
-
return {
|
|
209
|
-
sortedDimensions: r,
|
|
210
|
-
sortedTimeDimensions: s,
|
|
211
|
-
timeDimensions: s,
|
|
212
|
-
measures: t,
|
|
213
|
-
leafMeasureAdditive: !0,
|
|
214
|
-
leafMeasures: t,
|
|
215
|
-
measureToLeafMeasures: {},
|
|
216
|
-
hasNoTimeDimensionsWithoutGranularity: !0,
|
|
217
|
-
allFiltersWithinSelectedDimensions: !0,
|
|
218
|
-
isAdditive: !0,
|
|
219
|
-
granularityHierarchies: {},
|
|
220
|
-
hasMultipliedMeasures: !1,
|
|
221
|
-
hasCumulativeMeasures: !1,
|
|
222
|
-
windowGranularity: null,
|
|
223
|
-
filterDimensionsSingleValueEqual: {},
|
|
224
|
-
ownedDimensions: r,
|
|
225
|
-
ownedTimeDimensionsWithRollupGranularity: [],
|
|
226
|
-
ownedTimeDimensionsAsIs: [],
|
|
227
|
-
allBackAliasMembers: {},
|
|
228
|
-
hasMultiStage: !1
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
function h(e) {
|
|
232
|
-
if (e.hasExecutor()) {
|
|
233
|
-
const r = e.databaseExecutor;
|
|
234
|
-
if (r != null && r.engineType)
|
|
235
|
-
return r.engineType;
|
|
236
|
-
}
|
|
237
|
-
return "postgres";
|
|
238
|
-
}
|
|
239
|
-
async function f(e, r) {
|
|
240
|
-
var y, g, Q, A;
|
|
241
|
-
const s = a.validateQuery(e);
|
|
242
|
-
if (!s.isValid)
|
|
243
|
-
throw new Error(`Query validation failed: ${s.errors.join(", ")}`);
|
|
244
|
-
const t = /* @__PURE__ */ new Set();
|
|
245
|
-
(y = e.measures) == null || y.forEach((d) => {
|
|
246
|
-
const w = d.split(".")[0];
|
|
247
|
-
t.add(w);
|
|
248
|
-
}), (g = e.dimensions) == null || g.forEach((d) => {
|
|
249
|
-
const w = d.split(".")[0];
|
|
250
|
-
t.add(w);
|
|
251
|
-
}), (Q = e.timeDimensions) == null || Q.forEach((d) => {
|
|
252
|
-
const w = d.dimension.split(".")[0];
|
|
253
|
-
t.add(w);
|
|
254
|
-
}), (A = e.filters) == null || A.forEach((d) => {
|
|
255
|
-
if ("member" in d) {
|
|
256
|
-
const w = d.member.split(".")[0];
|
|
257
|
-
t.add(w);
|
|
258
|
-
}
|
|
259
|
-
});
|
|
260
|
-
const o = t.size > 1;
|
|
261
|
-
let i;
|
|
262
|
-
if (o)
|
|
263
|
-
i = await a.generateMultiCubeSQL(e, r);
|
|
264
|
-
else {
|
|
265
|
-
const d = Array.from(t)[0];
|
|
266
|
-
i = await a.generateSQL(d, e, r);
|
|
267
|
-
}
|
|
268
|
-
const l = Array.from(t).map((d) => {
|
|
269
|
-
var w, T;
|
|
270
|
-
return {
|
|
271
|
-
cube: d,
|
|
272
|
-
query: {
|
|
273
|
-
measures: ((w = e.measures) == null ? void 0 : w.filter((C) => C.startsWith(d + "."))) || [],
|
|
274
|
-
dimensions: ((T = e.dimensions) == null ? void 0 : T.filter((C) => C.startsWith(d + "."))) || [],
|
|
275
|
-
filters: e.filters || [],
|
|
276
|
-
timeDimensions: e.timeDimensions || [],
|
|
277
|
-
order: e.order || {},
|
|
278
|
-
limit: e.limit,
|
|
279
|
-
offset: e.offset
|
|
280
|
-
}
|
|
281
|
-
};
|
|
282
|
-
});
|
|
283
|
-
return {
|
|
284
|
-
queryType: "regularQuery",
|
|
285
|
-
normalizedQueries: l,
|
|
286
|
-
queryOrder: Array.from(t),
|
|
287
|
-
transformedQueries: l,
|
|
288
|
-
pivotQuery: {
|
|
289
|
-
query: e,
|
|
290
|
-
cubes: Array.from(t)
|
|
291
|
-
},
|
|
292
|
-
sql: {
|
|
293
|
-
sql: [i.sql],
|
|
294
|
-
params: i.params || []
|
|
295
|
-
},
|
|
296
|
-
complexity: p(e),
|
|
297
|
-
valid: !0,
|
|
298
|
-
cubesUsed: Array.from(t),
|
|
299
|
-
joinType: o ? "multi_cube_join" : "single_cube",
|
|
300
|
-
query: e
|
|
301
|
-
};
|
|
302
|
-
}
|
|
303
|
-
return m.post(`${n}/dry-run`, async (e) => {
|
|
157
|
+
}), s.post(`${d}/dry-run`, async (e) => {
|
|
304
158
|
try {
|
|
305
|
-
const r = await e.req.json(),
|
|
306
|
-
return e.json(
|
|
159
|
+
const r = await e.req.json(), t = r.query || r, o = await f(e), i = await C(t, o, a);
|
|
160
|
+
return e.json(i);
|
|
307
161
|
} catch (r) {
|
|
308
162
|
return console.error("Dry-run error:", r), e.json({
|
|
309
163
|
error: r instanceof Error ? r.message : "Dry-run validation failed",
|
|
310
164
|
valid: !1
|
|
311
165
|
}, 400);
|
|
312
166
|
}
|
|
313
|
-
}),
|
|
167
|
+
}), s.get(`${d}/dry-run`, async (e) => {
|
|
314
168
|
try {
|
|
315
169
|
const r = e.req.query("query");
|
|
316
170
|
if (!r)
|
|
@@ -318,26 +172,26 @@ function E(q) {
|
|
|
318
172
|
error: "Query parameter is required",
|
|
319
173
|
valid: !1
|
|
320
174
|
}, 400);
|
|
321
|
-
const
|
|
322
|
-
return e.json(
|
|
175
|
+
const t = JSON.parse(r), o = await f(e), i = await C(t, o, a);
|
|
176
|
+
return e.json(i);
|
|
323
177
|
} catch (r) {
|
|
324
178
|
return console.error("Dry-run error:", r), e.json({
|
|
325
179
|
error: r instanceof Error ? r.message : "Dry-run validation failed",
|
|
326
180
|
valid: !1
|
|
327
181
|
}, 400);
|
|
328
182
|
}
|
|
329
|
-
}),
|
|
183
|
+
}), s;
|
|
330
184
|
}
|
|
331
|
-
function
|
|
332
|
-
const
|
|
333
|
-
return
|
|
185
|
+
function E(y, c) {
|
|
186
|
+
const l = S(c);
|
|
187
|
+
return y.route("/", l), y;
|
|
334
188
|
}
|
|
335
|
-
function
|
|
336
|
-
const
|
|
337
|
-
return
|
|
189
|
+
function $(y) {
|
|
190
|
+
const c = new x();
|
|
191
|
+
return E(c, y);
|
|
338
192
|
}
|
|
339
193
|
export {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
194
|
+
$ as createCubeApp,
|
|
195
|
+
S as createCubeRoutes,
|
|
196
|
+
E as mountCubeRoutes
|
|
343
197
|
};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { NextRequest } from 'next/server';
|
|
2
|
+
import { SemanticQuery, SecurityContext, DatabaseExecutor, DrizzleDatabase, Cube } 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';
|
|
6
|
+
export interface NextCorsOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Allowed origins for CORS
|
|
9
|
+
*/
|
|
10
|
+
origin?: string | string[] | ((origin: string) => boolean);
|
|
11
|
+
/**
|
|
12
|
+
* Allowed HTTP methods
|
|
13
|
+
*/
|
|
14
|
+
methods?: string[];
|
|
15
|
+
/**
|
|
16
|
+
* Allowed headers
|
|
17
|
+
*/
|
|
18
|
+
allowedHeaders?: string[];
|
|
19
|
+
/**
|
|
20
|
+
* Allow credentials
|
|
21
|
+
*/
|
|
22
|
+
credentials?: boolean;
|
|
23
|
+
}
|
|
24
|
+
export interface NextAdapterOptions<TSchema extends Record<string, any> = Record<string, any>> {
|
|
25
|
+
/**
|
|
26
|
+
* Array of cube definitions to register
|
|
27
|
+
*/
|
|
28
|
+
cubes: Cube<TSchema>[];
|
|
29
|
+
/**
|
|
30
|
+
* Drizzle database instance (REQUIRED)
|
|
31
|
+
* This is the core of drizzle-cube - Drizzle ORM integration
|
|
32
|
+
* Accepts PostgreSQL, MySQL, or SQLite database instances
|
|
33
|
+
*/
|
|
34
|
+
drizzle: PostgresJsDatabase<TSchema> | MySql2Database<TSchema> | BetterSQLite3Database<TSchema> | DrizzleDatabase<TSchema>;
|
|
35
|
+
/**
|
|
36
|
+
* Database schema for type inference (RECOMMENDED)
|
|
37
|
+
* Provides full type safety for cube definitions
|
|
38
|
+
*/
|
|
39
|
+
schema?: TSchema;
|
|
40
|
+
/**
|
|
41
|
+
* Extract security context from incoming HTTP request.
|
|
42
|
+
* Called for EVERY API request to determine user permissions and multi-tenant isolation.
|
|
43
|
+
*
|
|
44
|
+
* This is your security boundary - ensure proper authentication and authorization here.
|
|
45
|
+
*
|
|
46
|
+
* @param request - Next.js Request object containing the incoming HTTP request
|
|
47
|
+
* @param context - Route context with params (optional)
|
|
48
|
+
* @returns Security context with organisationId, userId, roles, etc.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* extractSecurityContext: async (request, context) => {
|
|
52
|
+
* // Extract JWT from Authorization header
|
|
53
|
+
* const token = request.headers.get('Authorization')?.replace('Bearer ', '')
|
|
54
|
+
* const decoded = await verifyJWT(token)
|
|
55
|
+
*
|
|
56
|
+
* // Return context that will be available in all cube SQL functions
|
|
57
|
+
* return {
|
|
58
|
+
* organisationId: decoded.orgId,
|
|
59
|
+
* userId: decoded.userId,
|
|
60
|
+
* roles: decoded.roles
|
|
61
|
+
* }
|
|
62
|
+
* }
|
|
63
|
+
*/
|
|
64
|
+
extractSecurityContext: (request: NextRequest, context?: RouteContext) => SecurityContext | Promise<SecurityContext>;
|
|
65
|
+
/**
|
|
66
|
+
* Database engine type (optional - auto-detected if not provided)
|
|
67
|
+
*/
|
|
68
|
+
engineType?: 'postgres' | 'mysql' | 'sqlite';
|
|
69
|
+
/**
|
|
70
|
+
* CORS configuration (optional)
|
|
71
|
+
*/
|
|
72
|
+
cors?: NextCorsOptions;
|
|
73
|
+
/**
|
|
74
|
+
* Runtime environment (default: 'nodejs')
|
|
75
|
+
* 'edge' for Edge Runtime, 'nodejs' for Node.js Runtime
|
|
76
|
+
*/
|
|
77
|
+
runtime?: 'edge' | 'nodejs';
|
|
78
|
+
}
|
|
79
|
+
export interface RouteContext {
|
|
80
|
+
params?: Record<string, string | string[]>;
|
|
81
|
+
}
|
|
82
|
+
export type RouteHandler = (request: NextRequest, context?: RouteContext) => Promise<Response>;
|
|
83
|
+
export interface CubeHandlers {
|
|
84
|
+
load: RouteHandler;
|
|
85
|
+
meta: RouteHandler;
|
|
86
|
+
sql: RouteHandler;
|
|
87
|
+
dryRun: RouteHandler;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Create OPTIONS handler for CORS preflight requests
|
|
91
|
+
*/
|
|
92
|
+
export declare function createOptionsHandler(corsOptions: NextCorsOptions): RouteHandler;
|
|
93
|
+
/**
|
|
94
|
+
* Create load handler - Execute queries
|
|
95
|
+
*/
|
|
96
|
+
export declare function createLoadHandler<TSchema extends Record<string, any> = Record<string, any>>(options: NextAdapterOptions<TSchema>): RouteHandler;
|
|
97
|
+
/**
|
|
98
|
+
* Create meta handler - Get cube metadata
|
|
99
|
+
*/
|
|
100
|
+
export declare function createMetaHandler<TSchema extends Record<string, any> = Record<string, any>>(options: NextAdapterOptions<TSchema>): RouteHandler;
|
|
101
|
+
/**
|
|
102
|
+
* Create SQL handler - Generate SQL without execution
|
|
103
|
+
*/
|
|
104
|
+
export declare function createSqlHandler<TSchema extends Record<string, any> = Record<string, any>>(options: NextAdapterOptions<TSchema>): RouteHandler;
|
|
105
|
+
/**
|
|
106
|
+
* Create dry-run handler - Validate queries without execution
|
|
107
|
+
*/
|
|
108
|
+
export declare function createDryRunHandler<TSchema extends Record<string, any> = Record<string, any>>(options: NextAdapterOptions<TSchema>): RouteHandler;
|
|
109
|
+
/**
|
|
110
|
+
* Convenience function to create all route handlers
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* const handlers = createCubeHandlers({
|
|
114
|
+
* cubes: [salesCube, employeesCube],
|
|
115
|
+
* drizzle: db,
|
|
116
|
+
* schema,
|
|
117
|
+
* extractSecurityContext: async (request, context) => {
|
|
118
|
+
* const token = request.headers.get('Authorization')?.replace('Bearer ', '')
|
|
119
|
+
* const decoded = await verifyJWT(token)
|
|
120
|
+
* return { organisationId: decoded.orgId, userId: decoded.userId }
|
|
121
|
+
* }
|
|
122
|
+
* })
|
|
123
|
+
*
|
|
124
|
+
* // Use in your API routes:
|
|
125
|
+
* export const GET = handlers.load
|
|
126
|
+
* export const POST = handlers.load
|
|
127
|
+
*/
|
|
128
|
+
export declare function createCubeHandlers<TSchema extends Record<string, any> = Record<string, any>>(options: NextAdapterOptions<TSchema>): CubeHandlers;
|
|
129
|
+
export type { SecurityContext, DatabaseExecutor, SemanticQuery, DrizzleDatabase, NextCorsOptions as CorsOptions };
|