drizzle-cube 0.4.4 → 0.4.7
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 +8 -4
- package/dist/adapters/express/index.d.ts +7 -0
- package/dist/adapters/express/index.js +189 -139
- package/dist/adapters/fastify/index.cjs +8 -4
- package/dist/adapters/fastify/index.d.ts +7 -0
- package/dist/adapters/fastify/index.js +209 -150
- package/dist/adapters/handler-D6l8AbJV.cjs +7 -0
- package/dist/adapters/handler-DsNgnIPK.js +458 -0
- package/dist/adapters/hono/index.cjs +8 -4
- package/dist/adapters/hono/index.d.ts +7 -0
- package/dist/adapters/hono/index.js +202 -144
- package/dist/adapters/{mcp-transport-BqLo4hKi.cjs → mcp-transport-BB998cy5.cjs} +21 -21
- package/dist/adapters/{mcp-transport-YHDZWKOi.js → mcp-transport-DFTCWene.js} +4 -0
- package/dist/adapters/nextjs/index.cjs +7 -3
- package/dist/adapters/nextjs/index.d.ts +14 -0
- package/dist/adapters/nextjs/index.js +220 -144
- package/dist/client/charts.js +13 -13
- package/dist/client/chunks/{RetentionCombinedChart-BK8N-MOQ.js → RetentionCombinedChart-CEI8KQ3t.js} +2 -2
- package/dist/client/chunks/{RetentionCombinedChart-BK8N-MOQ.js.map → RetentionCombinedChart-CEI8KQ3t.js.map} +1 -1
- package/dist/client/chunks/{analysis-builder-CNBmAGAO.js → analysis-builder-Dn8xpgPQ.js} +6 -6
- package/dist/client/chunks/{analysis-builder-CNBmAGAO.js.map → analysis-builder-Dn8xpgPQ.js.map} +1 -1
- package/dist/client/chunks/{analysis-builder-shared-INGGwyTG.js → analysis-builder-shared-D3xYzXlh.js} +2 -2
- package/dist/client/chunks/{analysis-builder-shared-INGGwyTG.js.map → analysis-builder-shared-D3xYzXlh.js.map} +1 -1
- package/dist/client/chunks/{chart-activity-grid-DvgTYQaE.js → chart-activity-grid-DStNr34n.js} +2 -2
- package/dist/client/chunks/{chart-activity-grid-DvgTYQaE.js.map → chart-activity-grid-DStNr34n.js.map} +1 -1
- package/dist/client/chunks/{chart-area-BKjd_STS.js → chart-area-QKKboTbq.js} +3 -3
- package/dist/client/chunks/{chart-area-BKjd_STS.js.map → chart-area-QKKboTbq.js.map} +1 -1
- package/dist/client/chunks/{chart-bar-DBI41w05.js → chart-bar-HpXF42H1.js} +2 -2
- package/dist/client/chunks/{chart-bar-DBI41w05.js.map → chart-bar-HpXF42H1.js.map} +1 -1
- package/dist/client/chunks/{chart-bubble-BD-1kneU.js → chart-bubble-Bf42A1-B.js} +2 -2
- package/dist/client/chunks/{chart-bubble-BD-1kneU.js.map → chart-bubble-Bf42A1-B.js.map} +1 -1
- package/dist/client/chunks/{chart-config-markdown-6fsr-U6_.js → chart-config-markdown-BXKL5TbQ.js} +8 -1
- package/dist/client/chunks/{chart-config-markdown-6fsr-U6_.js.map → chart-config-markdown-BXKL5TbQ.js.map} +1 -1
- package/dist/client/chunks/{chart-data-table-B74HLpAx.js → chart-data-table-Ch_1c1Zo.js} +2 -2
- package/dist/client/chunks/{chart-data-table-B74HLpAx.js.map → chart-data-table-Ch_1c1Zo.js.map} +1 -1
- package/dist/client/chunks/{chart-funnel-DQ9cW6j9.js → chart-funnel-C9kenCpp.js} +2 -2
- package/dist/client/chunks/{chart-funnel-DQ9cW6j9.js.map → chart-funnel-C9kenCpp.js.map} +1 -1
- package/dist/client/chunks/{chart-heat-map-CpIr4tbs.js → chart-heat-map-CYGemyPB.js} +2 -2
- package/dist/client/chunks/{chart-heat-map-CpIr4tbs.js.map → chart-heat-map-CYGemyPB.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-delta-DPcSazD3.js → chart-kpi-delta-CWCmi8vL.js} +3 -3
- package/dist/client/chunks/{chart-kpi-delta-DPcSazD3.js.map → chart-kpi-delta-CWCmi8vL.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-number-D62PzKZ1.js → chart-kpi-number-C-5m3qt5.js} +2 -2
- package/dist/client/chunks/{chart-kpi-number-D62PzKZ1.js.map → chart-kpi-number-C-5m3qt5.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-text-B6Z5tFV1.js → chart-kpi-text--t4ibPmx.js} +3 -3
- package/dist/client/chunks/{chart-kpi-text-B6Z5tFV1.js.map → chart-kpi-text--t4ibPmx.js.map} +1 -1
- package/dist/client/chunks/{chart-line-Ds4BYA0K.js → chart-line-C7YcMWBw.js} +3 -3
- package/dist/client/chunks/{chart-line-Ds4BYA0K.js.map → chart-line-C7YcMWBw.js.map} +1 -1
- package/dist/client/chunks/chart-markdown-Du4Z2iqK.js +2695 -0
- package/dist/client/chunks/chart-markdown-Du4Z2iqK.js.map +1 -0
- package/dist/client/chunks/{chart-pie-BBrLh0iU.js → chart-pie-C4SuxKSN.js} +2 -2
- package/dist/client/chunks/{chart-pie-BBrLh0iU.js.map → chart-pie-C4SuxKSN.js.map} +1 -1
- package/dist/client/chunks/{chart-radar-vr5FgjHT.js → chart-radar-BW3Z_-Ly.js} +2 -2
- package/dist/client/chunks/{chart-radar-vr5FgjHT.js.map → chart-radar-BW3Z_-Ly.js.map} +1 -1
- package/dist/client/chunks/{chart-radial-bar-BV_3Nm5P.js → chart-radial-bar-0Fa3aeP5.js} +2 -2
- package/dist/client/chunks/{chart-radial-bar-BV_3Nm5P.js.map → chart-radial-bar-0Fa3aeP5.js.map} +1 -1
- package/dist/client/chunks/{chart-sankey-CHROzr4S.js → chart-sankey-DBghfbg1.js} +2 -2
- package/dist/client/chunks/{chart-sankey-CHROzr4S.js.map → chart-sankey-DBghfbg1.js.map} +1 -1
- package/dist/client/chunks/{chart-scatter-DbRTU3FG.js → chart-scatter-DOVu1TNq.js} +2 -2
- package/dist/client/chunks/{chart-scatter-DbRTU3FG.js.map → chart-scatter-DOVu1TNq.js.map} +1 -1
- package/dist/client/chunks/{chart-sunburst-B-aPUzYL.js → chart-sunburst-LfNthFlZ.js} +2 -2
- package/dist/client/chunks/{chart-sunburst-B-aPUzYL.js.map → chart-sunburst-LfNthFlZ.js.map} +1 -1
- package/dist/client/chunks/{chart-tree-map-qY148fiC.js → chart-tree-map-DZtQPyWX.js} +2 -2
- package/dist/client/chunks/{chart-tree-map-qY148fiC.js.map → chart-tree-map-DZtQPyWX.js.map} +1 -1
- package/dist/client/chunks/{chartConfigRegistry-Di34paQH.js → chartConfigRegistry-C5dZm-ZK.js} +2 -2
- package/dist/client/chunks/{chartConfigRegistry-Di34paQH.js.map → chartConfigRegistry-C5dZm-ZK.js.map} +1 -1
- package/dist/client/chunks/{charts-core-T8UglYyq.js → charts-core-DmGfleFz.js} +199 -187
- package/dist/client/chunks/{charts-core-T8UglYyq.js.map → charts-core-DmGfleFz.js.map} +1 -1
- package/dist/client/chunks/{charts-loader-YnhJHubD.js → charts-loader-DcFWOUeV.js} +21 -21
- package/dist/client/chunks/{charts-loader-YnhJHubD.js.map → charts-loader-DcFWOUeV.js.map} +1 -1
- package/dist/client/chunks/{components-D0i1yQsk.js → components-Bdt1AmzS.js} +3521 -3369
- package/dist/client/chunks/components-Bdt1AmzS.js.map +1 -0
- package/dist/client/components/AgenticNotebook/AgentChatPanel.d.ts +8 -0
- package/dist/client/components/AgenticNotebook/ChatInput.d.ts +14 -0
- package/dist/client/components/AgenticNotebook/ChatMessage.d.ts +7 -0
- package/dist/client/components/AgenticNotebook/NotebookCanvas.d.ts +3 -0
- package/dist/client/components/AgenticNotebook/NotebookMarkdownBlock.d.ts +12 -0
- package/dist/client/components/AgenticNotebook/NotebookPortletBlock.d.ts +12 -0
- package/dist/client/components/AgenticNotebook/index.d.ts +34 -0
- package/dist/client/components/DashboardPortletCard.d.ts +3 -2
- package/dist/client/components.js +1 -1
- package/dist/client/hooks/dashboard/layoutUtils.d.ts +7 -0
- package/dist/client/hooks/dashboard/useDashboardController.d.ts +53 -0
- package/dist/client/hooks/dashboard/useGridLayoutEngine.d.ts +10 -0
- package/dist/client/hooks/dashboard/useRowLayoutEngine.d.ts +18 -0
- package/dist/client/hooks/useAgentChat.d.ts +36 -0
- package/dist/client/index.d.ts +6 -0
- package/dist/client/index.js +923 -187
- package/dist/client/index.js.map +1 -1
- package/dist/client/stores/notebookStore.d.ts +152 -0
- package/dist/client/styles.css +1 -1
- package/dist/client/utils.js +4 -4
- package/dist/client-bundle-stats.html +1 -1
- package/dist/server/index.cjs +101 -91
- package/dist/server/index.d.ts +155 -0
- package/dist/server/index.js +4423 -3609
- package/package.json +7 -1
- package/dist/client/chunks/chart-markdown-Rq6ORisB.js +0 -276
- package/dist/client/chunks/chart-markdown-Rq6ORisB.js.map +0 -1
- package/dist/client/chunks/components-D0i1yQsk.js.map +0 -1
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const R=require("express"),M=require("cors"),c=require("../mcp-transport-BB998cy5.cjs"),n=require("../utils.cjs");function $(g){const{cubes:m,drizzle:w,schema:P,extractSecurityContext:y,engineType:A,cors:x,basePath:f="/cubejs-api/v1",jsonLimit:S="10mb",cache:H,mcp:v={enabled:!0},agent:j}=g;if(!m||m.length===0)throw new Error("At least one cube must be provided in the cubes array");const d=R.Router();x&&d.use(M(x)),d.use(R.json({limit:S})),d.use(R.urlencoded({extended:!0,limit:S}));const u=new c.SemanticLayerCompiler({drizzle:w,schema:P,engineType:A,cache:H});if(m.forEach(r=>{u.registerCube(r)}),d.post(`${f}/load`,async(r,t)=>{try{const e=r.body.query||r.body,o=await y(r,t),a=u.validateQuery(e);if(!a.isValid)return t.status(400).json(n.formatErrorResponse(`Query validation failed: ${a.errors.join(", ")}`,400));const s=r.headers["x-cache-control"]==="no-cache",i=await u.executeMultiCubeQuery(e,o,{skipCache:s});t.json(n.formatCubeResponse(e,i,u))}catch(e){console.error("Query execution error:",e),t.status(500).json(n.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500))}}),d.get(`${f}/load`,async(r,t)=>{try{const e=r.query.query;if(!e)return t.status(400).json(n.formatErrorResponse("Query parameter is required",400));let o;try{o=JSON.parse(e)}catch{return t.status(400).json(n.formatErrorResponse("Invalid JSON in query parameter",400))}const a=await y(r,t),s=u.validateQuery(o);if(!s.isValid)return t.status(400).json(n.formatErrorResponse(`Query validation failed: ${s.errors.join(", ")}`,400));const i=r.headers["x-cache-control"]==="no-cache",l=await u.executeMultiCubeQuery(o,a,{skipCache:i});t.json(n.formatCubeResponse(o,l,u))}catch(e){console.error("Query execution error:",e),t.status(500).json(n.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500))}}),d.post(`${f}/batch`,async(r,t)=>{try{const{queries:e}=r.body;if(!e||!Array.isArray(e))return t.status(400).json(n.formatErrorResponse('Request body must contain a "queries" array',400));if(e.length===0)return t.status(400).json(n.formatErrorResponse("Queries array cannot be empty",400));const o=await y(r,t),a=r.headers["x-cache-control"]==="no-cache",s=await n.handleBatchRequest(e,o,u,{skipCache:a});t.json(s)}catch(e){console.error("Batch execution error:",e),t.status(500).json(n.formatErrorResponse(e instanceof Error?e.message:"Batch execution failed",500))}}),d.get(`${f}/meta`,(r,t)=>{try{const e=u.getMetadata();t.json(n.formatMetaResponse(e))}catch(e){console.error("Metadata error:",e),t.status(500).json(n.formatErrorResponse(e instanceof Error?e.message:"Failed to fetch metadata",500))}}),d.post(`${f}/sql`,async(r,t)=>{try{const e=r.body,o=await y(r,t),a=u.validateQuery(e);if(!a.isValid)return t.status(400).json(n.formatErrorResponse(`Query validation failed: ${a.errors.join(", ")}`,400));const s=e.measures?.[0]||e.dimensions?.[0];if(!s)return t.status(400).json(n.formatErrorResponse("No measures or dimensions specified",400));const i=s.split(".")[0],l=await u.generateSQL(i,e,o);t.json(n.formatSqlResponse(e,l))}catch(e){console.error("SQL generation error:",e),t.status(500).json(n.formatErrorResponse(e instanceof Error?e.message:"SQL generation failed",500))}}),d.get(`${f}/sql`,async(r,t)=>{try{const e=r.query.query;if(!e)return t.status(400).json(n.formatErrorResponse("Query parameter is required",400));const o=JSON.parse(e),a=await y(r,t),s=u.validateQuery(o);if(!s.isValid)return t.status(400).json(n.formatErrorResponse(`Query validation failed: ${s.errors.join(", ")}`,400));const i=o.measures?.[0]||o.dimensions?.[0];if(!i)return t.status(400).json(n.formatErrorResponse("No measures or dimensions specified",400));const l=i.split(".")[0],h=await u.generateSQL(l,o,a);t.json(n.formatSqlResponse(o,h))}catch(e){console.error("SQL generation error:",e),t.status(500).json(n.formatErrorResponse(e instanceof Error?e.message:"SQL generation failed",500))}}),d.post(`${f}/dry-run`,async(r,t)=>{try{const e=r.body.query||r.body,o=await y(r,t),a=await n.handleDryRun(e,o,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})}}),d.get(`${f}/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),a=await y(r,t),s=await n.handleDryRun(o,a,u);t.json(s)}catch(e){console.error("Dry-run error:",e),t.status(400).json({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1})}}),d.post(`${f}/explain`,async(r,t)=>{try{const e=r.body.query||r.body,o=r.body.options||{},a=await y(r,t),s=u.validateQuery(e);if(!s.isValid)return t.status(400).json({error:`Query validation failed: ${s.errors.join(", ")}`});const i=await u.explainQuery(e,a,o);t.json(i)}catch(e){console.error("Explain error:",e),t.status(500).json({error:e instanceof Error?e.message:"Explain query failed"})}}),j&&d.post(`${f}/agent/chat`,async(r,t)=>{try{const{handleAgentChat:e}=await Promise.resolve().then(()=>require("../handler-D6l8AbJV.cjs")),{message:o,sessionId:a}=r.body;if(!o||typeof o!="string")return t.status(400).json({error:"message is required and must be a string"});let s=(j.apiKey||"").trim();if(j.allowClientApiKey){const l=r.headers["x-agent-api-key"];l&&(s=l.trim())}if(!s)return t.status(401).json({error:"No API key configured. Set agent.apiKey in server config or send X-Agent-Api-Key header."});const i=await y(r,t);t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});try{const l=e({message:o,sessionId:a,semanticLayer:u,securityContext:i,agentConfig:j,apiKey:s});for await(const h of l)t.write(`data: ${JSON.stringify(h)}
|
|
2
2
|
|
|
3
|
-
`)
|
|
3
|
+
`)}catch(l){const h={type:"error",data:{message:l instanceof Error?l.message:"Stream failed"}};t.write(`data: ${JSON.stringify(h)}
|
|
4
4
|
|
|
5
|
-
`),e.
|
|
5
|
+
`)}finally{t.end()}}catch(e){console.error("Agent chat error:",e),t.headersSent||t.status(500).json({error:e instanceof Error?e.message:"Agent chat failed"})}}),v.enabled!==!1){const r=v.basePath??"/mcp";d.post(`${r}`,async(t,e)=>{const o=c.validateOriginHeader(t.headers.origin,v.allowedOrigins?{allowedOrigins:v.allowedOrigins}:{});if(!o.valid)return e.status(403).json(c.buildJsonRpcError(null,-32600,o.reason));const a=t.headers.accept;if(!c.validateAcceptHeader(a))return e.status(400).json(c.buildJsonRpcError(null,-32600,"Accept header must include both application/json and text/event-stream"));const s=c.negotiateProtocol(t.headers);if(!s.ok)return e.status(426).json({error:"Unsupported MCP protocol version",supported:s.supported});const i=c.parseJsonRpc(t.body);if(!i)return e.status(400).json(c.buildJsonRpcError(null,-32600,"Invalid JSON-RPC 2.0 request"));const l=c.wantsEventStream(a),h=i.method==="initialize";try{const p=await c.dispatchMcpMethod(i.method,i.params,{semanticLayer:u,extractSecurityContext:y,rawRequest:t,rawResponse:e,negotiatedProtocol:s.negotiated});if(c.isNotification(i))return e.status(202).end();const b=h&&p&&typeof p=="object"&&"sessionId"in p?p.sessionId:void 0;b&&e.setHeader(c.MCP_SESSION_ID_HEADER,b);const C=c.buildJsonRpcResult(i.id??null,p);if(l){const E=c.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: ${E}
|
|
6
6
|
|
|
7
|
-
`)
|
|
7
|
+
`),e.write(c.serializeSseEvent(C,E)),e.end()}return e.json(C)}catch(p){if(c.isNotification(i))return console.error("MCP notification processing error:",p),e.status(202).end();console.error("MCP RPC error:",p);const b=p?.code??-32603,C=p?.data,E=p.message||"MCP request failed",Q=c.buildJsonRpcError(i.id??null,b,E,C);if(l){const q=c.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: ${q}
|
|
8
|
+
|
|
9
|
+
`),e.write(c.serializeSseEvent(Q,q)),e.end()}return e.status(200).json(Q)}}),d.get(`${r}`,async(t,e)=>{const o=c.primeEventId();e.status(200),e.setHeader("Content-Type","text/event-stream"),e.setHeader("Cache-Control","no-cache"),e.setHeader("Connection","keep-alive"),e.write(c.serializeSseEvent({jsonrpc:"2.0",method:"mcp/ready",params:{protocol:"streamable-http"}},o,15e3));const a=setInterval(()=>{e.write(`: keep-alive
|
|
10
|
+
|
|
11
|
+
`)},15e3);t.on("close",()=>{clearInterval(a)})}),d.delete(`${r}`,(t,e)=>e.status(405).json({error:"Session termination not supported"}))}return d.use((r,t,e,o)=>{console.error("Express adapter error:",r),e.headersSent||e.status(500).json(n.formatErrorResponse(r,500))}),d}function I(g,m){const w=$(m);return g.use("/",w),g}function N(g){const m=R();return I(m,g)}exports.createCubeApp=N;exports.createCubeRouter=$;exports.mountCubeRoutes=I;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Router, Request, Response, Express } from 'express';
|
|
2
2
|
import { CorsOptions } from 'cors';
|
|
3
3
|
import { SemanticQuery, SecurityContext, DatabaseExecutor, DrizzleDatabase, Cube, CacheConfig } from '../../server';
|
|
4
|
+
import { AgentConfig } from '../../server/agent/types';
|
|
4
5
|
import { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
|
|
5
6
|
import { MySql2Database } from 'drizzle-orm/mysql2';
|
|
6
7
|
import { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
|
|
@@ -73,6 +74,12 @@ export interface ExpressAdapterOptions {
|
|
|
73
74
|
* @default { enabled: true }
|
|
74
75
|
*/
|
|
75
76
|
mcp?: MCPOptions;
|
|
77
|
+
/**
|
|
78
|
+
* Agent configuration for the agentic AI notebook feature.
|
|
79
|
+
* When provided, enables the POST /agent/chat SSE endpoint.
|
|
80
|
+
* Requires `@anthropic-ai/sdk` as a peer dependency.
|
|
81
|
+
*/
|
|
82
|
+
agent?: AgentConfig;
|
|
76
83
|
}
|
|
77
84
|
/**
|
|
78
85
|
* Create Express router for Cube.js-compatible API
|
|
@@ -1,53 +1,54 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import { S as
|
|
4
|
-
import { formatErrorResponse as
|
|
5
|
-
function W(
|
|
1
|
+
import E, { Router as J } from "express";
|
|
2
|
+
import L from "cors";
|
|
3
|
+
import { S as D, v as _, b as w, a as K, n as V, p as z, w as T, d as B, i as P, M as F, c as U, e as S, s as Q } from "../mcp-transport-DFTCWene.js";
|
|
4
|
+
import { formatErrorResponse as u, formatCubeResponse as A, handleBatchRequest as X, formatMetaResponse as G, formatSqlResponse as H, handleDryRun as M } from "../utils.js";
|
|
5
|
+
function W(h) {
|
|
6
6
|
const {
|
|
7
|
-
cubes:
|
|
8
|
-
drizzle:
|
|
7
|
+
cubes: f,
|
|
8
|
+
drizzle: x,
|
|
9
9
|
schema: N,
|
|
10
|
-
extractSecurityContext:
|
|
11
|
-
engineType:
|
|
12
|
-
cors:
|
|
13
|
-
basePath:
|
|
14
|
-
jsonLimit:
|
|
15
|
-
cache:
|
|
16
|
-
mcp:
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
extractSecurityContext: y,
|
|
11
|
+
engineType: k,
|
|
12
|
+
cors: R,
|
|
13
|
+
basePath: p = "/cubejs-api/v1",
|
|
14
|
+
jsonLimit: $ = "10mb",
|
|
15
|
+
cache: O,
|
|
16
|
+
mcp: g = { enabled: !0 },
|
|
17
|
+
agent: j
|
|
18
|
+
} = h;
|
|
19
|
+
if (!f || f.length === 0)
|
|
19
20
|
throw new Error("At least one cube must be provided in the cubes array");
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
const i = new
|
|
23
|
-
drizzle:
|
|
21
|
+
const c = J();
|
|
22
|
+
R && c.use(L(R)), c.use(E.json({ limit: $ })), c.use(E.urlencoded({ extended: !0, limit: $ }));
|
|
23
|
+
const i = new D({
|
|
24
|
+
drizzle: x,
|
|
24
25
|
schema: N,
|
|
25
|
-
engineType:
|
|
26
|
-
cache:
|
|
26
|
+
engineType: k,
|
|
27
|
+
cache: O
|
|
27
28
|
});
|
|
28
|
-
if (
|
|
29
|
+
if (f.forEach((r) => {
|
|
29
30
|
i.registerCube(r);
|
|
30
|
-
}),
|
|
31
|
+
}), c.post(`${p}/load`, async (r, t) => {
|
|
31
32
|
try {
|
|
32
|
-
const e = r.body.query || r.body, o = await
|
|
33
|
-
if (!
|
|
34
|
-
return t.status(400).json(
|
|
35
|
-
`Query validation failed: ${
|
|
33
|
+
const e = r.body.query || r.body, o = await y(r, t), n = i.validateQuery(e);
|
|
34
|
+
if (!n.isValid)
|
|
35
|
+
return t.status(400).json(u(
|
|
36
|
+
`Query validation failed: ${n.errors.join(", ")}`,
|
|
36
37
|
400
|
|
37
38
|
));
|
|
38
|
-
const
|
|
39
|
-
t.json(
|
|
39
|
+
const a = r.headers["x-cache-control"] === "no-cache", s = await i.executeMultiCubeQuery(e, o, { skipCache: a });
|
|
40
|
+
t.json(A(e, s, i));
|
|
40
41
|
} catch (e) {
|
|
41
|
-
console.error("Query execution error:", e), t.status(500).json(
|
|
42
|
+
console.error("Query execution error:", e), t.status(500).json(u(
|
|
42
43
|
e instanceof Error ? e.message : "Query execution failed",
|
|
43
44
|
500
|
|
44
45
|
));
|
|
45
46
|
}
|
|
46
|
-
}),
|
|
47
|
+
}), c.get(`${p}/load`, async (r, t) => {
|
|
47
48
|
try {
|
|
48
49
|
const e = r.query.query;
|
|
49
50
|
if (!e)
|
|
50
|
-
return t.status(400).json(
|
|
51
|
+
return t.status(400).json(u(
|
|
51
52
|
"Query parameter is required",
|
|
52
53
|
400
|
|
53
54
|
));
|
|
@@ -55,117 +56,117 @@ function W(f) {
|
|
|
55
56
|
try {
|
|
56
57
|
o = JSON.parse(e);
|
|
57
58
|
} catch {
|
|
58
|
-
return t.status(400).json(
|
|
59
|
+
return t.status(400).json(u(
|
|
59
60
|
"Invalid JSON in query parameter",
|
|
60
61
|
400
|
|
61
62
|
));
|
|
62
63
|
}
|
|
63
|
-
const
|
|
64
|
-
if (!
|
|
65
|
-
return t.status(400).json(
|
|
66
|
-
`Query validation failed: ${
|
|
64
|
+
const n = await y(r, t), a = i.validateQuery(o);
|
|
65
|
+
if (!a.isValid)
|
|
66
|
+
return t.status(400).json(u(
|
|
67
|
+
`Query validation failed: ${a.errors.join(", ")}`,
|
|
67
68
|
400
|
|
68
69
|
));
|
|
69
|
-
const
|
|
70
|
-
t.json(
|
|
70
|
+
const s = r.headers["x-cache-control"] === "no-cache", d = await i.executeMultiCubeQuery(o, n, { skipCache: s });
|
|
71
|
+
t.json(A(o, d, i));
|
|
71
72
|
} catch (e) {
|
|
72
|
-
console.error("Query execution error:", e), t.status(500).json(
|
|
73
|
+
console.error("Query execution error:", e), t.status(500).json(u(
|
|
73
74
|
e instanceof Error ? e.message : "Query execution failed",
|
|
74
75
|
500
|
|
75
76
|
));
|
|
76
77
|
}
|
|
77
|
-
}),
|
|
78
|
+
}), c.post(`${p}/batch`, async (r, t) => {
|
|
78
79
|
try {
|
|
79
80
|
const { queries: e } = r.body;
|
|
80
81
|
if (!e || !Array.isArray(e))
|
|
81
|
-
return t.status(400).json(
|
|
82
|
+
return t.status(400).json(u(
|
|
82
83
|
'Request body must contain a "queries" array',
|
|
83
84
|
400
|
|
84
85
|
));
|
|
85
86
|
if (e.length === 0)
|
|
86
|
-
return t.status(400).json(
|
|
87
|
+
return t.status(400).json(u(
|
|
87
88
|
"Queries array cannot be empty",
|
|
88
89
|
400
|
|
89
90
|
));
|
|
90
|
-
const o = await
|
|
91
|
-
t.json(
|
|
91
|
+
const o = await y(r, t), n = r.headers["x-cache-control"] === "no-cache", a = await X(e, o, i, { skipCache: n });
|
|
92
|
+
t.json(a);
|
|
92
93
|
} catch (e) {
|
|
93
|
-
console.error("Batch execution error:", e), t.status(500).json(
|
|
94
|
+
console.error("Batch execution error:", e), t.status(500).json(u(
|
|
94
95
|
e instanceof Error ? e.message : "Batch execution failed",
|
|
95
96
|
500
|
|
96
97
|
));
|
|
97
98
|
}
|
|
98
|
-
}),
|
|
99
|
+
}), c.get(`${p}/meta`, (r, t) => {
|
|
99
100
|
try {
|
|
100
101
|
const e = i.getMetadata();
|
|
101
|
-
t.json(
|
|
102
|
+
t.json(G(e));
|
|
102
103
|
} catch (e) {
|
|
103
|
-
console.error("Metadata error:", e), t.status(500).json(
|
|
104
|
+
console.error("Metadata error:", e), t.status(500).json(u(
|
|
104
105
|
e instanceof Error ? e.message : "Failed to fetch metadata",
|
|
105
106
|
500
|
|
106
107
|
));
|
|
107
108
|
}
|
|
108
|
-
}),
|
|
109
|
+
}), c.post(`${p}/sql`, async (r, t) => {
|
|
109
110
|
try {
|
|
110
|
-
const e = r.body, o = await
|
|
111
|
-
if (!
|
|
112
|
-
return t.status(400).json(
|
|
113
|
-
`Query validation failed: ${
|
|
111
|
+
const e = r.body, o = await y(r, t), n = i.validateQuery(e);
|
|
112
|
+
if (!n.isValid)
|
|
113
|
+
return t.status(400).json(u(
|
|
114
|
+
`Query validation failed: ${n.errors.join(", ")}`,
|
|
114
115
|
400
|
|
115
116
|
));
|
|
116
|
-
const
|
|
117
|
-
if (!
|
|
118
|
-
return t.status(400).json(
|
|
117
|
+
const a = e.measures?.[0] || e.dimensions?.[0];
|
|
118
|
+
if (!a)
|
|
119
|
+
return t.status(400).json(u(
|
|
119
120
|
"No measures or dimensions specified",
|
|
120
121
|
400
|
|
121
122
|
));
|
|
122
|
-
const
|
|
123
|
-
t.json(H(e,
|
|
123
|
+
const s = a.split(".")[0], d = await i.generateSQL(s, e, o);
|
|
124
|
+
t.json(H(e, d));
|
|
124
125
|
} catch (e) {
|
|
125
|
-
console.error("SQL generation error:", e), t.status(500).json(
|
|
126
|
+
console.error("SQL generation error:", e), t.status(500).json(u(
|
|
126
127
|
e instanceof Error ? e.message : "SQL generation failed",
|
|
127
128
|
500
|
|
128
129
|
));
|
|
129
130
|
}
|
|
130
|
-
}),
|
|
131
|
+
}), c.get(`${p}/sql`, async (r, t) => {
|
|
131
132
|
try {
|
|
132
133
|
const e = r.query.query;
|
|
133
134
|
if (!e)
|
|
134
|
-
return t.status(400).json(
|
|
135
|
+
return t.status(400).json(u(
|
|
135
136
|
"Query parameter is required",
|
|
136
137
|
400
|
|
137
138
|
));
|
|
138
|
-
const o = JSON.parse(e),
|
|
139
|
-
if (!
|
|
140
|
-
return t.status(400).json(
|
|
141
|
-
`Query validation failed: ${
|
|
139
|
+
const o = JSON.parse(e), n = await y(r, t), a = i.validateQuery(o);
|
|
140
|
+
if (!a.isValid)
|
|
141
|
+
return t.status(400).json(u(
|
|
142
|
+
`Query validation failed: ${a.errors.join(", ")}`,
|
|
142
143
|
400
|
|
143
144
|
));
|
|
144
|
-
const
|
|
145
|
-
if (!
|
|
146
|
-
return t.status(400).json(
|
|
145
|
+
const s = o.measures?.[0] || o.dimensions?.[0];
|
|
146
|
+
if (!s)
|
|
147
|
+
return t.status(400).json(u(
|
|
147
148
|
"No measures or dimensions specified",
|
|
148
149
|
400
|
|
149
150
|
));
|
|
150
|
-
const
|
|
151
|
-
t.json(H(o,
|
|
151
|
+
const d = s.split(".")[0], m = await i.generateSQL(d, o, n);
|
|
152
|
+
t.json(H(o, m));
|
|
152
153
|
} catch (e) {
|
|
153
|
-
console.error("SQL generation error:", e), t.status(500).json(
|
|
154
|
+
console.error("SQL generation error:", e), t.status(500).json(u(
|
|
154
155
|
e instanceof Error ? e.message : "SQL generation failed",
|
|
155
156
|
500
|
|
156
157
|
));
|
|
157
158
|
}
|
|
158
|
-
}),
|
|
159
|
+
}), c.post(`${p}/dry-run`, async (r, t) => {
|
|
159
160
|
try {
|
|
160
|
-
const e = r.body.query || r.body, o = await
|
|
161
|
-
t.json(
|
|
161
|
+
const e = r.body.query || r.body, o = await y(r, t), n = await M(e, o, i);
|
|
162
|
+
t.json(n);
|
|
162
163
|
} catch (e) {
|
|
163
164
|
console.error("Dry-run error:", e), t.status(400).json({
|
|
164
165
|
error: e instanceof Error ? e.message : "Dry-run validation failed",
|
|
165
166
|
valid: !1
|
|
166
167
|
});
|
|
167
168
|
}
|
|
168
|
-
}),
|
|
169
|
+
}), c.get(`${p}/dry-run`, async (r, t) => {
|
|
169
170
|
try {
|
|
170
171
|
const e = r.query.query;
|
|
171
172
|
if (!e)
|
|
@@ -173,118 +174,167 @@ function W(f) {
|
|
|
173
174
|
error: "Query parameter is required",
|
|
174
175
|
valid: !1
|
|
175
176
|
});
|
|
176
|
-
const o = JSON.parse(e),
|
|
177
|
-
t.json(
|
|
177
|
+
const o = JSON.parse(e), n = await y(r, t), a = await M(o, n, i);
|
|
178
|
+
t.json(a);
|
|
178
179
|
} catch (e) {
|
|
179
180
|
console.error("Dry-run error:", e), t.status(400).json({
|
|
180
181
|
error: e instanceof Error ? e.message : "Dry-run validation failed",
|
|
181
182
|
valid: !1
|
|
182
183
|
});
|
|
183
184
|
}
|
|
184
|
-
}),
|
|
185
|
+
}), c.post(`${p}/explain`, async (r, t) => {
|
|
185
186
|
try {
|
|
186
|
-
const e = r.body.query || r.body, o = r.body.options || {},
|
|
187
|
-
if (!
|
|
187
|
+
const e = r.body.query || r.body, o = r.body.options || {}, n = await y(r, t), a = i.validateQuery(e);
|
|
188
|
+
if (!a.isValid)
|
|
188
189
|
return t.status(400).json({
|
|
189
|
-
error: `Query validation failed: ${
|
|
190
|
+
error: `Query validation failed: ${a.errors.join(", ")}`
|
|
190
191
|
});
|
|
191
|
-
const
|
|
192
|
-
t.json(
|
|
192
|
+
const s = await i.explainQuery(e, n, o);
|
|
193
|
+
t.json(s);
|
|
193
194
|
} catch (e) {
|
|
194
195
|
console.error("Explain error:", e), t.status(500).json({
|
|
195
196
|
error: e instanceof Error ? e.message : "Explain query failed"
|
|
196
197
|
});
|
|
197
198
|
}
|
|
198
|
-
}),
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
199
|
+
}), j && c.post(`${p}/agent/chat`, async (r, t) => {
|
|
200
|
+
try {
|
|
201
|
+
const { handleAgentChat: e } = await import("../handler-DsNgnIPK.js"), { message: o, sessionId: n } = r.body;
|
|
202
|
+
if (!o || typeof o != "string")
|
|
203
|
+
return t.status(400).json({ error: "message is required and must be a string" });
|
|
204
|
+
let a = (j.apiKey || "").trim();
|
|
205
|
+
if (j.allowClientApiKey) {
|
|
206
|
+
const d = r.headers["x-agent-api-key"];
|
|
207
|
+
d && (a = d.trim());
|
|
208
|
+
}
|
|
209
|
+
if (!a)
|
|
210
|
+
return t.status(401).json({
|
|
211
|
+
error: "No API key configured. Set agent.apiKey in server config or send X-Agent-Api-Key header."
|
|
212
|
+
});
|
|
213
|
+
const s = await y(r, t);
|
|
214
|
+
t.writeHead(200, {
|
|
215
|
+
"Content-Type": "text/event-stream",
|
|
216
|
+
"Cache-Control": "no-cache",
|
|
217
|
+
Connection: "keep-alive"
|
|
218
|
+
});
|
|
219
|
+
try {
|
|
220
|
+
const d = e({
|
|
221
|
+
message: o,
|
|
222
|
+
sessionId: n,
|
|
223
|
+
semanticLayer: i,
|
|
224
|
+
securityContext: s,
|
|
225
|
+
agentConfig: j,
|
|
226
|
+
apiKey: a
|
|
227
|
+
});
|
|
228
|
+
for await (const m of d)
|
|
229
|
+
t.write(`data: ${JSON.stringify(m)}
|
|
230
|
+
|
|
231
|
+
`);
|
|
232
|
+
} catch (d) {
|
|
233
|
+
const m = {
|
|
234
|
+
type: "error",
|
|
235
|
+
data: { message: d instanceof Error ? d.message : "Stream failed" }
|
|
236
|
+
};
|
|
237
|
+
t.write(`data: ${JSON.stringify(m)}
|
|
238
|
+
|
|
239
|
+
`);
|
|
240
|
+
} finally {
|
|
241
|
+
t.end();
|
|
242
|
+
}
|
|
243
|
+
} catch (e) {
|
|
244
|
+
console.error("Agent chat error:", e), t.headersSent || t.status(500).json({
|
|
245
|
+
error: e instanceof Error ? e.message : "Agent chat failed"
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
}), g.enabled !== !1) {
|
|
249
|
+
const r = g.basePath ?? "/mcp";
|
|
250
|
+
c.post(`${r}`, async (t, e) => {
|
|
251
|
+
const o = _(
|
|
202
252
|
t.headers.origin,
|
|
203
|
-
|
|
253
|
+
g.allowedOrigins ? { allowedOrigins: g.allowedOrigins } : {}
|
|
204
254
|
);
|
|
205
255
|
if (!o.valid)
|
|
206
|
-
return e.status(403).json(
|
|
207
|
-
const
|
|
208
|
-
if (!
|
|
209
|
-
return e.status(400).json(
|
|
210
|
-
const
|
|
211
|
-
if (!
|
|
256
|
+
return e.status(403).json(w(null, -32600, o.reason));
|
|
257
|
+
const n = t.headers.accept;
|
|
258
|
+
if (!K(n))
|
|
259
|
+
return e.status(400).json(w(null, -32600, "Accept header must include both application/json and text/event-stream"));
|
|
260
|
+
const a = V(t.headers);
|
|
261
|
+
if (!a.ok)
|
|
212
262
|
return e.status(426).json({
|
|
213
263
|
error: "Unsupported MCP protocol version",
|
|
214
|
-
supported:
|
|
264
|
+
supported: a.supported
|
|
215
265
|
});
|
|
216
|
-
const
|
|
217
|
-
if (!
|
|
218
|
-
return e.status(400).json(
|
|
219
|
-
const
|
|
266
|
+
const s = z(t.body);
|
|
267
|
+
if (!s)
|
|
268
|
+
return e.status(400).json(w(null, -32600, "Invalid JSON-RPC 2.0 request"));
|
|
269
|
+
const d = T(n), m = s.method === "initialize";
|
|
220
270
|
try {
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
|
|
271
|
+
const l = await B(
|
|
272
|
+
s.method,
|
|
273
|
+
s.params,
|
|
224
274
|
{
|
|
225
275
|
semanticLayer: i,
|
|
226
|
-
extractSecurityContext:
|
|
276
|
+
extractSecurityContext: y,
|
|
227
277
|
rawRequest: t,
|
|
228
278
|
rawResponse: e,
|
|
229
|
-
negotiatedProtocol:
|
|
279
|
+
negotiatedProtocol: a.negotiated
|
|
230
280
|
}
|
|
231
281
|
);
|
|
232
|
-
if (
|
|
282
|
+
if (P(s))
|
|
233
283
|
return e.status(202).end();
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
const
|
|
237
|
-
if (
|
|
238
|
-
const b =
|
|
284
|
+
const v = m && l && typeof l == "object" && "sessionId" in l ? l.sessionId : void 0;
|
|
285
|
+
v && e.setHeader(F, v);
|
|
286
|
+
const C = U(s.id ?? null, l);
|
|
287
|
+
if (d) {
|
|
288
|
+
const b = S();
|
|
239
289
|
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}
|
|
240
290
|
|
|
241
|
-
`), e.write(Q(
|
|
291
|
+
`), e.write(Q(C, b)), e.end();
|
|
242
292
|
}
|
|
243
|
-
return e.json(
|
|
244
|
-
} catch (
|
|
245
|
-
if (
|
|
246
|
-
return console.error("MCP notification processing error:",
|
|
247
|
-
console.error("MCP RPC error:",
|
|
248
|
-
const
|
|
249
|
-
if (
|
|
250
|
-
const
|
|
251
|
-
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: ${
|
|
293
|
+
return e.json(C);
|
|
294
|
+
} catch (l) {
|
|
295
|
+
if (P(s))
|
|
296
|
+
return console.error("MCP notification processing error:", l), e.status(202).end();
|
|
297
|
+
console.error("MCP RPC error:", l);
|
|
298
|
+
const v = l?.code ?? -32603, C = l?.data, b = l.message || "MCP request failed", q = w(s.id ?? null, v, b, C);
|
|
299
|
+
if (d) {
|
|
300
|
+
const I = S();
|
|
301
|
+
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: ${I}
|
|
252
302
|
|
|
253
|
-
`), e.write(Q(q,
|
|
303
|
+
`), e.write(Q(q, I)), e.end();
|
|
254
304
|
}
|
|
255
305
|
return e.status(200).json(q);
|
|
256
306
|
}
|
|
257
|
-
}),
|
|
258
|
-
const o =
|
|
307
|
+
}), c.get(`${r}`, async (t, e) => {
|
|
308
|
+
const o = S();
|
|
259
309
|
e.status(200), e.setHeader("Content-Type", "text/event-stream"), e.setHeader("Cache-Control", "no-cache"), e.setHeader("Connection", "keep-alive"), e.write(Q({
|
|
260
310
|
jsonrpc: "2.0",
|
|
261
311
|
method: "mcp/ready",
|
|
262
312
|
params: { protocol: "streamable-http" }
|
|
263
313
|
}, o, 15e3));
|
|
264
|
-
const
|
|
314
|
+
const n = setInterval(() => {
|
|
265
315
|
e.write(`: keep-alive
|
|
266
316
|
|
|
267
317
|
`);
|
|
268
318
|
}, 15e3);
|
|
269
319
|
t.on("close", () => {
|
|
270
|
-
clearInterval(
|
|
320
|
+
clearInterval(n);
|
|
271
321
|
});
|
|
272
|
-
}),
|
|
322
|
+
}), c.delete(`${r}`, (t, e) => e.status(405).json({ error: "Session termination not supported" }));
|
|
273
323
|
}
|
|
274
|
-
return
|
|
275
|
-
console.error("Express adapter error:", r), e.headersSent || e.status(500).json(
|
|
276
|
-
}),
|
|
324
|
+
return c.use((r, t, e, o) => {
|
|
325
|
+
console.error("Express adapter error:", r), e.headersSent || e.status(500).json(u(r, 500));
|
|
326
|
+
}), c;
|
|
277
327
|
}
|
|
278
|
-
function
|
|
279
|
-
const
|
|
280
|
-
return
|
|
328
|
+
function Y(h, f) {
|
|
329
|
+
const x = W(f);
|
|
330
|
+
return h.use("/", x), h;
|
|
281
331
|
}
|
|
282
|
-
function
|
|
283
|
-
const
|
|
284
|
-
return
|
|
332
|
+
function oe(h) {
|
|
333
|
+
const f = E();
|
|
334
|
+
return Y(f, h);
|
|
285
335
|
}
|
|
286
336
|
export {
|
|
287
|
-
|
|
337
|
+
oe as createCubeApp,
|
|
288
338
|
W as createCubeRouter,
|
|
289
|
-
|
|
339
|
+
Y as mountCubeRoutes
|
|
290
340
|
};
|