drizzle-cube 0.3.13 → 0.3.15
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/{compiler-DTOU8IsK.js → compiler-DdcGVWIl.js} +7429 -4165
- package/dist/adapters/compiler-mAJDpIQx.cjs +214 -0
- package/dist/adapters/express/index.cjs +1 -1
- package/dist/adapters/express/index.d.ts +1 -1
- package/dist/adapters/express/index.js +1 -1
- package/dist/adapters/fastify/index.cjs +1 -1
- package/dist/adapters/fastify/index.d.ts +1 -1
- package/dist/adapters/fastify/index.js +1 -1
- package/dist/adapters/hono/index.cjs +1 -1
- package/dist/adapters/hono/index.d.ts +1 -1
- package/dist/adapters/hono/index.js +1 -1
- package/dist/adapters/nextjs/index.cjs +1 -1
- package/dist/adapters/nextjs/index.d.ts +1 -1
- package/dist/adapters/nextjs/index.js +1 -1
- package/dist/adapters/utils.d.ts +29 -0
- package/dist/client/adapters/index.d.ts +2 -0
- package/dist/client/adapters/retentionModeAdapter.d.ts +3 -0
- package/dist/client/charts.js +12 -12
- package/dist/client/chunks/RetentionCombinedChart-CqMAkdcR.js +256 -0
- package/dist/client/chunks/RetentionCombinedChart-CqMAkdcR.js.map +1 -0
- package/dist/client/chunks/RetentionCombinedChart.config-C-ILIaEb.js +47 -0
- package/dist/client/chunks/RetentionCombinedChart.config-C-ILIaEb.js.map +1 -0
- package/dist/client/chunks/RetentionHeatmap-Bofadstm.js +178 -0
- package/dist/client/chunks/RetentionHeatmap-Bofadstm.js.map +1 -0
- package/dist/client/chunks/RetentionHeatmap.config-CIvhc-GT.js +28 -0
- package/dist/client/chunks/RetentionHeatmap.config-CIvhc-GT.js.map +1 -0
- package/dist/client/chunks/analysis-builder-D0MIKiKS.js +6939 -0
- package/dist/client/chunks/analysis-builder-D0MIKiKS.js.map +1 -0
- package/dist/client/chunks/analysis-builder-shared-gS0TDC6Y.js +2779 -0
- package/dist/client/chunks/analysis-builder-shared-gS0TDC6Y.js.map +1 -0
- package/dist/client/chunks/{chart-activity-grid-CuPARsr1.js → chart-activity-grid-B37W8fcE.js} +11 -11
- package/dist/client/chunks/{chart-activity-grid-CuPARsr1.js.map → chart-activity-grid-B37W8fcE.js.map} +1 -1
- package/dist/client/chunks/{chart-area-cPrJnhLj.js → chart-area-DZcxSVB1.js} +2 -2
- package/dist/client/chunks/{chart-area-cPrJnhLj.js.map → chart-area-DZcxSVB1.js.map} +1 -1
- package/dist/client/chunks/{chart-bar-D68HFPpa.js → chart-bar-BFAdRj-E.js} +2 -2
- package/dist/client/chunks/{chart-bar-D68HFPpa.js.map → chart-bar-BFAdRj-E.js.map} +1 -1
- package/dist/client/chunks/{chart-bubble-CquyYfNO.js → chart-bubble-eoCCbl3h.js} +2 -2
- package/dist/client/chunks/{chart-bubble-CquyYfNO.js.map → chart-bubble-eoCCbl3h.js.map} +1 -1
- package/dist/client/chunks/{chart-config-activity-grid-Bkvx0F-G.js → chart-config-activity-grid-BBSNCbkb.js} +2 -2
- package/dist/client/chunks/{chart-config-activity-grid-Bkvx0F-G.js.map → chart-config-activity-grid-BBSNCbkb.js.map} +1 -1
- package/dist/client/chunks/{chart-config-area-OApsRaYC.js → chart-config-area-CyyJOO2T.js} +2 -2
- package/dist/client/chunks/{chart-config-area-OApsRaYC.js.map → chart-config-area-CyyJOO2T.js.map} +1 -1
- package/dist/client/chunks/{chart-config-bar-Dy21oaIA.js → chart-config-bar-BJKGnfLt.js} +2 -2
- package/dist/client/chunks/{chart-config-bar-Dy21oaIA.js.map → chart-config-bar-BJKGnfLt.js.map} +1 -1
- package/dist/client/chunks/{chart-config-bubble-Chv0SoFm.js → chart-config-bubble-CuSsCHZ4.js} +2 -2
- package/dist/client/chunks/{chart-config-bubble-Chv0SoFm.js.map → chart-config-bubble-CuSsCHZ4.js.map} +1 -1
- package/dist/client/chunks/{chart-config-data-table-DTIdC35a.js → chart-config-data-table-BhgqwoqT.js} +2 -2
- package/dist/client/chunks/{chart-config-data-table-DTIdC35a.js.map → chart-config-data-table-BhgqwoqT.js.map} +1 -1
- package/dist/client/chunks/{chart-config-funnel-f17Livgr.js → chart-config-funnel-BlSQYng0.js} +4 -4
- package/dist/client/chunks/{chart-config-funnel-f17Livgr.js.map → chart-config-funnel-BlSQYng0.js.map} +1 -1
- package/dist/client/chunks/{chart-config-heat-map-DPhNICha.js → chart-config-heat-map-DHQGFZhX.js} +2 -2
- package/dist/client/chunks/{chart-config-heat-map-DPhNICha.js.map → chart-config-heat-map-DHQGFZhX.js.map} +1 -1
- package/dist/client/chunks/{chart-config-kpi-delta-CCl1d-St.js → chart-config-kpi-delta-yTA5ug_l.js} +2 -2
- package/dist/client/chunks/{chart-config-kpi-delta-CCl1d-St.js.map → chart-config-kpi-delta-yTA5ug_l.js.map} +1 -1
- package/dist/client/chunks/{chart-config-kpi-number-DkE3eSwH.js → chart-config-kpi-number-nVAwDXzq.js} +2 -2
- package/dist/client/chunks/{chart-config-kpi-number-DkE3eSwH.js.map → chart-config-kpi-number-nVAwDXzq.js.map} +1 -1
- package/dist/client/chunks/{chart-config-kpi-text-BMbgdxZm.js → chart-config-kpi-text-DZjqsx-b.js} +2 -2
- package/dist/client/chunks/{chart-config-kpi-text-BMbgdxZm.js.map → chart-config-kpi-text-DZjqsx-b.js.map} +1 -1
- package/dist/client/chunks/{chart-config-line-BnLlRUQE.js → chart-config-line-DR0ThxZy.js} +2 -2
- package/dist/client/chunks/{chart-config-line-BnLlRUQE.js.map → chart-config-line-DR0ThxZy.js.map} +1 -1
- package/dist/client/chunks/{chart-config-markdown-DIaMFC0Z.js → chart-config-markdown-DZxdGNVQ.js} +2 -2
- package/dist/client/chunks/{chart-config-markdown-DIaMFC0Z.js.map → chart-config-markdown-DZxdGNVQ.js.map} +1 -1
- package/dist/client/chunks/{chart-config-pie-O9y_T0BQ.js → chart-config-pie-BM5lgH-w.js} +2 -2
- package/dist/client/chunks/{chart-config-pie-O9y_T0BQ.js.map → chart-config-pie-BM5lgH-w.js.map} +1 -1
- package/dist/client/chunks/{chart-config-radar-CXa0354h.js → chart-config-radar-BBAVIF0S.js} +2 -2
- package/dist/client/chunks/{chart-config-radar-CXa0354h.js.map → chart-config-radar-BBAVIF0S.js.map} +1 -1
- package/dist/client/chunks/{chart-config-radial-bar-BppJU8-Q.js → chart-config-radial-bar-CTwjDRnB.js} +2 -2
- package/dist/client/chunks/{chart-config-radial-bar-BppJU8-Q.js.map → chart-config-radial-bar-CTwjDRnB.js.map} +1 -1
- package/dist/client/chunks/{chart-config-sankey-BfBHgL4x.js → chart-config-sankey-CNAgsMQ4.js} +2 -2
- package/dist/client/chunks/{chart-config-sankey-BfBHgL4x.js.map → chart-config-sankey-CNAgsMQ4.js.map} +1 -1
- package/dist/client/chunks/{chart-config-scatter-BTt8a10R.js → chart-config-scatter-CWvN2E-X.js} +2 -2
- package/dist/client/chunks/{chart-config-scatter-BTt8a10R.js.map → chart-config-scatter-CWvN2E-X.js.map} +1 -1
- package/dist/client/chunks/{chart-config-sunburst-DNmQpIIx.js → chart-config-sunburst-W_SKwaj0.js} +4 -4
- package/dist/client/chunks/{chart-config-sunburst-DNmQpIIx.js.map → chart-config-sunburst-W_SKwaj0.js.map} +1 -1
- package/dist/client/chunks/{chart-config-tree-map-HVgG4oa0.js → chart-config-tree-map-CLmRvvMR.js} +2 -2
- package/dist/client/chunks/{chart-config-tree-map-HVgG4oa0.js.map → chart-config-tree-map-CLmRvvMR.js.map} +1 -1
- package/dist/client/chunks/{chart-data-table-D4WDqbM0.js → chart-data-table-kudRwZxJ.js} +4 -4
- package/dist/client/chunks/{chart-data-table-D4WDqbM0.js.map → chart-data-table-kudRwZxJ.js.map} +1 -1
- package/dist/client/chunks/{chart-funnel-Csdn4FbN.js → chart-funnel-CA0XJkfh.js} +2 -2
- package/dist/client/chunks/{chart-funnel-Csdn4FbN.js.map → chart-funnel-CA0XJkfh.js.map} +1 -1
- package/dist/client/chunks/{chart-heat-map-v1afxnjq.js → chart-heat-map-DUy9_pWM.js} +2 -2
- package/dist/client/chunks/{chart-heat-map-v1afxnjq.js.map → chart-heat-map-DUy9_pWM.js.map} +1 -1
- package/dist/client/chunks/chart-kpi-delta-MIGGCpkG.js +351 -0
- package/dist/client/chunks/chart-kpi-delta-MIGGCpkG.js.map +1 -0
- package/dist/client/chunks/chart-kpi-number-DM0Brd91.js +473 -0
- package/dist/client/chunks/chart-kpi-number-DM0Brd91.js.map +1 -0
- package/dist/client/chunks/{chart-kpi-text-CRp8QWYG.js → chart-kpi-text-BAb28V4X.js} +3 -3
- package/dist/client/chunks/{chart-kpi-text-CRp8QWYG.js.map → chart-kpi-text-BAb28V4X.js.map} +1 -1
- package/dist/client/chunks/{chart-line-DqqE7ky9.js → chart-line-e3h8sa1R.js} +5 -5
- package/dist/client/chunks/{chart-line-DqqE7ky9.js.map → chart-line-e3h8sa1R.js.map} +1 -1
- package/dist/client/chunks/{chart-pie-B5WBzIRH.js → chart-pie-CFoHYqDB.js} +2 -2
- package/dist/client/chunks/{chart-pie-B5WBzIRH.js.map → chart-pie-CFoHYqDB.js.map} +1 -1
- package/dist/client/chunks/{chart-radar-DL_dvhA-.js → chart-radar-CPPwkfxj.js} +2 -2
- package/dist/client/chunks/{chart-radar-DL_dvhA-.js.map → chart-radar-CPPwkfxj.js.map} +1 -1
- package/dist/client/chunks/{chart-radial-bar-DDRo6nz-.js → chart-radial-bar-BdEOM-P1.js} +2 -2
- package/dist/client/chunks/{chart-radial-bar-DDRo6nz-.js.map → chart-radial-bar-BdEOM-P1.js.map} +1 -1
- package/dist/client/chunks/{chart-sankey-C_bgIfg-.js → chart-sankey-Bbady-8g.js} +2 -2
- package/dist/client/chunks/{chart-sankey-C_bgIfg-.js.map → chart-sankey-Bbady-8g.js.map} +1 -1
- package/dist/client/chunks/{chart-scatter-DjmJRlK0.js → chart-scatter-JFu0Pv3a.js} +15 -15
- package/dist/client/chunks/{chart-scatter-DjmJRlK0.js.map → chart-scatter-JFu0Pv3a.js.map} +1 -1
- package/dist/client/chunks/{chart-sunburst-CbMEnaes.js → chart-sunburst-sayxze15.js} +2 -2
- package/dist/client/chunks/{chart-sunburst-CbMEnaes.js.map → chart-sunburst-sayxze15.js.map} +1 -1
- package/dist/client/chunks/{chart-tree-map-DEfJtJVC.js → chart-tree-map-Ks2xev8b.js} +30 -30
- package/dist/client/chunks/{chart-tree-map-DEfJtJVC.js.map → chart-tree-map-Ks2xev8b.js.map} +1 -1
- package/dist/client/chunks/chartConfigRegistry-BumUIPw4.js +44 -0
- package/dist/client/chunks/{chartConfigRegistry-CiOq-PqX.js.map → chartConfigRegistry-BumUIPw4.js.map} +1 -1
- package/dist/client/chunks/charts-_yZ9gBJU.js +230 -0
- package/dist/client/chunks/charts-_yZ9gBJU.js.map +1 -0
- package/dist/client/chunks/{charts-core-CXrhEEVF.js → charts-core-Bzu9PzMd.js} +10 -10
- package/dist/client/chunks/{charts-core-CXrhEEVF.js.map → charts-core-Bzu9PzMd.js.map} +1 -1
- package/dist/client/chunks/{charts-loader-BtsnUO4Q.js → charts-loader-cMtx4zHx.js} +30 -28
- package/dist/client/chunks/charts-loader-cMtx4zHx.js.map +1 -0
- package/dist/client/chunks/{components-BDrlf9Er.js → components-DQuPThfA.js} +3575 -3208
- package/dist/client/chunks/components-DQuPThfA.js.map +1 -0
- package/dist/client/chunks/{core-B8zw0qRf.js → core-DwOXVb87.js} +2 -2
- package/dist/client/chunks/{core-B8zw0qRf.js.map → core-DwOXVb87.js.map} +1 -1
- package/dist/client/chunks/hooks-DPRv1Xhb.js +150 -0
- package/dist/client/chunks/{hooks-B8Zw5PfL.js.map → hooks-DPRv1Xhb.js.map} +1 -1
- package/dist/client/chunks/{icons-NzFHtqeM.js → icons-DRreo6m8.js} +128 -112
- package/dist/client/chunks/{icons-NzFHtqeM.js.map → icons-DRreo6m8.js.map} +1 -1
- package/dist/client/chunks/{providers-CqCiJTEj.js → providers-BW8D7Wso.js} +2 -2
- package/dist/client/chunks/{providers-CqCiJTEj.js.map → providers-BW8D7Wso.js.map} +1 -1
- package/dist/client/chunks/retention-CzCo8262.js +120 -0
- package/dist/client/chunks/retention-CzCo8262.js.map +1 -0
- package/dist/client/chunks/{useDirtyStateTracking-C_mitVwh.js → useDirtyStateTracking-Yu_qQXb-.js} +101 -99
- package/dist/client/chunks/useDirtyStateTracking-Yu_qQXb-.js.map +1 -0
- package/dist/client/chunks/{vendor-DzzxS7Ay.js → vendor-BSkQZgtm.js} +548 -540
- package/dist/client/chunks/vendor-BSkQZgtm.js.map +1 -0
- package/dist/client/components/AnalysisBuilder/AnalysisTypeSelector.d.ts +3 -1
- package/dist/client/components/AnalysisBuilder/RetentionConfigPanel.d.ts +36 -0
- package/dist/client/components/AnalysisBuilder/RetentionModeContent.d.ts +71 -0
- package/dist/client/components/AnalysisBuilder/types.d.ts +99 -0
- package/dist/client/components/DebugModal.d.ts +2 -1
- package/dist/client/components/charts/RetentionCombinedChart.config.d.ts +2 -0
- package/dist/client/components/charts/RetentionCombinedChart.d.ts +14 -0
- package/dist/client/components/charts/RetentionHeatmap.config.d.ts +2 -0
- package/dist/client/components/charts/RetentionHeatmap.d.ts +7 -0
- package/dist/client/components.js +2 -2
- package/dist/client/hooks/queries/index.d.ts +2 -1
- package/dist/client/hooks/queries/useDryRunQuery.d.ts +26 -0
- package/dist/client/hooks/queries/useExplainQuery.d.ts +3 -1
- package/dist/client/hooks/queries/useFlowQuery.d.ts +5 -0
- package/dist/client/hooks/queries/useRetentionQuery.d.ts +67 -0
- package/dist/client/hooks/useAnalysisBuilderHook.d.ts +61 -0
- package/dist/client/hooks/useAnalysisQueryExecution.d.ts +42 -1
- package/dist/client/hooks.js +3 -3
- package/dist/client/icons/customIcons.d.ts +7 -0
- package/dist/client/icons/types.d.ts +1 -0
- package/dist/client/icons.js +1 -1
- package/dist/client/index.js +11 -11
- package/dist/client/providers.js +1 -1
- package/dist/client/stores/analysisBuilderStore.d.ts +86 -1
- package/dist/client/stores/dashboardStore.d.ts +2 -1
- package/dist/client/stores/slices/index.d.ts +2 -0
- package/dist/client/stores/slices/retentionSlice.d.ts +66 -0
- package/dist/client/styles.css +1 -1
- package/dist/client/types/analysisConfig.d.ts +29 -4
- package/dist/client/types/funnel.d.ts +5 -0
- package/dist/client/types/retention.d.ts +301 -0
- package/dist/client/types.d.ts +6 -3
- package/dist/client-bundle-stats.html +1 -1
- package/dist/server/index.cjs +76 -54
- package/dist/server/index.d.ts +217 -0
- package/dist/server/index.js +7363 -4152
- package/package.json +5 -2
- package/dist/adapters/compiler-CO13DaEb.cjs +0 -192
- package/dist/client/chunks/analysis-builder-Dc9NrG_N.js +0 -6013
- package/dist/client/chunks/analysis-builder-Dc9NrG_N.js.map +0 -1
- package/dist/client/chunks/analysis-builder-shared-B3-UWqQ2.js +0 -2540
- package/dist/client/chunks/analysis-builder-shared-B3-UWqQ2.js.map +0 -1
- package/dist/client/chunks/chart-kpi-delta-Bs5R5xr4.js +0 -435
- package/dist/client/chunks/chart-kpi-delta-Bs5R5xr4.js.map +0 -1
- package/dist/client/chunks/chart-kpi-number-Cf4Pgkm9.js +0 -392
- package/dist/client/chunks/chart-kpi-number-Cf4Pgkm9.js.map +0 -1
- package/dist/client/chunks/chartConfigRegistry-CiOq-PqX.js +0 -44
- package/dist/client/chunks/charts-loader-BtsnUO4Q.js.map +0 -1
- package/dist/client/chunks/charts-xNubY0vm.js +0 -226
- package/dist/client/chunks/charts-xNubY0vm.js.map +0 -1
- package/dist/client/chunks/components-BDrlf9Er.js.map +0 -1
- package/dist/client/chunks/hooks-B8Zw5PfL.js +0 -123
- package/dist/client/chunks/useDirtyStateTracking-C_mitVwh.js.map +0 -1
- package/dist/client/chunks/vendor-DzzxS7Ay.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("express"),q=require("cors"),o=require("../compiler-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("express"),q=require("cors"),o=require("../compiler-mAJDpIQx.cjs");function R(f){const{cubes:d,drizzle:j,schema:x,extractSecurityContext:y,engineType:g,cors:h,basePath:l="/cubejs-api/v1",jsonLimit:b="10mb",cache:Q}=f;if(!d||d.length===0)throw new Error("At least one cube must be provided in the cubes array");const u=p.Router();h&&u.use(q(h)),u.use(p.json({limit:b})),u.use(p.urlencoded({extended:!0,limit:b}));const a=new o.SemanticLayerCompiler({drizzle:j,schema:x,engineType:g,cache:Q});return d.forEach(t=>{a.registerCube(t)}),u.post(`${l}/load`,async(t,r)=>{try{const e=t.body.query||t.body,s=await y(t,r),n=a.validateQuery(e);if(!n.isValid)return r.status(400).json(o.formatErrorResponse(`Query validation failed: ${n.errors.join(", ")}`,400));const i=t.headers["x-cache-control"]==="no-cache",c=await a.executeMultiCubeQuery(e,s,{skipCache:i});r.json(o.formatCubeResponse(e,c,a))}catch(e){console.error("Query execution error:",e),r.status(500).json(o.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500))}}),u.get(`${l}/load`,async(t,r)=>{try{const e=t.query.query;if(!e)return r.status(400).json(o.formatErrorResponse("Query parameter is required",400));let s;try{s=JSON.parse(e)}catch{return r.status(400).json(o.formatErrorResponse("Invalid JSON in query parameter",400))}const n=await y(t,r),i=a.validateQuery(s);if(!i.isValid)return r.status(400).json(o.formatErrorResponse(`Query validation failed: ${i.errors.join(", ")}`,400));const c=t.headers["x-cache-control"]==="no-cache",m=await a.executeMultiCubeQuery(s,n,{skipCache:c});r.json(o.formatCubeResponse(s,m,a))}catch(e){console.error("Query execution error:",e),r.status(500).json(o.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500))}}),u.post(`${l}/batch`,async(t,r)=>{try{const{queries:e}=t.body;if(!e||!Array.isArray(e))return r.status(400).json(o.formatErrorResponse('Request body must contain a "queries" array',400));if(e.length===0)return r.status(400).json(o.formatErrorResponse("Queries array cannot be empty",400));const s=await y(t,r),n=t.headers["x-cache-control"]==="no-cache",i=await o.handleBatchRequest(e,s,a,{skipCache:n});r.json(i)}catch(e){console.error("Batch execution error:",e),r.status(500).json(o.formatErrorResponse(e instanceof Error?e.message:"Batch execution failed",500))}}),u.get(`${l}/meta`,(t,r)=>{try{const e=a.getMetadata();r.json(o.formatMetaResponse(e))}catch(e){console.error("Metadata error:",e),r.status(500).json(o.formatErrorResponse(e instanceof Error?e.message:"Failed to fetch metadata",500))}}),u.post(`${l}/sql`,async(t,r)=>{try{const e=t.body,s=await y(t,r),n=a.validateQuery(e);if(!n.isValid)return r.status(400).json(o.formatErrorResponse(`Query validation failed: ${n.errors.join(", ")}`,400));const i=e.measures?.[0]||e.dimensions?.[0];if(!i)return r.status(400).json(o.formatErrorResponse("No measures or dimensions specified",400));const c=i.split(".")[0],m=await a.generateSQL(c,e,s);r.json(o.formatSqlResponse(e,m))}catch(e){console.error("SQL generation error:",e),r.status(500).json(o.formatErrorResponse(e instanceof Error?e.message:"SQL generation failed",500))}}),u.get(`${l}/sql`,async(t,r)=>{try{const e=t.query.query;if(!e)return r.status(400).json(o.formatErrorResponse("Query parameter is required",400));const s=JSON.parse(e),n=await y(t,r),i=a.validateQuery(s);if(!i.isValid)return r.status(400).json(o.formatErrorResponse(`Query validation failed: ${i.errors.join(", ")}`,400));const c=s.measures?.[0]||s.dimensions?.[0];if(!c)return r.status(400).json(o.formatErrorResponse("No measures or dimensions specified",400));const m=c.split(".")[0],C=await a.generateSQL(m,s,n);r.json(o.formatSqlResponse(s,C))}catch(e){console.error("SQL generation error:",e),r.status(500).json(o.formatErrorResponse(e instanceof Error?e.message:"SQL generation failed",500))}}),u.post(`${l}/dry-run`,async(t,r)=>{try{const e=t.body.query||t.body,s=await y(t,r),n=await o.handleDryRun(e,s,a);r.json(n)}catch(e){console.error("Dry-run error:",e),r.status(400).json({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1})}}),u.get(`${l}/dry-run`,async(t,r)=>{try{const e=t.query.query;if(!e)return r.status(400).json({error:"Query parameter is required",valid:!1});const s=JSON.parse(e),n=await y(t,r),i=await o.handleDryRun(s,n,a);r.json(i)}catch(e){console.error("Dry-run error:",e),r.status(400).json({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1})}}),u.post(`${l}/explain`,async(t,r)=>{try{const e=t.body.query||t.body,s=t.body.options||{},n=await y(t,r),i=a.validateQuery(e);if(!i.isValid)return r.status(400).json({error:`Query validation failed: ${i.errors.join(", ")}`});const c=await a.explainQuery(e,n,s);r.json(c)}catch(e){console.error("Explain error:",e),r.status(500).json({error:e instanceof Error?e.message:"Explain query failed"})}}),u.use((t,r,e,s)=>{console.error("Express adapter error:",t),e.headersSent||e.status(500).json(o.formatErrorResponse(t,500))}),u}function E(f,d){const j=R(d);return f.use("/",j),f}function v(f){const d=p();return E(d,f)}exports.createCubeApp=v;exports.createCubeRouter=R;exports.mountCubeRoutes=E;
|
|
@@ -48,7 +48,7 @@ export interface ExpressAdapterOptions {
|
|
|
48
48
|
/**
|
|
49
49
|
* Database engine type (optional - auto-detected if not provided)
|
|
50
50
|
*/
|
|
51
|
-
engineType?: 'postgres' | 'mysql' | 'sqlite';
|
|
51
|
+
engineType?: 'postgres' | 'mysql' | 'sqlite' | 'singlestore' | 'duckdb';
|
|
52
52
|
/**
|
|
53
53
|
* CORS configuration (optional)
|
|
54
54
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import h, { Router as E } from "express";
|
|
2
2
|
import R from "cors";
|
|
3
|
-
import { S, d as a, f as x, h as $, a as L, b as Q, c as g } from "../compiler-
|
|
3
|
+
import { S, d as a, f as x, h as $, a as L, b as Q, c as g } from "../compiler-DdcGVWIl.js";
|
|
4
4
|
function N(f) {
|
|
5
5
|
const {
|
|
6
6
|
cubes: d,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var w=Object.create;var E=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var $=Object.getPrototypeOf,P=Object.prototype.hasOwnProperty;var L=(u,s,g,b)=>{if(s&&typeof s=="object"||typeof s=="function")for(let y of j(s))!P.call(u,y)&&y!==g&&E(u,y,{get:()=>s[y],enumerable:!(b=S(s,y))||b.enumerable});return u};var M=(u,s,g)=>(g=u!=null?w($(u)):{},L(s||!u||!u.__esModule?E(g,"default",{value:u,enumerable:!0}):g,u));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("../compiler-
|
|
1
|
+
"use strict";var w=Object.create;var E=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var $=Object.getPrototypeOf,P=Object.prototype.hasOwnProperty;var L=(u,s,g,b)=>{if(s&&typeof s=="object"||typeof s=="function")for(let y of j(s))!P.call(u,y)&&y!==g&&E(u,y,{get:()=>s[y],enumerable:!(b=S(s,y))||b.enumerable});return u};var M=(u,s,g)=>(g=u!=null?w($(u)):{},L(s||!u||!u.__esModule?E(g,"default",{value:u,enumerable:!0}):g,u));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("../compiler-mAJDpIQx.cjs"),h=function(s,g,b){const{cubes:y,drizzle:q,schema:x,extractSecurityContext:p,engineType:C,cors:R,basePath:l="/cubejs-api/v1",bodyLimit:f=10485760,cache:v}=g;if(!y||y.length===0)return b(new Error("At least one cube must be provided in the cubes array"));R&&s.register(import("@fastify/cors"),R),s.addHook("onRequest",async(r,t)=>{r.method==="POST"&&(r.body=void 0)});const n=new a.SemanticLayerCompiler({drizzle:q,schema:x,engineType:C,cache:v});y.forEach(r=>{n.registerCube(r)}),s.post(`${l}/load`,{bodyLimit:f,schema:{body:{type:"object",additionalProperties:!0}}},async(r,t)=>{try{const e=r.body,o=e.query||e,i=await p(r),c=n.validateQuery(o);if(!c.isValid)return t.status(400).send(a.formatErrorResponse(`Query validation failed: ${c.errors.join(", ")}`,400));const d=r.headers["x-cache-control"]==="no-cache",m=await n.executeMultiCubeQuery(o,i,{skipCache:d});return a.formatCubeResponse(o,m,n)}catch(e){return r.log.error(e,"Query execution error"),t.status(500).send(a.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500))}}),s.get(`${l}/load`,{schema:{querystring:{type:"object",properties:{query:{type:"string"}},required:["query"]}}},async(r,t)=>{try{const{query:e}=r.query;let o;try{o=JSON.parse(e)}catch{return t.status(400).send(a.formatErrorResponse("Invalid JSON in query parameter",400))}const i=await p(r),c=n.validateQuery(o);if(!c.isValid)return t.status(400).send(a.formatErrorResponse(`Query validation failed: ${c.errors.join(", ")}`,400));const d=r.headers["x-cache-control"]==="no-cache",m=await n.executeMultiCubeQuery(o,i,{skipCache:d});return a.formatCubeResponse(o,m,n)}catch(e){return r.log.error(e,"Query execution error"),t.status(500).send(a.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500))}}),s.post(`${l}/batch`,{bodyLimit:f,schema:{body:{type:"object",required:["queries"],properties:{queries:{type:"array",items:{type:"object"}}}}}},async(r,t)=>{try{const{queries:e}=r.body;if(!e||!Array.isArray(e))return t.status(400).send(a.formatErrorResponse('Request body must contain a "queries" array',400));if(e.length===0)return t.status(400).send(a.formatErrorResponse("Queries array cannot be empty",400));const o=await p(r),i=r.headers["x-cache-control"]==="no-cache";return await a.handleBatchRequest(e,o,n,{skipCache:i})}catch(e){return r.log.error(e,"Batch execution error"),t.status(500).send(a.formatErrorResponse(e instanceof Error?e.message:"Batch execution failed",500))}}),s.get(`${l}/meta`,async(r,t)=>{try{const e=n.getMetadata();return a.formatMetaResponse(e)}catch(e){return r.log.error(e,"Metadata error"),t.status(500).send(a.formatErrorResponse(e instanceof Error?e.message:"Failed to fetch metadata",500))}}),s.post(`${l}/sql`,{bodyLimit:f,schema:{body:{type:"object",additionalProperties:!0}}},async(r,t)=>{try{const e=r.body,o=await p(r),i=n.validateQuery(e);if(!i.isValid)return t.status(400).send(a.formatErrorResponse(`Query validation failed: ${i.errors.join(", ")}`,400));const c=e.measures?.[0]||e.dimensions?.[0];if(!c)return t.status(400).send(a.formatErrorResponse("No measures or dimensions specified",400));const d=c.split(".")[0],m=await n.generateSQL(d,e,o);return a.formatSqlResponse(e,m)}catch(e){return r.log.error(e,"SQL generation error"),t.status(500).send(a.formatErrorResponse(e instanceof Error?e.message:"SQL generation failed",500))}}),s.get(`${l}/sql`,{schema:{querystring:{type:"object",properties:{query:{type:"string"}},required:["query"]}}},async(r,t)=>{try{const{query:e}=r.query,o=JSON.parse(e),i=await p(r),c=n.validateQuery(o);if(!c.isValid)return t.status(400).send(a.formatErrorResponse(`Query validation failed: ${c.errors.join(", ")}`,400));const d=o.measures?.[0]||o.dimensions?.[0];if(!d)return t.status(400).send(a.formatErrorResponse("No measures or dimensions specified",400));const m=d.split(".")[0],Q=await n.generateSQL(m,o,i);return a.formatSqlResponse(o,Q)}catch(e){return r.log.error(e,"SQL generation error"),t.status(500).send(a.formatErrorResponse(e instanceof Error?e.message:"SQL generation failed",500))}}),s.post(`${l}/dry-run`,{bodyLimit:f,schema:{body:{type:"object",additionalProperties:!0}}},async(r,t)=>{try{const e=r.body,o=e.query||e,i=await p(r);return await a.handleDryRun(o,i,n)}catch(e){return r.log.error(e,"Dry-run error"),t.status(400).send({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1})}}),s.get(`${l}/dry-run`,{schema:{querystring:{type:"object",properties:{query:{type:"string"}},required:["query"]}}},async(r,t)=>{try{const{query:e}=r.query,o=JSON.parse(e),i=await p(r);return await a.handleDryRun(o,i,n)}catch(e){return r.log.error(e,"Dry-run error"),t.status(400).send({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1})}}),s.post(`${l}/explain`,{bodyLimit:f,schema:{body:{type:"object",additionalProperties:!0}}},async(r,t)=>{try{const e=r.body,o=e.query||e,i=e.options||{},c=await p(r),d=n.validateQuery(o);return d.isValid?await n.explainQuery(o,c,i):t.status(400).send({error:`Query validation failed: ${d.errors.join(", ")}`})}catch(e){return r.log.error(e,"Explain error"),t.status(500).send({error:e instanceof Error?e.message:"Explain query failed"})}}),s.setErrorHandler(async(r,t,e)=>{t.log.error(r,"Fastify cube adapter error"),e.statusCode<400&&e.status(500);const o=r instanceof Error?r:String(r);return a.formatErrorResponse(o,e.statusCode)}),b()};async function N(u,s){await u.register(h,s)}function A(u){const s=require("fastify")({logger:!0});return s.register(h,u),s}exports.createCubeApp=A;exports.cubePlugin=h;exports.registerCubeRoutes=N;
|
|
@@ -47,7 +47,7 @@ export interface FastifyAdapterOptions {
|
|
|
47
47
|
/**
|
|
48
48
|
* Database engine type (optional - auto-detected if not provided)
|
|
49
49
|
*/
|
|
50
|
-
engineType?: 'postgres' | 'mysql' | 'sqlite';
|
|
50
|
+
engineType?: 'postgres' | 'mysql' | 'sqlite' | 'singlestore' | 'duckdb';
|
|
51
51
|
/**
|
|
52
52
|
* CORS configuration (optional)
|
|
53
53
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const g=require("hono"),q=require("../compiler-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const g=require("hono"),q=require("../compiler-mAJDpIQx.cjs");var b=m=>{const u={...{origin:"*",allowMethods:["GET","HEAD","PUT","POST","DELETE","PATCH"],allowHeaders:[],exposeHeaders:[]},...m},j=(i=>typeof i=="string"?i==="*"?()=>i:n=>i===n?n:null:typeof i=="function"?i:n=>i.includes(n)?n:null)(u.origin),y=(i=>typeof i=="function"?i:Array.isArray(i)?()=>i:()=>[])(u.allowMethods);return async function(n,d){function f(o,e){n.res.headers.set(o,e)}const c=await j(n.req.header("origin")||"",n);if(c&&f("Access-Control-Allow-Origin",c),u.credentials&&f("Access-Control-Allow-Credentials","true"),u.exposeHeaders?.length&&f("Access-Control-Expose-Headers",u.exposeHeaders.join(",")),n.req.method==="OPTIONS"){u.origin!=="*"&&f("Vary","Origin"),u.maxAge!=null&&f("Access-Control-Max-Age",u.maxAge.toString());const o=await y(n.req.header("origin")||"",n);o.length&&f("Access-Control-Allow-Methods",o.join(","));let e=u.allowHeaders;if(!e?.length){const r=n.req.header("Access-Control-Request-Headers");r&&(e=r.split(/\s*,\s*/))}return e?.length&&(f("Access-Control-Allow-Headers",e.join(",")),n.res.headers.append("Vary","Access-Control-Request-Headers")),n.res.headers.delete("Content-Length"),n.res.headers.delete("Content-Type"),new Response(null,{headers:n.res.headers,status:204,statusText:"No Content"})}await d(),u.origin!=="*"&&n.header("Vary","Origin",{append:!0})}};function w(m){const{cubes:p,drizzle:u,schema:j,extractSecurityContext:y,engineType:i,cors:n,basePath:d="/cubejs-api/v1",cache:f}=m;if(!p||p.length===0)throw new Error("At least one cube must be provided in the cubes array");const c=new g.Hono;n&&c.use("/*",b(n));const o=new q.SemanticLayerCompiler({drizzle:u,schema:j,engineType:i,cache:f});return p.forEach(e=>{o.registerCube(e)}),c.post(`${d}/load`,async e=>{try{const r=await e.req.json(),t=r.query||r,a=await y(e),s=o.validateQuery(t);if(!s.isValid)return e.json({error:`Query validation failed: ${s.errors.join(", ")}`},400);const l=e.req.header("x-cache-control")==="no-cache",h=await o.executeMultiCubeQuery(t,a,{skipCache:l});return e.json(q.formatCubeResponse(t,h,o))}catch(r){return console.error("Query execution error:",r),e.json({error:r instanceof Error?r.message:"Query execution failed"},500)}}),c.get(`${d}/load`,async e=>{try{const r=e.req.query("query");if(!r)return e.json({error:"Query parameter is required"},400);let t;try{t=JSON.parse(r)}catch{return e.json({error:"Invalid JSON in query parameter"},400)}const a=await y(e),s=o.validateQuery(t);if(!s.isValid)return e.json({error:`Query validation failed: ${s.errors.join(", ")}`},400);const l=e.req.header("x-cache-control")==="no-cache",h=await o.executeMultiCubeQuery(t,a,{skipCache:l});return e.json(q.formatCubeResponse(t,h,o))}catch(r){return console.error("Query execution error:",r),e.json({error:r instanceof Error?r.message:"Query execution failed"},500)}}),c.post(`${d}/batch`,async e=>{try{const r=await e.req.json(),{queries:t}=r;if(!t||!Array.isArray(t))return e.json({error:'Request body must contain a "queries" array'},400);if(t.length===0)return e.json({error:"Queries array cannot be empty"},400);const a=await y(e),s=e.req.header("x-cache-control")==="no-cache",l=await q.handleBatchRequest(t,a,o,{skipCache:s});return e.json(l)}catch(r){return console.error("Batch execution error:",r),e.json({error:r instanceof Error?r.message:"Batch execution failed"},500)}}),c.get(`${d}/meta`,e=>{try{const r=o.getMetadata();return e.json(q.formatMetaResponse(r))}catch(r){return console.error("Metadata error:",r),e.json({error:r instanceof Error?r.message:"Failed to fetch metadata"},500)}}),c.post(`${d}/sql`,async e=>{try{const r=await e.req.json(),t=await y(e),a=o.validateQuery(r);if(!a.isValid)return e.json({error:`Query validation failed: ${a.errors.join(", ")}`},400);const s=r.measures?.[0]||r.dimensions?.[0];if(!s)return e.json({error:"No measures or dimensions specified"},400);const l=s.split(".")[0],h=await o.generateSQL(l,r,t);return e.json(q.formatSqlResponse(r,h))}catch(r){return console.error("SQL generation error:",r),e.json({error:r instanceof Error?r.message:"SQL generation failed"},500)}}),c.get(`${d}/sql`,async e=>{try{const r=e.req.query("query");if(!r)return e.json({error:"Query parameter is required"},400);const t=JSON.parse(r),a=await y(e),s=o.validateQuery(t);if(!s.isValid)return e.json({error:`Query validation failed: ${s.errors.join(", ")}`},400);const l=t.measures?.[0]||t.dimensions?.[0];if(!l)return e.json({error:"No measures or dimensions specified"},400);const h=l.split(".")[0],x=await o.generateSQL(h,t,a);return e.json(q.formatSqlResponse(t,x))}catch(r){return console.error("SQL generation error:",r),e.json({error:r instanceof Error?r.message:"SQL generation failed"},500)}}),c.post(`${d}/dry-run`,async e=>{try{const r=await e.req.json(),t=r.query||r,a=await y(e),s=await q.handleDryRun(t,a,o);return e.json(s)}catch(r){return console.error("Dry-run error:",r),e.json({error:r instanceof Error?r.message:"Dry-run validation failed",valid:!1},400)}}),c.get(`${d}/dry-run`,async e=>{try{const r=e.req.query("query");if(!r)return e.json({error:"Query parameter is required",valid:!1},400);const t=JSON.parse(r),a=await y(e),s=await q.handleDryRun(t,a,o);return e.json(s)}catch(r){return console.error("Dry-run error:",r),e.json({error:r instanceof Error?r.message:"Dry-run validation failed",valid:!1},400)}}),c.post(`${d}/explain`,async e=>{try{const r=await e.req.json(),t=r.query||r,a=r.options||{},s=await y(e),l=o.validateQuery(t);if(!l.isValid)return e.json({error:`Query validation failed: ${l.errors.join(", ")}`},400);const h=await o.explainQuery(t,s,a);return e.json(h)}catch(r){return console.error("Explain error:",r),e.json({error:r instanceof Error?r.message:"Explain query failed"},500)}}),c}function C(m,p){const u=w(p);return m.route("/",u),m}function Q(m){const p=new g.Hono;return C(p,m)}exports.createCubeApp=Q;exports.createCubeRoutes=w;exports.mountCubeRoutes=C;
|
|
@@ -46,7 +46,7 @@ export interface HonoAdapterOptions {
|
|
|
46
46
|
/**
|
|
47
47
|
* Database engine type (optional - auto-detected if not provided)
|
|
48
48
|
*/
|
|
49
|
-
engineType?: 'postgres' | 'mysql' | 'sqlite';
|
|
49
|
+
engineType?: 'postgres' | 'mysql' | 'sqlite' | 'singlestore' | 'duckdb';
|
|
50
50
|
/**
|
|
51
51
|
* CORS configuration (optional)
|
|
52
52
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("next/server"),c=require("../compiler-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("next/server"),c=require("../compiler-mAJDpIQx.cjs");function h(t){const{cubes:n,drizzle:a,schema:o,engineType:f,cache:r}=t;if(!n||n.length===0)throw new Error("At least one cube must be provided in the cubes array");const i=new c.SemanticLayerCompiler({drizzle:a,schema:o,engineType:f,cache:r});return n.forEach(e=>{i.registerCube(e)}),i}function p(t,n){const a=t.headers.get("origin"),o={};return n.origin&&(typeof n.origin=="string"?o["Access-Control-Allow-Origin"]=n.origin:Array.isArray(n.origin)?a&&n.origin.includes(a)&&(o["Access-Control-Allow-Origin"]=a):typeof n.origin=="function"&&a&&n.origin(a)&&(o["Access-Control-Allow-Origin"]=a)),n.methods&&(o["Access-Control-Allow-Methods"]=n.methods.join(", ")),n.allowedHeaders&&(o["Access-Control-Allow-Headers"]=n.allowedHeaders.join(", ")),n.credentials&&(o["Access-Control-Allow-Credentials"]="true"),o}function S(t){return async function(a){const o=p(a,t);return new Response(null,{status:200,headers:o})}}function N(t){const{extractSecurityContext:n,cors:a}=t,o=h(t);return async function(r,i){try{let e;if(r.method==="POST"){const m=await r.json();e=m.query||m}else if(r.method==="GET"){const m=r.nextUrl.searchParams.get("query");if(!m)return s.NextResponse.json(c.formatErrorResponse("Query parameter is required",400),{status:400});try{e=JSON.parse(m)}catch{return s.NextResponse.json(c.formatErrorResponse("Invalid JSON in query parameter",400),{status:400})}}else return s.NextResponse.json(c.formatErrorResponse("Method not allowed",405),{status:405});const u=await n(r,i),d=o.validateQuery(e);if(!d.isValid)return s.NextResponse.json(c.formatErrorResponse(`Query validation failed: ${d.errors.join(", ")}`,400),{status:400});const l=r.headers.get("x-cache-control")==="no-cache",y=await o.executeMultiCubeQuery(e,u,{skipCache:l}),x=c.formatCubeResponse(e,y,o);return s.NextResponse.json(x,{headers:a?p(r,a):{}})}catch(e){return process.env.NODE_ENV!=="test"&&console.error("Next.js load handler error:",e),s.NextResponse.json(c.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500),{status:500})}}}function j(t){const{cors:n}=t,a=h(t);return async function(f,r){try{const i=a.getMetadata(),e=c.formatMetaResponse(i);return s.NextResponse.json(e,{headers:n?p(f,n):{}})}catch(i){return process.env.NODE_ENV!=="test"&&console.error("Next.js meta handler error:",i),s.NextResponse.json(c.formatErrorResponse(i instanceof Error?i.message:"Failed to fetch metadata",500),{status:500})}}}function E(t){const{extractSecurityContext:n,cors:a}=t,o=h(t);return async function(r,i){try{let e;if(r.method==="POST"){const R=await r.json();e=R.query||R}else if(r.method==="GET"){const R=r.nextUrl.searchParams.get("query");if(!R)return s.NextResponse.json(c.formatErrorResponse("Query parameter is required",400),{status:400});try{e=JSON.parse(R)}catch{return s.NextResponse.json(c.formatErrorResponse("Invalid JSON in query parameter",400),{status:400})}}else return s.NextResponse.json(c.formatErrorResponse("Method not allowed",405),{status:405});const u=await n(r,i),d=o.validateQuery(e);if(!d.isValid)return s.NextResponse.json(c.formatErrorResponse(`Query validation failed: ${d.errors.join(", ")}`,400),{status:400});const l=e.measures?.[0]||e.dimensions?.[0];if(!l)return s.NextResponse.json(c.formatErrorResponse("No measures or dimensions specified",400),{status:400});const y=l.split(".")[0],x=await o.generateSQL(y,e,u),m=c.formatSqlResponse(e,x);return s.NextResponse.json(m,{headers:a?p(r,a):{}})}catch(e){return process.env.NODE_ENV!=="test"&&console.error("Next.js SQL handler error:",e),s.NextResponse.json(c.formatErrorResponse(e instanceof Error?e.message:"SQL generation failed",500),{status:500})}}}function g(t){const{extractSecurityContext:n,cors:a}=t,o=h(t);return async function(r,i){try{let e;if(r.method==="POST"){const l=await r.json();e=l.query||l}else if(r.method==="GET"){const l=r.nextUrl.searchParams.get("query");if(!l)return s.NextResponse.json({error:"Query parameter is required",valid:!1},{status:400});try{e=JSON.parse(l)}catch{return s.NextResponse.json({error:"Invalid JSON in query parameter",valid:!1},{status:400})}}else return s.NextResponse.json({error:"Method not allowed",valid:!1},{status:405});const u=await n(r,i),d=await c.handleDryRun(e,u,o);return s.NextResponse.json(d,{headers:a?p(r,a):{}})}catch(e){return process.env.NODE_ENV!=="test"&&console.error("Next.js dry-run handler error:",e),s.NextResponse.json({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1},{status:400})}}}function w(t){const{extractSecurityContext:n,cors:a}=t,o=h(t);return async function(r,i){try{if(r.method!=="POST")return s.NextResponse.json(c.formatErrorResponse("Method not allowed - use POST",405),{status:405});const e=await r.json(),{queries:u}=e;if(!u||!Array.isArray(u))return s.NextResponse.json(c.formatErrorResponse('Request body must contain a "queries" array',400),{status:400});if(u.length===0)return s.NextResponse.json(c.formatErrorResponse("Queries array cannot be empty",400),{status:400});const d=await n(r,i),l=r.headers.get("x-cache-control")==="no-cache",y=await c.handleBatchRequest(u,d,o,{skipCache:l});return s.NextResponse.json(y,{headers:a?p(r,a):{}})}catch(e){return process.env.NODE_ENV!=="test"&&console.error("Next.js batch handler error:",e),s.NextResponse.json(c.formatErrorResponse(e instanceof Error?e.message:"Batch execution failed",500),{status:500})}}}function H(t){const{extractSecurityContext:n,cors:a}=t,o=h(t);return async function(r,i){try{if(r.method!=="POST")return s.NextResponse.json({error:"Method not allowed"},{status:405});const e=await r.json(),u=e.query||e,d=e.options||{},l=await n(r,i),y=o.validateQuery(u);if(!y.isValid)return s.NextResponse.json({error:`Query validation failed: ${y.errors.join(", ")}`},{status:400});const x=await o.explainQuery(u,l,d);return s.NextResponse.json(x,{headers:a?p(r,a):{}})}catch(e){return process.env.NODE_ENV!=="test"&&console.error("Next.js explain handler error:",e),s.NextResponse.json({error:e instanceof Error?e.message:"Explain query failed"},{status:500})}}}function v(t){return{load:N(t),meta:j(t),sql:E(t),dryRun:g(t),batch:w(t),explain:H(t)}}exports.createBatchHandler=w;exports.createCubeHandlers=v;exports.createDryRunHandler=g;exports.createExplainHandler=H;exports.createLoadHandler=N;exports.createMetaHandler=j;exports.createOptionsHandler=S;exports.createSqlHandler=E;
|
|
@@ -65,7 +65,7 @@ export interface NextAdapterOptions {
|
|
|
65
65
|
/**
|
|
66
66
|
* Database engine type (optional - auto-detected if not provided)
|
|
67
67
|
*/
|
|
68
|
-
engineType?: 'postgres' | 'mysql' | 'sqlite';
|
|
68
|
+
engineType?: 'postgres' | 'mysql' | 'sqlite' | 'singlestore' | 'duckdb';
|
|
69
69
|
/**
|
|
70
70
|
* CORS configuration (optional)
|
|
71
71
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NextResponse as a } from "next/server";
|
|
2
|
-
import { d as i, f as w, a as p, b as N, c as E, h as C, S } from "../compiler-
|
|
2
|
+
import { d as i, f as w, a as p, b as N, c as E, h as C, S } from "../compiler-DdcGVWIl.js";
|
|
3
3
|
function j(t) {
|
|
4
4
|
const { cubes: n, drizzle: s, schema: o, engineType: y, cache: r } = t;
|
|
5
5
|
if (!n || n.length === 0)
|
package/dist/adapters/utils.d.ts
CHANGED
|
@@ -85,6 +85,33 @@ export declare function handleDryRun(query: SemanticQuery, securityContext: Secu
|
|
|
85
85
|
sql: string;
|
|
86
86
|
params: any[];
|
|
87
87
|
};
|
|
88
|
+
} | {
|
|
89
|
+
queryType: string;
|
|
90
|
+
normalizedQueries: never[];
|
|
91
|
+
queryOrder: string[];
|
|
92
|
+
transformedQueries: never[];
|
|
93
|
+
pivotQuery: {
|
|
94
|
+
measures: never[];
|
|
95
|
+
dimensions: never[];
|
|
96
|
+
timeDimensions: never[];
|
|
97
|
+
order: {};
|
|
98
|
+
filters: never[];
|
|
99
|
+
queryType: string;
|
|
100
|
+
joinType: string;
|
|
101
|
+
query: SemanticQuery;
|
|
102
|
+
retention: {
|
|
103
|
+
timeDimension: string | import('../server').RetentionTimeDimensionMapping;
|
|
104
|
+
bindingKey: string | import('../server').RetentionBindingKeyMapping[];
|
|
105
|
+
granularity: "day" | "week" | "month";
|
|
106
|
+
periods: number;
|
|
107
|
+
retentionType: "classic" | "rolling";
|
|
108
|
+
breakdownDimensions: string[] | undefined;
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
sql: {
|
|
112
|
+
sql: string;
|
|
113
|
+
params: any[];
|
|
114
|
+
};
|
|
88
115
|
} | {
|
|
89
116
|
queryType: string;
|
|
90
117
|
normalizedQueries: {
|
|
@@ -173,6 +200,7 @@ export declare function formatCubeResponse(query: SemanticQuery, result: {
|
|
|
173
200
|
fillMissingDatesValue?: number | null;
|
|
174
201
|
funnel?: import('../server').FunnelQueryConfig;
|
|
175
202
|
flow?: import('../server/types/flow').FlowQueryConfig;
|
|
203
|
+
retention?: import('../server').RetentionQueryConfig;
|
|
176
204
|
};
|
|
177
205
|
slowQuery: boolean;
|
|
178
206
|
};
|
|
@@ -259,6 +287,7 @@ export declare function handleBatchRequest(queries: SemanticQuery[], securityCon
|
|
|
259
287
|
fillMissingDatesValue?: number | null;
|
|
260
288
|
funnel?: import('../server').FunnelQueryConfig;
|
|
261
289
|
flow?: import('../server/types/flow').FlowQueryConfig;
|
|
290
|
+
retention?: import('../server').RetentionQueryConfig;
|
|
262
291
|
};
|
|
263
292
|
slowQuery: boolean;
|
|
264
293
|
success: boolean;
|
|
@@ -11,6 +11,8 @@ export type { QuerySliceState } from './queryModeAdapter';
|
|
|
11
11
|
export { funnelModeAdapter } from './funnelModeAdapter';
|
|
12
12
|
export type { FunnelSliceState } from './funnelModeAdapter';
|
|
13
13
|
export { flowModeAdapter } from './flowModeAdapter';
|
|
14
|
+
export { retentionModeAdapter } from './retentionModeAdapter';
|
|
15
|
+
export type { RetentionSliceState } from '../types/retention';
|
|
14
16
|
/**
|
|
15
17
|
* Manually initialize and register all adapters.
|
|
16
18
|
*
|
package/dist/client/charts.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { L as t, g as e, c as s, b as o, i as C, p as h, a as f } from "./chunks/charts-loader-
|
|
2
|
-
import { k as p, f as i, e as d, h as R, i as c, l as g, p as m, j as n, u as x } from "./chunks/charts-
|
|
3
|
-
import {
|
|
4
|
-
import { default as b } from "./chunks/chart-bar-
|
|
5
|
-
import { default as I } from "./chunks/chart-line-
|
|
6
|
-
import { default as v } from "./chunks/chart-area-
|
|
7
|
-
import { default as N } from "./chunks/chart-pie-
|
|
8
|
-
import { default as V } from "./chunks/chart-scatter-
|
|
9
|
-
import { default as D } from "./chunks/chart-radar-
|
|
10
|
-
import { default as H } from "./chunks/chart-radial-bar-
|
|
11
|
-
import { default as j } from "./chunks/chart-tree-map-
|
|
12
|
-
import { default as z } from "./chunks/chart-data-table-
|
|
1
|
+
import { L as t, g as e, c as s, b as o, i as C, p as h, a as f } from "./chunks/charts-loader-cMtx4zHx.js";
|
|
2
|
+
import { k as p, f as i, e as d, h as R, i as c, l as g, p as m, j as n, u as x } from "./chunks/charts-_yZ9gBJU.js";
|
|
3
|
+
import { c as T, C as A, N as y, P as L } from "./chunks/charts-core-Bzu9PzMd.js";
|
|
4
|
+
import { default as b } from "./chunks/chart-bar-BFAdRj-E.js";
|
|
5
|
+
import { default as I } from "./chunks/chart-line-e3h8sa1R.js";
|
|
6
|
+
import { default as v } from "./chunks/chart-area-DZcxSVB1.js";
|
|
7
|
+
import { default as N } from "./chunks/chart-pie-CFoHYqDB.js";
|
|
8
|
+
import { default as V } from "./chunks/chart-scatter-JFu0Pv3a.js";
|
|
9
|
+
import { default as D } from "./chunks/chart-radar-CPPwkfxj.js";
|
|
10
|
+
import { default as H } from "./chunks/chart-radial-bar-BdEOM-P1.js";
|
|
11
|
+
import { default as j } from "./chunks/chart-tree-map-Ks2xev8b.js";
|
|
12
|
+
import { default as z } from "./chunks/chart-data-table-kudRwZxJ.js";
|
|
13
13
|
export {
|
|
14
14
|
T as CHART_COLORS,
|
|
15
15
|
A as CHART_MARGINS,
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { jsx as e, jsxs as l } from "react/jsx-runtime";
|
|
2
|
+
import E, { useState as M, useMemo as T } from "react";
|
|
3
|
+
import { ComposedChart as O, CartesianGrid as W, XAxis as F, YAxis as B, Legend as I, Line as X } from "recharts";
|
|
4
|
+
import { a as Y, C as q, b as J, c as $ } from "./charts-core-Bzu9PzMd.js";
|
|
5
|
+
import { i as K } from "./retention-CzCo8262.js";
|
|
6
|
+
function Q(i) {
|
|
7
|
+
return `rgba(34, 197, 94, ${0.1 + Math.max(0, Math.min(1, i)) * 0.7})`;
|
|
8
|
+
}
|
|
9
|
+
function v(i) {
|
|
10
|
+
return `${Math.round(i * 100)}%`;
|
|
11
|
+
}
|
|
12
|
+
function g(i, r) {
|
|
13
|
+
const c = r === "day" ? "Day" : r === "week" ? "Week" : r === "month" ? "Month" : "P";
|
|
14
|
+
return i === 0 ? r ? `< 1 ${c}` : "P0" : r ? `${c} ${i}` : `P${i}`;
|
|
15
|
+
}
|
|
16
|
+
function Z(i) {
|
|
17
|
+
return "Total";
|
|
18
|
+
}
|
|
19
|
+
function ee(i) {
|
|
20
|
+
return i ? `${i} Retention` : "Retention";
|
|
21
|
+
}
|
|
22
|
+
function te(i, r, c, h, b) {
|
|
23
|
+
const u = ee(b);
|
|
24
|
+
return !c || c.length === 0 ? { chartData: r.map((m) => {
|
|
25
|
+
const t = i.find((d) => d.period === m && !d.breakdownValue);
|
|
26
|
+
return {
|
|
27
|
+
period: m,
|
|
28
|
+
periodLabel: g(m, h),
|
|
29
|
+
[u]: t ? t.retentionRate : null,
|
|
30
|
+
cohortSize: t?.cohortSize ?? 0,
|
|
31
|
+
retainedUsers: t?.retainedUsers ?? 0
|
|
32
|
+
};
|
|
33
|
+
}), seriesKeys: [u], defaultSeriesName: u } : { chartData: r.map((s) => {
|
|
34
|
+
const m = {
|
|
35
|
+
period: s,
|
|
36
|
+
periodLabel: g(s, h)
|
|
37
|
+
};
|
|
38
|
+
return c.forEach((t) => {
|
|
39
|
+
const d = i.find((p) => p.period === s && p.breakdownValue === t);
|
|
40
|
+
m[t] = d ? d.retentionRate : null, m[`${t}_cohortSize`] = d?.cohortSize ?? 0, m[`${t}_retainedUsers`] = d?.retainedUsers ?? 0;
|
|
41
|
+
}), m;
|
|
42
|
+
}), seriesKeys: c, defaultSeriesName: u };
|
|
43
|
+
}
|
|
44
|
+
const se = E.memo(function({
|
|
45
|
+
data: r,
|
|
46
|
+
height: c = "100%",
|
|
47
|
+
displayConfig: h,
|
|
48
|
+
colorPalette: b
|
|
49
|
+
}) {
|
|
50
|
+
const [u, N] = M(null), [s, m] = M(null), t = T(() => {
|
|
51
|
+
if (!r) return null;
|
|
52
|
+
if (K(r))
|
|
53
|
+
return r;
|
|
54
|
+
if (Array.isArray(r) && r.length > 0) {
|
|
55
|
+
const a = r, x = [...new Set(a.map((o) => o.period))].sort((o, y) => o - y), n = [
|
|
56
|
+
...new Set(a.filter((o) => o.breakdownValue).map((o) => o.breakdownValue))
|
|
57
|
+
];
|
|
58
|
+
return {
|
|
59
|
+
rows: a,
|
|
60
|
+
periods: x,
|
|
61
|
+
breakdownValues: n.length > 0 ? n : void 0
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}, [r]), { chartData: d, seriesKeys: p, defaultSeriesName: A } = T(() => t ? te(
|
|
66
|
+
t.rows,
|
|
67
|
+
t.periods,
|
|
68
|
+
t.breakdownValues,
|
|
69
|
+
t.granularity,
|
|
70
|
+
t.bindingKeyLabel
|
|
71
|
+
) : { chartData: [], seriesKeys: [], defaultSeriesName: "Retention" }, [t]), U = Z(), R = h?.retentionDisplayMode || "line", _ = h?.showLegend ?? !0, V = h?.showGrid ?? !0, H = h?.showTooltip ?? !0;
|
|
72
|
+
if (!r || Array.isArray(r) && r.length === 0)
|
|
73
|
+
return /* @__PURE__ */ e(
|
|
74
|
+
"div",
|
|
75
|
+
{
|
|
76
|
+
className: "flex items-center justify-center w-full text-dc-text-muted",
|
|
77
|
+
style: { height: c },
|
|
78
|
+
children: /* @__PURE__ */ l("div", { className: "text-center", children: [
|
|
79
|
+
/* @__PURE__ */ e("div", { className: "text-sm font-semibold mb-1", children: "No data available" }),
|
|
80
|
+
/* @__PURE__ */ e("div", { className: "text-xs text-dc-text-secondary", children: "Configure retention analysis to see results" })
|
|
81
|
+
] })
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
if (!d || d.length === 0)
|
|
85
|
+
return /* @__PURE__ */ e(
|
|
86
|
+
"div",
|
|
87
|
+
{
|
|
88
|
+
className: "flex items-center justify-center w-full text-dc-text-muted",
|
|
89
|
+
style: { height: c },
|
|
90
|
+
children: /* @__PURE__ */ l("div", { className: "text-center", children: [
|
|
91
|
+
/* @__PURE__ */ e("div", { className: "text-sm font-semibold mb-1", children: "Unable to render retention data" }),
|
|
92
|
+
/* @__PURE__ */ e("div", { className: "text-xs text-dc-text-secondary", children: "Data format may be incorrect" })
|
|
93
|
+
] })
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
const C = (a) => {
|
|
97
|
+
const x = {
|
|
98
|
+
...q,
|
|
99
|
+
left: 50,
|
|
100
|
+
right: 20
|
|
101
|
+
};
|
|
102
|
+
return /* @__PURE__ */ e(Y, { height: a, children: /* @__PURE__ */ l(O, { data: d, margin: x, children: [
|
|
103
|
+
V && /* @__PURE__ */ e(W, { strokeDasharray: "3 3" }),
|
|
104
|
+
/* @__PURE__ */ e(
|
|
105
|
+
F,
|
|
106
|
+
{
|
|
107
|
+
dataKey: "periodLabel",
|
|
108
|
+
tick: { fontSize: 12 },
|
|
109
|
+
axisLine: { stroke: "var(--dc-border)" },
|
|
110
|
+
tickLine: { stroke: "var(--dc-border)" }
|
|
111
|
+
}
|
|
112
|
+
),
|
|
113
|
+
/* @__PURE__ */ e(
|
|
114
|
+
B,
|
|
115
|
+
{
|
|
116
|
+
domain: [0, 1],
|
|
117
|
+
tickFormatter: (n) => v(n),
|
|
118
|
+
tick: { fontSize: 12 },
|
|
119
|
+
axisLine: { stroke: "var(--dc-border)" },
|
|
120
|
+
tickLine: { stroke: "var(--dc-border)" },
|
|
121
|
+
label: {
|
|
122
|
+
value: "Retention %",
|
|
123
|
+
angle: -90,
|
|
124
|
+
position: "insideLeft",
|
|
125
|
+
style: { textAnchor: "middle", fontSize: "12px", fill: "var(--dc-text-secondary)" }
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
),
|
|
129
|
+
H && /* @__PURE__ */ e(
|
|
130
|
+
J,
|
|
131
|
+
{
|
|
132
|
+
formatter: (n, o) => n == null ? ["No data", o] : [v(n), o],
|
|
133
|
+
labelFormatter: (n) => n
|
|
134
|
+
}
|
|
135
|
+
),
|
|
136
|
+
_ && /* @__PURE__ */ e(
|
|
137
|
+
I,
|
|
138
|
+
{
|
|
139
|
+
wrapperStyle: { fontSize: "12px", paddingTop: "10px" },
|
|
140
|
+
iconType: "line",
|
|
141
|
+
iconSize: 8,
|
|
142
|
+
layout: "horizontal",
|
|
143
|
+
align: "center",
|
|
144
|
+
verticalAlign: "bottom",
|
|
145
|
+
onMouseEnter: (n) => N(String(n.dataKey || "")),
|
|
146
|
+
onMouseLeave: () => N(null)
|
|
147
|
+
}
|
|
148
|
+
),
|
|
149
|
+
p.map((n, o) => /* @__PURE__ */ e(
|
|
150
|
+
X,
|
|
151
|
+
{
|
|
152
|
+
type: "monotone",
|
|
153
|
+
dataKey: n,
|
|
154
|
+
stroke: b?.colors && b.colors[o % b.colors.length] || $[o % $.length],
|
|
155
|
+
strokeWidth: 2,
|
|
156
|
+
dot: { r: 4, strokeWidth: 2 },
|
|
157
|
+
activeDot: { r: 6 },
|
|
158
|
+
strokeOpacity: u ? u === n ? 1 : 0.3 : 1,
|
|
159
|
+
connectNulls: !1
|
|
160
|
+
},
|
|
161
|
+
n
|
|
162
|
+
))
|
|
163
|
+
] }) });
|
|
164
|
+
}, D = () => /* @__PURE__ */ l("table", { className: "w-full border-collapse text-sm", children: [
|
|
165
|
+
/* @__PURE__ */ e("thead", { className: "sticky top-0 bg-dc-bg z-10", children: /* @__PURE__ */ l("tr", { children: [
|
|
166
|
+
/* @__PURE__ */ e("th", { className: "text-left p-2 font-medium text-dc-text border-b border-dc-border min-w-[100px] whitespace-nowrap", children: t?.breakdownValues?.length ? "Segment" : "Cohort" }),
|
|
167
|
+
/* @__PURE__ */ e("th", { className: "text-right p-2 font-medium text-dc-text border-b border-dc-border min-w-[60px] whitespace-nowrap", children: U }),
|
|
168
|
+
t?.periods.map((a) => /* @__PURE__ */ e(
|
|
169
|
+
"th",
|
|
170
|
+
{
|
|
171
|
+
className: "text-center p-2 font-medium text-dc-text border-b border-dc-border min-w-[70px] whitespace-nowrap",
|
|
172
|
+
children: g(a, t?.granularity)
|
|
173
|
+
},
|
|
174
|
+
a
|
|
175
|
+
))
|
|
176
|
+
] }) }),
|
|
177
|
+
/* @__PURE__ */ e("tbody", { children: p.map((a, x) => {
|
|
178
|
+
const n = d.find((w) => w.period === 0), o = a === A, y = o ? n?.cohortSize ?? 0 : n?.[`${a}_cohortSize`] ?? 0;
|
|
179
|
+
return /* @__PURE__ */ l(
|
|
180
|
+
"tr",
|
|
181
|
+
{
|
|
182
|
+
className: x % 2 === 0 ? "bg-dc-bg" : "bg-dc-surface-secondary",
|
|
183
|
+
children: [
|
|
184
|
+
/* @__PURE__ */ e("td", { className: "p-2 font-medium text-dc-text border-b border-dc-border whitespace-nowrap", children: a }),
|
|
185
|
+
/* @__PURE__ */ e("td", { className: "p-2 text-right text-dc-text-secondary border-b border-dc-border", children: y.toLocaleString() }),
|
|
186
|
+
t?.periods.map((w) => {
|
|
187
|
+
const S = d.find((k) => k.period === w), f = S?.[a] ?? 0, P = f > 0 ? Q(f) : "transparent", j = f > 0.5 ? "#ffffff" : "var(--dc-text)";
|
|
188
|
+
return /* @__PURE__ */ e(
|
|
189
|
+
"td",
|
|
190
|
+
{
|
|
191
|
+
className: "p-2 text-center border-b border-dc-border cursor-default transition-opacity hover:opacity-80",
|
|
192
|
+
style: { backgroundColor: P, color: j },
|
|
193
|
+
onMouseEnter: (k) => {
|
|
194
|
+
const L = k.currentTarget.getBoundingClientRect(), G = o ? S?.retainedUsers ?? 0 : S?.[`${a}_retainedUsers`] ?? 0;
|
|
195
|
+
m({
|
|
196
|
+
period: w,
|
|
197
|
+
breakdownValue: o ? null : a,
|
|
198
|
+
cohortSize: y,
|
|
199
|
+
retainedUsers: G,
|
|
200
|
+
retentionRate: f,
|
|
201
|
+
x: L.left + L.width / 2,
|
|
202
|
+
y: L.top
|
|
203
|
+
});
|
|
204
|
+
},
|
|
205
|
+
onMouseLeave: () => m(null),
|
|
206
|
+
children: f > 0 ? v(f) : "-"
|
|
207
|
+
},
|
|
208
|
+
w
|
|
209
|
+
);
|
|
210
|
+
})
|
|
211
|
+
]
|
|
212
|
+
},
|
|
213
|
+
a
|
|
214
|
+
);
|
|
215
|
+
}) })
|
|
216
|
+
] }), z = () => s && /* @__PURE__ */ l(
|
|
217
|
+
"div",
|
|
218
|
+
{
|
|
219
|
+
className: "fixed z-50 px-3 py-2 bg-dc-surface border border-dc-border rounded shadow-lg text-sm pointer-events-none",
|
|
220
|
+
style: {
|
|
221
|
+
left: s.x,
|
|
222
|
+
top: s.y - 10,
|
|
223
|
+
transform: "translate(-50%, -100%)"
|
|
224
|
+
},
|
|
225
|
+
children: [
|
|
226
|
+
/* @__PURE__ */ e("div", { className: "font-medium text-dc-text mb-1", children: s.breakdownValue ? `${s.breakdownValue} - ${g(s.period, t?.granularity)}` : g(s.period, t?.granularity) }),
|
|
227
|
+
/* @__PURE__ */ l("div", { className: "text-dc-text-secondary space-y-0.5", children: [
|
|
228
|
+
/* @__PURE__ */ l("div", { children: [
|
|
229
|
+
"Cohort Size: ",
|
|
230
|
+
s.cohortSize.toLocaleString()
|
|
231
|
+
] }),
|
|
232
|
+
/* @__PURE__ */ l("div", { children: [
|
|
233
|
+
"Retained: ",
|
|
234
|
+
s.retainedUsers.toLocaleString()
|
|
235
|
+
] }),
|
|
236
|
+
/* @__PURE__ */ l("div", { className: "font-medium text-dc-text", children: [
|
|
237
|
+
"Rate: ",
|
|
238
|
+
v(s.retentionRate)
|
|
239
|
+
] })
|
|
240
|
+
] })
|
|
241
|
+
]
|
|
242
|
+
}
|
|
243
|
+
);
|
|
244
|
+
return R === "heatmap" ? /* @__PURE__ */ l("div", { className: "relative w-full h-full overflow-auto", style: { height: c }, children: [
|
|
245
|
+
D(),
|
|
246
|
+
z()
|
|
247
|
+
] }) : R === "combined" ? /* @__PURE__ */ l("div", { className: "flex flex-col w-full h-full", style: { height: c }, children: [
|
|
248
|
+
/* @__PURE__ */ e("div", { className: "flex-1 min-h-[200px]", children: C("100%") }),
|
|
249
|
+
/* @__PURE__ */ e("div", { className: "flex-shrink-0 max-h-[40%] overflow-auto border-t border-dc-border", children: D() }),
|
|
250
|
+
z()
|
|
251
|
+
] }) : C(c);
|
|
252
|
+
});
|
|
253
|
+
export {
|
|
254
|
+
se as default
|
|
255
|
+
};
|
|
256
|
+
//# sourceMappingURL=RetentionCombinedChart-CqMAkdcR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RetentionCombinedChart-CqMAkdcR.js","sources":["../../../src/client/components/charts/RetentionCombinedChart.tsx"],"sourcesContent":["/**\n * RetentionCombinedChart Component\n *\n * Combined visualization for retention analysis data.\n * Supports multiple display modes: heatmap, line chart, or combined view.\n *\n * Features:\n * - X-axis: Period numbers (P0, P1, P2...)\n * - Y-axis: Retention % (0-100%)\n * - Lines: One per breakdown value (or single if no breakdown)\n * - Display modes: 'heatmap' | 'line' | 'combined'\n * - Heatmap shows color-coded retention matrix\n * - Line chart shows retention curves over periods\n */\n\nimport React, { useMemo, useState } from 'react'\nimport {\n ComposedChart,\n Line,\n XAxis,\n YAxis,\n CartesianGrid,\n Legend,\n} from 'recharts'\nimport ChartContainer from './ChartContainer'\nimport ChartTooltip from './ChartTooltip'\nimport { CHART_COLORS, CHART_MARGINS } from '../../utils/chartConstants'\nimport type { ChartProps } from '../../types'\nimport type { RetentionChartData, RetentionResultRow, RetentionGranularity } from '../../types/retention'\nimport { isRetentionData } from '../../types/retention'\n\n/**\n * Retention display mode\n * - 'heatmap': Show retention as color-coded bars\n * - 'line': Show retention as line curves\n * - 'combined': Show both heatmap background and line overlay\n */\nexport type RetentionDisplayMode = 'heatmap' | 'line' | 'combined'\n\n/**\n * Get color with opacity based on retention rate for heatmap cells\n * Uses a green gradient: higher retention = more saturated green\n */\nfunction getRetentionColor(rate: number): string {\n const clampedRate = Math.max(0, Math.min(1, rate))\n const alpha = 0.1 + clampedRate * 0.7\n return `rgba(34, 197, 94, ${alpha})`\n}\n\n/**\n * Format percentage for display\n */\nfunction formatPercentage(rate: number): string {\n return `${Math.round(rate * 100)}%`\n}\n\n/**\n * Format period label based on granularity\n * Period 0 shows \"< 1 Day\" / \"< 1 Week\" etc. to indicate the initial cohort\n * e.g., Period 0 with 'week' granularity → \"< 1 Week\", Period 1 → \"Week 1\"\n */\nfunction formatPeriodLabel(period: number, granularity?: RetentionGranularity): string {\n const prefix = granularity === 'day' ? 'Day'\n : granularity === 'week' ? 'Week'\n : granularity === 'month' ? 'Month'\n : 'P' // Fallback to P0, P1, etc.\n\n // Period 0 is special - shows \"< 1 Day\" / \"< 1 Week\" etc.\n if (period === 0) {\n return granularity ? `< 1 ${prefix}` : 'P0'\n }\n\n return granularity ? `${prefix} ${period}` : `P${period}`\n}\n\n/**\n * Get display label for the cohort total column\n * Shows \"Total\" regardless of binding key - it's the cohort size count\n */\nfunction getCohortLabel(_bindingKeyLabel?: string): string {\n return 'Total'\n}\n\n/**\n * Get default series name based on binding key\n * e.g., \"userId\" → \"userId Retention\", null → \"Retention\"\n */\nfunction getDefaultSeriesName(bindingKeyLabel?: string): string {\n if (!bindingKeyLabel) return 'Retention'\n return `${bindingKeyLabel} Retention`\n}\n\n/**\n * Transform retention data for chart display\n * Groups data by period with breakdown values as series\n */\nfunction transformRetentionData(\n rows: RetentionResultRow[],\n periods: number[],\n breakdownValues?: string[],\n granularity?: RetentionGranularity,\n bindingKeyLabel?: string\n): { chartData: any[]; seriesKeys: string[]; defaultSeriesName: string } {\n const defaultSeriesName = getDefaultSeriesName(bindingKeyLabel)\n\n // If no breakdown, single series\n if (!breakdownValues || breakdownValues.length === 0) {\n const chartData = periods.map((period) => {\n const row = rows.find((r) => r.period === period && !r.breakdownValue)\n return {\n period,\n periodLabel: formatPeriodLabel(period, granularity),\n [defaultSeriesName]: row ? row.retentionRate : null,\n cohortSize: row?.cohortSize ?? 0,\n retainedUsers: row?.retainedUsers ?? 0,\n }\n })\n return { chartData, seriesKeys: [defaultSeriesName], defaultSeriesName }\n }\n\n // With breakdown, create series per breakdown value\n const chartData = periods.map((period) => {\n const dataPoint: any = {\n period,\n periodLabel: formatPeriodLabel(period, granularity),\n }\n\n breakdownValues.forEach((bv) => {\n const row = rows.find((r) => r.period === period && r.breakdownValue === bv)\n dataPoint[bv] = row ? row.retentionRate : null\n dataPoint[`${bv}_cohortSize`] = row?.cohortSize ?? 0\n dataPoint[`${bv}_retainedUsers`] = row?.retainedUsers ?? 0\n })\n\n return dataPoint\n })\n\n return { chartData, seriesKeys: breakdownValues, defaultSeriesName }\n}\n\ninterface TooltipData {\n period: number\n breakdownValue?: string | null\n cohortSize: number\n retainedUsers: number\n retentionRate: number\n x: number\n y: number\n}\n\n/**\n * RetentionCombinedChart Component\n */\nconst RetentionCombinedChart = React.memo(function RetentionCombinedChart({\n data,\n height = '100%',\n displayConfig,\n colorPalette,\n}: ChartProps) {\n const [hoveredLegend, setHoveredLegend] = useState<string | null>(null)\n const [heatmapTooltip, setHeatmapTooltip] = useState<TooltipData | null>(null)\n\n // Parse retention data\n const retentionData = useMemo<RetentionChartData | null>(() => {\n if (!data) return null\n\n // Check if data is already in RetentionChartData format\n if (isRetentionData(data)) {\n return data\n }\n\n // If data is an array of RetentionResultRow, convert it\n if (Array.isArray(data) && data.length > 0) {\n const rows = data as RetentionResultRow[]\n const periods = [...new Set(rows.map((r) => r.period))].sort((a, b) => a - b)\n const breakdownValues = [\n ...new Set(rows.filter((r) => r.breakdownValue).map((r) => r.breakdownValue!)),\n ]\n\n return {\n rows,\n periods,\n breakdownValues: breakdownValues.length > 0 ? breakdownValues : undefined,\n }\n }\n\n return null\n }, [data])\n\n // Transform data for chart\n const { chartData, seriesKeys, defaultSeriesName } = useMemo(() => {\n if (!retentionData) {\n return { chartData: [], seriesKeys: [], defaultSeriesName: 'Retention' }\n }\n return transformRetentionData(\n retentionData.rows,\n retentionData.periods,\n retentionData.breakdownValues,\n retentionData.granularity,\n retentionData.bindingKeyLabel\n )\n }, [retentionData])\n\n // Get cohort label for heatmap column header\n const cohortLabel = getCohortLabel(retentionData?.bindingKeyLabel)\n\n // Display mode from config\n const displayMode: RetentionDisplayMode =\n (displayConfig as any)?.retentionDisplayMode || 'line'\n\n const showLegend = displayConfig?.showLegend ?? true\n const showGrid = displayConfig?.showGrid ?? true\n const showTooltip = displayConfig?.showTooltip ?? true\n\n // Handle empty/loading states\n if (!data || (Array.isArray(data) && data.length === 0)) {\n return (\n <div\n className=\"flex items-center justify-center w-full text-dc-text-muted\"\n style={{ height }}\n >\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">No data available</div>\n <div className=\"text-xs text-dc-text-secondary\">\n Configure retention analysis to see results\n </div>\n </div>\n </div>\n )\n }\n\n if (!chartData || chartData.length === 0) {\n return (\n <div\n className=\"flex items-center justify-center w-full text-dc-text-muted\"\n style={{ height }}\n >\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">Unable to render retention data</div>\n <div className=\"text-xs text-dc-text-secondary\">Data format may be incorrect</div>\n </div>\n </div>\n )\n }\n\n // Render line chart component (reused in line and combined modes)\n const renderLineChart = (chartHeight: string | number) => {\n const chartMargins = {\n ...CHART_MARGINS,\n left: 50,\n right: 20,\n }\n\n return (\n <ChartContainer height={chartHeight}>\n <ComposedChart data={chartData} margin={chartMargins}>\n {showGrid && <CartesianGrid strokeDasharray=\"3 3\" />}\n <XAxis\n dataKey=\"periodLabel\"\n tick={{ fontSize: 12 }}\n axisLine={{ stroke: 'var(--dc-border)' }}\n tickLine={{ stroke: 'var(--dc-border)' }}\n />\n <YAxis\n domain={[0, 1]}\n tickFormatter={(value) => formatPercentage(value)}\n tick={{ fontSize: 12 }}\n axisLine={{ stroke: 'var(--dc-border)' }}\n tickLine={{ stroke: 'var(--dc-border)' }}\n label={{\n value: 'Retention %',\n angle: -90,\n position: 'insideLeft',\n style: { textAnchor: 'middle', fontSize: '12px', fill: 'var(--dc-text-secondary)' },\n }}\n />\n {showTooltip && (\n <ChartTooltip\n formatter={(value: any, name: string) => {\n if (value === null || value === undefined) {\n return ['No data', name]\n }\n return [formatPercentage(value), name]\n }}\n labelFormatter={(label: string) => label}\n />\n )}\n {showLegend && (\n <Legend\n wrapperStyle={{ fontSize: '12px', paddingTop: '10px' }}\n iconType=\"line\"\n iconSize={8}\n layout=\"horizontal\"\n align=\"center\"\n verticalAlign=\"bottom\"\n onMouseEnter={(o) => setHoveredLegend(String(o.dataKey || ''))}\n onMouseLeave={() => setHoveredLegend(null)}\n />\n )}\n\n {/* Render lines */}\n {seriesKeys.map((seriesKey, index) => (\n <Line\n key={seriesKey}\n type=\"monotone\"\n dataKey={seriesKey}\n stroke={\n (colorPalette?.colors && colorPalette.colors[index % colorPalette.colors.length]) ||\n CHART_COLORS[index % CHART_COLORS.length]\n }\n strokeWidth={2}\n dot={{ r: 4, strokeWidth: 2 }}\n activeDot={{ r: 6 }}\n strokeOpacity={hoveredLegend ? (hoveredLegend === seriesKey ? 1 : 0.3) : 1}\n connectNulls={false}\n />\n ))}\n </ComposedChart>\n </ChartContainer>\n )\n }\n\n // Render heatmap table component (reused in heatmap and combined modes)\n const renderHeatmapTable = () => (\n <table className=\"w-full border-collapse text-sm\">\n <thead className=\"sticky top-0 bg-dc-bg z-10\">\n <tr>\n <th className=\"text-left p-2 font-medium text-dc-text border-b border-dc-border min-w-[100px] whitespace-nowrap\">\n {retentionData?.breakdownValues?.length ? 'Segment' : 'Cohort'}\n </th>\n <th className=\"text-right p-2 font-medium text-dc-text border-b border-dc-border min-w-[60px] whitespace-nowrap\">\n {cohortLabel}\n </th>\n {retentionData?.periods.map((period) => (\n <th\n key={period}\n className=\"text-center p-2 font-medium text-dc-text border-b border-dc-border min-w-[70px] whitespace-nowrap\"\n >\n {formatPeriodLabel(period, retentionData?.granularity)}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {seriesKeys.map((seriesKey, rowIndex) => {\n const period0Data = chartData.find((d) => d.period === 0)\n const isDefaultSeries = seriesKey === defaultSeriesName\n const cohortSize = isDefaultSeries\n ? period0Data?.cohortSize ?? 0\n : period0Data?.[`${seriesKey}_cohortSize`] ?? 0\n\n return (\n <tr\n key={seriesKey}\n className={rowIndex % 2 === 0 ? 'bg-dc-bg' : 'bg-dc-surface-secondary'}\n >\n <td className=\"p-2 font-medium text-dc-text border-b border-dc-border whitespace-nowrap\">\n {seriesKey}\n </td>\n <td className=\"p-2 text-right text-dc-text-secondary border-b border-dc-border\">\n {cohortSize.toLocaleString()}\n </td>\n {retentionData?.periods.map((period) => {\n const dataPoint = chartData.find((d) => d.period === period)\n const rate = dataPoint?.[seriesKey] ?? 0\n const bgColor = rate > 0 ? getRetentionColor(rate) : 'transparent'\n const textColor = rate > 0.5 ? '#ffffff' : 'var(--dc-text)'\n\n return (\n <td\n key={period}\n className=\"p-2 text-center border-b border-dc-border cursor-default transition-opacity hover:opacity-80\"\n style={{ backgroundColor: bgColor, color: textColor }}\n onMouseEnter={(e) => {\n const rect = e.currentTarget.getBoundingClientRect()\n const retainedUsers = isDefaultSeries\n ? dataPoint?.retainedUsers ?? 0\n : dataPoint?.[`${seriesKey}_retainedUsers`] ?? 0\n setHeatmapTooltip({\n period,\n breakdownValue: isDefaultSeries ? null : seriesKey,\n cohortSize,\n retainedUsers,\n retentionRate: rate,\n x: rect.left + rect.width / 2,\n y: rect.top,\n })\n }}\n onMouseLeave={() => setHeatmapTooltip(null)}\n >\n {rate > 0 ? formatPercentage(rate) : '-'}\n </td>\n )\n })}\n </tr>\n )\n })}\n </tbody>\n </table>\n )\n\n // Render heatmap tooltip (shared between heatmap and combined modes)\n const renderHeatmapTooltip = () =>\n heatmapTooltip && (\n <div\n className=\"fixed z-50 px-3 py-2 bg-dc-surface border border-dc-border rounded shadow-lg text-sm pointer-events-none\"\n style={{\n left: heatmapTooltip.x,\n top: heatmapTooltip.y - 10,\n transform: 'translate(-50%, -100%)',\n }}\n >\n <div className=\"font-medium text-dc-text mb-1\">\n {heatmapTooltip.breakdownValue\n ? `${heatmapTooltip.breakdownValue} - ${formatPeriodLabel(heatmapTooltip.period, retentionData?.granularity)}`\n : formatPeriodLabel(heatmapTooltip.period, retentionData?.granularity)}\n </div>\n <div className=\"text-dc-text-secondary space-y-0.5\">\n <div>Cohort Size: {heatmapTooltip.cohortSize.toLocaleString()}</div>\n <div>Retained: {heatmapTooltip.retainedUsers.toLocaleString()}</div>\n <div className=\"font-medium text-dc-text\">\n Rate: {formatPercentage(heatmapTooltip.retentionRate)}\n </div>\n </div>\n </div>\n )\n\n // Render heatmap mode (table-based only)\n if (displayMode === 'heatmap') {\n return (\n <div className=\"relative w-full h-full overflow-auto\" style={{ height }}>\n {renderHeatmapTable()}\n {renderHeatmapTooltip()}\n </div>\n )\n }\n\n // Combined mode: line chart on top, heatmap table below\n if (displayMode === 'combined') {\n return (\n <div className=\"flex flex-col w-full h-full\" style={{ height }}>\n {/* Line chart - takes remaining space after heatmap */}\n <div className=\"flex-1 min-h-[200px]\">\n {renderLineChart('100%')}\n </div>\n {/* Heatmap table - auto-height based on content, scrolls if needed */}\n <div className=\"flex-shrink-0 max-h-[40%] overflow-auto border-t border-dc-border\">\n {renderHeatmapTable()}\n </div>\n {/* Shared heatmap tooltip */}\n {renderHeatmapTooltip()}\n </div>\n )\n }\n\n // Line mode: just the line chart\n return renderLineChart(height)\n})\n\nexport default RetentionCombinedChart\n"],"names":["getRetentionColor","rate","formatPercentage","formatPeriodLabel","period","granularity","prefix","getCohortLabel","_bindingKeyLabel","getDefaultSeriesName","bindingKeyLabel","transformRetentionData","rows","periods","breakdownValues","defaultSeriesName","row","r","dataPoint","bv","RetentionCombinedChart","React","data","height","displayConfig","colorPalette","hoveredLegend","setHoveredLegend","useState","heatmapTooltip","setHeatmapTooltip","retentionData","useMemo","isRetentionData","a","b","chartData","seriesKeys","cohortLabel","displayMode","showLegend","showGrid","showTooltip","jsx","jsxs","renderLineChart","chartHeight","chartMargins","CHART_MARGINS","ChartContainer","ComposedChart","CartesianGrid","XAxis","YAxis","value","ChartTooltip","name","label","Legend","o","seriesKey","index","Line","CHART_COLORS","renderHeatmapTable","rowIndex","period0Data","d","isDefaultSeries","cohortSize","bgColor","textColor","e","rect","retainedUsers","renderHeatmapTooltip"],"mappings":"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"}
|