drizzle-cube 0.4.34 → 0.4.36
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 +1 -1
- package/dist/adapters/express/index.cjs +1 -1
- package/dist/adapters/express/index.d.ts +7 -1
- package/dist/adapters/express/index.js +5 -4
- package/dist/adapters/fastify/index.cjs +1 -1
- package/dist/adapters/fastify/index.d.ts +7 -1
- package/dist/adapters/fastify/index.js +5 -4
- package/dist/adapters/{handler-ClgB__a-.cjs → handler-DzUX7CBs.cjs} +1 -1
- package/dist/adapters/{handler-rPpxuopb.js → handler-J55KQKe5.js} +1 -1
- package/dist/adapters/hono/index.cjs +1 -1
- package/dist/adapters/hono/index.d.ts +7 -1
- package/dist/adapters/hono/index.js +5 -4
- package/dist/adapters/{mcp-transport-DPpei63d.cjs → mcp-transport-CjA5_6G_.cjs} +2 -2
- package/dist/adapters/{mcp-transport-DWSNkwUY.js → mcp-transport-x_A7Q5OL.js} +35 -20
- package/dist/adapters/nextjs/index.cjs +1 -1
- package/dist/adapters/nextjs/index.d.ts +7 -1
- package/dist/adapters/nextjs/index.js +9 -8
- package/dist/adapters/{utils-BLFzzCI9.cjs → utils-CDExg9uP.cjs} +1 -1
- package/dist/adapters/{utils-B7VkyzMv.js → utils-DkKcpkx5.js} +1 -5
- package/dist/adapters/utils.cjs +1 -1
- package/dist/adapters/utils.js +1 -1
- package/dist/client/charts.js +3 -3
- package/dist/client/chunks/{DashboardEditModal-DenRJiYr.js → DashboardEditModal-kWEk4KJC.js} +8 -8
- package/dist/client/chunks/{DashboardEditModal-DenRJiYr.js.map → DashboardEditModal-kWEk4KJC.js.map} +1 -1
- package/dist/client/chunks/{FieldSearchModal-BQS1v1up.js → FieldSearchModal-rB26lhBD.js} +3 -3
- package/dist/client/chunks/{FieldSearchModal-BQS1v1up.js.map → FieldSearchModal-rB26lhBD.js.map} +1 -1
- package/dist/client/chunks/{analysis-builder-DG38V1gO.js → analysis-builder-CdDPUAEU.js} +8 -8
- package/dist/client/chunks/{analysis-builder-DG38V1gO.js.map → analysis-builder-CdDPUAEU.js.map} +1 -1
- package/dist/client/chunks/{analysis-builder-shared-DaFu78dk.js → analysis-builder-shared-3V70XUNW.js} +15 -19
- package/dist/client/chunks/{analysis-builder-shared-DaFu78dk.js.map → analysis-builder-shared-3V70XUNW.js.map} +1 -1
- package/dist/client/chunks/{chart-data-table-B2m_6EZe.js → chart-data-table-BlkFWPhF.js} +602 -581
- package/dist/client/chunks/chart-data-table-BlkFWPhF.js.map +1 -0
- package/dist/client/chunks/{chart-kpi-delta-S6qDEoJO.js → chart-kpi-delta-CUIjCDS3.js} +2 -2
- package/dist/client/chunks/{chart-kpi-delta-S6qDEoJO.js.map → chart-kpi-delta-CUIjCDS3.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-number-CEUBsVW2.js → chart-kpi-number-CxlpSKYh.js} +3 -3
- package/dist/client/chunks/{chart-kpi-number-CEUBsVW2.js.map → chart-kpi-number-CxlpSKYh.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-text-DgRig_jQ.js → chart-kpi-text-C16fwohp.js} +2 -2
- package/dist/client/chunks/{chart-kpi-text-DgRig_jQ.js.map → chart-kpi-text-C16fwohp.js.map} +1 -1
- package/dist/client/chunks/{chart-markdown-DXxc43w1.js → chart-markdown-B2X4IwLO.js} +1132 -1119
- package/dist/client/chunks/chart-markdown-B2X4IwLO.js.map +1 -0
- package/dist/client/chunks/{charts-loader-BI07yxaQ.js → charts-loader-BFhQWB_d.js} +6 -6
- package/dist/client/chunks/{charts-loader-BI07yxaQ.js.map → charts-loader-BFhQWB_d.js.map} +1 -1
- package/dist/client/chunks/{core-D1TOj17W.js → core-DJrniqct.js} +2 -6
- package/dist/client/chunks/{core-D1TOj17W.js.map → core-DJrniqct.js.map} +1 -1
- package/dist/client/chunks/{schema-visualization-DPL5_Tkh.js → schema-visualization-qmLI8MGQ.js} +13 -14
- package/dist/client/chunks/{schema-visualization-DPL5_Tkh.js.map → schema-visualization-qmLI8MGQ.js.map} +1 -1
- package/dist/client/chunks/{syntaxHighlighting-87bOwTxj.js → syntaxHighlighting-BLl0ch4A.js} +2 -2
- package/dist/client/chunks/{syntaxHighlighting-87bOwTxj.js.map → syntaxHighlighting-BLl0ch4A.js.map} +1 -1
- package/dist/client/chunks/{useDebounce-DkuM7nQk.js → useDebounce-xfPFr2fi.js} +2 -2
- package/dist/client/chunks/{useDebounce-DkuM7nQk.js.map → useDebounce-xfPFr2fi.js.map} +1 -1
- package/dist/client/chunks/{useExplainAI-RflLTDVL.js → useExplainAI-6COjssus.js} +4 -4
- package/dist/client/chunks/{useExplainAI-RflLTDVL.js.map → useExplainAI-6COjssus.js.map} +1 -1
- package/dist/client/chunks/{utils--32ZtfbZ.js → utils-nCeVL-Hm.js} +2 -2
- package/dist/client/chunks/{utils--32ZtfbZ.js.map → utils-nCeVL-Hm.js.map} +1 -1
- package/dist/client/chunks/{vendor-CZX7UVzM.js → vendor-WzXX36hd.js} +3 -3
- package/dist/client/chunks/{vendor-CZX7UVzM.js.map → vendor-WzXX36hd.js.map} +1 -1
- package/dist/client/components.js +3 -3
- package/dist/client/hooks.js +3 -3
- package/dist/client/icons.js +1 -1
- package/dist/client/index.js +12 -12
- package/dist/client/providers.js +1 -1
- package/dist/client/utils.js +4 -4
- package/dist/client-bundle-stats.html +1 -1
- package/dist/server/index.cjs +2 -2
- package/dist/server/index.d.ts +47 -5
- package/dist/server/index.js +34 -19
- package/package.json +3 -3
- package/dist/client/chunks/chart-data-table-B2m_6EZe.js.map +0 -1
- package/dist/client/chunks/chart-markdown-DXxc43w1.js.map +0 -1
package/dist/server/index.d.ts
CHANGED
|
@@ -1367,6 +1367,7 @@ export declare interface DrizzleDatabase {
|
|
|
1367
1367
|
};
|
|
1368
1368
|
with: (...args: any[]) => any;
|
|
1369
1369
|
schema?: unknown;
|
|
1370
|
+
transaction?: <T>(fn: (tx: any) => Promise<T>, ...args: any[]) => Promise<T>;
|
|
1370
1371
|
}
|
|
1371
1372
|
|
|
1372
1373
|
/**
|
|
@@ -1519,6 +1520,13 @@ export declare class DrizzleSqlBuilder {
|
|
|
1519
1520
|
buildLogicalFilter(filter: Filter, cubes: Map<string, Cube>, context: QueryContext): SQL | null;
|
|
1520
1521
|
}
|
|
1521
1522
|
|
|
1523
|
+
/**
|
|
1524
|
+
* Transaction-scoped database instance passed to RLS setup.
|
|
1525
|
+
* Structurally identical to DrizzleDatabase — the alias communicates
|
|
1526
|
+
* that the value lives inside a transaction, not the root connection.
|
|
1527
|
+
*/
|
|
1528
|
+
export declare type DrizzleTransaction = DrizzleDatabase;
|
|
1529
|
+
|
|
1522
1530
|
export declare class DuckDBExecutor extends BaseDatabaseExecutor {
|
|
1523
1531
|
execute<T = any[]>(query: SQL | any, numericFields?: string[]): Promise<T>;
|
|
1524
1532
|
/**
|
|
@@ -3850,7 +3858,19 @@ export declare class QueryExecutor {
|
|
|
3850
3858
|
private cacheConfig?;
|
|
3851
3859
|
private logicalPlanBuilder;
|
|
3852
3860
|
private planOptimiser;
|
|
3853
|
-
|
|
3861
|
+
private rlsSetup?;
|
|
3862
|
+
constructor(dbExecutor: DatabaseExecutor, cacheConfig?: CacheConfig, rlsSetup?: RLSSetupFn);
|
|
3863
|
+
/**
|
|
3864
|
+
* Execute a function within a RLS-configured transaction context.
|
|
3865
|
+
* If no rlsSetup function is configured, the function is called directly.
|
|
3866
|
+
* Otherwise, opens a transaction, calls rlsSetup to configure RLS, then
|
|
3867
|
+
* runs fn with this.dbExecutor replaced by a transaction-scoped executor.
|
|
3868
|
+
*
|
|
3869
|
+
* Concurrency-safe: the dbExecutor is per-request (created fresh by
|
|
3870
|
+
* SemanticLayerCompiler.createQueryExecutor), so reassigning this.dbExecutor
|
|
3871
|
+
* only affects this request.
|
|
3872
|
+
*/
|
|
3873
|
+
private withRLSContext;
|
|
3854
3874
|
/**
|
|
3855
3875
|
* Unified query execution method that handles both single and multi-cube queries
|
|
3856
3876
|
* @param options.skipCache - Skip cache lookup (but still cache the fresh result)
|
|
@@ -4370,6 +4390,16 @@ export declare interface RetentionTimeDimensionMapping {
|
|
|
4370
4390
|
dimension: string;
|
|
4371
4391
|
}
|
|
4372
4392
|
|
|
4393
|
+
/**
|
|
4394
|
+
* Row-Level Security setup function.
|
|
4395
|
+
* Called inside a transaction before query execution to configure
|
|
4396
|
+
* database-level RLS (e.g., setting JWT claims and switching roles in Postgres).
|
|
4397
|
+
*
|
|
4398
|
+
* @param tx - The transaction-scoped Drizzle database instance
|
|
4399
|
+
* @param securityContext - The security context extracted from the request
|
|
4400
|
+
*/
|
|
4401
|
+
export declare type RLSSetupFn = (tx: DrizzleTransaction, securityContext: SecurityContext) => Promise<void>;
|
|
4402
|
+
|
|
4373
4403
|
/**
|
|
4374
4404
|
* A link (edge) in the Sankey diagram
|
|
4375
4405
|
* Represents a transition between two nodes
|
|
@@ -4414,9 +4444,12 @@ export declare interface SecurityContext {
|
|
|
4414
4444
|
|
|
4415
4445
|
export declare class SemanticLayerCompiler {
|
|
4416
4446
|
private cubes;
|
|
4417
|
-
private dbExecutor?;
|
|
4418
4447
|
private metadataCache?;
|
|
4419
4448
|
private cacheConfig?;
|
|
4449
|
+
private rlsSetup?;
|
|
4450
|
+
private db?;
|
|
4451
|
+
private schema?;
|
|
4452
|
+
private engineType?;
|
|
4420
4453
|
constructor(options?: {
|
|
4421
4454
|
drizzle?: DatabaseExecutor['db'];
|
|
4422
4455
|
schema?: any;
|
|
@@ -4424,9 +4457,16 @@ export declare class SemanticLayerCompiler {
|
|
|
4424
4457
|
engineType?: 'postgres' | 'mysql' | 'sqlite' | 'singlestore' | 'duckdb' | 'databend' | 'snowflake';
|
|
4425
4458
|
/** Cache configuration for query result caching */
|
|
4426
4459
|
cache?: CacheConfig;
|
|
4460
|
+
/**
|
|
4461
|
+
* Row-Level Security setup function.
|
|
4462
|
+
* When provided, every query execution opens a transaction, calls this function
|
|
4463
|
+
* to configure RLS (e.g., set JWT claims and switch roles), then runs the query.
|
|
4464
|
+
* Dry-run/SQL generation is NOT wrapped in a transaction.
|
|
4465
|
+
*/
|
|
4466
|
+
rlsSetup?: RLSSetupFn;
|
|
4427
4467
|
});
|
|
4428
4468
|
/**
|
|
4429
|
-
* Set or update the database
|
|
4469
|
+
* Set or update the database connection
|
|
4430
4470
|
*/
|
|
4431
4471
|
setDatabaseExecutor(executor: DatabaseExecutor): void;
|
|
4432
4472
|
/**
|
|
@@ -4442,11 +4482,13 @@ export declare class SemanticLayerCompiler {
|
|
|
4442
4482
|
*/
|
|
4443
4483
|
hasExecutor(): boolean;
|
|
4444
4484
|
/**
|
|
4445
|
-
*
|
|
4485
|
+
* Create a fresh DatabaseExecutor from stored ingredients, or throw.
|
|
4446
4486
|
*/
|
|
4447
|
-
private
|
|
4487
|
+
private createDbExecutor;
|
|
4448
4488
|
/**
|
|
4449
4489
|
* Create a query executor with optional cache integration.
|
|
4490
|
+
* Each call creates a fresh DatabaseExecutor so concurrent requests
|
|
4491
|
+
* never share mutable state.
|
|
4450
4492
|
*/
|
|
4451
4493
|
private createQueryExecutor;
|
|
4452
4494
|
/**
|
package/dist/server/index.js
CHANGED
|
@@ -6565,7 +6565,7 @@ var Yt = class {
|
|
|
6565
6565
|
//#endregion
|
|
6566
6566
|
//#region src/server/executor.ts
|
|
6567
6567
|
function Xt(e, t) {
|
|
6568
|
-
if (process.env
|
|
6568
|
+
if (!(typeof process > "u" || !process.env?.DC_DEBUG)) try {
|
|
6569
6569
|
let { sql: n, params: r } = t.toSQL();
|
|
6570
6570
|
console.log(`\n[DC_DEBUG] ${e}`), console.log(n), r.length > 0 && console.log("params:", r), console.log();
|
|
6571
6571
|
} catch {}
|
|
@@ -6581,11 +6581,23 @@ var Zt = class {
|
|
|
6581
6581
|
cacheConfig;
|
|
6582
6582
|
logicalPlanBuilder;
|
|
6583
6583
|
planOptimiser;
|
|
6584
|
-
|
|
6584
|
+
rlsSetup;
|
|
6585
|
+
constructor(e, t, n) {
|
|
6585
6586
|
if (this.dbExecutor = e, this.databaseAdapter = e.databaseAdapter, !this.databaseAdapter) throw Error("DatabaseExecutor must have a databaseAdapter property");
|
|
6586
6587
|
this.queryBuilder = new _t(this.databaseAdapter);
|
|
6587
|
-
let
|
|
6588
|
-
this.drizzlePlanBuilder = new Yt(this.queryBuilder,
|
|
6588
|
+
let r = new yt(), i = new bt(this.queryBuilder);
|
|
6589
|
+
this.drizzlePlanBuilder = new Yt(this.queryBuilder, i, this.databaseAdapter), this.comparisonQueryBuilder = new kt(this.databaseAdapter), this.funnelQueryBuilder = new At(this.databaseAdapter), this.flowQueryBuilder = new jt(this.databaseAdapter), this.retentionQueryBuilder = new It(this.databaseAdapter), this.logicalPlanBuilder = new Lt(r), this.planOptimiser = new Rt(), this.cacheConfig = t, this.rlsSetup = n;
|
|
6590
|
+
}
|
|
6591
|
+
async withRLSContext(e, t) {
|
|
6592
|
+
if (!this.rlsSetup) return t();
|
|
6593
|
+
let n = this.dbExecutor.db;
|
|
6594
|
+
if (!n.transaction) throw Error("rlsSetup requires a database driver that supports transactions (db.transaction)");
|
|
6595
|
+
let r = this.rlsSetup;
|
|
6596
|
+
return n.transaction(async (n) => {
|
|
6597
|
+
await r(n, e);
|
|
6598
|
+
let i = Object.create(this.dbExecutor);
|
|
6599
|
+
return i.db = n, this.dbExecutor = i, t();
|
|
6600
|
+
});
|
|
6589
6601
|
}
|
|
6590
6602
|
async execute(e, t, n, r) {
|
|
6591
6603
|
try {
|
|
@@ -6625,7 +6637,7 @@ var Zt = class {
|
|
|
6625
6637
|
} catch (e) {
|
|
6626
6638
|
this.cacheConfig.onError?.(e, "get");
|
|
6627
6639
|
}
|
|
6628
|
-
return await this.executeQueryByModeWithCache(i, e, t, n, a);
|
|
6640
|
+
return await this.withRLSContext(n, () => this.executeQueryByModeWithCache(i, e, t, n, a));
|
|
6629
6641
|
} catch (e) {
|
|
6630
6642
|
if (e instanceof Error) {
|
|
6631
6643
|
let t = e;
|
|
@@ -6825,8 +6837,8 @@ var Zt = class {
|
|
|
6825
6837
|
for (let e of i) if (!a.has(e.name)) {
|
|
6826
6838
|
a.add(e.name);
|
|
6827
6839
|
try {
|
|
6828
|
-
if (e.public) continue;
|
|
6829
|
-
e.sql(t).where || console.warn(`[drizzle-cube] WARNING: Cube '${e.name}' has no security filtering. If this cube contains public data, add 'public: true' to suppress this warning. Otherwise, ensure sql() returns: { from: table, where: eq(table.orgId, ctx.securityContext.orgId) }
|
|
6840
|
+
if (e.public || this.rlsSetup) continue;
|
|
6841
|
+
e.sql(t).where || console.warn(`[drizzle-cube] WARNING: Cube '${e.name}' has no security filtering. If this cube contains public data, add 'public: true' to suppress this warning. Otherwise, ensure sql() returns: { from: table, where: eq(table.orgId, ctx.securityContext.orgId) }. For databases that support Row Level Security (e.g. PostgreSQL), you can configure rlsSetup to run session-level commands (SET LOCAL, SET ROLE) instead.`);
|
|
6830
6842
|
} catch {}
|
|
6831
6843
|
}
|
|
6832
6844
|
}
|
|
@@ -6881,7 +6893,7 @@ var Zt = class {
|
|
|
6881
6893
|
}
|
|
6882
6894
|
async explainQuery(e, t, n, r) {
|
|
6883
6895
|
let i = await this.dryRunSQL(e, t, n);
|
|
6884
|
-
return this.dbExecutor.explainQuery(i.sql, i.params || [], r);
|
|
6896
|
+
return this.withRLSContext(n, () => this.dbExecutor.explainQuery(i.sql, i.params || [], r));
|
|
6885
6897
|
}
|
|
6886
6898
|
async dryRunSQL(e, t, n) {
|
|
6887
6899
|
let r = this.resolveQueryMode(t);
|
|
@@ -11191,33 +11203,36 @@ async function hc(e, t, n) {
|
|
|
11191
11203
|
//#region src/server/compiler.ts
|
|
11192
11204
|
var gc = class e {
|
|
11193
11205
|
cubes = /* @__PURE__ */ new Map();
|
|
11194
|
-
dbExecutor;
|
|
11195
11206
|
metadataCache;
|
|
11196
11207
|
cacheConfig;
|
|
11208
|
+
rlsSetup;
|
|
11209
|
+
db;
|
|
11210
|
+
schema;
|
|
11211
|
+
engineType;
|
|
11197
11212
|
constructor(e) {
|
|
11198
|
-
e?.databaseExecutor ? this.
|
|
11213
|
+
e?.databaseExecutor ? (this.db = e.databaseExecutor.db, this.schema = e.databaseExecutor.schema, this.engineType = e.databaseExecutor.getEngineType()) : e?.drizzle && (this.db = e.drizzle, this.schema = e.schema, this.engineType = e.engineType), this.cacheConfig = e?.cache, this.rlsSetup = e?.rlsSetup;
|
|
11199
11214
|
}
|
|
11200
11215
|
setDatabaseExecutor(e) {
|
|
11201
|
-
this.
|
|
11216
|
+
this.db = e.db, this.schema = e.schema, this.engineType = e.getEngineType();
|
|
11202
11217
|
}
|
|
11203
11218
|
getEngineType() {
|
|
11204
|
-
return this.
|
|
11219
|
+
return this.engineType;
|
|
11205
11220
|
}
|
|
11206
11221
|
setDrizzle(e, t, n) {
|
|
11207
|
-
this.
|
|
11222
|
+
this.db = e, this.schema = t, this.engineType = n;
|
|
11208
11223
|
}
|
|
11209
11224
|
hasExecutor() {
|
|
11210
|
-
return !!this.
|
|
11225
|
+
return !!this.db;
|
|
11211
11226
|
}
|
|
11212
|
-
|
|
11213
|
-
if (!this.
|
|
11214
|
-
return this.
|
|
11227
|
+
createDbExecutor() {
|
|
11228
|
+
if (!this.db) throw Error("Database executor not configured");
|
|
11229
|
+
return Ue(this.db, this.schema, this.engineType);
|
|
11215
11230
|
}
|
|
11216
11231
|
createQueryExecutor(e = !1) {
|
|
11217
|
-
return new Zt(this.
|
|
11232
|
+
return new Zt(this.createDbExecutor(), e ? this.cacheConfig : void 0, this.rlsSetup);
|
|
11218
11233
|
}
|
|
11219
11234
|
formatSqlResult(e) {
|
|
11220
|
-
let t = this.
|
|
11235
|
+
let t = this.getEngineType() ?? "postgres";
|
|
11221
11236
|
return {
|
|
11222
11237
|
sql: pc(e.sql, t),
|
|
11223
11238
|
params: e.params
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "drizzle-cube",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.36",
|
|
4
4
|
"description": "Drizzle ORM-first semantic layer with Cube.js compatibility. Type-safe analytics and dashboards with SQL injection protection.",
|
|
5
5
|
"main": "./dist/server/index.js",
|
|
6
6
|
"types": "./dist/server/index.d.ts",
|
|
@@ -266,7 +266,7 @@
|
|
|
266
266
|
"@leonardovida-md/drizzle-neo-duckdb": "^1.2.2"
|
|
267
267
|
},
|
|
268
268
|
"devDependencies": {
|
|
269
|
-
"@anthropic-ai/sdk": "^0.
|
|
269
|
+
"@anthropic-ai/sdk": "^0.80.0",
|
|
270
270
|
"@eslint/eslintrc": "^3.3.1",
|
|
271
271
|
"@eslint/js": "^10.0.0",
|
|
272
272
|
"@fastify/cors": "^11.1.0",
|
|
@@ -317,7 +317,7 @@
|
|
|
317
317
|
"globals": "^17.0.0",
|
|
318
318
|
"hono": "^4.0.0",
|
|
319
319
|
"html2canvas": "^1.4.1",
|
|
320
|
-
"jsdom": "^
|
|
320
|
+
"jsdom": "^29.0.0",
|
|
321
321
|
"modern-screenshot": "^4.6.7",
|
|
322
322
|
"msw": "^2.12.7",
|
|
323
323
|
"mysql2": "^3.14.3",
|