drizzle-cube 0.4.7 → 0.4.9
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 +1 -1
- package/dist/adapters/express/index.js +2 -2
- package/dist/adapters/fastify/index.cjs +1 -1
- package/dist/adapters/fastify/index.js +2 -2
- package/dist/adapters/handler-CSHsefnC.js +1965 -0
- package/dist/adapters/handler-Xe_2ItOo.cjs +23 -0
- package/dist/adapters/hono/index.cjs +1 -1
- package/dist/adapters/hono/index.js +2 -2
- package/dist/adapters/{mcp-transport-DFTCWene.js → mcp-transport-CU5g9bxj.js} +3 -3
- package/dist/adapters/{mcp-transport-BB998cy5.cjs → mcp-transport-KX92EgkF.cjs} +2 -2
- package/dist/adapters/nextjs/index.cjs +2 -2
- package/dist/adapters/nextjs/index.js +3 -3
- package/dist/client/charts/chartConfigs.d.ts +2 -9
- package/dist/client/charts.js +72 -70
- package/dist/client/charts.js.map +1 -1
- package/dist/client/chunks/{RetentionCombinedChart.config-C-ILIaEb.js → RetentionCombinedChart.config-Bbp2ghim.js} +2 -1
- package/dist/client/chunks/RetentionCombinedChart.config-Bbp2ghim.js.map +1 -0
- package/dist/client/chunks/{RetentionHeatmap.config-CIvhc-GT.js → RetentionHeatmap.config-BWf_-vdj.js} +2 -1
- package/dist/client/chunks/RetentionHeatmap.config-BWf_-vdj.js.map +1 -0
- package/dist/client/chunks/{analysis-builder-Dn8xpgPQ.js → analysis-builder-DFt9p8tj.js} +1426 -1411
- package/dist/client/chunks/analysis-builder-DFt9p8tj.js.map +1 -0
- package/dist/client/chunks/{analysis-builder-shared-D3xYzXlh.js → analysis-builder-shared-DOHV2W8A.js} +713 -787
- package/dist/client/chunks/analysis-builder-shared-DOHV2W8A.js.map +1 -0
- package/dist/client/chunks/{chart-activity-grid-DStNr34n.js → chart-activity-grid-CE7xGFQo.js} +2 -2
- package/dist/client/chunks/{chart-activity-grid-DStNr34n.js.map → chart-activity-grid-CE7xGFQo.js.map} +1 -1
- package/dist/client/chunks/chart-box-plot-Dja4LS3O.js +313 -0
- package/dist/client/chunks/chart-box-plot-Dja4LS3O.js.map +1 -0
- package/dist/client/chunks/{chart-config-activity-grid-CAlo1cHA.js → chart-config-activity-grid-CmOqDuOT.js} +4 -5
- package/dist/client/chunks/chart-config-activity-grid-CmOqDuOT.js.map +1 -0
- package/dist/client/chunks/{chart-config-area-CyyJOO2T.js → chart-config-area-CK_GVApT.js} +4 -5
- package/dist/client/chunks/chart-config-area-CK_GVApT.js.map +1 -0
- package/dist/client/chunks/{chart-config-bar-soxw6m2o.js → chart-config-bar-C8uzktxl.js} +4 -5
- package/dist/client/chunks/chart-config-bar-C8uzktxl.js.map +1 -0
- package/dist/client/chunks/chart-config-box-plot-D3DA7_pr.js +85 -0
- package/dist/client/chunks/chart-config-box-plot-D3DA7_pr.js.map +1 -0
- package/dist/client/chunks/{chart-config-bubble-CuSsCHZ4.js → chart-config-bubble-q3DoQX5F.js} +4 -5
- package/dist/client/chunks/chart-config-bubble-q3DoQX5F.js.map +1 -0
- package/dist/client/chunks/{chart-config-data-table-BhgqwoqT.js → chart-config-data-table-B20Y5JCm.js} +4 -5
- package/dist/client/chunks/chart-config-data-table-B20Y5JCm.js.map +1 -0
- package/dist/client/chunks/{chart-config-funnel-BlSQYng0.js → chart-config-funnel-3eYnGg8M.js} +4 -5
- package/dist/client/chunks/chart-config-funnel-3eYnGg8M.js.map +1 -0
- package/dist/client/chunks/{chart-config-heat-map-DHQGFZhX.js → chart-config-heat-map-_wEnTnRA.js} +4 -5
- package/dist/client/chunks/chart-config-heat-map-_wEnTnRA.js.map +1 -0
- package/dist/client/chunks/{chart-config-kpi-delta-yTA5ug_l.js → chart-config-kpi-delta-DLGZ2A3X.js} +4 -5
- package/dist/client/chunks/chart-config-kpi-delta-DLGZ2A3X.js.map +1 -0
- package/dist/client/chunks/{chart-config-kpi-number-nVAwDXzq.js → chart-config-kpi-number-K-wzviXF.js} +4 -5
- package/dist/client/chunks/chart-config-kpi-number-K-wzviXF.js.map +1 -0
- package/dist/client/chunks/{chart-config-kpi-text-DZjqsx-b.js → chart-config-kpi-text-BjYqwqaJ.js} +4 -5
- package/dist/client/chunks/chart-config-kpi-text-BjYqwqaJ.js.map +1 -0
- package/dist/client/chunks/{chart-config-line-D5ME6w0v.js → chart-config-line-JNagi9tf.js} +4 -5
- package/dist/client/chunks/chart-config-line-JNagi9tf.js.map +1 -0
- package/dist/client/chunks/{chart-config-markdown-BXKL5TbQ.js → chart-config-markdown-BWQSjJpy.js} +4 -5
- package/dist/client/chunks/chart-config-markdown-BWQSjJpy.js.map +1 -0
- package/dist/client/chunks/{chart-config-pie-DlHa2jTy.js → chart-config-pie-CNLXb-fr.js} +4 -5
- package/dist/client/chunks/chart-config-pie-CNLXb-fr.js.map +1 -0
- package/dist/client/chunks/{chart-config-radar-BBAVIF0S.js → chart-config-radar-oxHfRAa3.js} +4 -5
- package/dist/client/chunks/chart-config-radar-oxHfRAa3.js.map +1 -0
- package/dist/client/chunks/{chart-config-radial-bar-CTwjDRnB.js → chart-config-radial-bar-_Aw3jAEm.js} +4 -5
- package/dist/client/chunks/chart-config-radial-bar-_Aw3jAEm.js.map +1 -0
- package/dist/client/chunks/{chart-config-sankey-CNAgsMQ4.js → chart-config-sankey-C8FX9hGF.js} +4 -5
- package/dist/client/chunks/chart-config-sankey-C8FX9hGF.js.map +1 -0
- package/dist/client/chunks/{chart-config-scatter-CWvN2E-X.js → chart-config-scatter-DFKM80eO.js} +4 -5
- package/dist/client/chunks/chart-config-scatter-DFKM80eO.js.map +1 -0
- package/dist/client/chunks/{chart-config-sunburst-W_SKwaj0.js → chart-config-sunburst-BmC0NLTU.js} +4 -5
- package/dist/client/chunks/chart-config-sunburst-BmC0NLTU.js.map +1 -0
- package/dist/client/chunks/{chart-config-tree-map-IRAYf9YM.js → chart-config-tree-map-DGMbNTaa.js} +4 -5
- package/dist/client/chunks/chart-config-tree-map-DGMbNTaa.js.map +1 -0
- package/dist/client/chunks/{chart-data-table-Ch_1c1Zo.js → chart-data-table-Ba_6tuJw.js} +2 -2
- package/dist/client/chunks/{chart-data-table-Ch_1c1Zo.js.map → chart-data-table-Ba_6tuJw.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-delta-CWCmi8vL.js → chart-kpi-delta-D9XJoKuA.js} +3 -3
- package/dist/client/chunks/{chart-kpi-delta-CWCmi8vL.js.map → chart-kpi-delta-D9XJoKuA.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-number-C-5m3qt5.js → chart-kpi-number-C29Vj2g8.js} +2 -2
- package/dist/client/chunks/{chart-kpi-number-C-5m3qt5.js.map → chart-kpi-number-C29Vj2g8.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-text--t4ibPmx.js → chart-kpi-text-CgjjrurK.js} +2 -2
- package/dist/client/chunks/{chart-kpi-text--t4ibPmx.js.map → chart-kpi-text-CgjjrurK.js.map} +1 -1
- package/dist/client/chunks/{charts-loader-DcFWOUeV.js → charts-loader-HYQFVOo4.js} +13 -12
- package/dist/client/chunks/charts-loader-HYQFVOo4.js.map +1 -0
- package/dist/client/chunks/{components-Bdt1AmzS.js → components-8FAXo62Z.js} +1496 -1417
- package/dist/client/chunks/components-8FAXo62Z.js.map +1 -0
- package/dist/client/chunks/{icons-DRreo6m8.js → icons-DAeqv1iX.js} +7 -7
- package/dist/client/chunks/{icons-DRreo6m8.js.map → icons-DAeqv1iX.js.map} +1 -1
- package/dist/client/components/AgenticNotebook/NotebookPortletBlock.d.ts +1 -0
- package/dist/client/components/charts/BoxPlotChart.config.d.ts +11 -0
- package/dist/client/components/charts/BoxPlotChart.d.ts +4 -0
- package/dist/client/components/charts/index.d.ts +1 -0
- package/dist/client/components.js +8 -8
- package/dist/client/icons.js +1 -1
- package/dist/client/index.js +655 -584
- package/dist/client/index.js.map +1 -1
- package/dist/client/stores/notebookStore.d.ts +2 -0
- package/dist/client/styles.css +1 -1
- package/dist/client/types.d.ts +1 -1
- package/dist/client/utils.js +3 -3
- package/dist/client-bundle-stats.html +4 -4
- package/dist/server/index.cjs +118 -102
- package/dist/server/index.js +6584 -5077
- package/package.json +6 -6
- package/dist/adapters/handler-D6l8AbJV.cjs +0 -7
- package/dist/adapters/handler-DsNgnIPK.js +0 -458
- package/dist/client/chunks/RetentionCombinedChart.config-C-ILIaEb.js.map +0 -1
- package/dist/client/chunks/RetentionHeatmap.config-CIvhc-GT.js.map +0 -1
- package/dist/client/chunks/analysis-builder-Dn8xpgPQ.js.map +0 -1
- package/dist/client/chunks/analysis-builder-shared-D3xYzXlh.js.map +0 -1
- package/dist/client/chunks/chart-config-activity-grid-CAlo1cHA.js.map +0 -1
- package/dist/client/chunks/chart-config-area-CyyJOO2T.js.map +0 -1
- package/dist/client/chunks/chart-config-bar-soxw6m2o.js.map +0 -1
- package/dist/client/chunks/chart-config-bubble-CuSsCHZ4.js.map +0 -1
- package/dist/client/chunks/chart-config-data-table-BhgqwoqT.js.map +0 -1
- package/dist/client/chunks/chart-config-funnel-BlSQYng0.js.map +0 -1
- package/dist/client/chunks/chart-config-heat-map-DHQGFZhX.js.map +0 -1
- package/dist/client/chunks/chart-config-kpi-delta-yTA5ug_l.js.map +0 -1
- package/dist/client/chunks/chart-config-kpi-number-nVAwDXzq.js.map +0 -1
- package/dist/client/chunks/chart-config-kpi-text-DZjqsx-b.js.map +0 -1
- package/dist/client/chunks/chart-config-line-D5ME6w0v.js.map +0 -1
- package/dist/client/chunks/chart-config-markdown-BXKL5TbQ.js.map +0 -1
- package/dist/client/chunks/chart-config-pie-DlHa2jTy.js.map +0 -1
- package/dist/client/chunks/chart-config-radar-BBAVIF0S.js.map +0 -1
- package/dist/client/chunks/chart-config-radial-bar-CTwjDRnB.js.map +0 -1
- package/dist/client/chunks/chart-config-sankey-CNAgsMQ4.js.map +0 -1
- package/dist/client/chunks/chart-config-scatter-CWvN2E-X.js.map +0 -1
- package/dist/client/chunks/chart-config-sunburst-W_SKwaj0.js.map +0 -1
- package/dist/client/chunks/chart-config-tree-map-IRAYf9YM.js.map +0 -1
- package/dist/client/chunks/chartConfigRegistry-C5dZm-ZK.js +0 -44
- package/dist/client/chunks/chartConfigRegistry-C5dZm-ZK.js.map +0 -1
- package/dist/client/chunks/charts-loader-DcFWOUeV.js.map +0 -1
- package/dist/client/chunks/components-Bdt1AmzS.js.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("next/server"),f=require("../mcp-transport-BB998cy5.cjs"),i=require("../utils.cjs");function g(n){const{cubes:o,drizzle:s,schema:c,engineType:d,cache:a}=n;if(!o||o.length===0)throw new Error("At least one cube must be provided in the cubes array");const t=new f.SemanticLayerCompiler({drizzle:s,schema:c,engineType:d,cache:a});return o.forEach(e=>{t.registerCube(e)}),t}function R(n,o){const s=n.headers.get("origin"),c={};return o.origin&&(typeof o.origin=="string"?c["Access-Control-Allow-Origin"]=o.origin:Array.isArray(o.origin)?s&&o.origin.includes(s)&&(c["Access-Control-Allow-Origin"]=s):typeof o.origin=="function"&&s&&o.origin(s)&&(c["Access-Control-Allow-Origin"]=s)),o.methods&&(c["Access-Control-Allow-Methods"]=o.methods.join(", ")),o.allowedHeaders&&(c["Access-Control-Allow-Headers"]=o.allowedHeaders.join(", ")),o.credentials&&(c["Access-Control-Allow-Credentials"]="true"),c}function J(n){return async function(s){const c=R(s,n);return new Response(null,{status:200,headers:c})}}function T(n){const{extractSecurityContext:o,cors:s}=n,c=g(n);return async function(a,t){try{let e;if(a.method==="POST"){const j=await a.json();e=j.query||j}else if(a.method==="GET"){const j=a.nextUrl.searchParams.get("query");if(!j)return r.NextResponse.json(i.formatErrorResponse("Query parameter is required",400),{status:400});try{e=JSON.parse(j)}catch{return r.NextResponse.json(i.formatErrorResponse("Invalid JSON in query parameter",400),{status:400})}}else return r.NextResponse.json(i.formatErrorResponse("Method not allowed",405),{status:405});const l=await o(a,t),y=c.validateQuery(e);if(!y.isValid)return r.NextResponse.json(i.formatErrorResponse(`Query validation failed: ${y.errors.join(", ")}`,400),{status:400});const u=a.headers.get("x-cache-control")==="no-cache",p=await c.executeMultiCubeQuery(e,l,{skipCache:u}),E=i.formatCubeResponse(e,p,c);return r.NextResponse.json(E,{headers:s?R(a,s):{}})}catch(e){return process.env.NODE_ENV!=="test"&&console.error("Next.js load handler error:",e),r.NextResponse.json(i.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500),{status:500})}}}function M(n){const{cors:o}=n,s=g(n);return async function(d,a){try{const t=s.getMetadata(),e=i.formatMetaResponse(t);return r.NextResponse.json(e,{headers:o?R(d,o):{}})}catch(t){return process.env.NODE_ENV!=="test"&&console.error("Next.js meta handler error:",t),r.NextResponse.json(i.formatErrorResponse(t instanceof Error?t.message:"Failed to fetch metadata",500),{status:500})}}}function A(n){const{extractSecurityContext:o,cors:s}=n,c=g(n);return async function(a,t){try{let e;if(a.method==="POST"){const w=await a.json();e=w.query||w}else if(a.method==="GET"){const w=a.nextUrl.searchParams.get("query");if(!w)return r.NextResponse.json(i.formatErrorResponse("Query parameter is required",400),{status:400});try{e=JSON.parse(w)}catch{return r.NextResponse.json(i.formatErrorResponse("Invalid JSON in query parameter",400),{status:400})}}else return r.NextResponse.json(i.formatErrorResponse("Method not allowed",405),{status:405});const l=await o(a,t),y=c.validateQuery(e);if(!y.isValid)return r.NextResponse.json(i.formatErrorResponse(`Query validation failed: ${y.errors.join(", ")}`,400),{status:400});const u=e.measures?.[0]||e.dimensions?.[0];if(!u)return r.NextResponse.json(i.formatErrorResponse("No measures or dimensions specified",400),{status:400});const p=u.split(".")[0],E=await c.generateSQL(p,e,l),j=i.formatSqlResponse(e,E);return r.NextResponse.json(j,{headers:s?R(a,s):{}})}catch(e){return process.env.NODE_ENV!=="test"&&console.error("Next.js SQL handler error:",e),r.NextResponse.json(i.formatErrorResponse(e instanceof Error?e.message:"SQL generation failed",500),{status:500})}}}function L(n){const{extractSecurityContext:o,cors:s}=n,c=g(n);return async function(a,t){try{let e;if(a.method==="POST"){const u=await a.json();e=u.query||u}else if(a.method==="GET"){const u=a.nextUrl.searchParams.get("query");if(!u)return r.NextResponse.json({error:"Query parameter is required",valid:!1},{status:400});try{e=JSON.parse(u)}catch{return r.NextResponse.json({error:"Invalid JSON in query parameter",valid:!1},{status:400})}}else return r.NextResponse.json({error:"Method not allowed",valid:!1},{status:405});const l=await o(a,t),y=await i.handleDryRun(e,l,c);return r.NextResponse.json(y,{headers:s?R(a,s):{}})}catch(e){return process.env.NODE_ENV!=="test"&&console.error("Next.js dry-run handler error:",e),r.NextResponse.json({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1},{status:400})}}}function D(n){const{extractSecurityContext:o,cors:s}=n,c=g(n);return async function(a,t){try{if(a.method!=="POST")return r.NextResponse.json(i.formatErrorResponse("Method not allowed - use POST",405),{status:405});const e=await a.json(),{queries:l}=e;if(!l||!Array.isArray(l))return r.NextResponse.json(i.formatErrorResponse('Request body must contain a "queries" array',400),{status:400});if(l.length===0)return r.NextResponse.json(i.formatErrorResponse("Queries array cannot be empty",400),{status:400});const y=await o(a,t),u=a.headers.get("x-cache-control")==="no-cache",p=await i.handleBatchRequest(l,y,c,{skipCache:u});return r.NextResponse.json(p,{headers:s?R(a,s):{}})}catch(e){return process.env.NODE_ENV!=="test"&&console.error("Next.js batch handler error:",e),r.NextResponse.json(i.formatErrorResponse(e instanceof Error?e.message:"Batch execution failed",500),{status:500})}}}function V(n){const{extractSecurityContext:o,cors:s}=n,c=g(n);return async function(a,t){try{if(a.method!=="POST")return r.NextResponse.json({error:"Method not allowed"},{status:405});const e=await a.json(),l=e.query||e,y=e.options||{},u=await o(a,t),p=c.validateQuery(l);if(!p.isValid)return r.NextResponse.json({error:`Query validation failed: ${p.errors.join(", ")}`},{status:400});const E=await c.explainQuery(l,u,y);return r.NextResponse.json(E,{headers:s?R(a,s):{}})}catch(e){return process.env.NODE_ENV!=="test"&&console.error("Next.js explain handler error:",e),r.NextResponse.json({error:e instanceof Error?e.message:"Explain query failed"},{status:500})}}}function k(n){const{cors:o}=n,s=g(n);return async function(d,a){try{if(d.method!=="POST")return r.NextResponse.json(i.formatErrorResponse("Method not allowed - use POST",405),{status:405});const t=await d.json(),e=await i.handleDiscover(s,t);return r.NextResponse.json(e,{headers:o?R(d,o):{}})}catch(t){return process.env.NODE_ENV!=="test"&&console.error("Next.js discover handler error:",t),r.NextResponse.json(i.formatErrorResponse(t instanceof Error?t.message:"Discovery failed",500),{status:500})}}}function q(n){const{cors:o}=n,s=g(n);return async function(d,a){try{if(d.method!=="POST")return r.NextResponse.json(i.formatErrorResponse("Method not allowed - use POST",405),{status:405});const t=await d.json();if(!t.naturalLanguage)return r.NextResponse.json(i.formatErrorResponse("naturalLanguage field is required",400),{status:400});const e=await i.handleSuggest(s,t);return r.NextResponse.json(e,{headers:o?R(d,o):{}})}catch(t){return process.env.NODE_ENV!=="test"&&console.error("Next.js suggest handler error:",t),r.NextResponse.json(i.formatErrorResponse(t instanceof Error?t.message:"Query suggestion failed",500),{status:500})}}}function z(n){const{cors:o}=n,s=g(n);return async function(d,a){try{if(d.method!=="POST")return r.NextResponse.json(i.formatErrorResponse("Method not allowed - use POST",405),{status:405});const t=await d.json();if(!t.query)return r.NextResponse.json(i.formatErrorResponse("query field is required",400),{status:400});const e=await i.handleValidate(s,t);return r.NextResponse.json(e,{headers:o?R(d,o):{}})}catch(t){return process.env.NODE_ENV!=="test"&&console.error("Next.js validate handler error:",t),r.NextResponse.json(i.formatErrorResponse(t instanceof Error?t.message:"Query validation failed",500),{status:500})}}}function $(n){const{extractSecurityContext:o,cors:s}=n,c=g(n);return async function(a,t){try{if(a.method!=="POST")return r.NextResponse.json(i.formatErrorResponse("Method not allowed - use POST",405),{status:405});const e=await a.json();if(!e.query)return r.NextResponse.json(i.formatErrorResponse("query field is required",400),{status:400});const l=await o(a,t),y=await i.handleLoad(c,l,e);return r.NextResponse.json(y,{headers:s?R(a,s):{}})}catch(e){return process.env.NODE_ENV!=="test"&&console.error("Next.js MCP load handler error:",e),r.NextResponse.json(i.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500),{status:500})}}}function _(n){const{extractSecurityContext:o,cors:s,mcp:c={enabled:!0}}=n,d=g(n);return async function(t){if(t.method==="DELETE")return r.NextResponse.json({error:"Session termination not supported"},{status:405});if(t.method==="GET"){const h=new TextEncoder,v=f.primeEventId(),m=new ReadableStream({start(x){x.enqueue(h.encode(f.serializeSseEvent({jsonrpc:"2.0",method:"mcp/ready",params:{protocol:"streamable-http"}},v,15e3)))}}),N=new Headers({"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});if(s){const x=R(t,s);Object.entries(x).forEach(([C,b])=>N.set(C,b))}return new r.NextResponse(m,{status:200,headers:N})}if(t.method!=="POST")return r.NextResponse.json(i.formatErrorResponse("Method not allowed - use POST",405),{status:405});const e=f.validateOriginHeader(t.headers.get("origin"),c.allowedOrigins?{allowedOrigins:c.allowedOrigins}:{});if(!e.valid)return r.NextResponse.json(f.buildJsonRpcError(null,-32600,e.reason),{status:403});const l=t.headers.get("accept");if(!f.validateAcceptHeader(l))return r.NextResponse.json(f.buildJsonRpcError(null,-32600,"Accept header must include both application/json and text/event-stream"),{status:400});const y=f.negotiateProtocol(Object.fromEntries(t.headers.entries()));if(!y.ok)return r.NextResponse.json({error:"Unsupported MCP protocol version",supported:y.supported},{status:426});let u=null;try{u=await t.json()}catch{u=null}const p=f.parseJsonRpc(u);if(!p)return r.NextResponse.json(f.buildJsonRpcError(null,-32600,"Invalid JSON-RPC 2.0 request"),{status:400});const E=f.wantsEventStream(l),j=p.method==="initialize",w=(h,v=200,m={})=>r.NextResponse.json(h,{status:v,headers:{...s?R(t,s):{},...m}});try{const h=await f.dispatchMcpMethod(p.method,p.params,{semanticLayer:d,extractSecurityContext:x=>o(x),rawRequest:t,rawResponse:null});if(f.isNotification(p))return new r.NextResponse(null,{status:202});const v=j&&h&&typeof h=="object"&&"sessionId"in h?h.sessionId:void 0,m={};v&&(m[f.MCP_SESSION_ID_HEADER]=v);const N=f.buildJsonRpcResult(p.id??null,h);if(E){const x=new TextEncoder,C=f.primeEventId(),b=new ReadableStream({start(S){S.enqueue(x.encode(`id: ${C}
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("next/server"),f=require("../mcp-transport-KX92EgkF.cjs"),i=require("../utils.cjs");function g(n){const{cubes:o,drizzle:s,schema:c,engineType:d,cache:a}=n;if(!o||o.length===0)throw new Error("At least one cube must be provided in the cubes array");const t=new f.SemanticLayerCompiler({drizzle:s,schema:c,engineType:d,cache:a});return o.forEach(e=>{t.registerCube(e)}),t}function R(n,o){const s=n.headers.get("origin"),c={};return o.origin&&(typeof o.origin=="string"?c["Access-Control-Allow-Origin"]=o.origin:Array.isArray(o.origin)?s&&o.origin.includes(s)&&(c["Access-Control-Allow-Origin"]=s):typeof o.origin=="function"&&s&&o.origin(s)&&(c["Access-Control-Allow-Origin"]=s)),o.methods&&(c["Access-Control-Allow-Methods"]=o.methods.join(", ")),o.allowedHeaders&&(c["Access-Control-Allow-Headers"]=o.allowedHeaders.join(", ")),o.credentials&&(c["Access-Control-Allow-Credentials"]="true"),c}function J(n){return async function(s){const c=R(s,n);return new Response(null,{status:200,headers:c})}}function T(n){const{extractSecurityContext:o,cors:s}=n,c=g(n);return async function(a,t){try{let e;if(a.method==="POST"){const j=await a.json();e=j.query||j}else if(a.method==="GET"){const j=a.nextUrl.searchParams.get("query");if(!j)return r.NextResponse.json(i.formatErrorResponse("Query parameter is required",400),{status:400});try{e=JSON.parse(j)}catch{return r.NextResponse.json(i.formatErrorResponse("Invalid JSON in query parameter",400),{status:400})}}else return r.NextResponse.json(i.formatErrorResponse("Method not allowed",405),{status:405});const l=await o(a,t),y=c.validateQuery(e);if(!y.isValid)return r.NextResponse.json(i.formatErrorResponse(`Query validation failed: ${y.errors.join(", ")}`,400),{status:400});const u=a.headers.get("x-cache-control")==="no-cache",p=await c.executeMultiCubeQuery(e,l,{skipCache:u}),E=i.formatCubeResponse(e,p,c);return r.NextResponse.json(E,{headers:s?R(a,s):{}})}catch(e){return process.env.NODE_ENV!=="test"&&console.error("Next.js load handler error:",e),r.NextResponse.json(i.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500),{status:500})}}}function M(n){const{cors:o}=n,s=g(n);return async function(d,a){try{const t=s.getMetadata(),e=i.formatMetaResponse(t);return r.NextResponse.json(e,{headers:o?R(d,o):{}})}catch(t){return process.env.NODE_ENV!=="test"&&console.error("Next.js meta handler error:",t),r.NextResponse.json(i.formatErrorResponse(t instanceof Error?t.message:"Failed to fetch metadata",500),{status:500})}}}function A(n){const{extractSecurityContext:o,cors:s}=n,c=g(n);return async function(a,t){try{let e;if(a.method==="POST"){const w=await a.json();e=w.query||w}else if(a.method==="GET"){const w=a.nextUrl.searchParams.get("query");if(!w)return r.NextResponse.json(i.formatErrorResponse("Query parameter is required",400),{status:400});try{e=JSON.parse(w)}catch{return r.NextResponse.json(i.formatErrorResponse("Invalid JSON in query parameter",400),{status:400})}}else return r.NextResponse.json(i.formatErrorResponse("Method not allowed",405),{status:405});const l=await o(a,t),y=c.validateQuery(e);if(!y.isValid)return r.NextResponse.json(i.formatErrorResponse(`Query validation failed: ${y.errors.join(", ")}`,400),{status:400});const u=e.measures?.[0]||e.dimensions?.[0];if(!u)return r.NextResponse.json(i.formatErrorResponse("No measures or dimensions specified",400),{status:400});const p=u.split(".")[0],E=await c.generateSQL(p,e,l),j=i.formatSqlResponse(e,E);return r.NextResponse.json(j,{headers:s?R(a,s):{}})}catch(e){return process.env.NODE_ENV!=="test"&&console.error("Next.js SQL handler error:",e),r.NextResponse.json(i.formatErrorResponse(e instanceof Error?e.message:"SQL generation failed",500),{status:500})}}}function L(n){const{extractSecurityContext:o,cors:s}=n,c=g(n);return async function(a,t){try{let e;if(a.method==="POST"){const u=await a.json();e=u.query||u}else if(a.method==="GET"){const u=a.nextUrl.searchParams.get("query");if(!u)return r.NextResponse.json({error:"Query parameter is required",valid:!1},{status:400});try{e=JSON.parse(u)}catch{return r.NextResponse.json({error:"Invalid JSON in query parameter",valid:!1},{status:400})}}else return r.NextResponse.json({error:"Method not allowed",valid:!1},{status:405});const l=await o(a,t),y=await i.handleDryRun(e,l,c);return r.NextResponse.json(y,{headers:s?R(a,s):{}})}catch(e){return process.env.NODE_ENV!=="test"&&console.error("Next.js dry-run handler error:",e),r.NextResponse.json({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1},{status:400})}}}function D(n){const{extractSecurityContext:o,cors:s}=n,c=g(n);return async function(a,t){try{if(a.method!=="POST")return r.NextResponse.json(i.formatErrorResponse("Method not allowed - use POST",405),{status:405});const e=await a.json(),{queries:l}=e;if(!l||!Array.isArray(l))return r.NextResponse.json(i.formatErrorResponse('Request body must contain a "queries" array',400),{status:400});if(l.length===0)return r.NextResponse.json(i.formatErrorResponse("Queries array cannot be empty",400),{status:400});const y=await o(a,t),u=a.headers.get("x-cache-control")==="no-cache",p=await i.handleBatchRequest(l,y,c,{skipCache:u});return r.NextResponse.json(p,{headers:s?R(a,s):{}})}catch(e){return process.env.NODE_ENV!=="test"&&console.error("Next.js batch handler error:",e),r.NextResponse.json(i.formatErrorResponse(e instanceof Error?e.message:"Batch execution failed",500),{status:500})}}}function V(n){const{extractSecurityContext:o,cors:s}=n,c=g(n);return async function(a,t){try{if(a.method!=="POST")return r.NextResponse.json({error:"Method not allowed"},{status:405});const e=await a.json(),l=e.query||e,y=e.options||{},u=await o(a,t),p=c.validateQuery(l);if(!p.isValid)return r.NextResponse.json({error:`Query validation failed: ${p.errors.join(", ")}`},{status:400});const E=await c.explainQuery(l,u,y);return r.NextResponse.json(E,{headers:s?R(a,s):{}})}catch(e){return process.env.NODE_ENV!=="test"&&console.error("Next.js explain handler error:",e),r.NextResponse.json({error:e instanceof Error?e.message:"Explain query failed"},{status:500})}}}function k(n){const{cors:o}=n,s=g(n);return async function(d,a){try{if(d.method!=="POST")return r.NextResponse.json(i.formatErrorResponse("Method not allowed - use POST",405),{status:405});const t=await d.json(),e=await i.handleDiscover(s,t);return r.NextResponse.json(e,{headers:o?R(d,o):{}})}catch(t){return process.env.NODE_ENV!=="test"&&console.error("Next.js discover handler error:",t),r.NextResponse.json(i.formatErrorResponse(t instanceof Error?t.message:"Discovery failed",500),{status:500})}}}function q(n){const{cors:o}=n,s=g(n);return async function(d,a){try{if(d.method!=="POST")return r.NextResponse.json(i.formatErrorResponse("Method not allowed - use POST",405),{status:405});const t=await d.json();if(!t.naturalLanguage)return r.NextResponse.json(i.formatErrorResponse("naturalLanguage field is required",400),{status:400});const e=await i.handleSuggest(s,t);return r.NextResponse.json(e,{headers:o?R(d,o):{}})}catch(t){return process.env.NODE_ENV!=="test"&&console.error("Next.js suggest handler error:",t),r.NextResponse.json(i.formatErrorResponse(t instanceof Error?t.message:"Query suggestion failed",500),{status:500})}}}function z(n){const{cors:o}=n,s=g(n);return async function(d,a){try{if(d.method!=="POST")return r.NextResponse.json(i.formatErrorResponse("Method not allowed - use POST",405),{status:405});const t=await d.json();if(!t.query)return r.NextResponse.json(i.formatErrorResponse("query field is required",400),{status:400});const e=await i.handleValidate(s,t);return r.NextResponse.json(e,{headers:o?R(d,o):{}})}catch(t){return process.env.NODE_ENV!=="test"&&console.error("Next.js validate handler error:",t),r.NextResponse.json(i.formatErrorResponse(t instanceof Error?t.message:"Query validation failed",500),{status:500})}}}function $(n){const{extractSecurityContext:o,cors:s}=n,c=g(n);return async function(a,t){try{if(a.method!=="POST")return r.NextResponse.json(i.formatErrorResponse("Method not allowed - use POST",405),{status:405});const e=await a.json();if(!e.query)return r.NextResponse.json(i.formatErrorResponse("query field is required",400),{status:400});const l=await o(a,t),y=await i.handleLoad(c,l,e);return r.NextResponse.json(y,{headers:s?R(a,s):{}})}catch(e){return process.env.NODE_ENV!=="test"&&console.error("Next.js MCP load handler error:",e),r.NextResponse.json(i.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500),{status:500})}}}function _(n){const{extractSecurityContext:o,cors:s,mcp:c={enabled:!0}}=n,d=g(n);return async function(t){if(t.method==="DELETE")return r.NextResponse.json({error:"Session termination not supported"},{status:405});if(t.method==="GET"){const h=new TextEncoder,v=f.primeEventId(),m=new ReadableStream({start(x){x.enqueue(h.encode(f.serializeSseEvent({jsonrpc:"2.0",method:"mcp/ready",params:{protocol:"streamable-http"}},v,15e3)))}}),N=new Headers({"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});if(s){const x=R(t,s);Object.entries(x).forEach(([C,b])=>N.set(C,b))}return new r.NextResponse(m,{status:200,headers:N})}if(t.method!=="POST")return r.NextResponse.json(i.formatErrorResponse("Method not allowed - use POST",405),{status:405});const e=f.validateOriginHeader(t.headers.get("origin"),c.allowedOrigins?{allowedOrigins:c.allowedOrigins}:{});if(!e.valid)return r.NextResponse.json(f.buildJsonRpcError(null,-32600,e.reason),{status:403});const l=t.headers.get("accept");if(!f.validateAcceptHeader(l))return r.NextResponse.json(f.buildJsonRpcError(null,-32600,"Accept header must include both application/json and text/event-stream"),{status:400});const y=f.negotiateProtocol(Object.fromEntries(t.headers.entries()));if(!y.ok)return r.NextResponse.json({error:"Unsupported MCP protocol version",supported:y.supported},{status:426});let u;try{u=await t.json()}catch{u=null}const p=f.parseJsonRpc(u);if(!p)return r.NextResponse.json(f.buildJsonRpcError(null,-32600,"Invalid JSON-RPC 2.0 request"),{status:400});const E=f.wantsEventStream(l),j=p.method==="initialize",w=(h,v=200,m={})=>r.NextResponse.json(h,{status:v,headers:{...s?R(t,s):{},...m}});try{const h=await f.dispatchMcpMethod(p.method,p.params,{semanticLayer:d,extractSecurityContext:x=>o(x),rawRequest:t,rawResponse:null});if(f.isNotification(p))return new r.NextResponse(null,{status:202});const v=j&&h&&typeof h=="object"&&"sessionId"in h?h.sessionId:void 0,m={};v&&(m[f.MCP_SESSION_ID_HEADER]=v);const N=f.buildJsonRpcResult(p.id??null,h);if(E){const x=new TextEncoder,C=f.primeEventId(),b=new ReadableStream({start(S){S.enqueue(x.encode(`id: ${C}
|
|
2
2
|
|
|
3
3
|
`)),S.enqueue(x.encode(f.serializeSseEvent(N,C))),S.close()}}),O=new Headers({"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive",...m});if(s){const S=R(t,s);Object.entries(S).forEach(([H,P])=>O.set(H,P))}return new r.NextResponse(b,{status:200,headers:O})}return w(N,200,m)}catch(h){if(f.isNotification(p))return process.env.NODE_ENV!=="test"&&console.error("Next.js MCP notification processing error:",h),new r.NextResponse(null,{status:202});process.env.NODE_ENV!=="test"&&console.error("Next.js MCP RPC handler error:",h);const v=h?.code??-32603,m=h?.data,N=h.message||"MCP request failed",x=f.buildJsonRpcError(p.id??null,v,N,m);if(E){const C=new TextEncoder,b=f.primeEventId(),O=new ReadableStream({start(H){H.enqueue(C.encode(`id: ${b}
|
|
4
4
|
|
|
5
|
-
`)),H.enqueue(C.encode(f.serializeSseEvent(x,b))),H.close()}}),S=new Headers({"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});if(s){const H=R(t,s);Object.entries(H).forEach(([P,I])=>S.set(P,I))}return new r.NextResponse(O,{status:200,headers:S})}return w(x,200)}}}function Q(n){const{extractSecurityContext:o,cors:s,agent:c}=n;if(!c)throw new Error("agent config is required for createAgentChatHandler");const d=g(n);return async function(t,e){try{if(t.method!=="POST")return r.NextResponse.json({error:"Method not allowed - use POST"},{status:405});const{handleAgentChat:l}=await Promise.resolve().then(()=>require("../handler-
|
|
5
|
+
`)),H.enqueue(C.encode(f.serializeSseEvent(x,b))),H.close()}}),S=new Headers({"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});if(s){const H=R(t,s);Object.entries(H).forEach(([P,I])=>S.set(P,I))}return new r.NextResponse(O,{status:200,headers:S})}return w(x,200)}}}function Q(n){const{extractSecurityContext:o,cors:s,agent:c}=n;if(!c)throw new Error("agent config is required for createAgentChatHandler");const d=g(n);return async function(t,e){try{if(t.method!=="POST")return r.NextResponse.json({error:"Method not allowed - use POST"},{status:405});const{handleAgentChat:l}=await Promise.resolve().then(()=>require("../handler-Xe_2ItOo.cjs")),y=await t.json(),{message:u,sessionId:p}=y;if(!u||typeof u!="string")return r.NextResponse.json({error:"message is required and must be a string"},{status:400});let E=(c.apiKey||"").trim();if(c.allowClientApiKey){const m=t.headers.get("x-agent-api-key");m&&(E=m.trim())}if(!E)return r.NextResponse.json({error:"No API key configured. Set agent.apiKey in server config or send X-Agent-Api-Key header."},{status:401});const j=await o(t,e),w=new TextEncoder,h=new ReadableStream({async start(m){try{const N=l({message:u,sessionId:p,semanticLayer:d,securityContext:j,agentConfig:c,apiKey:E});for await(const x of N){const C=`data: ${JSON.stringify(x)}
|
|
6
6
|
|
|
7
7
|
`;m.enqueue(w.encode(C))}}catch(N){const x={type:"error",data:{message:N instanceof Error?N.message:"Stream failed"}};m.enqueue(w.encode(`data: ${JSON.stringify(x)}
|
|
8
8
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NextResponse as t } from "next/server";
|
|
2
|
-
import { e as T, s as A, v as D, b as P, a as _, n as Q, p as V, w as I, d as J, i as M, M as k, c as $, S as K } from "../mcp-transport-
|
|
2
|
+
import { e as T, s as A, v as D, b as P, a as _, n as Q, p as V, w as I, d as J, i as M, M as k, c as $, S as K } from "../mcp-transport-CU5g9bxj.js";
|
|
3
3
|
import { formatErrorResponse as i, formatCubeResponse as z, formatMetaResponse as G, formatSqlResponse as U, handleDryRun as q, handleBatchRequest as B, handleDiscover as F, handleSuggest as X, handleValidate as W, handleLoad as Y } from "../utils.js";
|
|
4
4
|
function x(n) {
|
|
5
5
|
const { cubes: a, drizzle: s, schema: c, engineType: d, cache: o } = n;
|
|
@@ -428,7 +428,7 @@ function ae(n) {
|
|
|
428
428
|
error: "Unsupported MCP protocol version",
|
|
429
429
|
supported: y.supported
|
|
430
430
|
}, { status: 426 });
|
|
431
|
-
let l
|
|
431
|
+
let l;
|
|
432
432
|
try {
|
|
433
433
|
l = await r.json();
|
|
434
434
|
} catch {
|
|
@@ -519,7 +519,7 @@ function oe(n) {
|
|
|
519
519
|
{ error: "Method not allowed - use POST" },
|
|
520
520
|
{ status: 405 }
|
|
521
521
|
);
|
|
522
|
-
const { handleAgentChat: u } = await import("../handler-
|
|
522
|
+
const { handleAgentChat: u } = await import("../handler-CSHsefnC.js"), y = await r.json(), { message: l, sessionId: f } = y;
|
|
523
523
|
if (!l || typeof l != "string")
|
|
524
524
|
return t.json(
|
|
525
525
|
{ error: "message is required and must be a string" },
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ComponentType } from 'react';
|
|
2
1
|
/**
|
|
3
2
|
* Configuration for a single axis drop zone in the chart configuration UI
|
|
4
3
|
*/
|
|
@@ -15,10 +14,6 @@ export interface AxisDropZoneConfig {
|
|
|
15
14
|
maxItems?: number;
|
|
16
15
|
/** Which field types this drop zone accepts */
|
|
17
16
|
acceptTypes?: ('dimension' | 'timeDimension' | 'measure')[];
|
|
18
|
-
/** Optional icon component to display */
|
|
19
|
-
icon?: ComponentType<{
|
|
20
|
-
className?: string;
|
|
21
|
-
}>;
|
|
22
17
|
/** Placeholder text when drop zone is empty */
|
|
23
18
|
emptyText?: string;
|
|
24
19
|
/** Enable L/R axis toggle for items in this drop zone (for dual Y-axis support) */
|
|
@@ -75,6 +70,8 @@ export interface ClickableElementsConfig {
|
|
|
75
70
|
* Complete configuration for a chart type
|
|
76
71
|
*/
|
|
77
72
|
export interface ChartTypeConfig {
|
|
73
|
+
/** Display label for the chart type in the picker (e.g., 'Bar Chart', 'KPI Number') */
|
|
74
|
+
label?: string;
|
|
78
75
|
/** Configuration for each drop zone */
|
|
79
76
|
dropZones: AxisDropZoneConfig[];
|
|
80
77
|
/** Simple display options (backward compatibility) - rendered as boolean checkboxes */
|
|
@@ -86,10 +83,6 @@ export interface ChartTypeConfig {
|
|
|
86
83
|
isValid: boolean;
|
|
87
84
|
message?: string;
|
|
88
85
|
};
|
|
89
|
-
/** Icon component for the chart type */
|
|
90
|
-
icon?: ComponentType<{
|
|
91
|
-
className?: string;
|
|
92
|
-
}>;
|
|
93
86
|
/** Brief description of the chart */
|
|
94
87
|
description?: string;
|
|
95
88
|
/** When to use this chart type */
|
package/dist/client/charts.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { L as w, g as L, c as T, b as O, i as S, p as N, a as
|
|
1
|
+
import { L as w, g as L, c as T, b as O, i as S, p as N, a as P } from "./chunks/charts-loader-HYQFVOo4.js";
|
|
2
2
|
import { useState as f, useEffect as c } from "react";
|
|
3
|
-
import { f as
|
|
4
|
-
import { c as
|
|
3
|
+
import { f as B } from "./chunks/index-CApFCBF9.js";
|
|
4
|
+
import { c as M, C as E, N as H, P as I } from "./chunks/charts-core-DmGfleFz.js";
|
|
5
5
|
import { B as _ } from "./chunks/chart-bar-HpXF42H1.js";
|
|
6
6
|
import { L as j } from "./chunks/chart-line-C7YcMWBw.js";
|
|
7
7
|
import { default as U } from "./chunks/chart-area-QKKboTbq.js";
|
|
@@ -9,9 +9,9 @@ import { default as Y } from "./chunks/chart-pie-C4SuxKSN.js";
|
|
|
9
9
|
import { default as $ } from "./chunks/chart-scatter-DOVu1TNq.js";
|
|
10
10
|
import { default as J } from "./chunks/chart-radar-BW3Z_-Ly.js";
|
|
11
11
|
import { default as Q } from "./chunks/chart-radial-bar-0Fa3aeP5.js";
|
|
12
|
-
import { default as
|
|
13
|
-
import { default as
|
|
14
|
-
import { D as
|
|
12
|
+
import { default as tt } from "./chunks/chart-tree-map-DZtQPyWX.js";
|
|
13
|
+
import { default as at } from "./chunks/chart-funnel-C9kenCpp.js";
|
|
14
|
+
import { D as ot } from "./chunks/chart-data-table-Ba_6tuJw.js";
|
|
15
15
|
const s = {
|
|
16
16
|
dropZones: [
|
|
17
17
|
{
|
|
@@ -41,27 +41,28 @@ const s = {
|
|
|
41
41
|
],
|
|
42
42
|
displayOptions: ["showLegend", "showGrid", "showTooltip"]
|
|
43
43
|
}, l = {
|
|
44
|
-
bar: () => import("./chunks/chart-config-bar-
|
|
45
|
-
line: () => import("./chunks/chart-config-line-
|
|
46
|
-
area: () => import("./chunks/chart-config-area-
|
|
47
|
-
pie: () => import("./chunks/chart-config-pie-
|
|
48
|
-
scatter: () => import("./chunks/chart-config-scatter-
|
|
49
|
-
radar: () => import("./chunks/chart-config-radar-
|
|
50
|
-
radialBar: () => import("./chunks/chart-config-radial-bar-
|
|
51
|
-
treemap: () => import("./chunks/chart-config-tree-map-
|
|
52
|
-
bubble: () => import("./chunks/chart-config-bubble-
|
|
53
|
-
table: () => import("./chunks/chart-config-data-table-
|
|
54
|
-
activityGrid: () => import("./chunks/chart-config-activity-grid-
|
|
55
|
-
kpiNumber: () => import("./chunks/chart-config-kpi-number-
|
|
56
|
-
kpiDelta: () => import("./chunks/chart-config-kpi-delta-
|
|
57
|
-
kpiText: () => import("./chunks/chart-config-kpi-text-
|
|
58
|
-
markdown: () => import("./chunks/chart-config-markdown-
|
|
59
|
-
funnel: () => import("./chunks/chart-config-funnel-
|
|
60
|
-
sankey: () => import("./chunks/chart-config-sankey-
|
|
61
|
-
sunburst: () => import("./chunks/chart-config-sunburst-
|
|
62
|
-
heatmap: () => import("./chunks/chart-config-heat-map-
|
|
63
|
-
retentionHeatmap: () => import("./chunks/RetentionHeatmap.config-
|
|
64
|
-
retentionCombined: () => import("./chunks/RetentionCombinedChart.config-
|
|
44
|
+
bar: () => import("./chunks/chart-config-bar-C8uzktxl.js"),
|
|
45
|
+
line: () => import("./chunks/chart-config-line-JNagi9tf.js"),
|
|
46
|
+
area: () => import("./chunks/chart-config-area-CK_GVApT.js"),
|
|
47
|
+
pie: () => import("./chunks/chart-config-pie-CNLXb-fr.js"),
|
|
48
|
+
scatter: () => import("./chunks/chart-config-scatter-DFKM80eO.js"),
|
|
49
|
+
radar: () => import("./chunks/chart-config-radar-oxHfRAa3.js"),
|
|
50
|
+
radialBar: () => import("./chunks/chart-config-radial-bar-_Aw3jAEm.js"),
|
|
51
|
+
treemap: () => import("./chunks/chart-config-tree-map-DGMbNTaa.js"),
|
|
52
|
+
bubble: () => import("./chunks/chart-config-bubble-q3DoQX5F.js"),
|
|
53
|
+
table: () => import("./chunks/chart-config-data-table-B20Y5JCm.js"),
|
|
54
|
+
activityGrid: () => import("./chunks/chart-config-activity-grid-CmOqDuOT.js"),
|
|
55
|
+
kpiNumber: () => import("./chunks/chart-config-kpi-number-K-wzviXF.js"),
|
|
56
|
+
kpiDelta: () => import("./chunks/chart-config-kpi-delta-DLGZ2A3X.js"),
|
|
57
|
+
kpiText: () => import("./chunks/chart-config-kpi-text-BjYqwqaJ.js"),
|
|
58
|
+
markdown: () => import("./chunks/chart-config-markdown-BWQSjJpy.js"),
|
|
59
|
+
funnel: () => import("./chunks/chart-config-funnel-3eYnGg8M.js"),
|
|
60
|
+
sankey: () => import("./chunks/chart-config-sankey-C8FX9hGF.js"),
|
|
61
|
+
sunburst: () => import("./chunks/chart-config-sunburst-BmC0NLTU.js"),
|
|
62
|
+
heatmap: () => import("./chunks/chart-config-heat-map-_wEnTnRA.js"),
|
|
63
|
+
retentionHeatmap: () => import("./chunks/RetentionHeatmap.config-BWf_-vdj.js"),
|
|
64
|
+
retentionCombined: () => import("./chunks/RetentionCombinedChart.config-Bbp2ghim.js"),
|
|
65
|
+
boxPlot: () => import("./chunks/chart-config-box-plot-D3DA7_pr.js")
|
|
65
66
|
}, d = {
|
|
66
67
|
bar: "barChartConfig",
|
|
67
68
|
line: "lineChartConfig",
|
|
@@ -83,58 +84,59 @@ const s = {
|
|
|
83
84
|
sunburst: "sunburstChartConfig",
|
|
84
85
|
heatmap: "heatmapChartConfig",
|
|
85
86
|
retentionHeatmap: "retentionHeatmapConfig",
|
|
86
|
-
retentionCombined: "retentionCombinedConfig"
|
|
87
|
+
retentionCombined: "retentionCombinedConfig",
|
|
88
|
+
boxPlot: "boxPlotChartConfig"
|
|
87
89
|
}, a = /* @__PURE__ */ new Map();
|
|
88
|
-
async function p(
|
|
89
|
-
if (a.has(
|
|
90
|
-
return a.get(
|
|
91
|
-
const r = l[
|
|
90
|
+
async function p(t) {
|
|
91
|
+
if (a.has(t))
|
|
92
|
+
return a.get(t);
|
|
93
|
+
const r = l[t];
|
|
92
94
|
if (!r)
|
|
93
95
|
return null;
|
|
94
96
|
try {
|
|
95
|
-
const
|
|
96
|
-
return
|
|
97
|
-
} catch (
|
|
98
|
-
return console.error(`Failed to load config for chart type: ${
|
|
97
|
+
const e = await r(), o = d[t], i = e[o];
|
|
98
|
+
return i ? (a.set(t, i), i) : null;
|
|
99
|
+
} catch (e) {
|
|
100
|
+
return console.error(`Failed to load config for chart type: ${t}`, e), null;
|
|
99
101
|
}
|
|
100
102
|
}
|
|
101
|
-
function u(
|
|
102
|
-
return a.get(
|
|
103
|
+
function u(t) {
|
|
104
|
+
return a.get(t) || s;
|
|
103
105
|
}
|
|
104
|
-
function b(
|
|
105
|
-
return a.has(
|
|
106
|
+
function b(t) {
|
|
107
|
+
return a.has(t);
|
|
106
108
|
}
|
|
107
|
-
function x(
|
|
108
|
-
const [r,
|
|
109
|
-
|
|
110
|
-
), [
|
|
109
|
+
function x(t) {
|
|
110
|
+
const [r, e] = f(
|
|
111
|
+
t ? u(t) : s
|
|
112
|
+
), [o, i] = f(!1), [C, n] = f(!1);
|
|
111
113
|
return c(() => {
|
|
112
|
-
if (!
|
|
113
|
-
|
|
114
|
+
if (!t) {
|
|
115
|
+
e(s), n(!1);
|
|
114
116
|
return;
|
|
115
117
|
}
|
|
116
|
-
if (a.has(
|
|
117
|
-
|
|
118
|
+
if (a.has(t)) {
|
|
119
|
+
e(a.get(t)), n(!0);
|
|
118
120
|
return;
|
|
119
121
|
}
|
|
120
|
-
|
|
121
|
-
m ? (
|
|
122
|
-
}).finally(() =>
|
|
123
|
-
}, [
|
|
122
|
+
i(!0), p(t).then((m) => {
|
|
123
|
+
m ? (e(m), n(!0)) : (e(s), n(!0));
|
|
124
|
+
}).finally(() => i(!1));
|
|
125
|
+
}, [t]), { config: r, loading: o, loaded: C };
|
|
124
126
|
}
|
|
125
|
-
async function h(
|
|
126
|
-
a.has(
|
|
127
|
+
async function h(t) {
|
|
128
|
+
a.has(t) || await p(t);
|
|
127
129
|
}
|
|
128
|
-
async function y(
|
|
129
|
-
await Promise.all(
|
|
130
|
+
async function y(t) {
|
|
131
|
+
await Promise.all(t.map(h));
|
|
130
132
|
}
|
|
131
133
|
async function k() {
|
|
132
|
-
const
|
|
133
|
-
await Promise.all(
|
|
134
|
+
const t = Object.keys(l);
|
|
135
|
+
await Promise.all(t.map(p));
|
|
134
136
|
const r = {};
|
|
135
|
-
for (const
|
|
136
|
-
const
|
|
137
|
-
|
|
137
|
+
for (const e of t) {
|
|
138
|
+
const o = a.get(e);
|
|
139
|
+
o && (r[e] = o);
|
|
138
140
|
}
|
|
139
141
|
return r;
|
|
140
142
|
}
|
|
@@ -142,13 +144,13 @@ function R() {
|
|
|
142
144
|
a.clear();
|
|
143
145
|
}
|
|
144
146
|
export {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
M as CHART_COLORS,
|
|
148
|
+
E as CHART_MARGINS,
|
|
149
|
+
ot as DataTable,
|
|
150
|
+
at as FunnelChart,
|
|
149
151
|
w as LazyChart,
|
|
150
|
-
|
|
151
|
-
|
|
152
|
+
H as NEGATIVE_COLOR,
|
|
153
|
+
I as POSITIVE_COLOR,
|
|
152
154
|
U as RechartsAreaChart,
|
|
153
155
|
_ as RechartsBarChart,
|
|
154
156
|
j as RechartsLineChart,
|
|
@@ -156,9 +158,9 @@ export {
|
|
|
156
158
|
J as RechartsRadarChart,
|
|
157
159
|
Q as RechartsRadialBarChart,
|
|
158
160
|
$ as RechartsScatterChart,
|
|
159
|
-
|
|
161
|
+
tt as RechartsTreeMapChart,
|
|
160
162
|
R as clearChartConfigCache,
|
|
161
|
-
|
|
163
|
+
B as formatChartData,
|
|
162
164
|
L as getAvailableChartTypes,
|
|
163
165
|
p as getChartConfigAsync,
|
|
164
166
|
u as getChartConfigSync,
|
|
@@ -170,7 +172,7 @@ export {
|
|
|
170
172
|
N as preloadChart,
|
|
171
173
|
h as preloadChartConfig,
|
|
172
174
|
y as preloadChartConfigs,
|
|
173
|
-
|
|
175
|
+
P as preloadCharts,
|
|
174
176
|
x as useChartConfig
|
|
175
177
|
};
|
|
176
178
|
//# sourceMappingURL=charts.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"charts.js","sources":["../../src/client/charts/chartConfigs.ts","../../src/client/charts/lazyChartConfigRegistry.ts"],"sourcesContent":["import { ComponentType } from 'react'\n\n/**\n * Configuration for a single axis drop zone in the chart configuration UI\n */\nexport interface AxisDropZoneConfig {\n /** The key to store this field in chartConfig (e.g., 'xAxis', 'yAxis', 'sizeField') */\n key: string\n \n /** Display label for the drop zone */\n label: string\n \n /** Optional description/help text shown below the label */\n description?: string\n \n /** Whether at least one field is required in this drop zone */\n mandatory?: boolean\n \n /** Maximum number of items allowed in this drop zone */\n maxItems?: number\n \n /** Which field types this drop zone accepts */\n acceptTypes?: ('dimension' | 'timeDimension' | 'measure')[]\n \n /** Optional icon component to display */\n icon?: ComponentType<{ className?: string }>\n\n /** Placeholder text when drop zone is empty */\n emptyText?: string\n\n /** Enable L/R axis toggle for items in this drop zone (for dual Y-axis support) */\n enableDualAxis?: boolean\n}\n\n/**\n * Configuration for a single display option\n */\nexport interface DisplayOptionConfig {\n /** The key to store this field in displayConfig */\n key: string\n \n /** Display label for the option */\n label: string\n \n /** Type of input control to render */\n type: 'boolean' | 'string' | 'number' | 'select' | 'color' | 'paletteColor' | 'axisFormat' | 'stringArray' | 'buttonGroup'\n \n /** Default value for the option */\n defaultValue?: any\n \n /** Placeholder text for string/number inputs */\n placeholder?: string\n \n /** Options for select type */\n options?: Array<{ value: any; label: string }>\n \n /** Help text shown below the input */\n description?: string\n \n /** Minimum value for number inputs */\n min?: number\n \n /** Maximum value for number inputs */\n max?: number\n \n /** Step value for number inputs */\n step?: number\n}\n\n/**\n * Configuration for which elements in a chart support clicking (for drill-down)\n */\nexport interface ClickableElementsConfig {\n /** Bars in bar charts */\n bar?: boolean\n /** Points/dots in line/scatter charts */\n point?: boolean\n /** Slices in pie/donut charts */\n slice?: boolean\n /** Cells in heatmaps */\n cell?: boolean\n /** Nodes in treemaps, sankey diagrams */\n node?: boolean\n /** Areas in area charts */\n area?: boolean\n /** Rows in data tables */\n row?: boolean\n}\n\n/**\n * Complete configuration for a chart type\n */\nexport interface ChartTypeConfig {\n /** Configuration for each drop zone */\n dropZones: AxisDropZoneConfig[]\n\n /** Simple display options (backward compatibility) - rendered as boolean checkboxes */\n displayOptions?: string[]\n\n /** Structured display options with metadata for different input types */\n displayOptionsConfig?: DisplayOptionConfig[]\n\n /** Optional custom validation function */\n validate?: (config: any) => { isValid: boolean; message?: string }\n\n /** Icon component for the chart type */\n icon?: ComponentType<{ className?: string }>\n\n /** Brief description of the chart */\n description?: string\n\n /** When to use this chart type */\n useCase?: string\n\n /** Whether this chart type skips query requirements (for content-based charts like markdown) */\n skipQuery?: boolean\n\n /** Configuration for which elements support clicking (for drill-down) */\n clickableElements?: ClickableElementsConfig\n}\n\n/**\n * Registry of all chart type configurations\n */\nexport interface ChartConfigRegistry {\n [chartType: string]: ChartTypeConfig\n}\n\n/**\n * Default configuration for charts without specific requirements\n */\nexport const defaultChartConfig: ChartTypeConfig = {\n dropZones: [\n {\n key: 'xAxis',\n label: 'X-Axis (Categories)',\n description: 'Dimensions and time dimensions for grouping',\n mandatory: false,\n acceptTypes: ['dimension', 'timeDimension'],\n emptyText: 'Drop dimensions & time dimensions here'\n },\n {\n key: 'yAxis',\n label: 'Y-Axis (Values)',\n description: 'Measures for values or dimensions for series',\n mandatory: false,\n acceptTypes: ['measure', 'dimension'],\n emptyText: 'Drop measures or dimensions here'\n },\n {\n key: 'series',\n label: 'Series (Split into Multiple Series)',\n description: 'Dimensions to create separate data series',\n mandatory: false,\n acceptTypes: ['dimension'],\n emptyText: 'Drop dimensions here to split data into series'\n }\n ],\n displayOptions: ['showLegend', 'showGrid', 'showTooltip']\n}\n\n/**\n * Helper function to get configuration for a chart type\n */\nexport function getChartConfig(chartType: string, registry: ChartConfigRegistry): ChartTypeConfig {\n return registry[chartType] || defaultChartConfig\n}","/**\n * Lazy Chart Config Registry\n *\n * Provides async loading for chart configurations.\n * This enables code splitting - each chart config loads only when needed.\n */\n\nimport { useState, useEffect } from 'react'\nimport type { ChartType } from '../types'\nimport type { ChartTypeConfig, ChartConfigRegistry } from './chartConfigs'\nimport { defaultChartConfig } from './chartConfigs'\n\n// Config import map - lazy imports for each chart config\nconst configImportMap: Record<ChartType, () => Promise<{ [key: string]: ChartTypeConfig }>> = {\n bar: () => import('../components/charts/BarChart.config'),\n line: () => import('../components/charts/LineChart.config'),\n area: () => import('../components/charts/AreaChart.config'),\n pie: () => import('../components/charts/PieChart.config'),\n scatter: () => import('../components/charts/ScatterChart.config'),\n radar: () => import('../components/charts/RadarChart.config'),\n radialBar: () => import('../components/charts/RadialBarChart.config'),\n treemap: () => import('../components/charts/TreeMapChart.config'),\n bubble: () => import('../components/charts/BubbleChart.config'),\n table: () => import('../components/charts/DataTable.config'),\n activityGrid: () => import('../components/charts/ActivityGridChart.config'),\n kpiNumber: () => import('../components/charts/KpiNumber.config'),\n kpiDelta: () => import('../components/charts/KpiDelta.config'),\n kpiText: () => import('../components/charts/KpiText.config'),\n markdown: () => import('../components/charts/MarkdownChart.config'),\n funnel: () => import('../components/charts/FunnelChart.config'),\n sankey: () => import('../components/charts/SankeyChart.config'),\n sunburst: () => import('../components/charts/SunburstChart.config'),\n heatmap: () => import('../components/charts/HeatMapChart.config'),\n retentionHeatmap: () => import('../components/charts/RetentionHeatmap.config'),\n retentionCombined: () => import('../components/charts/RetentionCombinedChart.config'),\n}\n\n// Map from chart type to expected export name\nconst configExportNames: Record<ChartType, string> = {\n bar: 'barChartConfig',\n line: 'lineChartConfig',\n area: 'areaChartConfig',\n pie: 'pieChartConfig',\n scatter: 'scatterChartConfig',\n radar: 'radarChartConfig',\n radialBar: 'radialBarChartConfig',\n treemap: 'treemapChartConfig',\n bubble: 'bubbleChartConfig',\n table: 'dataTableConfig',\n activityGrid: 'activityGridChartConfig',\n kpiNumber: 'kpiNumberConfig',\n kpiDelta: 'kpiDeltaConfig',\n kpiText: 'kpiTextConfig',\n markdown: 'markdownConfig',\n funnel: 'funnelChartConfig',\n sankey: 'sankeyChartConfig',\n sunburst: 'sunburstChartConfig',\n heatmap: 'heatmapChartConfig',\n retentionHeatmap: 'retentionHeatmapConfig',\n retentionCombined: 'retentionCombinedConfig',\n}\n\n// Cache for loaded configs\nconst configCache = new Map<ChartType, ChartTypeConfig>()\n\n/**\n * Get a chart config asynchronously\n *\n * @param chartType The chart type to load config for\n * @returns The chart type config, or null if not found\n *\n * @example\n * ```typescript\n * const config = await getChartConfigAsync('bar')\n * console.log(config?.dropZones)\n * ```\n */\nexport async function getChartConfigAsync(chartType: ChartType): Promise<ChartTypeConfig | null> {\n // Check cache first\n if (configCache.has(chartType)) {\n return configCache.get(chartType)!\n }\n\n const importFn = configImportMap[chartType]\n if (!importFn) {\n return null\n }\n\n try {\n const module = await importFn()\n const exportName = configExportNames[chartType]\n const config = module[exportName]\n\n if (config) {\n configCache.set(chartType, config)\n return config\n }\n return null\n } catch (error) {\n console.error(`Failed to load config for chart type: ${chartType}`, error)\n return null\n }\n}\n\n/**\n * Get a chart config synchronously from cache\n *\n * Returns the cached config if available, otherwise returns the default config.\n * Use this when you need sync access and have already preloaded the config.\n *\n * @param chartType The chart type to get config for\n * @returns The chart type config (from cache or default)\n */\nexport function getChartConfigSync(chartType: ChartType): ChartTypeConfig {\n return configCache.get(chartType) || defaultChartConfig\n}\n\n/**\n * Check if a chart config is already loaded\n */\nexport function isChartConfigLoaded(chartType: ChartType): boolean {\n return configCache.has(chartType)\n}\n\n/**\n * React hook for using chart config\n *\n * Loads the chart config asynchronously and caches it.\n * Returns the default config while loading.\n *\n * @param chartType The chart type to load config for\n * @returns Object with config, loading state, and loaded flag\n *\n * @example\n * ```tsx\n * function ChartSetup({ chartType }) {\n * const { config, loading } = useChartConfig(chartType)\n *\n * if (loading) return <Spinner />\n * return <ConfigForm config={config} />\n * }\n * ```\n */\nexport function useChartConfig(chartType: ChartType | undefined): {\n config: ChartTypeConfig\n loading: boolean\n loaded: boolean\n} {\n const [config, setConfig] = useState<ChartTypeConfig>(\n chartType ? getChartConfigSync(chartType) : defaultChartConfig\n )\n const [loading, setLoading] = useState(false)\n const [loaded, setLoaded] = useState(false)\n\n useEffect(() => {\n if (!chartType) {\n setConfig(defaultChartConfig)\n setLoaded(false)\n return\n }\n\n // Check cache synchronously first\n if (configCache.has(chartType)) {\n setConfig(configCache.get(chartType)!)\n setLoaded(true)\n return\n }\n\n // Load async\n setLoading(true)\n getChartConfigAsync(chartType)\n .then((loadedConfig) => {\n if (loadedConfig) {\n setConfig(loadedConfig)\n setLoaded(true)\n } else {\n setConfig(defaultChartConfig)\n setLoaded(true)\n }\n })\n .finally(() => setLoading(false))\n }, [chartType])\n\n return { config, loading, loaded }\n}\n\n/**\n * Preload a chart config\n *\n * Triggers the async import without needing to use the config immediately.\n * Useful for prefetching configs that will likely be needed.\n *\n * @param chartType The chart type to preload config for\n */\nexport async function preloadChartConfig(chartType: ChartType): Promise<void> {\n if (!configCache.has(chartType)) {\n await getChartConfigAsync(chartType)\n }\n}\n\n/**\n * Preload multiple chart configs\n *\n * @param chartTypes Array of chart types to preload\n */\nexport async function preloadChartConfigs(chartTypes: ChartType[]): Promise<void> {\n await Promise.all(chartTypes.map(preloadChartConfig))\n}\n\n/**\n * Load all chart configs and return as a registry\n *\n * Useful for SSR or when you need all configs upfront.\n * After calling this, all configs are cached and available synchronously.\n *\n * @returns Complete chart config registry\n *\n * @example\n * ```typescript\n * // On server or during initialization\n * const registry = await loadAllChartConfigs()\n * // Now all configs are cached and getChartConfigSync works for all types\n * ```\n */\nexport async function loadAllChartConfigs(): Promise<ChartConfigRegistry> {\n const chartTypes = Object.keys(configImportMap) as ChartType[]\n await Promise.all(chartTypes.map(getChartConfigAsync))\n\n const registry: ChartConfigRegistry = {}\n for (const chartType of chartTypes) {\n const config = configCache.get(chartType)\n if (config) {\n registry[chartType] = config\n }\n }\n return registry\n}\n\n/**\n * Clear the config cache\n *\n * Useful for testing or when configs need to be reloaded.\n */\nexport function clearChartConfigCache(): void {\n configCache.clear()\n}\n"],"names":["defaultChartConfig","configImportMap","configExportNames","configCache","getChartConfigAsync","chartType","importFn","module","exportName","config","error","getChartConfigSync","isChartConfigLoaded","useChartConfig","setConfig","useState","loading","setLoading","loaded","setLoaded","useEffect","loadedConfig","preloadChartConfig","preloadChartConfigs","chartTypes","loadAllChartConfigs","registry","clearChartConfigCache"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"charts.js","sources":["../../src/client/charts/chartConfigs.ts","../../src/client/charts/lazyChartConfigRegistry.ts"],"sourcesContent":["/**\n * Configuration for a single axis drop zone in the chart configuration UI\n */\nexport interface AxisDropZoneConfig {\n /** The key to store this field in chartConfig (e.g., 'xAxis', 'yAxis', 'sizeField') */\n key: string\n\n /** Display label for the drop zone */\n label: string\n\n /** Optional description/help text shown below the label */\n description?: string\n\n /** Whether at least one field is required in this drop zone */\n mandatory?: boolean\n\n /** Maximum number of items allowed in this drop zone */\n maxItems?: number\n\n /** Which field types this drop zone accepts */\n acceptTypes?: ('dimension' | 'timeDimension' | 'measure')[]\n\n /** Placeholder text when drop zone is empty */\n emptyText?: string\n\n /** Enable L/R axis toggle for items in this drop zone (for dual Y-axis support) */\n enableDualAxis?: boolean\n}\n\n/**\n * Configuration for a single display option\n */\nexport interface DisplayOptionConfig {\n /** The key to store this field in displayConfig */\n key: string\n \n /** Display label for the option */\n label: string\n \n /** Type of input control to render */\n type: 'boolean' | 'string' | 'number' | 'select' | 'color' | 'paletteColor' | 'axisFormat' | 'stringArray' | 'buttonGroup'\n \n /** Default value for the option */\n defaultValue?: any\n \n /** Placeholder text for string/number inputs */\n placeholder?: string\n \n /** Options for select type */\n options?: Array<{ value: any; label: string }>\n \n /** Help text shown below the input */\n description?: string\n \n /** Minimum value for number inputs */\n min?: number\n \n /** Maximum value for number inputs */\n max?: number\n \n /** Step value for number inputs */\n step?: number\n}\n\n/**\n * Configuration for which elements in a chart support clicking (for drill-down)\n */\nexport interface ClickableElementsConfig {\n /** Bars in bar charts */\n bar?: boolean\n /** Points/dots in line/scatter charts */\n point?: boolean\n /** Slices in pie/donut charts */\n slice?: boolean\n /** Cells in heatmaps */\n cell?: boolean\n /** Nodes in treemaps, sankey diagrams */\n node?: boolean\n /** Areas in area charts */\n area?: boolean\n /** Rows in data tables */\n row?: boolean\n}\n\n/**\n * Complete configuration for a chart type\n */\nexport interface ChartTypeConfig {\n /** Display label for the chart type in the picker (e.g., 'Bar Chart', 'KPI Number') */\n label?: string\n\n /** Configuration for each drop zone */\n dropZones: AxisDropZoneConfig[]\n\n /** Simple display options (backward compatibility) - rendered as boolean checkboxes */\n displayOptions?: string[]\n\n /** Structured display options with metadata for different input types */\n displayOptionsConfig?: DisplayOptionConfig[]\n\n /** Optional custom validation function */\n validate?: (config: any) => { isValid: boolean; message?: string }\n\n /** Brief description of the chart */\n description?: string\n\n /** When to use this chart type */\n useCase?: string\n\n /** Whether this chart type skips query requirements (for content-based charts like markdown) */\n skipQuery?: boolean\n\n /** Configuration for which elements support clicking (for drill-down) */\n clickableElements?: ClickableElementsConfig\n}\n\n/**\n * Registry of all chart type configurations\n */\nexport interface ChartConfigRegistry {\n [chartType: string]: ChartTypeConfig\n}\n\n/**\n * Default configuration for charts without specific requirements\n */\nexport const defaultChartConfig: ChartTypeConfig = {\n dropZones: [\n {\n key: 'xAxis',\n label: 'X-Axis (Categories)',\n description: 'Dimensions and time dimensions for grouping',\n mandatory: false,\n acceptTypes: ['dimension', 'timeDimension'],\n emptyText: 'Drop dimensions & time dimensions here'\n },\n {\n key: 'yAxis',\n label: 'Y-Axis (Values)',\n description: 'Measures for values or dimensions for series',\n mandatory: false,\n acceptTypes: ['measure', 'dimension'],\n emptyText: 'Drop measures or dimensions here'\n },\n {\n key: 'series',\n label: 'Series (Split into Multiple Series)',\n description: 'Dimensions to create separate data series',\n mandatory: false,\n acceptTypes: ['dimension'],\n emptyText: 'Drop dimensions here to split data into series'\n }\n ],\n displayOptions: ['showLegend', 'showGrid', 'showTooltip']\n}\n\n/**\n * Helper function to get configuration for a chart type\n */\nexport function getChartConfig(chartType: string, registry: ChartConfigRegistry): ChartTypeConfig {\n return registry[chartType] || defaultChartConfig\n}","/**\n * Lazy Chart Config Registry\n *\n * Provides async loading for chart configurations.\n * This enables code splitting - each chart config loads only when needed.\n */\n\nimport { useState, useEffect } from 'react'\nimport type { ChartType } from '../types'\nimport type { ChartTypeConfig, ChartConfigRegistry } from './chartConfigs'\nimport { defaultChartConfig } from './chartConfigs'\n\n// Config import map - lazy imports for each chart config\nconst configImportMap: Record<ChartType, () => Promise<{ [key: string]: ChartTypeConfig }>> = {\n bar: () => import('../components/charts/BarChart.config'),\n line: () => import('../components/charts/LineChart.config'),\n area: () => import('../components/charts/AreaChart.config'),\n pie: () => import('../components/charts/PieChart.config'),\n scatter: () => import('../components/charts/ScatterChart.config'),\n radar: () => import('../components/charts/RadarChart.config'),\n radialBar: () => import('../components/charts/RadialBarChart.config'),\n treemap: () => import('../components/charts/TreeMapChart.config'),\n bubble: () => import('../components/charts/BubbleChart.config'),\n table: () => import('../components/charts/DataTable.config'),\n activityGrid: () => import('../components/charts/ActivityGridChart.config'),\n kpiNumber: () => import('../components/charts/KpiNumber.config'),\n kpiDelta: () => import('../components/charts/KpiDelta.config'),\n kpiText: () => import('../components/charts/KpiText.config'),\n markdown: () => import('../components/charts/MarkdownChart.config'),\n funnel: () => import('../components/charts/FunnelChart.config'),\n sankey: () => import('../components/charts/SankeyChart.config'),\n sunburst: () => import('../components/charts/SunburstChart.config'),\n heatmap: () => import('../components/charts/HeatMapChart.config'),\n retentionHeatmap: () => import('../components/charts/RetentionHeatmap.config'),\n retentionCombined: () => import('../components/charts/RetentionCombinedChart.config'),\n boxPlot: () => import('../components/charts/BoxPlotChart.config'),\n}\n\n// Map from chart type to expected export name\nconst configExportNames: Record<ChartType, string> = {\n bar: 'barChartConfig',\n line: 'lineChartConfig',\n area: 'areaChartConfig',\n pie: 'pieChartConfig',\n scatter: 'scatterChartConfig',\n radar: 'radarChartConfig',\n radialBar: 'radialBarChartConfig',\n treemap: 'treemapChartConfig',\n bubble: 'bubbleChartConfig',\n table: 'dataTableConfig',\n activityGrid: 'activityGridChartConfig',\n kpiNumber: 'kpiNumberConfig',\n kpiDelta: 'kpiDeltaConfig',\n kpiText: 'kpiTextConfig',\n markdown: 'markdownConfig',\n funnel: 'funnelChartConfig',\n sankey: 'sankeyChartConfig',\n sunburst: 'sunburstChartConfig',\n heatmap: 'heatmapChartConfig',\n retentionHeatmap: 'retentionHeatmapConfig',\n retentionCombined: 'retentionCombinedConfig',\n boxPlot: 'boxPlotChartConfig',\n}\n\n// Cache for loaded configs\nconst configCache = new Map<ChartType, ChartTypeConfig>()\n\n/**\n * Get a chart config asynchronously\n *\n * @param chartType The chart type to load config for\n * @returns The chart type config, or null if not found\n *\n * @example\n * ```typescript\n * const config = await getChartConfigAsync('bar')\n * console.log(config?.dropZones)\n * ```\n */\nexport async function getChartConfigAsync(chartType: ChartType): Promise<ChartTypeConfig | null> {\n // Check cache first\n if (configCache.has(chartType)) {\n return configCache.get(chartType)!\n }\n\n const importFn = configImportMap[chartType]\n if (!importFn) {\n return null\n }\n\n try {\n const module = await importFn()\n const exportName = configExportNames[chartType]\n const config = module[exportName]\n\n if (config) {\n configCache.set(chartType, config)\n return config\n }\n return null\n } catch (error) {\n console.error(`Failed to load config for chart type: ${chartType}`, error)\n return null\n }\n}\n\n/**\n * Get a chart config synchronously from cache\n *\n * Returns the cached config if available, otherwise returns the default config.\n * Use this when you need sync access and have already preloaded the config.\n *\n * @param chartType The chart type to get config for\n * @returns The chart type config (from cache or default)\n */\nexport function getChartConfigSync(chartType: ChartType): ChartTypeConfig {\n return configCache.get(chartType) || defaultChartConfig\n}\n\n/**\n * Check if a chart config is already loaded\n */\nexport function isChartConfigLoaded(chartType: ChartType): boolean {\n return configCache.has(chartType)\n}\n\n/**\n * React hook for using chart config\n *\n * Loads the chart config asynchronously and caches it.\n * Returns the default config while loading.\n *\n * @param chartType The chart type to load config for\n * @returns Object with config, loading state, and loaded flag\n *\n * @example\n * ```tsx\n * function ChartSetup({ chartType }) {\n * const { config, loading } = useChartConfig(chartType)\n *\n * if (loading) return <Spinner />\n * return <ConfigForm config={config} />\n * }\n * ```\n */\nexport function useChartConfig(chartType: ChartType | undefined): {\n config: ChartTypeConfig\n loading: boolean\n loaded: boolean\n} {\n const [config, setConfig] = useState<ChartTypeConfig>(\n chartType ? getChartConfigSync(chartType) : defaultChartConfig\n )\n const [loading, setLoading] = useState(false)\n const [loaded, setLoaded] = useState(false)\n\n useEffect(() => {\n if (!chartType) {\n setConfig(defaultChartConfig)\n setLoaded(false)\n return\n }\n\n // Check cache synchronously first\n if (configCache.has(chartType)) {\n setConfig(configCache.get(chartType)!)\n setLoaded(true)\n return\n }\n\n // Load async\n setLoading(true)\n getChartConfigAsync(chartType)\n .then((loadedConfig) => {\n if (loadedConfig) {\n setConfig(loadedConfig)\n setLoaded(true)\n } else {\n setConfig(defaultChartConfig)\n setLoaded(true)\n }\n })\n .finally(() => setLoading(false))\n }, [chartType])\n\n return { config, loading, loaded }\n}\n\n/**\n * Preload a chart config\n *\n * Triggers the async import without needing to use the config immediately.\n * Useful for prefetching configs that will likely be needed.\n *\n * @param chartType The chart type to preload config for\n */\nexport async function preloadChartConfig(chartType: ChartType): Promise<void> {\n if (!configCache.has(chartType)) {\n await getChartConfigAsync(chartType)\n }\n}\n\n/**\n * Preload multiple chart configs\n *\n * @param chartTypes Array of chart types to preload\n */\nexport async function preloadChartConfigs(chartTypes: ChartType[]): Promise<void> {\n await Promise.all(chartTypes.map(preloadChartConfig))\n}\n\n/**\n * Load all chart configs and return as a registry\n *\n * Useful for SSR or when you need all configs upfront.\n * After calling this, all configs are cached and available synchronously.\n *\n * @returns Complete chart config registry\n *\n * @example\n * ```typescript\n * // On server or during initialization\n * const registry = await loadAllChartConfigs()\n * // Now all configs are cached and getChartConfigSync works for all types\n * ```\n */\nexport async function loadAllChartConfigs(): Promise<ChartConfigRegistry> {\n const chartTypes = Object.keys(configImportMap) as ChartType[]\n await Promise.all(chartTypes.map(getChartConfigAsync))\n\n const registry: ChartConfigRegistry = {}\n for (const chartType of chartTypes) {\n const config = configCache.get(chartType)\n if (config) {\n registry[chartType] = config\n }\n }\n return registry\n}\n\n/**\n * Clear the config cache\n *\n * Useful for testing or when configs need to be reloaded.\n */\nexport function clearChartConfigCache(): void {\n configCache.clear()\n}\n"],"names":["defaultChartConfig","configImportMap","configExportNames","configCache","getChartConfigAsync","chartType","importFn","module","exportName","config","error","getChartConfigSync","isChartConfigLoaded","useChartConfig","setConfig","useState","loading","setLoading","loaded","setLoaded","useEffect","loadedConfig","preloadChartConfig","preloadChartConfigs","chartTypes","loadAllChartConfigs","registry","clearChartConfigCache"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const e = {
|
|
2
|
+
label: "Retention Chart",
|
|
2
3
|
// RetentionCombinedChart auto-configures from the retention data structure
|
|
3
4
|
// No drop zones needed as the chart maps directly to retention result data
|
|
4
5
|
dropZones: [],
|
|
@@ -44,4 +45,4 @@ const e = {
|
|
|
44
45
|
export {
|
|
45
46
|
e as retentionCombinedConfig
|
|
46
47
|
};
|
|
47
|
-
//# sourceMappingURL=RetentionCombinedChart.config-
|
|
48
|
+
//# sourceMappingURL=RetentionCombinedChart.config-Bbp2ghim.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RetentionCombinedChart.config-Bbp2ghim.js","sources":["../../../src/client/components/charts/RetentionCombinedChart.config.ts"],"sourcesContent":["/**\n * RetentionCombinedChart Configuration\n *\n * The RetentionCombinedChart visualizes retention analysis data with multiple display modes.\n * It auto-configures from retention data and provides display mode selection.\n */\n\nimport type { ChartTypeConfig } from '../../charts/chartConfigs'\n\nexport const retentionCombinedConfig: ChartTypeConfig = {\n label: 'Retention Chart',\n // RetentionCombinedChart auto-configures from the retention data structure\n // No drop zones needed as the chart maps directly to retention result data\n dropZones: [],\n\n // Display options\n displayOptionsConfig: [\n {\n key: 'retentionDisplayMode',\n label: 'Display Mode',\n type: 'select',\n defaultValue: 'line',\n options: [\n { value: 'line', label: 'Line Chart' },\n { value: 'heatmap', label: 'Heatmap Table' },\n { value: 'combined', label: 'Combined' },\n ],\n description: 'Choose how to visualize retention data',\n },\n {\n key: 'showLegend',\n label: 'Show Legend',\n type: 'boolean',\n defaultValue: true,\n description: 'Show the legend for breakdown segments',\n },\n {\n key: 'showGrid',\n label: 'Show Grid',\n type: 'boolean',\n defaultValue: true,\n description: 'Show grid lines on the chart',\n },\n {\n key: 'showTooltip',\n label: 'Show Tooltip',\n type: 'boolean',\n defaultValue: true,\n description: 'Show tooltip on hover with detailed stats',\n },\n ],\n\n description: 'Combined retention visualization with line chart and heatmap modes',\n useCase: 'Visualize user retention over time with optional breakdown segmentation',\n}\n"],"names":["retentionCombinedConfig"],"mappings":"AASO,MAAMA,IAA2C;AAAA,EACtD,OAAO;AAAA;AAAA;AAAA,EAGP,WAAW,CAAA;AAAA;AAAA,EAGX,sBAAsB;AAAA,IACpB;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,cAAc;AAAA,MACd,SAAS;AAAA,QACP,EAAE,OAAO,QAAQ,OAAO,aAAA;AAAA,QACxB,EAAE,OAAO,WAAW,OAAO,gBAAA;AAAA,QAC3B,EAAE,OAAO,YAAY,OAAO,WAAA;AAAA,MAAW;AAAA,MAEzC,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,cAAc;AAAA,MACd,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,cAAc;AAAA,MACd,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,cAAc;AAAA,MACd,aAAa;AAAA,IAAA;AAAA,EACf;AAAA,EAGF,aAAa;AAAA,EACb,SAAS;AACX;"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const e = {
|
|
2
|
+
label: "Retention Matrix",
|
|
2
3
|
// RetentionHeatmap auto-configures from the retention data structure
|
|
3
4
|
// No drop zones needed as the chart maps directly to cohort × period matrix
|
|
4
5
|
dropZones: [],
|
|
@@ -25,4 +26,4 @@ const e = {
|
|
|
25
26
|
export {
|
|
26
27
|
e as retentionHeatmapConfig
|
|
27
28
|
};
|
|
28
|
-
//# sourceMappingURL=RetentionHeatmap.config-
|
|
29
|
+
//# sourceMappingURL=RetentionHeatmap.config-BWf_-vdj.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RetentionHeatmap.config-BWf_-vdj.js","sources":["../../../src/client/components/charts/RetentionHeatmap.config.ts"],"sourcesContent":["/**\n * RetentionHeatmap Chart Configuration\n *\n * The RetentionHeatmap is a specialized chart for retention analysis.\n * It auto-configures from retention data and doesn't need typical axis configuration.\n */\n\nimport type { ChartTypeConfig } from '../../charts/chartConfigs'\n\nexport const retentionHeatmapConfig: ChartTypeConfig = {\n label: 'Retention Matrix',\n // RetentionHeatmap auto-configures from the retention data structure\n // No drop zones needed as the chart maps directly to cohort × period matrix\n dropZones: [],\n\n // Display options\n displayOptionsConfig: [\n {\n key: 'showLegend',\n label: 'Show Legend',\n type: 'boolean',\n defaultValue: true,\n description: 'Show the color intensity legend',\n },\n {\n key: 'showTooltip',\n label: 'Show Tooltip',\n type: 'boolean',\n defaultValue: true,\n description: 'Show tooltip on hover with detailed stats',\n },\n ],\n\n description: 'Cohort retention matrix visualization',\n useCase: 'Visualize user retention over time by cohort',\n}\n"],"names":["retentionHeatmapConfig"],"mappings":"AASO,MAAMA,IAA0C;AAAA,EACrD,OAAO;AAAA;AAAA;AAAA,EAGP,WAAW,CAAA;AAAA;AAAA,EAGX,sBAAsB;AAAA,IACpB;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,cAAc;AAAA,MACd,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,cAAc;AAAA,MACd,aAAa;AAAA,IAAA;AAAA,EACf;AAAA,EAGF,aAAa;AAAA,EACb,SAAS;AACX;"}
|