drizzle-cube 0.3.25 → 0.3.28
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 +6 -0
- package/dist/adapters/express/index.cjs +1 -1
- package/dist/adapters/express/index.js +1 -1
- package/dist/adapters/fastify/index.cjs +1 -1
- package/dist/adapters/fastify/index.js +1 -1
- package/dist/adapters/hono/index.cjs +1 -1
- package/dist/adapters/hono/index.js +1 -1
- package/dist/adapters/{mcp-transport-B4BZSsMC.js → mcp-transport-CXGL1hg7.js} +1655 -1624
- package/dist/adapters/{mcp-transport-C8pLznZG.cjs → mcp-transport-ConlvewL.cjs} +73 -73
- package/dist/adapters/nextjs/index.cjs +1 -1
- package/dist/adapters/nextjs/index.js +1 -1
- package/dist/adapters/utils.cjs +1 -1
- package/dist/adapters/utils.js +5 -5
- package/dist/client/charts.js +12 -12
- package/dist/client/chunks/{DashboardEditModal-CVMSvpJ-.js → DashboardEditModal-t5XeTZom.js} +45 -45
- package/dist/client/chunks/DashboardEditModal-t5XeTZom.js.map +1 -0
- package/dist/client/chunks/{RetentionCombinedChart-BVKWmxc-.js → RetentionCombinedChart-SsBGHJWi.js} +9 -9
- package/dist/client/chunks/RetentionCombinedChart-SsBGHJWi.js.map +1 -0
- package/dist/client/chunks/{RetentionHeatmap-BiqfhGYk.js → RetentionHeatmap-BHYU8MXY.js} +8 -8
- package/dist/client/chunks/RetentionHeatmap-BHYU8MXY.js.map +1 -0
- package/dist/client/chunks/{analysis-builder-CuTR61Ct.js → analysis-builder-CKVYG9jJ.js} +67 -67
- package/dist/client/chunks/analysis-builder-CKVYG9jJ.js.map +1 -0
- package/dist/client/chunks/{analysis-builder-shared-D7iqklYk.js → analysis-builder-shared-CF8Vx1oD.js} +8 -8
- package/dist/client/chunks/analysis-builder-shared-CF8Vx1oD.js.map +1 -0
- package/dist/client/chunks/{chart-activity-grid-BcMRkaq4.js → chart-activity-grid-Bpu_-8uT.js} +5 -5
- package/dist/client/chunks/{chart-activity-grid-BcMRkaq4.js.map → chart-activity-grid-Bpu_-8uT.js.map} +1 -1
- package/dist/client/chunks/{chart-area-KlBSb_ur.js → chart-area-DcvLkvGb.js} +8 -8
- package/dist/client/chunks/chart-area-DcvLkvGb.js.map +1 -0
- package/dist/client/chunks/{chart-bar-D1i2jmIg.js → chart-bar-CNfm5iMY.js} +7 -7
- package/dist/client/chunks/chart-bar-CNfm5iMY.js.map +1 -0
- package/dist/client/chunks/{chart-bubble-BFjnOwNZ.js → chart-bubble-KA-RYWR8.js} +4 -4
- package/dist/client/chunks/{chart-bubble-BFjnOwNZ.js.map → chart-bubble-KA-RYWR8.js.map} +1 -1
- package/dist/client/chunks/{chart-data-table-CYMMAHau.js → chart-data-table-Cq14arji.js} +9 -9
- package/dist/client/chunks/chart-data-table-Cq14arji.js.map +1 -0
- package/dist/client/chunks/{chart-funnel-BH7r4HWZ.js → chart-funnel-DFKWS49U.js} +7 -7
- package/dist/client/chunks/chart-funnel-DFKWS49U.js.map +1 -0
- package/dist/client/chunks/{chart-heat-map-DyGtODLE.js → chart-heat-map-D2g0dbKz.js} +5 -5
- package/dist/client/chunks/chart-heat-map-D2g0dbKz.js.map +1 -0
- package/dist/client/chunks/{chart-kpi-delta-Bk396suk.js → chart-kpi-delta-Cc-jiBd0.js} +30 -30
- package/dist/client/chunks/chart-kpi-delta-Cc-jiBd0.js.map +1 -0
- package/dist/client/chunks/{chart-kpi-number-CIGqZ5Dw.js → chart-kpi-number-BXolYaZA.js} +8 -8
- package/dist/client/chunks/chart-kpi-number-BXolYaZA.js.map +1 -0
- package/dist/client/chunks/{chart-kpi-text-iwlaSQCi.js → chart-kpi-text-PA8oyypA.js} +7 -7
- package/dist/client/chunks/chart-kpi-text-PA8oyypA.js.map +1 -0
- package/dist/client/chunks/{chart-line-BKqhoW9A.js → chart-line-BOrtUdOD.js} +8 -8
- package/dist/client/chunks/chart-line-BOrtUdOD.js.map +1 -0
- package/dist/client/chunks/{chart-markdown-CiPhRY9s.js → chart-markdown-Cget3iEq.js} +6 -6
- package/dist/client/chunks/chart-markdown-Cget3iEq.js.map +1 -0
- package/dist/client/chunks/{chart-pie-BNr-GgTh.js → chart-pie-B-Sbsvd2.js} +7 -7
- package/dist/client/chunks/chart-pie-B-Sbsvd2.js.map +1 -0
- package/dist/client/chunks/{chart-radar-CYrGVYEQ.js → chart-radar-CezgvXhm.js} +6 -6
- package/dist/client/chunks/chart-radar-CezgvXhm.js.map +1 -0
- package/dist/client/chunks/{chart-radial-bar-2PR3ucIR.js → chart-radial-bar-COBPiBxm.js} +6 -6
- package/dist/client/chunks/chart-radial-bar-COBPiBxm.js.map +1 -0
- package/dist/client/chunks/{chart-sankey-C7w7h2ZV.js → chart-sankey-O4WQBRDk.js} +27 -27
- package/dist/client/chunks/{chart-sankey-C7w7h2ZV.js.map → chart-sankey-O4WQBRDk.js.map} +1 -1
- package/dist/client/chunks/{chart-scatter-D3Z9bl8H.js → chart-scatter-BVF0n9DR.js} +22 -22
- package/dist/client/chunks/chart-scatter-BVF0n9DR.js.map +1 -0
- package/dist/client/chunks/{chart-sunburst-C4ydFeaK.js → chart-sunburst-DZzVj_6S.js} +4 -4
- package/dist/client/chunks/{chart-sunburst-C4ydFeaK.js.map → chart-sunburst-DZzVj_6S.js.map} +1 -1
- package/dist/client/chunks/{chart-tree-map-DCCmMyz1.js → chart-tree-map-CeEtNuo6.js} +6 -6
- package/dist/client/chunks/chart-tree-map-CeEtNuo6.js.map +1 -0
- package/dist/client/chunks/{charts-core-DIW3Dd7n.js → charts-core-DF99lItO.js} +4 -4
- package/dist/client/chunks/charts-core-DF99lItO.js.map +1 -0
- package/dist/client/chunks/{charts-loader-BCBnMYjH.js → charts-loader-AkRviD9H.js} +22 -22
- package/dist/client/chunks/{charts-loader-BCBnMYjH.js.map → charts-loader-AkRviD9H.js.map} +1 -1
- package/dist/client/chunks/{core-BITzuqYm.js → core-Bso4ultM.js} +2 -2
- package/dist/client/chunks/{core-BITzuqYm.js.map → core-Bso4ultM.js.map} +1 -1
- package/dist/client/chunks/{hooks-Dd_nnv0J.js → hooks-B69r8rwU.js} +4 -4
- package/dist/client/chunks/{hooks-Dd_nnv0J.js.map → hooks-B69r8rwU.js.map} +1 -1
- package/dist/client/chunks/{providers-BjxD1ZmC.js → providers-CxlSRYvE.js} +2 -2
- package/dist/client/chunks/{providers-BjxD1ZmC.js.map → providers-CxlSRYvE.js.map} +1 -1
- package/dist/client/chunks/{syntaxHighlighting-Cmqp7_Mx.js → syntaxHighlighting-yTdSle2t.js} +2 -2
- package/dist/client/chunks/{syntaxHighlighting-Cmqp7_Mx.js.map → syntaxHighlighting-yTdSle2t.js.map} +1 -1
- package/dist/client/chunks/{useDirtyStateTracking-B5g-bw7a.js → useDirtyStateTracking-GZtwGRu7.js} +3 -3
- package/dist/client/chunks/{useDirtyStateTracking-B5g-bw7a.js.map → useDirtyStateTracking-GZtwGRu7.js.map} +1 -1
- package/dist/client/chunks/{vendor-CJRtj0__.js → vendor-B_H-VRhj.js} +97 -99
- package/dist/client/chunks/vendor-B_H-VRhj.js.map +1 -0
- package/dist/client/components.js +4 -4
- package/dist/client/components.js.map +1 -1
- package/dist/client/hooks.js +3 -3
- package/dist/client/index.js +10 -10
- package/dist/client/index.js.map +1 -1
- package/dist/client/providers.js +1 -1
- package/dist/client/styles.css +1 -1
- package/dist/client/utils.js +6 -6
- package/dist/client-bundle-stats.html +1 -1
- package/dist/server/index.cjs +20 -20
- package/dist/server/index.d.ts +10 -0
- package/dist/server/index.js +674 -643
- package/package.json +1 -1
- package/dist/client/chunks/DashboardEditModal-CVMSvpJ-.js.map +0 -1
- package/dist/client/chunks/RetentionCombinedChart-BVKWmxc-.js.map +0 -1
- package/dist/client/chunks/RetentionHeatmap-BiqfhGYk.js.map +0 -1
- package/dist/client/chunks/analysis-builder-CuTR61Ct.js.map +0 -1
- package/dist/client/chunks/analysis-builder-shared-D7iqklYk.js.map +0 -1
- package/dist/client/chunks/chart-area-KlBSb_ur.js.map +0 -1
- package/dist/client/chunks/chart-bar-D1i2jmIg.js.map +0 -1
- package/dist/client/chunks/chart-data-table-CYMMAHau.js.map +0 -1
- package/dist/client/chunks/chart-funnel-BH7r4HWZ.js.map +0 -1
- package/dist/client/chunks/chart-heat-map-DyGtODLE.js.map +0 -1
- package/dist/client/chunks/chart-kpi-delta-Bk396suk.js.map +0 -1
- package/dist/client/chunks/chart-kpi-number-CIGqZ5Dw.js.map +0 -1
- package/dist/client/chunks/chart-kpi-text-iwlaSQCi.js.map +0 -1
- package/dist/client/chunks/chart-line-BKqhoW9A.js.map +0 -1
- package/dist/client/chunks/chart-markdown-CiPhRY9s.js.map +0 -1
- package/dist/client/chunks/chart-pie-BNr-GgTh.js.map +0 -1
- package/dist/client/chunks/chart-radar-CYrGVYEQ.js.map +0 -1
- package/dist/client/chunks/chart-radial-bar-2PR3ucIR.js.map +0 -1
- package/dist/client/chunks/chart-scatter-D3Z9bl8H.js.map +0 -1
- package/dist/client/chunks/chart-tree-map-DCCmMyz1.js.map +0 -1
- package/dist/client/chunks/charts-core-DIW3Dd7n.js.map +0 -1
- package/dist/client/chunks/vendor-CJRtj0__.js.map +0 -1
package/README.md
CHANGED
|
@@ -220,6 +220,12 @@ Then configure your API endpoint in `.drizzle-cube.json` and ask Claude things l
|
|
|
220
220
|
- **Security** - Multi-tenant isolation via security context
|
|
221
221
|
- **Cross-cube queries** - Automatic join resolution
|
|
222
222
|
|
|
223
|
+
### Modeling Note: Multi-Fact Queries
|
|
224
|
+
- For `FactA -> Dimension <- FactB` (star/snowflake patterns), define reverse `hasMany` joins on the center dimension back to each fact.
|
|
225
|
+
- Example: if `Sales` and `Inventory` both `belongsTo Products`, `Products` should define `hasMany Sales` and `hasMany Inventory`.
|
|
226
|
+
- Why: join-path traversal is directional. Without reverse joins, the planner may not be able to pick the center dimension as the primary cube, which can lead to fan-out-prone execution plans.
|
|
227
|
+
- If you cannot add reverse joins immediately, include the center join key dimension (for example `Products.id`) in the query grain to reduce aggregation ambiguity.
|
|
228
|
+
|
|
223
229
|
### Client Components
|
|
224
230
|
- **AnalysisBuilder** - Interactive query builder with chart visualization
|
|
225
231
|
- **AnalyticsDashboard** - Configurable dashboards with grid layouts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=require("express"),H=require("cors"),i=require("../mcp-transport-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=require("express"),H=require("cors"),i=require("../mcp-transport-ConlvewL.cjs"),s=require("../utils.cjs");function q(h){const{cubes:f,drizzle:C,schema:I,extractSecurityContext:p,engineType:P,cors:x,basePath:y="/cubejs-api/v1",jsonLimit:w="10mb",cache:M,mcp:j={enabled:!0}}=h;if(!f||f.length===0)throw new Error("At least one cube must be provided in the cubes array");const l=E.Router();x&&l.use(H(x)),l.use(E.json({limit:w})),l.use(E.urlencoded({extended:!0,limit:w}));const u=new i.SemanticLayerCompiler({drizzle:C,schema:I,engineType:P,cache:M});if(f.forEach(r=>{u.registerCube(r)}),l.post(`${y}/load`,async(r,t)=>{try{const e=r.body.query||r.body,o=await p(r,t),n=u.validateQuery(e);if(!n.isValid)return t.status(400).json(s.formatErrorResponse(`Query validation failed: ${n.errors.join(", ")}`,400));const a=r.headers["x-cache-control"]==="no-cache",c=await u.executeMultiCubeQuery(e,o,{skipCache:a});t.json(s.formatCubeResponse(e,c,u))}catch(e){console.error("Query execution error:",e),t.status(500).json(s.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500))}}),l.get(`${y}/load`,async(r,t)=>{try{const e=r.query.query;if(!e)return t.status(400).json(s.formatErrorResponse("Query parameter is required",400));let o;try{o=JSON.parse(e)}catch{return t.status(400).json(s.formatErrorResponse("Invalid JSON in query parameter",400))}const n=await p(r,t),a=u.validateQuery(o);if(!a.isValid)return t.status(400).json(s.formatErrorResponse(`Query validation failed: ${a.errors.join(", ")}`,400));const c=r.headers["x-cache-control"]==="no-cache",m=await u.executeMultiCubeQuery(o,n,{skipCache:c});t.json(s.formatCubeResponse(o,m,u))}catch(e){console.error("Query execution error:",e),t.status(500).json(s.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500))}}),l.post(`${y}/batch`,async(r,t)=>{try{const{queries:e}=r.body;if(!e||!Array.isArray(e))return t.status(400).json(s.formatErrorResponse('Request body must contain a "queries" array',400));if(e.length===0)return t.status(400).json(s.formatErrorResponse("Queries array cannot be empty",400));const o=await p(r,t),n=r.headers["x-cache-control"]==="no-cache",a=await s.handleBatchRequest(e,o,u,{skipCache:n});t.json(a)}catch(e){console.error("Batch execution error:",e),t.status(500).json(s.formatErrorResponse(e instanceof Error?e.message:"Batch execution failed",500))}}),l.get(`${y}/meta`,(r,t)=>{try{const e=u.getMetadata();t.json(s.formatMetaResponse(e))}catch(e){console.error("Metadata error:",e),t.status(500).json(s.formatErrorResponse(e instanceof Error?e.message:"Failed to fetch metadata",500))}}),l.post(`${y}/sql`,async(r,t)=>{try{const e=r.body,o=await p(r,t),n=u.validateQuery(e);if(!n.isValid)return t.status(400).json(s.formatErrorResponse(`Query validation failed: ${n.errors.join(", ")}`,400));const a=e.measures?.[0]||e.dimensions?.[0];if(!a)return t.status(400).json(s.formatErrorResponse("No measures or dimensions specified",400));const c=a.split(".")[0],m=await u.generateSQL(c,e,o);t.json(s.formatSqlResponse(e,m))}catch(e){console.error("SQL generation error:",e),t.status(500).json(s.formatErrorResponse(e instanceof Error?e.message:"SQL generation failed",500))}}),l.get(`${y}/sql`,async(r,t)=>{try{const e=r.query.query;if(!e)return t.status(400).json(s.formatErrorResponse("Query parameter is required",400));const o=JSON.parse(e),n=await p(r,t),a=u.validateQuery(o);if(!a.isValid)return t.status(400).json(s.formatErrorResponse(`Query validation failed: ${a.errors.join(", ")}`,400));const c=o.measures?.[0]||o.dimensions?.[0];if(!c)return t.status(400).json(s.formatErrorResponse("No measures or dimensions specified",400));const m=c.split(".")[0],g=await u.generateSQL(m,o,n);t.json(s.formatSqlResponse(o,g))}catch(e){console.error("SQL generation error:",e),t.status(500).json(s.formatErrorResponse(e instanceof Error?e.message:"SQL generation failed",500))}}),l.post(`${y}/dry-run`,async(r,t)=>{try{const e=r.body.query||r.body,o=await p(r,t),n=await s.handleDryRun(e,o,u);t.json(n)}catch(e){console.error("Dry-run error:",e),t.status(400).json({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1})}}),l.get(`${y}/dry-run`,async(r,t)=>{try{const e=r.query.query;if(!e)return t.status(400).json({error:"Query parameter is required",valid:!1});const o=JSON.parse(e),n=await p(r,t),a=await s.handleDryRun(o,n,u);t.json(a)}catch(e){console.error("Dry-run error:",e),t.status(400).json({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1})}}),l.post(`${y}/explain`,async(r,t)=>{try{const e=r.body.query||r.body,o=r.body.options||{},n=await p(r,t),a=u.validateQuery(e);if(!a.isValid)return t.status(400).json({error:`Query validation failed: ${a.errors.join(", ")}`});const c=await u.explainQuery(e,n,o);t.json(c)}catch(e){console.error("Explain error:",e),t.status(500).json({error:e instanceof Error?e.message:"Explain query failed"})}}),j.enabled!==!1){const r=j.basePath??"/mcp";l.post(`${r}`,async(t,e)=>{const o=i.validateOriginHeader(t.headers.origin,j.allowedOrigins?{allowedOrigins:j.allowedOrigins}:{});if(!o.valid)return e.status(403).json(i.buildJsonRpcError(null,-32600,o.reason));const n=t.headers.accept;if(!i.validateAcceptHeader(n))return e.status(400).json(i.buildJsonRpcError(null,-32600,"Accept header must include both application/json and text/event-stream"));const a=i.negotiateProtocol(t.headers);if(!a.ok)return e.status(426).json({error:"Unsupported MCP protocol version",supported:a.supported});const c=i.parseJsonRpc(t.body);if(!c)return e.status(400).json(i.buildJsonRpcError(null,-32600,"Invalid JSON-RPC 2.0 request"));const m=i.wantsEventStream(n),g=c.method==="initialize";try{const d=await i.dispatchMcpMethod(c.method,c.params,{semanticLayer:u,extractSecurityContext:p,rawRequest:t,rawResponse:e,negotiatedProtocol:a.negotiated});if(i.isNotification(c))return e.status(202).end();const v=g&&d&&typeof d=="object"&&"sessionId"in d?d.sessionId:void 0;v&&e.setHeader(i.MCP_SESSION_ID_HEADER,v);const b=i.buildJsonRpcResult(c.id??null,d);if(m){const R=i.primeEventId();return e.status(200),e.setHeader("Content-Type","text/event-stream"),e.setHeader("Cache-Control","no-cache"),e.setHeader("Connection","keep-alive"),e.write(`id: ${R}
|
|
2
2
|
|
|
3
3
|
`),e.write(i.serializeSseEvent(b,R)),e.end()}return e.json(b)}catch(d){if(i.isNotification(c))return console.error("MCP notification processing error:",d),e.status(202).end();console.error("MCP RPC error:",d);const v=d?.code??-32603,b=d?.data,R=d.message||"MCP request failed",Q=i.buildJsonRpcError(c.id??null,v,R,b);if(m){const S=i.primeEventId();return e.status(200),e.setHeader("Content-Type","text/event-stream"),e.setHeader("Cache-Control","no-cache"),e.setHeader("Connection","keep-alive"),e.write(`id: ${S}
|
|
4
4
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import R, { Router as L } from "express";
|
|
2
2
|
import A from "cors";
|
|
3
|
-
import { S as J, v as D, b as C, a as _, n as V, p as z, w as B, d as T, i as M, M as F, c as U, e as w, s as Q } from "../mcp-transport-
|
|
3
|
+
import { S as J, v as D, b as C, a as _, n as V, p as z, w as B, d as T, i as M, M as F, c as U, e as w, s as Q } from "../mcp-transport-CXGL1hg7.js";
|
|
4
4
|
import { formatErrorResponse as c, formatCubeResponse as P, handleBatchRequest as G, formatMetaResponse as K, formatSqlResponse as H, handleDryRun as I } from "../utils.js";
|
|
5
5
|
function W(f) {
|
|
6
6
|
const {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var O=Object.create;var $=Object.defineProperty;var J=Object.getOwnPropertyDescriptor;var k=Object.getOwnPropertyNames;var A=Object.getPrototypeOf,L=Object.prototype.hasOwnProperty;var D=(l,s,b,v)=>{if(s&&typeof s=="object"||typeof s=="function")for(let m of k(s))!L.call(l,m)&&m!==b&&$(l,m,{get:()=>s[m],enumerable:!(v=J(s,m))||v.enumerable});return l};var z=(l,s,b)=>(b=l!=null?O(A(l)):{},D(s||!l||!l.__esModule?$(b,"default",{value:l,enumerable:!0}):b,l));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("../mcp-transport-
|
|
1
|
+
"use strict";var O=Object.create;var $=Object.defineProperty;var J=Object.getOwnPropertyDescriptor;var k=Object.getOwnPropertyNames;var A=Object.getPrototypeOf,L=Object.prototype.hasOwnProperty;var D=(l,s,b,v)=>{if(s&&typeof s=="object"||typeof s=="function")for(let m of k(s))!L.call(l,m)&&m!==b&&$(l,m,{get:()=>s[m],enumerable:!(v=J(s,m))||v.enumerable});return l};var z=(l,s,b)=>(b=l!=null?O(A(l)):{},D(s||!l||!l.__esModule?$(b,"default",{value:l,enumerable:!0}):b,l));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("../mcp-transport-ConlvewL.cjs"),n=require("../utils.cjs"),q=function(s,b,v){const{cubes:m,drizzle:j,schema:I,extractSecurityContext:h,engineType:M,cors:S,basePath:g="/cubejs-api/v1",bodyLimit:f=10485760,cache:N,mcp:R={enabled:!0}}=b;if(!m||m.length===0)return v(new Error("At least one cube must be provided in the cubes array"));S&&s.register(import("@fastify/cors"),S),s.addHook("onRequest",async(r,t)=>{r.method==="POST"&&(r.body=void 0)});const d=new i.SemanticLayerCompiler({drizzle:j,schema:I,engineType:M,cache:N});if(m.forEach(r=>{d.registerCube(r)}),s.post(`${g}/load`,{bodyLimit:f,schema:{body:{type:"object",additionalProperties:!0}}},async(r,t)=>{try{const e=r.body,o=e.query||e,a=await h(r),c=d.validateQuery(o);if(!c.isValid)return t.status(400).send(n.formatErrorResponse(`Query validation failed: ${c.errors.join(", ")}`,400));const u=r.headers["x-cache-control"]==="no-cache",p=await d.executeMultiCubeQuery(o,a,{skipCache:u});return n.formatCubeResponse(o,p,d)}catch(e){return r.log.error(e,"Query execution error"),t.status(500).send(n.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500))}}),s.get(`${g}/load`,{schema:{querystring:{type:"object",properties:{query:{type:"string"}},required:["query"]}}},async(r,t)=>{try{const{query:e}=r.query;let o;try{o=JSON.parse(e)}catch{return t.status(400).send(n.formatErrorResponse("Invalid JSON in query parameter",400))}const a=await h(r),c=d.validateQuery(o);if(!c.isValid)return t.status(400).send(n.formatErrorResponse(`Query validation failed: ${c.errors.join(", ")}`,400));const u=r.headers["x-cache-control"]==="no-cache",p=await d.executeMultiCubeQuery(o,a,{skipCache:u});return n.formatCubeResponse(o,p,d)}catch(e){return r.log.error(e,"Query execution error"),t.status(500).send(n.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500))}}),s.post(`${g}/batch`,{bodyLimit:f,schema:{body:{type:"object",required:["queries"],properties:{queries:{type:"array",items:{type:"object"}}}}}},async(r,t)=>{try{const{queries:e}=r.body;if(!e||!Array.isArray(e))return t.status(400).send(n.formatErrorResponse('Request body must contain a "queries" array',400));if(e.length===0)return t.status(400).send(n.formatErrorResponse("Queries array cannot be empty",400));const o=await h(r),a=r.headers["x-cache-control"]==="no-cache";return await n.handleBatchRequest(e,o,d,{skipCache:a})}catch(e){return r.log.error(e,"Batch execution error"),t.status(500).send(n.formatErrorResponse(e instanceof Error?e.message:"Batch execution failed",500))}}),s.get(`${g}/meta`,async(r,t)=>{try{const e=d.getMetadata();return n.formatMetaResponse(e)}catch(e){return r.log.error(e,"Metadata error"),t.status(500).send(n.formatErrorResponse(e instanceof Error?e.message:"Failed to fetch metadata",500))}}),s.post(`${g}/sql`,{bodyLimit:f,schema:{body:{type:"object",additionalProperties:!0}}},async(r,t)=>{try{const e=r.body,o=await h(r),a=d.validateQuery(e);if(!a.isValid)return t.status(400).send(n.formatErrorResponse(`Query validation failed: ${a.errors.join(", ")}`,400));const c=e.measures?.[0]||e.dimensions?.[0];if(!c)return t.status(400).send(n.formatErrorResponse("No measures or dimensions specified",400));const u=c.split(".")[0],p=await d.generateSQL(u,e,o);return n.formatSqlResponse(e,p)}catch(e){return r.log.error(e,"SQL generation error"),t.status(500).send(n.formatErrorResponse(e instanceof Error?e.message:"SQL generation failed",500))}}),s.get(`${g}/sql`,{schema:{querystring:{type:"object",properties:{query:{type:"string"}},required:["query"]}}},async(r,t)=>{try{const{query:e}=r.query,o=JSON.parse(e),a=await h(r),c=d.validateQuery(o);if(!c.isValid)return t.status(400).send(n.formatErrorResponse(`Query validation failed: ${c.errors.join(", ")}`,400));const u=o.measures?.[0]||o.dimensions?.[0];if(!u)return t.status(400).send(n.formatErrorResponse("No measures or dimensions specified",400));const p=u.split(".")[0],x=await d.generateSQL(p,o,a);return n.formatSqlResponse(o,x)}catch(e){return r.log.error(e,"SQL generation error"),t.status(500).send(n.formatErrorResponse(e instanceof Error?e.message:"SQL generation failed",500))}}),s.post(`${g}/dry-run`,{bodyLimit:f,schema:{body:{type:"object",additionalProperties:!0}}},async(r,t)=>{try{const e=r.body,o=e.query||e,a=await h(r);return await n.handleDryRun(o,a,d)}catch(e){return r.log.error(e,"Dry-run error"),t.status(400).send({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1})}}),s.get(`${g}/dry-run`,{schema:{querystring:{type:"object",properties:{query:{type:"string"}},required:["query"]}}},async(r,t)=>{try{const{query:e}=r.query,o=JSON.parse(e),a=await h(r);return await n.handleDryRun(o,a,d)}catch(e){return r.log.error(e,"Dry-run error"),t.status(400).send({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1})}}),s.post(`${g}/explain`,{bodyLimit:f,schema:{body:{type:"object",additionalProperties:!0}}},async(r,t)=>{try{const e=r.body,o=e.query||e,a=e.options||{},c=await h(r),u=d.validateQuery(o);return u.isValid?await d.explainQuery(o,c,a):t.status(400).send({error:`Query validation failed: ${u.errors.join(", ")}`})}catch(e){return r.log.error(e,"Explain error"),t.status(500).send({error:e instanceof Error?e.message:"Explain query failed"})}}),R.enabled!==!1){const r=R.basePath??"/mcp";s.post(`${r}`,{bodyLimit:f,schema:{body:{type:"object",additionalProperties:!0}}},async(t,e)=>{const o=i.validateOriginHeader(t.headers.origin,R.allowedOrigins?{allowedOrigins:R.allowedOrigins}:{});if(!o.valid)return e.status(403).send(i.buildJsonRpcError(null,-32600,o.reason));const a=t.headers.accept;if(!i.validateAcceptHeader(a))return e.status(400).send(i.buildJsonRpcError(null,-32600,"Accept header must include both application/json and text/event-stream"));const c=i.negotiateProtocol(t.headers);if(!c.ok)return e.status(426).send({error:"Unsupported MCP protocol version",supported:c.supported});const u=i.parseJsonRpc(t.body);if(!u)return e.status(400).send(i.buildJsonRpcError(null,-32600,"Invalid JSON-RPC 2.0 request"));const p=i.wantsEventStream(a),x=u.method==="initialize";try{const y=await i.dispatchMcpMethod(u.method,u.params,{semanticLayer:d,extractSecurityContext:h,rawRequest:t,rawResponse:e,negotiatedProtocol:c.negotiated});if(i.isNotification(u))return e.status(202).send();const E=x&&y&&typeof y=="object"&&"sessionId"in y?y.sessionId:void 0;E&&e.header(i.MCP_SESSION_ID_HEADER,E);const C=i.buildJsonRpcResult(u.id??null,y);if(p){const w=i.primeEventId();e.header("Content-Type","text/event-stream").header("Cache-Control","no-cache").header("Connection","keep-alive").send(`id: ${w}
|
|
2
2
|
|
|
3
3
|
${i.serializeSseEvent(C,w)}`);return}return e.send(C)}catch(y){if(i.isNotification(u))return t.log.error(y,"MCP notification processing error"),e.status(202).send();t.log.error(y,"MCP RPC error");const E=y?.code??-32603,C=y?.data,w=y.message||"MCP request failed",P=i.buildJsonRpcError(u.id??null,E,w,C);if(p){const Q=i.primeEventId();e.header("Content-Type","text/event-stream").header("Cache-Control","no-cache").header("Connection","keep-alive").send(`id: ${Q}
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as D, v as H, b as C, a as V, n as z, p as T, w as _, d as B, i as $, M as F, c as U, e as q, s as R } from "../mcp-transport-
|
|
1
|
+
import { S as D, v as H, b as C, a as V, n as z, p as T, w as _, d as B, i as $, M as F, c as U, e as q, s as R } from "../mcp-transport-CXGL1hg7.js";
|
|
2
2
|
import { formatErrorResponse as u, formatCubeResponse as j, handleBatchRequest as G, formatMetaResponse as K, formatSqlResponse as M, handleDryRun as I } from "../utils.js";
|
|
3
3
|
const N = function(n, O, E) {
|
|
4
4
|
const {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const T=require("hono"),s=require("../mcp-transport-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const T=require("hono"),s=require("../mcp-transport-ConlvewL.cjs"),w=require("../utils.cjs");var J=C=>{const d={...{origin:"*",allowMethods:["GET","HEAD","PUT","POST","DELETE","PATCH"],allowHeaders:[],exposeHeaders:[]},...C},P=(l=>typeof l=="string"?l==="*"?()=>l:a=>l===a?a:null:typeof l=="function"?l:a=>l.includes(a)?a:null)(d.origin),y=(l=>typeof l=="function"?l:Array.isArray(l)?()=>l:()=>[])(d.allowMethods);return async function(a,f){function q(u,o){a.res.headers.set(u,o)}const v=await P(a.req.header("origin")||"",a);if(v&&q("Access-Control-Allow-Origin",v),d.credentials&&q("Access-Control-Allow-Credentials","true"),d.exposeHeaders?.length&&q("Access-Control-Expose-Headers",d.exposeHeaders.join(",")),a.req.method==="OPTIONS"){d.origin!=="*"&&q("Vary","Origin"),d.maxAge!=null&&q("Access-Control-Max-Age",d.maxAge.toString());const u=await y(a.req.header("origin")||"",a);u.length&&q("Access-Control-Allow-Methods",u.join(","));let o=d.allowHeaders;if(!o?.length){const r=a.req.header("Access-Control-Request-Headers");r&&(o=r.split(/\s*,\s*/))}return o?.length&&(q("Access-Control-Allow-Headers",o.join(",")),a.res.headers.append("Vary","Access-Control-Request-Headers")),a.res.headers.delete("Content-Length"),a.res.headers.delete("Content-Type"),new Response(null,{headers:a.res.headers,status:204,statusText:"No Content"})}await f(),d.origin!=="*"&&a.header("Vary","Origin",{append:!0})}};function I(C){const{cubes:j,drizzle:d,schema:P,extractSecurityContext:y,engineType:l,cors:a,basePath:f="/cubejs-api/v1",cache:q,mcp:v={enabled:!0}}=C;if(!j||j.length===0)throw new Error("At least one cube must be provided in the cubes array");const u=new T.Hono;a&&u.use("/*",J(a));const o=new s.SemanticLayerCompiler({drizzle:d,schema:P,engineType:l,cache:q});if(j.forEach(r=>{o.registerCube(r)}),u.post(`${f}/load`,async r=>{try{const e=await r.req.json(),n=e.query||e,i=await y(r),t=o.validateQuery(n);if(!t.isValid)return r.json({error:`Query validation failed: ${t.errors.join(", ")}`},400);const c=r.req.header("x-cache-control")==="no-cache",p=await o.executeMultiCubeQuery(n,i,{skipCache:c});return r.json(w.formatCubeResponse(n,p,o))}catch(e){return console.error("Query execution error:",e),r.json({error:e instanceof Error?e.message:"Query execution failed"},500)}}),u.get(`${f}/load`,async r=>{try{const e=r.req.query("query");if(!e)return r.json({error:"Query parameter is required"},400);let n;try{n=JSON.parse(e)}catch{return r.json({error:"Invalid JSON in query parameter"},400)}const i=await y(r),t=o.validateQuery(n);if(!t.isValid)return r.json({error:`Query validation failed: ${t.errors.join(", ")}`},400);const c=r.req.header("x-cache-control")==="no-cache",p=await o.executeMultiCubeQuery(n,i,{skipCache:c});return r.json(w.formatCubeResponse(n,p,o))}catch(e){return console.error("Query execution error:",e),r.json({error:e instanceof Error?e.message:"Query execution failed"},500)}}),u.post(`${f}/batch`,async r=>{try{const e=await r.req.json(),{queries:n}=e;if(!n||!Array.isArray(n))return r.json({error:'Request body must contain a "queries" array'},400);if(n.length===0)return r.json({error:"Queries array cannot be empty"},400);const i=await y(r),t=r.req.header("x-cache-control")==="no-cache",c=await w.handleBatchRequest(n,i,o,{skipCache:t});return r.json(c)}catch(e){return console.error("Batch execution error:",e),r.json({error:e instanceof Error?e.message:"Batch execution failed"},500)}}),u.get(`${f}/meta`,r=>{try{const e=o.getMetadata();return r.json(w.formatMetaResponse(e))}catch(e){return console.error("Metadata error:",e),r.json({error:e instanceof Error?e.message:"Failed to fetch metadata"},500)}}),u.post(`${f}/sql`,async r=>{try{const e=await r.req.json(),n=await y(r),i=o.validateQuery(e);if(!i.isValid)return r.json({error:`Query validation failed: ${i.errors.join(", ")}`},400);const t=e.measures?.[0]||e.dimensions?.[0];if(!t)return r.json({error:"No measures or dimensions specified"},400);const c=t.split(".")[0],p=await o.generateSQL(c,e,n);return r.json(w.formatSqlResponse(e,p))}catch(e){return console.error("SQL generation error:",e),r.json({error:e instanceof Error?e.message:"SQL generation failed"},500)}}),u.get(`${f}/sql`,async r=>{try{const e=r.req.query("query");if(!e)return r.json({error:"Query parameter is required"},400);const n=JSON.parse(e),i=await y(r),t=o.validateQuery(n);if(!t.isValid)return r.json({error:`Query validation failed: ${t.errors.join(", ")}`},400);const c=n.measures?.[0]||n.dimensions?.[0];if(!c)return r.json({error:"No measures or dimensions specified"},400);const p=c.split(".")[0],g=await o.generateSQL(p,n,i);return r.json(w.formatSqlResponse(n,g))}catch(e){return console.error("SQL generation error:",e),r.json({error:e instanceof Error?e.message:"SQL generation failed"},500)}}),u.post(`${f}/dry-run`,async r=>{try{const e=await r.req.json(),n=e.query||e,i=await y(r),t=await w.handleDryRun(n,i,o);return r.json(t)}catch(e){return console.error("Dry-run error:",e),r.json({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1},400)}}),u.get(`${f}/dry-run`,async r=>{try{const e=r.req.query("query");if(!e)return r.json({error:"Query parameter is required",valid:!1},400);const n=JSON.parse(e),i=await y(r),t=await w.handleDryRun(n,i,o);return r.json(t)}catch(e){return console.error("Dry-run error:",e),r.json({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1},400)}}),u.post(`${f}/explain`,async r=>{try{const e=await r.req.json(),n=e.query||e,i=e.options||{},t=await y(r),c=o.validateQuery(n);if(!c.isValid)return r.json({error:`Query validation failed: ${c.errors.join(", ")}`},400);const p=await o.explainQuery(n,t,i);return r.json(p)}catch(e){return console.error("Explain error:",e),r.json({error:e instanceof Error?e.message:"Explain query failed"},500)}}),v.enabled!==!1){const r={uri:"drizzle-cube://schema",name:"Cube Schema",description:"Current cube metadata as JSON",mimeType:"application/json",text:JSON.stringify(o.getMetadata(),null,2)},e=[...s.getDefaultResources(),r],n=s.getDefaultPrompts(),i=v.basePath??"/mcp";u.post(`${i}`,async t=>{const c=s.validateOriginHeader(t.req.header("origin"),v.allowedOrigins?{allowedOrigins:v.allowedOrigins}:{});if(!c.valid)return t.json(s.buildJsonRpcError(null,-32600,c.reason),403);const p=t.req.header("accept");if(!s.validateAcceptHeader(p))return t.json(s.buildJsonRpcError(null,-32600,"Accept header must include both application/json and text/event-stream"),400);const g=s.negotiateProtocol(t.req.header());if(!g.ok)return t.json({error:"Unsupported MCP protocol version",supported:g.supported},426);const H=await t.req.json().catch(()=>null),m=s.parseJsonRpc(H);if(!m)return t.json(s.buildJsonRpcError(null,-32600,"Invalid JSON-RPC 2.0 request"),400);const $=s.wantsEventStream(p),O=m.method==="initialize";try{const h=await s.dispatchMcpMethod(m.method,m.params,{semanticLayer:o,extractSecurityContext:y,rawRequest:t,rawResponse:null,negotiatedProtocol:g.negotiated,resources:e,prompts:n});if(s.isNotification(m))return t.body(null,202);const S=s.buildJsonRpcResult(m.id??null,h),A=O&&h&&typeof h=="object"&&"sessionId"in h?h.sessionId:void 0,b={};if(A&&(b[s.MCP_SESSION_ID_HEADER]=A),$){const R=new TextEncoder,x=s.primeEventId(),Q=new ReadableStream({start(E){E.enqueue(R.encode(`id: ${x}
|
|
2
2
|
|
|
3
3
|
`)),E.enqueue(R.encode(s.serializeSseEvent(S,x))),E.close()}});return new Response(Q,{status:200,headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive",...b}})}return t.json(S,200,b)}catch(h){if(s.isNotification(m))return console.error("MCP notification processing error:",h),t.body(null,202);console.error("MCP RPC error:",h);const S=h?.code??-32603,A=h?.data,b=h.message||"MCP request failed",R=s.buildJsonRpcError(m.id??null,S,b,A);if($){const x=new TextEncoder,Q=s.primeEventId(),E=new ReadableStream({start(M){M.enqueue(x.encode(`id: ${Q}
|
|
4
4
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Hono as J } from "hono";
|
|
2
|
-
import { S as k, v as V, b as Q, a as B, n as z, p as _, w as U, d as F, g as G, f as K, i as I, c as W, M as X, e as $, s as H } from "../mcp-transport-
|
|
2
|
+
import { S as k, v as V, b as Q, a as B, n as z, p as _, w as U, d as F, g as G, f as K, i as I, c as W, M as X, e as $, s as H } from "../mcp-transport-CXGL1hg7.js";
|
|
3
3
|
import { formatCubeResponse as N, handleBatchRequest as Y, formatMetaResponse as Z, formatSqlResponse as O, handleDryRun as D } from "../utils.js";
|
|
4
4
|
var ee = (q) => {
|
|
5
5
|
const l = {
|