drizzle-cube 0.3.23 → 0.3.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/express/index.cjs +4 -4
- package/dist/adapters/express/index.js +26 -25
- package/dist/adapters/fastify/index.cjs +4 -4
- package/dist/adapters/fastify/index.js +38 -37
- package/dist/adapters/hono/index.cjs +4 -4
- package/dist/adapters/hono/index.js +40 -39
- package/dist/adapters/mcp-transport-B4BZSsMC.js +9723 -0
- package/dist/adapters/mcp-transport-C8pLznZG.cjs +257 -0
- package/dist/adapters/nextjs/index.cjs +3 -3
- package/dist/adapters/nextjs/index.js +44 -43
- package/dist/adapters/types.cjs +1 -0
- package/dist/adapters/types.js +1 -0
- package/dist/adapters/utils.cjs +19 -0
- package/dist/adapters/utils.d.ts +24 -0
- package/dist/adapters/utils.js +21342 -0
- package/dist/client/charts.d.ts +1 -1
- package/dist/client/charts.js +172 -40
- package/dist/client/charts.js.map +1 -1
- package/dist/client/chunks/{components-vl_fdWud.js → DashboardEditModal-CVMSvpJ-.js} +2737 -3099
- package/dist/client/chunks/DashboardEditModal-CVMSvpJ-.js.map +1 -0
- package/dist/client/chunks/{RetentionCombinedChart-DpEKFYsd.js → RetentionCombinedChart-BVKWmxc-.js} +2 -2
- package/dist/client/chunks/{RetentionCombinedChart-DpEKFYsd.js.map → RetentionCombinedChart-BVKWmxc-.js.map} +1 -1
- package/dist/client/chunks/{analysis-builder-DiaxkEY-.js → analysis-builder-CuTR61Ct.js} +2814 -3547
- package/dist/client/chunks/analysis-builder-CuTR61Ct.js.map +1 -0
- package/dist/client/chunks/analysis-builder-shared-D7iqklYk.js +3211 -0
- package/dist/client/chunks/analysis-builder-shared-D7iqklYk.js.map +1 -0
- package/dist/client/chunks/{chart-activity-grid-CCGyWo1c.js → chart-activity-grid-BcMRkaq4.js} +2 -2
- package/dist/client/chunks/{chart-activity-grid-CCGyWo1c.js.map → chart-activity-grid-BcMRkaq4.js.map} +1 -1
- package/dist/client/chunks/{chart-area-ZZp1libT.js → chart-area-KlBSb_ur.js} +3 -3
- package/dist/client/chunks/{chart-area-ZZp1libT.js.map → chart-area-KlBSb_ur.js.map} +1 -1
- package/dist/client/chunks/{chart-bar-B4grbo6Q.js → chart-bar-D1i2jmIg.js} +2 -2
- package/dist/client/chunks/{chart-bar-B4grbo6Q.js.map → chart-bar-D1i2jmIg.js.map} +1 -1
- package/dist/client/chunks/{chart-bubble-BGGAQQUQ.js → chart-bubble-BFjnOwNZ.js} +2 -2
- package/dist/client/chunks/{chart-bubble-BGGAQQUQ.js.map → chart-bubble-BFjnOwNZ.js.map} +1 -1
- package/dist/client/chunks/{chart-data-table-BcH_h6kZ.js → chart-data-table-CYMMAHau.js} +39 -30
- package/dist/client/chunks/{chart-data-table-BcH_h6kZ.js.map → chart-data-table-CYMMAHau.js.map} +1 -1
- package/dist/client/chunks/{chart-funnel-DI8RMacf.js → chart-funnel-BH7r4HWZ.js} +2 -2
- package/dist/client/chunks/{chart-funnel-DI8RMacf.js.map → chart-funnel-BH7r4HWZ.js.map} +1 -1
- package/dist/client/chunks/{chart-heat-map-D3xNV9ep.js → chart-heat-map-DyGtODLE.js} +2 -2
- package/dist/client/chunks/{chart-heat-map-D3xNV9ep.js.map → chart-heat-map-DyGtODLE.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-delta-BJMQKPor.js → chart-kpi-delta-Bk396suk.js} +3 -3
- package/dist/client/chunks/{chart-kpi-delta-BJMQKPor.js.map → chart-kpi-delta-Bk396suk.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-number-B8u4tWmu.js → chart-kpi-number-CIGqZ5Dw.js} +34 -31
- package/dist/client/chunks/{chart-kpi-number-B8u4tWmu.js.map → chart-kpi-number-CIGqZ5Dw.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-text--r1d4zAz.js → chart-kpi-text-iwlaSQCi.js} +3 -3
- package/dist/client/chunks/{chart-kpi-text--r1d4zAz.js.map → chart-kpi-text-iwlaSQCi.js.map} +1 -1
- package/dist/client/chunks/chart-line-BKqhoW9A.js +450 -0
- package/dist/client/chunks/{chart-line-K0ACw4cV.js.map → chart-line-BKqhoW9A.js.map} +1 -1
- package/dist/client/chunks/{chart-pie-DC7axSwd.js → chart-pie-BNr-GgTh.js} +2 -2
- package/dist/client/chunks/{chart-pie-DC7axSwd.js.map → chart-pie-BNr-GgTh.js.map} +1 -1
- package/dist/client/chunks/{chart-radar-BDKgpLw5.js → chart-radar-CYrGVYEQ.js} +2 -2
- package/dist/client/chunks/{chart-radar-BDKgpLw5.js.map → chart-radar-CYrGVYEQ.js.map} +1 -1
- package/dist/client/chunks/{chart-radial-bar-BYNng7Nz.js → chart-radial-bar-2PR3ucIR.js} +2 -2
- package/dist/client/chunks/{chart-radial-bar-BYNng7Nz.js.map → chart-radial-bar-2PR3ucIR.js.map} +1 -1
- package/dist/client/chunks/{chart-sankey-CpsKerey.js → chart-sankey-C7w7h2ZV.js} +2 -2
- package/dist/client/chunks/{chart-sankey-CpsKerey.js.map → chart-sankey-C7w7h2ZV.js.map} +1 -1
- package/dist/client/chunks/{chart-scatter-CXqFltJg.js → chart-scatter-D3Z9bl8H.js} +2 -2
- package/dist/client/chunks/{chart-scatter-CXqFltJg.js.map → chart-scatter-D3Z9bl8H.js.map} +1 -1
- package/dist/client/chunks/{chart-sunburst-DSsO2CzY.js → chart-sunburst-C4ydFeaK.js} +2 -2
- package/dist/client/chunks/{chart-sunburst-DSsO2CzY.js.map → chart-sunburst-C4ydFeaK.js.map} +1 -1
- package/dist/client/chunks/{chart-tree-map-D_SeBBD-.js → chart-tree-map-DCCmMyz1.js} +2 -2
- package/dist/client/chunks/{chart-tree-map-D_SeBBD-.js.map → chart-tree-map-DCCmMyz1.js.map} +1 -1
- package/dist/client/chunks/{charts-core-8jDh3mKC.js → charts-core-DIW3Dd7n.js} +133 -112
- package/dist/client/chunks/{charts-core-8jDh3mKC.js.map → charts-core-DIW3Dd7n.js.map} +1 -1
- package/dist/client/chunks/{charts-loader-DpJr9z2e.js → charts-loader-BCBnMYjH.js} +20 -20
- package/dist/client/chunks/{charts-loader-DpJr9z2e.js.map → charts-loader-BCBnMYjH.js.map} +1 -1
- package/dist/client/chunks/{core-BRC075EG.js → core-BITzuqYm.js} +2 -2
- package/dist/client/chunks/{core-BRC075EG.js.map → core-BITzuqYm.js.map} +1 -1
- package/dist/client/chunks/hooks-Dd_nnv0J.js +236 -0
- package/dist/client/chunks/hooks-Dd_nnv0J.js.map +1 -0
- package/dist/client/chunks/index-CApFCBF9.js +81 -0
- package/dist/client/chunks/index-CApFCBF9.js.map +1 -0
- package/dist/client/chunks/{providers-BBrUJB2U.js → providers-BjxD1ZmC.js} +119 -113
- package/dist/client/chunks/{providers-BBrUJB2U.js.map → providers-BjxD1ZmC.js.map} +1 -1
- package/dist/client/chunks/syntaxHighlighting-Cmqp7_Mx.js +34 -0
- package/dist/client/chunks/syntaxHighlighting-Cmqp7_Mx.js.map +1 -0
- package/dist/client/chunks/useDirtyStateTracking-B5g-bw7a.js +1231 -0
- package/dist/client/chunks/useDirtyStateTracking-B5g-bw7a.js.map +1 -0
- package/dist/client/chunks/{vendor-cTQhZ_G3.js → vendor-CJRtj0__.js} +145 -145
- package/dist/client/chunks/vendor-CJRtj0__.js.map +1 -0
- package/dist/client/components/AnalysisBuilder/types.d.ts +5 -0
- package/dist/client/components/charts/index.d.ts +1 -0
- package/dist/client/components/shared/DateRangeFilter.d.ts +1 -1
- package/dist/client/components/shared/FilterBuilder.d.ts +1 -1
- package/dist/client/components/shared/FilterGroup.d.ts +1 -1
- package/dist/client/components/shared/FilterItem.d.ts +1 -1
- package/dist/client/components/shared/FilterValueSelector.d.ts +1 -1
- package/dist/client/components/shared/types.d.ts +60 -0
- package/dist/client/components/shared/utils.d.ts +1 -1
- package/dist/client/components.d.ts +1 -1
- package/dist/client/components.js +352 -15
- package/dist/client/components.js.map +1 -1
- package/dist/client/hooks/queries/useCubeLoadQuery.d.ts +3 -0
- package/dist/client/hooks/useAnalysisBuilderHook.d.ts +5 -0
- package/dist/client/hooks/useAnalysisQueryExecution.d.ts +5 -0
- package/dist/client/hooks.d.ts +2 -2
- package/dist/client/hooks.js +20 -12
- package/dist/client/index.d.ts +16 -3
- package/dist/client/index.js +176 -138
- package/dist/client/index.js.map +1 -1
- package/dist/client/providers.js +1 -1
- package/dist/client/shared/types.d.ts +29 -0
- package/dist/client/styles.css +1 -1
- package/dist/client/utils.d.ts +1 -1
- package/dist/client/utils.js +73 -1
- package/dist/client/utils.js.map +1 -1
- package/dist/client-bundle-stats.html +1 -1
- package/dist/server/index.cjs +85 -85
- package/dist/server/index.d.ts +170 -4
- package/dist/server/index.js +3492 -3206
- package/package.json +12 -2
- package/dist/adapters/mcp-transport-lkEjNwDH.js +0 -30769
- package/dist/adapters/mcp-transport-oPf8JYHv.cjs +0 -275
- package/dist/client/chunks/analysis-builder-DiaxkEY-.js.map +0 -1
- package/dist/client/chunks/analysis-builder-shared-BzM5Vwpr.js +0 -2779
- package/dist/client/chunks/analysis-builder-shared-BzM5Vwpr.js.map +0 -1
- package/dist/client/chunks/chart-line-K0ACw4cV.js +0 -413
- package/dist/client/chunks/charts-T6qNi6FO.js +0 -230
- package/dist/client/chunks/charts-T6qNi6FO.js.map +0 -1
- package/dist/client/chunks/components-vl_fdWud.js.map +0 -1
- package/dist/client/chunks/hooks-CKYzVf_7.js +0 -150
- package/dist/client/chunks/hooks-CKYzVf_7.js.map +0 -1
- package/dist/client/chunks/useDirtyStateTracking-DDQ_Lbki.js +0 -795
- package/dist/client/chunks/useDirtyStateTracking-DDQ_Lbki.js.map +0 -1
- package/dist/client/chunks/vendor-cTQhZ_G3.js.map +0 -1
- package/dist/client/components/AxisDropZone.d.ts +0 -27
- package/dist/client/components/ChartConfigPanel.d.ts +0 -16
- package/dist/client/components/QueryBuilder/types.d.ts +0 -152
- package/dist/client/components/QueryBuilderShim.d.ts +0 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=require("express"),H=require("cors"),i=require("../mcp-transport-C8pLznZG.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
|
-
`),e.write(
|
|
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
|
|
|
5
|
-
`),e.write(
|
|
5
|
+
`),e.write(i.serializeSseEvent(Q,S)),e.end()}return e.status(200).json(Q)}}),l.get(`${r}`,async(t,e)=>{const o=i.primeEventId();e.status(200),e.setHeader("Content-Type","text/event-stream"),e.setHeader("Cache-Control","no-cache"),e.setHeader("Connection","keep-alive"),e.write(i.serializeSseEvent({jsonrpc:"2.0",method:"mcp/ready",params:{protocol:"streamable-http"}},o,15e3));const n=setInterval(()=>{e.write(`: keep-alive
|
|
6
6
|
|
|
7
|
-
`)},15e3);t.on("close",()=>{clearInterval(n)})}),
|
|
7
|
+
`)},15e3);t.on("close",()=>{clearInterval(n)})}),l.delete(`${r}`,(t,e)=>e.status(405).json({error:"Session termination not supported"}))}return l.use((r,t,e,o)=>{console.error("Express adapter error:",r),e.headersSent||e.status(500).json(s.formatErrorResponse(r,500))}),l}function $(h,f){const C=q(f);return h.use("/",C),h}function N(h){const f=E();return $(f,h)}exports.createCubeApp=N;exports.createCubeRouter=q;exports.mountCubeRoutes=$;
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import R, { Router as L } from "express";
|
|
2
2
|
import A from "cors";
|
|
3
|
-
import { S as J,
|
|
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-B4BZSsMC.js";
|
|
4
|
+
import { formatErrorResponse as c, formatCubeResponse as P, handleBatchRequest as G, formatMetaResponse as K, formatSqlResponse as H, handleDryRun as I } from "../utils.js";
|
|
4
5
|
function W(f) {
|
|
5
6
|
const {
|
|
6
7
|
cubes: m,
|
|
7
8
|
drizzle: g,
|
|
8
9
|
schema: N,
|
|
9
10
|
extractSecurityContext: l,
|
|
10
|
-
engineType:
|
|
11
|
+
engineType: O,
|
|
11
12
|
cors: E,
|
|
12
13
|
basePath: y = "/cubejs-api/v1",
|
|
13
14
|
jsonLimit: S = "10mb",
|
|
14
|
-
cache:
|
|
15
|
+
cache: k,
|
|
15
16
|
mcp: h = { enabled: !0 }
|
|
16
17
|
} = f;
|
|
17
18
|
if (!m || m.length === 0)
|
|
@@ -21,8 +22,8 @@ function W(f) {
|
|
|
21
22
|
const i = new J({
|
|
22
23
|
drizzle: g,
|
|
23
24
|
schema: N,
|
|
24
|
-
engineType:
|
|
25
|
-
cache:
|
|
25
|
+
engineType: O,
|
|
26
|
+
cache: k
|
|
26
27
|
});
|
|
27
28
|
if (m.forEach((r) => {
|
|
28
29
|
i.registerCube(r);
|
|
@@ -35,7 +36,7 @@ function W(f) {
|
|
|
35
36
|
400
|
|
36
37
|
));
|
|
37
38
|
const s = r.headers["x-cache-control"] === "no-cache", n = await i.executeMultiCubeQuery(e, o, { skipCache: s });
|
|
38
|
-
t.json(
|
|
39
|
+
t.json(P(e, n, i));
|
|
39
40
|
} catch (e) {
|
|
40
41
|
console.error("Query execution error:", e), t.status(500).json(c(
|
|
41
42
|
e instanceof Error ? e.message : "Query execution failed",
|
|
@@ -66,7 +67,7 @@ function W(f) {
|
|
|
66
67
|
400
|
|
67
68
|
));
|
|
68
69
|
const n = r.headers["x-cache-control"] === "no-cache", p = await i.executeMultiCubeQuery(o, a, { skipCache: n });
|
|
69
|
-
t.json(
|
|
70
|
+
t.json(P(o, p, i));
|
|
70
71
|
} catch (e) {
|
|
71
72
|
console.error("Query execution error:", e), t.status(500).json(c(
|
|
72
73
|
e instanceof Error ? e.message : "Query execution failed",
|
|
@@ -86,7 +87,7 @@ function W(f) {
|
|
|
86
87
|
"Queries array cannot be empty",
|
|
87
88
|
400
|
|
88
89
|
));
|
|
89
|
-
const o = await l(r, t), a = r.headers["x-cache-control"] === "no-cache", s = await
|
|
90
|
+
const o = await l(r, t), a = r.headers["x-cache-control"] === "no-cache", s = await G(e, o, i, { skipCache: a });
|
|
90
91
|
t.json(s);
|
|
91
92
|
} catch (e) {
|
|
92
93
|
console.error("Batch execution error:", e), t.status(500).json(c(
|
|
@@ -97,7 +98,7 @@ function W(f) {
|
|
|
97
98
|
}), u.get(`${y}/meta`, (r, t) => {
|
|
98
99
|
try {
|
|
99
100
|
const e = i.getMetadata();
|
|
100
|
-
t.json(
|
|
101
|
+
t.json(K(e));
|
|
101
102
|
} catch (e) {
|
|
102
103
|
console.error("Metadata error:", e), t.status(500).json(c(
|
|
103
104
|
e instanceof Error ? e.message : "Failed to fetch metadata",
|
|
@@ -119,7 +120,7 @@ function W(f) {
|
|
|
119
120
|
400
|
|
120
121
|
));
|
|
121
122
|
const n = s.split(".")[0], p = await i.generateSQL(n, e, o);
|
|
122
|
-
t.json(
|
|
123
|
+
t.json(H(e, p));
|
|
123
124
|
} catch (e) {
|
|
124
125
|
console.error("SQL generation error:", e), t.status(500).json(c(
|
|
125
126
|
e instanceof Error ? e.message : "SQL generation failed",
|
|
@@ -147,7 +148,7 @@ function W(f) {
|
|
|
147
148
|
400
|
|
148
149
|
));
|
|
149
150
|
const p = n.split(".")[0], x = await i.generateSQL(p, o, a);
|
|
150
|
-
t.json(
|
|
151
|
+
t.json(H(o, x));
|
|
151
152
|
} catch (e) {
|
|
152
153
|
console.error("SQL generation error:", e), t.status(500).json(c(
|
|
153
154
|
e instanceof Error ? e.message : "SQL generation failed",
|
|
@@ -156,7 +157,7 @@ function W(f) {
|
|
|
156
157
|
}
|
|
157
158
|
}), u.post(`${y}/dry-run`, async (r, t) => {
|
|
158
159
|
try {
|
|
159
|
-
const e = r.body.query || r.body, o = await l(r, t), a = await
|
|
160
|
+
const e = r.body.query || r.body, o = await l(r, t), a = await I(e, o, i);
|
|
160
161
|
t.json(a);
|
|
161
162
|
} catch (e) {
|
|
162
163
|
console.error("Dry-run error:", e), t.status(400).json({
|
|
@@ -172,7 +173,7 @@ function W(f) {
|
|
|
172
173
|
error: "Query parameter is required",
|
|
173
174
|
valid: !1
|
|
174
175
|
});
|
|
175
|
-
const o = JSON.parse(e), a = await l(r, t), s = await
|
|
176
|
+
const o = JSON.parse(e), a = await l(r, t), s = await I(o, a, i);
|
|
176
177
|
t.json(s);
|
|
177
178
|
} catch (e) {
|
|
178
179
|
console.error("Dry-run error:", e), t.status(400).json({
|
|
@@ -197,27 +198,27 @@ function W(f) {
|
|
|
197
198
|
}), h.enabled !== !1) {
|
|
198
199
|
const r = h.basePath ?? "/mcp";
|
|
199
200
|
u.post(`${r}`, async (t, e) => {
|
|
200
|
-
const o =
|
|
201
|
+
const o = D(
|
|
201
202
|
t.headers.origin,
|
|
202
203
|
h.allowedOrigins ? { allowedOrigins: h.allowedOrigins } : {}
|
|
203
204
|
);
|
|
204
205
|
if (!o.valid)
|
|
205
206
|
return e.status(403).json(C(null, -32600, o.reason));
|
|
206
207
|
const a = t.headers.accept;
|
|
207
|
-
if (!
|
|
208
|
+
if (!_(a))
|
|
208
209
|
return e.status(400).json(C(null, -32600, "Accept header must include both application/json and text/event-stream"));
|
|
209
|
-
const s =
|
|
210
|
+
const s = V(t.headers);
|
|
210
211
|
if (!s.ok)
|
|
211
212
|
return e.status(426).json({
|
|
212
213
|
error: "Unsupported MCP protocol version",
|
|
213
214
|
supported: s.supported
|
|
214
215
|
});
|
|
215
|
-
const n =
|
|
216
|
+
const n = z(t.body);
|
|
216
217
|
if (!n)
|
|
217
218
|
return e.status(400).json(C(null, -32600, "Invalid JSON-RPC 2.0 request"));
|
|
218
|
-
const p =
|
|
219
|
+
const p = B(a), x = n.method === "initialize";
|
|
219
220
|
try {
|
|
220
|
-
const d = await
|
|
221
|
+
const d = await T(
|
|
221
222
|
n.method,
|
|
222
223
|
n.params,
|
|
223
224
|
{
|
|
@@ -228,11 +229,11 @@ function W(f) {
|
|
|
228
229
|
negotiatedProtocol: s.negotiated
|
|
229
230
|
}
|
|
230
231
|
);
|
|
231
|
-
if (
|
|
232
|
+
if (M(n))
|
|
232
233
|
return e.status(202).end();
|
|
233
234
|
const j = x && d && typeof d == "object" && "sessionId" in d ? d.sessionId : void 0;
|
|
234
|
-
j && e.setHeader(
|
|
235
|
-
const v =
|
|
235
|
+
j && e.setHeader(F, j);
|
|
236
|
+
const v = U(n.id ?? null, d);
|
|
236
237
|
if (p) {
|
|
237
238
|
const b = w();
|
|
238
239
|
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: ${b}
|
|
@@ -241,7 +242,7 @@ function W(f) {
|
|
|
241
242
|
}
|
|
242
243
|
return e.json(v);
|
|
243
244
|
} catch (d) {
|
|
244
|
-
if (
|
|
245
|
+
if (M(n))
|
|
245
246
|
return console.error("MCP notification processing error:", d), e.status(202).end();
|
|
246
247
|
console.error("MCP RPC error:", d);
|
|
247
248
|
const j = d?.code ?? -32603, v = d?.data, b = d.message || "MCP request failed", q = C(n.id ?? null, j, b, v);
|
|
@@ -278,12 +279,12 @@ function X(f, m) {
|
|
|
278
279
|
const g = W(m);
|
|
279
280
|
return f.use("/", g), f;
|
|
280
281
|
}
|
|
281
|
-
function
|
|
282
|
+
function re(f) {
|
|
282
283
|
const m = R();
|
|
283
284
|
return X(m, f);
|
|
284
285
|
}
|
|
285
286
|
export {
|
|
286
|
-
|
|
287
|
+
re as createCubeApp,
|
|
287
288
|
W as createCubeRouter,
|
|
288
289
|
X as mountCubeRoutes
|
|
289
290
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
"use strict";var
|
|
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-C8pLznZG.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
|
|
|
5
|
-
${
|
|
5
|
+
${i.serializeSseEvent(P,Q)}`);return}return e.send(P)}}),s.get(`${r}`,async(t,e)=>{const o=i.primeEventId();e.raw.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}),e.raw.write(i.serializeSseEvent({jsonrpc:"2.0",method:"mcp/ready",params:{protocol:"streamable-http"}},o,15e3));const a=setInterval(()=>{e.raw.write(`: keep-alive
|
|
6
6
|
|
|
7
|
-
`)},15e3);
|
|
7
|
+
`)},15e3);t.raw.on("close",()=>{clearInterval(a)})}),s.delete(`${r}`,async(t,e)=>e.status(405).send({error:"Session termination not supported"}))}s.setErrorHandler(async(r,t,e)=>{t.log.error(r,"Fastify cube adapter error"),e.statusCode<400&&e.status(500);const o=r instanceof Error?r:String(r);return n.formatErrorResponse(o,e.statusCode)}),v()};async function H(l,s){await l.register(q,s)}function T(l){const s=require("fastify")({logger:!0});return s.register(q,l),s}exports.createCubeApp=T;exports.cubePlugin=q;exports.registerCubeRoutes=H;
|
|
@@ -1,25 +1,26 @@
|
|
|
1
|
-
import { S as D,
|
|
2
|
-
|
|
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-B4BZSsMC.js";
|
|
2
|
+
import { formatErrorResponse as u, formatCubeResponse as j, handleBatchRequest as G, formatMetaResponse as K, formatSqlResponse as M, handleDryRun as I } from "../utils.js";
|
|
3
|
+
const N = function(n, O, E) {
|
|
3
4
|
const {
|
|
4
5
|
cubes: w,
|
|
5
|
-
drizzle:
|
|
6
|
+
drizzle: k,
|
|
6
7
|
schema: A,
|
|
7
8
|
extractSecurityContext: y,
|
|
8
9
|
engineType: L,
|
|
9
10
|
cors: Q,
|
|
10
11
|
basePath: p = "/cubejs-api/v1",
|
|
11
|
-
bodyLimit:
|
|
12
|
+
bodyLimit: m = 10485760,
|
|
12
13
|
// 10MB
|
|
13
14
|
cache: J,
|
|
14
15
|
mcp: g = { enabled: !0 }
|
|
15
|
-
} =
|
|
16
|
+
} = O;
|
|
16
17
|
if (!w || w.length === 0)
|
|
17
18
|
return E(new Error("At least one cube must be provided in the cubes array"));
|
|
18
19
|
Q && n.register(import("@fastify/cors"), Q), n.addHook("onRequest", async (r, t) => {
|
|
19
20
|
r.method === "POST" && (r.body = void 0);
|
|
20
21
|
});
|
|
21
22
|
const c = new D({
|
|
22
|
-
drizzle:
|
|
23
|
+
drizzle: k,
|
|
23
24
|
schema: A,
|
|
24
25
|
engineType: L,
|
|
25
26
|
cache: J
|
|
@@ -27,7 +28,7 @@ const k = function(n, N, E) {
|
|
|
27
28
|
if (w.forEach((r) => {
|
|
28
29
|
c.registerCube(r);
|
|
29
30
|
}), n.post(`${p}/load`, {
|
|
30
|
-
bodyLimit:
|
|
31
|
+
bodyLimit: m,
|
|
31
32
|
schema: {
|
|
32
33
|
body: {
|
|
33
34
|
type: "object",
|
|
@@ -43,7 +44,7 @@ const k = function(n, N, E) {
|
|
|
43
44
|
400
|
|
44
45
|
));
|
|
45
46
|
const i = r.headers["x-cache-control"] === "no-cache", d = await c.executeMultiCubeQuery(a, s, { skipCache: i });
|
|
46
|
-
return
|
|
47
|
+
return j(a, d, c);
|
|
47
48
|
} catch (e) {
|
|
48
49
|
return r.log.error(e, "Query execution error"), t.status(500).send(u(
|
|
49
50
|
e instanceof Error ? e.message : "Query execution failed",
|
|
@@ -79,7 +80,7 @@ const k = function(n, N, E) {
|
|
|
79
80
|
400
|
|
80
81
|
));
|
|
81
82
|
const i = r.headers["x-cache-control"] === "no-cache", d = await c.executeMultiCubeQuery(a, s, { skipCache: i });
|
|
82
|
-
return
|
|
83
|
+
return j(a, d, c);
|
|
83
84
|
} catch (e) {
|
|
84
85
|
return r.log.error(e, "Query execution error"), t.status(500).send(u(
|
|
85
86
|
e instanceof Error ? e.message : "Query execution failed",
|
|
@@ -87,7 +88,7 @@ const k = function(n, N, E) {
|
|
|
87
88
|
));
|
|
88
89
|
}
|
|
89
90
|
}), n.post(`${p}/batch`, {
|
|
90
|
-
bodyLimit:
|
|
91
|
+
bodyLimit: m,
|
|
91
92
|
schema: {
|
|
92
93
|
body: {
|
|
93
94
|
type: "object",
|
|
@@ -114,7 +115,7 @@ const k = function(n, N, E) {
|
|
|
114
115
|
400
|
|
115
116
|
));
|
|
116
117
|
const a = await y(r), s = r.headers["x-cache-control"] === "no-cache";
|
|
117
|
-
return await
|
|
118
|
+
return await G(e, a, c, { skipCache: s });
|
|
118
119
|
} catch (e) {
|
|
119
120
|
return r.log.error(e, "Batch execution error"), t.status(500).send(u(
|
|
120
121
|
e instanceof Error ? e.message : "Batch execution failed",
|
|
@@ -124,7 +125,7 @@ const k = function(n, N, E) {
|
|
|
124
125
|
}), n.get(`${p}/meta`, async (r, t) => {
|
|
125
126
|
try {
|
|
126
127
|
const e = c.getMetadata();
|
|
127
|
-
return
|
|
128
|
+
return K(e);
|
|
128
129
|
} catch (e) {
|
|
129
130
|
return r.log.error(e, "Metadata error"), t.status(500).send(u(
|
|
130
131
|
e instanceof Error ? e.message : "Failed to fetch metadata",
|
|
@@ -132,7 +133,7 @@ const k = function(n, N, E) {
|
|
|
132
133
|
));
|
|
133
134
|
}
|
|
134
135
|
}), n.post(`${p}/sql`, {
|
|
135
|
-
bodyLimit:
|
|
136
|
+
bodyLimit: m,
|
|
136
137
|
schema: {
|
|
137
138
|
body: {
|
|
138
139
|
type: "object",
|
|
@@ -154,7 +155,7 @@ const k = function(n, N, E) {
|
|
|
154
155
|
400
|
|
155
156
|
));
|
|
156
157
|
const i = o.split(".")[0], d = await c.generateSQL(i, e, a);
|
|
157
|
-
return
|
|
158
|
+
return M(e, d);
|
|
158
159
|
} catch (e) {
|
|
159
160
|
return r.log.error(e, "SQL generation error"), t.status(500).send(u(
|
|
160
161
|
e instanceof Error ? e.message : "SQL generation failed",
|
|
@@ -186,7 +187,7 @@ const k = function(n, N, E) {
|
|
|
186
187
|
400
|
|
187
188
|
));
|
|
188
189
|
const d = i.split(".")[0], x = await c.generateSQL(d, a, s);
|
|
189
|
-
return
|
|
190
|
+
return M(a, x);
|
|
190
191
|
} catch (e) {
|
|
191
192
|
return r.log.error(e, "SQL generation error"), t.status(500).send(u(
|
|
192
193
|
e instanceof Error ? e.message : "SQL generation failed",
|
|
@@ -194,7 +195,7 @@ const k = function(n, N, E) {
|
|
|
194
195
|
));
|
|
195
196
|
}
|
|
196
197
|
}), n.post(`${p}/dry-run`, {
|
|
197
|
-
bodyLimit:
|
|
198
|
+
bodyLimit: m,
|
|
198
199
|
schema: {
|
|
199
200
|
body: {
|
|
200
201
|
type: "object",
|
|
@@ -204,7 +205,7 @@ const k = function(n, N, E) {
|
|
|
204
205
|
}, async (r, t) => {
|
|
205
206
|
try {
|
|
206
207
|
const e = r.body, a = e.query || e, s = await y(r);
|
|
207
|
-
return await
|
|
208
|
+
return await I(a, s, c);
|
|
208
209
|
} catch (e) {
|
|
209
210
|
return r.log.error(e, "Dry-run error"), t.status(400).send({
|
|
210
211
|
error: e instanceof Error ? e.message : "Dry-run validation failed",
|
|
@@ -224,7 +225,7 @@ const k = function(n, N, E) {
|
|
|
224
225
|
}, async (r, t) => {
|
|
225
226
|
try {
|
|
226
227
|
const { query: e } = r.query, a = JSON.parse(e), s = await y(r);
|
|
227
|
-
return await
|
|
228
|
+
return await I(a, s, c);
|
|
228
229
|
} catch (e) {
|
|
229
230
|
return r.log.error(e, "Dry-run error"), t.status(400).send({
|
|
230
231
|
error: e instanceof Error ? e.message : "Dry-run validation failed",
|
|
@@ -232,7 +233,7 @@ const k = function(n, N, E) {
|
|
|
232
233
|
});
|
|
233
234
|
}
|
|
234
235
|
}), n.post(`${p}/explain`, {
|
|
235
|
-
bodyLimit:
|
|
236
|
+
bodyLimit: m,
|
|
236
237
|
schema: {
|
|
237
238
|
body: {
|
|
238
239
|
type: "object",
|
|
@@ -253,7 +254,7 @@ const k = function(n, N, E) {
|
|
|
253
254
|
}), g.enabled !== !1) {
|
|
254
255
|
const r = g.basePath ?? "/mcp";
|
|
255
256
|
n.post(`${r}`, {
|
|
256
|
-
bodyLimit:
|
|
257
|
+
bodyLimit: m,
|
|
257
258
|
schema: {
|
|
258
259
|
body: {
|
|
259
260
|
type: "object",
|
|
@@ -261,27 +262,27 @@ const k = function(n, N, E) {
|
|
|
261
262
|
}
|
|
262
263
|
}
|
|
263
264
|
}, async (t, e) => {
|
|
264
|
-
const a =
|
|
265
|
+
const a = H(
|
|
265
266
|
t.headers.origin,
|
|
266
267
|
g.allowedOrigins ? { allowedOrigins: g.allowedOrigins } : {}
|
|
267
268
|
);
|
|
268
269
|
if (!a.valid)
|
|
269
270
|
return e.status(403).send(C(null, -32600, a.reason));
|
|
270
271
|
const s = t.headers.accept;
|
|
271
|
-
if (!
|
|
272
|
+
if (!V(s))
|
|
272
273
|
return e.status(400).send(C(null, -32600, "Accept header must include both application/json and text/event-stream"));
|
|
273
|
-
const o =
|
|
274
|
+
const o = z(t.headers);
|
|
274
275
|
if (!o.ok)
|
|
275
276
|
return e.status(426).send({
|
|
276
277
|
error: "Unsupported MCP protocol version",
|
|
277
278
|
supported: o.supported
|
|
278
279
|
});
|
|
279
|
-
const i =
|
|
280
|
+
const i = T(t.body);
|
|
280
281
|
if (!i)
|
|
281
282
|
return e.status(400).send(C(null, -32600, "Invalid JSON-RPC 2.0 request"));
|
|
282
|
-
const d =
|
|
283
|
+
const d = _(s), x = i.method === "initialize";
|
|
283
284
|
try {
|
|
284
|
-
const l = await
|
|
285
|
+
const l = await B(
|
|
285
286
|
i.method,
|
|
286
287
|
i.params,
|
|
287
288
|
{
|
|
@@ -292,11 +293,11 @@ const k = function(n, N, E) {
|
|
|
292
293
|
negotiatedProtocol: o.negotiated
|
|
293
294
|
}
|
|
294
295
|
);
|
|
295
|
-
if (
|
|
296
|
+
if ($(i))
|
|
296
297
|
return e.status(202).send();
|
|
297
298
|
const b = x && l && typeof l == "object" && "sessionId" in l ? l.sessionId : void 0;
|
|
298
|
-
b && e.header(
|
|
299
|
-
const v =
|
|
299
|
+
b && e.header(F, b);
|
|
300
|
+
const v = U(i.id ?? null, l);
|
|
300
301
|
if (d) {
|
|
301
302
|
const f = q();
|
|
302
303
|
e.header("Content-Type", "text/event-stream").header("Cache-Control", "no-cache").header("Connection", "keep-alive").send(`id: ${f}
|
|
@@ -306,7 +307,7 @@ ${R(v, f)}`);
|
|
|
306
307
|
}
|
|
307
308
|
return e.send(v);
|
|
308
309
|
} catch (l) {
|
|
309
|
-
if (
|
|
310
|
+
if ($(i))
|
|
310
311
|
return t.log.error(l, "MCP notification processing error"), e.status(202).send();
|
|
311
312
|
t.log.error(l, "MCP RPC error");
|
|
312
313
|
const b = l?.code ?? -32603, v = l?.data, f = l.message || "MCP request failed", S = C(i.id ?? null, b, f, v);
|
|
@@ -346,17 +347,17 @@ ${R(S, P)}`);
|
|
|
346
347
|
return u(a, e.statusCode);
|
|
347
348
|
}), E();
|
|
348
349
|
};
|
|
349
|
-
async function
|
|
350
|
-
await
|
|
350
|
+
async function Y(h, n) {
|
|
351
|
+
await h.register(N, n);
|
|
351
352
|
}
|
|
352
|
-
function
|
|
353
|
+
function Z(h) {
|
|
353
354
|
const n = require("fastify")({
|
|
354
355
|
logger: !0
|
|
355
356
|
});
|
|
356
|
-
return n.register(
|
|
357
|
+
return n.register(N, h), n;
|
|
357
358
|
}
|
|
358
359
|
export {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
360
|
+
Z as createCubeApp,
|
|
361
|
+
N as cubePlugin,
|
|
362
|
+
Y as registerCubeRoutes
|
|
362
363
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const T=require("hono"),s=require("../mcp-transport-C8pLznZG.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
|
|
|
5
|
-
`)),
|
|
5
|
+
`)),M.enqueue(x.encode(s.serializeSseEvent(R,Q))),M.close()}});return new Response(E,{status:200,headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}})}return t.json(R,200)}}),u.delete(`${i}`,t=>t.json({error:"Session termination not supported"},405)),u.get(`${i}`,t=>{const c=new TextEncoder,p=s.primeEventId();let g;const H=new ReadableStream({start(m){m.enqueue(c.encode(s.serializeSseEvent({jsonrpc:"2.0",method:"mcp/ready",params:{protocol:"streamable-http"}},p,15e3))),g=setInterval(()=>{m.enqueue(c.encode(`: keep-alive
|
|
6
6
|
|
|
7
|
-
`))},15e3)},cancel(){clearInterval(g)}});return new Response(
|
|
7
|
+
`))},15e3)},cancel(){clearInterval(g)}});return new Response(H,{status:200,headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}})})}return u}function N(C,j){const d=I(j);return C.route("/",d),C}function D(C){const j=new T.Hono;return N(j,C)}exports.createCubeApp=D;exports.createCubeRoutes=I;exports.mountCubeRoutes=N;
|