drizzle-cube 0.7.1 → 0.8.0
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/ActivityGridChart.config-BQhBE_Mr.js +2 -0
- package/dist/adapters/ActivityGridChart.config-C3tSuOGV.cjs +1 -0
- package/dist/adapters/AreaChart.config-3cme8HyQ.js +2 -0
- package/dist/adapters/AreaChart.config-BSxrT52Z.cjs +1 -0
- package/dist/adapters/BarChart.config-BKS8IecE.cjs +1 -0
- package/dist/adapters/BarChart.config-lt_7PdIi.js +2 -0
- package/dist/adapters/BoxPlotChart.config-B7qvRnrF.cjs +1 -0
- package/dist/adapters/BoxPlotChart.config-Dv6ECj2j.js +2 -0
- package/dist/adapters/BubbleChart.config-BrIH7OAy.cjs +1 -0
- package/dist/adapters/BubbleChart.config-Fhotb7Pg.js +2 -0
- package/dist/adapters/CandlestickChart.config-CWH41FmF.cjs +1 -0
- package/dist/adapters/CandlestickChart.config-RPtXuxsX.js +2 -0
- package/dist/adapters/DataTable.config-71L0GzlT.js +2 -0
- package/dist/adapters/DataTable.config-BsOMQq3J.cjs +1 -0
- package/dist/adapters/FunnelChart.config-Cqte9C04.cjs +1 -0
- package/dist/adapters/FunnelChart.config-DJtwWeNz.js +2 -0
- package/dist/adapters/GaugeChart.config-WkwZ9VdS.cjs +1 -0
- package/dist/adapters/GaugeChart.config-vpVQlP5B.js +2 -0
- package/dist/adapters/HeatMapChart.config-DcmkDl07.cjs +1 -0
- package/dist/adapters/HeatMapChart.config-DsmMgGxJ.js +2 -0
- package/dist/adapters/KpiDelta.config-DVy561BH.js +2 -0
- package/dist/adapters/KpiDelta.config-dpqwLHNE.cjs +1 -0
- package/dist/adapters/KpiNumber.config-927l8nq8.js +2 -0
- package/dist/adapters/KpiNumber.config-BqFBMfPf.cjs +1 -0
- package/dist/adapters/KpiText.config-C-fZXuHq.cjs +1 -0
- package/dist/adapters/KpiText.config-CWoXuhMA.js +2 -0
- package/dist/adapters/LineChart.config-DTp7pqOY.js +2 -0
- package/dist/adapters/LineChart.config-DUGvSjcH.cjs +1 -0
- package/dist/adapters/MarkdownChart.config-23Dmv2Ty.cjs +1 -0
- package/dist/adapters/MarkdownChart.config-Cb2TnS0I.js +2 -0
- package/dist/adapters/MeasureProfileChart.config-B2qbWdhy.cjs +1 -0
- package/dist/adapters/MeasureProfileChart.config-CvBCeI5b.js +2 -0
- package/dist/adapters/PieChart.config-BzJb13QA.js +2 -0
- package/dist/adapters/PieChart.config-plCn5Ehr.cjs +1 -0
- package/dist/adapters/ProportionBarChart.config-1r-_moBH.cjs +1 -0
- package/dist/adapters/ProportionBarChart.config-CN6TtHTp.js +2 -0
- package/dist/adapters/RadarChart.config-BYhdj9M7.js +2 -0
- package/dist/adapters/RadarChart.config-CeUMP-1g.cjs +1 -0
- package/dist/adapters/RadialBarChart.config-B88yXNsq.cjs +1 -0
- package/dist/adapters/RadialBarChart.config-ZMK9HMoh.js +2 -0
- package/dist/adapters/RetentionCombinedChart.config-B5yvgUHM.cjs +1 -0
- package/dist/adapters/RetentionCombinedChart.config-Dd-YMdK8.js +2 -0
- package/dist/adapters/RetentionHeatmap.config-BYzDleoV.cjs +1 -0
- package/dist/adapters/RetentionHeatmap.config-Dvj7yTB0.js +2 -0
- package/dist/adapters/SankeyChart.config-CPFRmgFb.cjs +1 -0
- package/dist/adapters/SankeyChart.config-ClgqXM1N.js +2 -0
- package/dist/adapters/ScatterChart.config-CvJiqPa5.cjs +1 -0
- package/dist/adapters/ScatterChart.config-DLZ3rYMq.js +2 -0
- package/dist/adapters/SunburstChart.config-C_1V5hoQ.cjs +1 -0
- package/dist/adapters/SunburstChart.config-FNU75NCg.js +2 -0
- package/dist/adapters/TreeMapChart.config-CprZk_YF.js +2 -0
- package/dist/adapters/TreeMapChart.config-DNwd0ge9.cjs +1 -0
- package/dist/adapters/WaterfallChart.config-BBhcN_Fh.cjs +1 -0
- package/dist/adapters/WaterfallChart.config-H7s6SSV3.js +2 -0
- package/dist/adapters/{compiler-BNjqYdmc.cjs → compiler-BaLO10VN.cjs} +7 -7
- package/dist/adapters/{compiler-DiYxWAKg.js → compiler-CQJ5GOwF.js} +286 -119
- package/dist/adapters/core/http-port.d.ts +34 -7
- package/dist/adapters/core/index.cjs +1 -1
- package/dist/adapters/core/index.d.ts +1 -0
- package/dist/adapters/core/index.js +2 -2
- package/dist/adapters/core/rest-handlers.d.ts +1 -1
- package/dist/adapters/{core-BOPRmxPc.js → core-DXkuSUBg.js} +80 -64
- package/dist/adapters/core-DgTGXxDu.cjs +1 -0
- package/dist/adapters/express/index.cjs +2 -2
- package/dist/adapters/express/index.d.ts +11 -2
- package/dist/adapters/express/index.js +14 -14
- package/dist/adapters/fastify/index.cjs +2 -2
- package/dist/adapters/fastify/index.d.ts +11 -2
- package/dist/adapters/fastify/index.js +12 -12
- package/dist/adapters/{handler-DGud-C-w.js → handler-CphYSZRh.js} +74 -74
- package/dist/adapters/{handler-m6WgA9xu.cjs → handler-DrRT6c14.cjs} +8 -8
- package/dist/adapters/hono/index.cjs +1 -1
- package/dist/adapters/hono/index.js +9 -9
- package/dist/adapters/mcp-tools-handlers.d.ts +10 -3
- package/dist/adapters/mcp-tools.cjs +1 -1
- package/dist/adapters/mcp-tools.js +18 -20
- package/dist/adapters/mcp-transport-BGkSz-ZT.cjs +40 -0
- package/dist/adapters/mcp-transport-fJud19xz.js +606 -0
- package/dist/adapters/mcp-transport.d.ts +13 -2
- package/dist/adapters/nextjs/index.cjs +1 -1
- package/dist/adapters/nextjs/index.d.ts +5 -2
- package/dist/adapters/nextjs/index.js +32 -32
- package/dist/adapters/{openai-CGJM6Qun.js → openai-CBrN4nxl.js} +2 -2
- package/dist/adapters/{openai-Dwt9bxOE.cjs → openai-CI9vGKSf.cjs} +1 -1
- package/dist/adapters/{openai-CmdN7Sj1.cjs → openai-CSzWluuv.cjs} +1 -1
- package/dist/{server/openai-Czk1BdHa.js → adapters/openai-D-VMcPao.js} +1 -1
- package/dist/adapters/{utils-BoOeig94.cjs → utils-BY0-KFyI.cjs} +2 -2
- package/dist/adapters/{utils-DboNUT3A.js → utils-DkmShl5f.js} +23 -20
- package/dist/adapters/utils.cjs +1 -1
- package/dist/adapters/utils.d.ts +2 -2
- package/dist/adapters/utils.js +1 -1
- package/dist/cjs/adapters/core/http-port.d.ts +34 -7
- package/dist/cjs/adapters/core/index.d.ts +1 -0
- package/dist/cjs/adapters/core/rest-handlers.d.ts +1 -1
- package/dist/cjs/adapters/express/index.d.ts +11 -2
- package/dist/cjs/adapters/fastify/index.d.ts +11 -2
- package/dist/cjs/adapters/mcp-tools-handlers.d.ts +10 -3
- package/dist/cjs/adapters/mcp-transport.d.ts +13 -2
- package/dist/cjs/adapters/nextjs/index.d.ts +5 -2
- package/dist/cjs/adapters/utils.d.ts +2 -2
- package/dist/cjs/server/adapters/base-adapter.d.ts +46 -0
- package/dist/cjs/server/adapters/databend-adapter.d.ts +5 -0
- package/dist/cjs/server/adapters/duckdb-adapter.d.ts +5 -0
- package/dist/cjs/server/adapters/mysql-adapter.d.ts +14 -0
- package/dist/cjs/server/adapters/postgres-adapter.d.ts +15 -0
- package/dist/cjs/server/adapters/snowflake-adapter.d.ts +6 -0
- package/dist/cjs/server/adapters/sqlite-adapter.d.ts +21 -0
- package/dist/cjs/server/attribute-dimensions.d.ts +99 -0
- package/dist/cjs/server/cache-utils.d.ts +5 -1
- package/dist/cjs/server/compiler-metadata.d.ts +24 -3
- package/dist/cjs/server/compiler.d.ts +157 -10
- package/dist/cjs/server/execution/query-result-cache.d.ts +1 -1
- package/dist/cjs/server/index.d.ts +11 -3
- package/dist/cjs/server/query-handlers.d.ts +1 -1
- package/dist/cjs/server/types/core.d.ts +8 -0
- package/dist/cjs/server/types/cube.d.ts +27 -2
- package/dist/client/charts.js +12 -12
- package/dist/client/chunks/{DashboardEditModal-BOfLdTgV.js → DashboardEditModal-9An5EDAz.js} +12 -12
- package/dist/client/chunks/{DashboardEditModal-BOfLdTgV.js.map → DashboardEditModal-9An5EDAz.js.map} +1 -1
- package/dist/client/chunks/{ProportionBarChart-DwoXU5VP.js → ProportionBarChart-BVcbGY2C.js} +3 -3
- package/dist/client/chunks/{ProportionBarChart-DwoXU5VP.js.map → ProportionBarChart-BVcbGY2C.js.map} +1 -1
- package/dist/client/chunks/{RetentionCombinedChart-BqlSV7yF.js → RetentionCombinedChart-D68Rvdi-.js} +3 -3
- package/dist/client/chunks/{RetentionCombinedChart-BqlSV7yF.js.map → RetentionCombinedChart-D68Rvdi-.js.map} +1 -1
- package/dist/client/chunks/{RetentionHeatmap-VdVkBg8Q.js → RetentionHeatmap-CE7BAjrB.js} +2 -2
- package/dist/client/chunks/{RetentionHeatmap-VdVkBg8Q.js.map → RetentionHeatmap-CE7BAjrB.js.map} +1 -1
- package/dist/client/chunks/{analysis-builder-DXw60SEs.js → analysis-builder-D1pYvvwc.js} +9 -9
- package/dist/client/chunks/{analysis-builder-DXw60SEs.js.map → analysis-builder-D1pYvvwc.js.map} +1 -1
- package/dist/client/chunks/{analysis-builder-shared-CEvHIlmk.js → analysis-builder-shared-BQvwUc6z.js} +9 -9
- package/dist/client/chunks/{analysis-builder-shared-CEvHIlmk.js.map → analysis-builder-shared-BQvwUc6z.js.map} +1 -1
- package/dist/client/chunks/{chart-activity-grid-4jfS8khG.js → chart-activity-grid-DvD_4wJz.js} +5 -2
- package/dist/client/chunks/chart-activity-grid-DvD_4wJz.js.map +1 -0
- package/dist/client/chunks/{chart-area-Dol6s9no.js → chart-area-DPp3hSOK.js} +2 -2
- package/dist/client/chunks/{chart-area-Dol6s9no.js.map → chart-area-DPp3hSOK.js.map} +1 -1
- package/dist/client/chunks/{chart-bar-5_niozi2.js → chart-bar-Od3pOyZ0.js} +3 -3
- package/dist/client/chunks/{chart-bar-5_niozi2.js.map → chart-bar-Od3pOyZ0.js.map} +1 -1
- package/dist/client/chunks/{chart-box-plot-Dhp-VwhD.js → chart-box-plot-l0iFn2n2.js} +2 -2
- package/dist/client/chunks/{chart-box-plot-Dhp-VwhD.js.map → chart-box-plot-l0iFn2n2.js.map} +1 -1
- package/dist/client/chunks/{chart-bubble-BM2BAMSo.js → chart-bubble-Dl0RcP8N.js} +2 -2
- package/dist/client/chunks/{chart-bubble-BM2BAMSo.js.map → chart-bubble-Dl0RcP8N.js.map} +1 -1
- package/dist/client/chunks/{chart-candlestick-BNwLIBfm.js → chart-candlestick-DZMqbscF.js} +2 -2
- package/dist/client/chunks/{chart-candlestick-BNwLIBfm.js.map → chart-candlestick-DZMqbscF.js.map} +1 -1
- package/dist/client/chunks/{chart-data-table-DoDHQRe7.js → chart-data-table-DgiNBOWf.js} +3 -3
- package/dist/client/chunks/chart-data-table-DgiNBOWf.js.map +1 -0
- package/dist/client/chunks/{chart-funnel-Cd7da_sa.js → chart-funnel-YLZlyN1X.js} +2 -2
- package/dist/client/chunks/{chart-funnel-Cd7da_sa.js.map → chart-funnel-YLZlyN1X.js.map} +1 -1
- package/dist/client/chunks/{chart-gauge-DOpul-Oz.js → chart-gauge-BsqE2wwF.js} +3 -3
- package/dist/client/chunks/{chart-gauge-DOpul-Oz.js.map → chart-gauge-BsqE2wwF.js.map} +1 -1
- package/dist/client/chunks/{chart-heat-map-CeKbK655.js → chart-heat-map-BsND8RM_.js} +3 -3
- package/dist/client/chunks/{chart-heat-map-CeKbK655.js.map → chart-heat-map-BsND8RM_.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-delta-Dq8qUOOT.js → chart-kpi-delta-m0azuva-.js} +3 -3
- package/dist/client/chunks/{chart-kpi-delta-Dq8qUOOT.js.map → chart-kpi-delta-m0azuva-.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-number-DgiqTi9g.js → chart-kpi-number-6JS15SqF.js} +5 -5
- package/dist/client/chunks/{chart-kpi-number-DgiqTi9g.js.map → chart-kpi-number-6JS15SqF.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-text-CsZMVEnM.js → chart-kpi-text-BqX8p8Jn.js} +3 -3
- package/dist/client/chunks/{chart-kpi-text-CsZMVEnM.js.map → chart-kpi-text-BqX8p8Jn.js.map} +1 -1
- package/dist/client/chunks/{chart-line-DlwOB7C7.js → chart-line-NCmpxBfE.js} +3 -3
- package/dist/client/chunks/{chart-line-DlwOB7C7.js.map → chart-line-NCmpxBfE.js.map} +1 -1
- package/dist/client/chunks/{chart-markdown-DPE34SjC.js → chart-markdown-ZOobqiiX.js} +2 -2
- package/dist/client/chunks/{chart-markdown-DPE34SjC.js.map → chart-markdown-ZOobqiiX.js.map} +1 -1
- package/dist/client/chunks/{chart-measure-profile-BpTz1fce.js → chart-measure-profile-CBAZaicJ.js} +3 -3
- package/dist/client/chunks/{chart-measure-profile-BpTz1fce.js.map → chart-measure-profile-CBAZaicJ.js.map} +1 -1
- package/dist/client/chunks/{chart-pie-FGw66XAH.js → chart-pie-ChrasEI8.js} +3 -3
- package/dist/client/chunks/{chart-pie-FGw66XAH.js.map → chart-pie-ChrasEI8.js.map} +1 -1
- package/dist/client/chunks/{chart-radar-D-eRDoiA.js → chart-radar-CxSVF7yL.js} +3 -3
- package/dist/client/chunks/{chart-radar-D-eRDoiA.js.map → chart-radar-CxSVF7yL.js.map} +1 -1
- package/dist/client/chunks/{chart-radial-bar-DgtkNTs3.js → chart-radial-bar--SN0Wph0.js} +3 -3
- package/dist/client/chunks/{chart-radial-bar-DgtkNTs3.js.map → chart-radial-bar--SN0Wph0.js.map} +1 -1
- package/dist/client/chunks/{chart-sankey-D0hhb_EQ.js → chart-sankey-CDOSGg9r.js} +2 -2
- package/dist/client/chunks/{chart-sankey-D0hhb_EQ.js.map → chart-sankey-CDOSGg9r.js.map} +1 -1
- package/dist/client/chunks/{chart-scatter-D9EcAiMQ.js → chart-scatter-DgcEF-kI.js} +3 -3
- package/dist/client/chunks/{chart-scatter-D9EcAiMQ.js.map → chart-scatter-DgcEF-kI.js.map} +1 -1
- package/dist/client/chunks/{chart-sunburst-DCYmJ5DU.js → chart-sunburst-MB-jlGBm.js} +3 -3
- package/dist/client/chunks/{chart-sunburst-DCYmJ5DU.js.map → chart-sunburst-MB-jlGBm.js.map} +1 -1
- package/dist/client/chunks/{chart-tree-map-D_ACSSiB.js → chart-tree-map-DeDXveVd.js} +3 -3
- package/dist/client/chunks/{chart-tree-map-D_ACSSiB.js.map → chart-tree-map-DeDXveVd.js.map} +1 -1
- package/dist/client/chunks/{chart-waterfall-CVUVNa1R.js → chart-waterfall-ur4vkO1j.js} +3 -3
- package/dist/client/chunks/{chart-waterfall-CVUVNa1R.js.map → chart-waterfall-ur4vkO1j.js.map} +1 -1
- package/dist/client/chunks/{charts-core-BPD_hLaL.js → charts-core-BAH5pkSB.js} +2 -2
- package/dist/client/chunks/{charts-core-BPD_hLaL.js.map → charts-core-BAH5pkSB.js.map} +1 -1
- package/dist/client/chunks/charts-loader-eToV8je7.js +85 -0
- package/dist/client/chunks/{charts-loader-CwMcOfwT.js.map → charts-loader-eToV8je7.js.map} +1 -1
- package/dist/client/chunks/{exceljs.min-DWC_b8G9.js → exceljs.min-CiByP8VQ.js} +2 -3
- package/dist/client/chunks/{exceljs.min-DWC_b8G9.js.map → exceljs.min-CiByP8VQ.js.map} +1 -1
- package/dist/client/chunks/{nl-NL-DFLVORiD.js → nl-NL-CMXHDBr0.js} +4 -1
- package/dist/client/chunks/nl-NL-CMXHDBr0.js.map +1 -0
- package/dist/client/chunks/{schema-visualization-C6g_LCiA.js → schema-visualization-BEbFtUIL.js} +3 -3
- package/dist/client/chunks/{schema-visualization-C6g_LCiA.js.map → schema-visualization-BEbFtUIL.js.map} +1 -1
- package/dist/client/chunks/{useDirtyStateTracking-ZfChDEd3.js → useDirtyStateTracking-CSDg96Rw.js} +4 -4
- package/dist/client/chunks/{useDirtyStateTracking-ZfChDEd3.js.map → useDirtyStateTracking-CSDg96Rw.js.map} +1 -1
- package/dist/client/chunks/{useExplainAI-im9e1rVb.js → useExplainAI-BnkoZ-zS.js} +4 -4
- package/dist/client/chunks/{useExplainAI-im9e1rVb.js.map → useExplainAI-BnkoZ-zS.js.map} +1 -1
- package/dist/client/chunks/{vendor-Qa1s8oSX.js → vendor-BmJDaduD.js} +2 -2
- package/dist/client/chunks/vendor-BmJDaduD.js.map +1 -0
- package/dist/client/components.js +1 -1
- package/dist/client/hooks.js +3 -3
- package/dist/client/icons.js +1 -1
- package/dist/client/index.js +13 -13
- package/dist/client/providers.js +1 -1
- package/dist/client/schema.js +1 -1
- package/dist/client/utils.js +4 -4
- package/dist/client-bundle-stats.html +1 -1
- package/dist/mcp-app/mcp-app.html +43 -43
- package/dist/server/adapters/base-adapter.d.ts +46 -0
- package/dist/server/adapters/databend-adapter.d.ts +5 -0
- package/dist/server/adapters/duckdb-adapter.d.ts +5 -0
- package/dist/server/adapters/mysql-adapter.d.ts +14 -0
- package/dist/server/adapters/postgres-adapter.d.ts +15 -0
- package/dist/server/adapters/snowflake-adapter.d.ts +6 -0
- package/dist/server/adapters/sqlite-adapter.d.ts +21 -0
- package/dist/server/attribute-dimensions.d.ts +99 -0
- package/dist/server/cache-utils.d.ts +5 -1
- package/dist/server/compiler-metadata.d.ts +24 -3
- package/dist/server/compiler.d.ts +157 -10
- package/dist/server/execution/query-result-cache.d.ts +1 -1
- package/dist/server/index.cjs +39 -35
- package/dist/server/index.d.ts +11 -3
- package/dist/server/index.js +673 -477
- package/dist/{adapters/openai-Crp3X_zg.js → server/openai-6uUf7h-5.js} +1 -1
- package/dist/server/{openai-DBwI1OSu.cjs → openai-BBe1XbZd.cjs} +1 -1
- package/dist/server/{openai-Cu4TXXjl.cjs → openai-BmADmD1e.cjs} +1 -1
- package/dist/server/{openai-CUf4vc3Q.js → openai-C1gLuR-0.js} +1 -1
- package/dist/server/query-handlers.d.ts +1 -1
- package/dist/server/types/core.d.ts +8 -0
- package/dist/server/types/cube.d.ts +27 -2
- package/package.json +2 -2
- package/dist/adapters/ActivityGridChart.config-D6hhj345.cjs +0 -1
- package/dist/adapters/ActivityGridChart.config-QZKs_NYg.js +0 -2
- package/dist/adapters/AreaChart.config-B5XM6G22.js +0 -2
- package/dist/adapters/AreaChart.config-NP34BH5y.cjs +0 -1
- package/dist/adapters/BarChart.config-Bqlmr81N.js +0 -2
- package/dist/adapters/BarChart.config-C3bw-cAP.cjs +0 -1
- package/dist/adapters/BoxPlotChart.config-BOAvoj6x.cjs +0 -1
- package/dist/adapters/BoxPlotChart.config-CTXiycYY.js +0 -2
- package/dist/adapters/BubbleChart.config-CGFIkl4H.cjs +0 -1
- package/dist/adapters/BubbleChart.config-Njxx4Eq1.js +0 -2
- package/dist/adapters/CandlestickChart.config-BZ_yWaSo.cjs +0 -1
- package/dist/adapters/CandlestickChart.config-D4Svhmef.js +0 -2
- package/dist/adapters/DataTable.config-B-bT9puT.js +0 -2
- package/dist/adapters/DataTable.config-BHtt1cPM.cjs +0 -1
- package/dist/adapters/FunnelChart.config-C1e07O7B.cjs +0 -1
- package/dist/adapters/FunnelChart.config-CVEy0tV9.js +0 -2
- package/dist/adapters/GaugeChart.config-5PLNlQlu.js +0 -2
- package/dist/adapters/GaugeChart.config-Cdv6knjZ.cjs +0 -1
- package/dist/adapters/HeatMapChart.config-MGTfYpWJ.js +0 -2
- package/dist/adapters/HeatMapChart.config-jfBEi1ZI.cjs +0 -1
- package/dist/adapters/KpiDelta.config-D2IUsEYz.cjs +0 -1
- package/dist/adapters/KpiDelta.config-DT_MmAHw.js +0 -2
- package/dist/adapters/KpiNumber.config-ChgbKmx8.cjs +0 -1
- package/dist/adapters/KpiNumber.config-CvZ_FhyL.js +0 -2
- package/dist/adapters/KpiText.config-Bgkw8gr2.js +0 -2
- package/dist/adapters/KpiText.config-Bz9orqt6.cjs +0 -1
- package/dist/adapters/LineChart.config-BVew35dI.cjs +0 -1
- package/dist/adapters/LineChart.config-DSCCKXNg.js +0 -2
- package/dist/adapters/MarkdownChart.config-Bu6XUuhI.js +0 -2
- package/dist/adapters/MarkdownChart.config-E4aSVTf3.cjs +0 -1
- package/dist/adapters/MeasureProfileChart.config-BF249hc_.cjs +0 -1
- package/dist/adapters/MeasureProfileChart.config-lERVe38G.js +0 -2
- package/dist/adapters/PieChart.config-7Ujwp8R5.cjs +0 -1
- package/dist/adapters/PieChart.config-jQl2HIcA.js +0 -2
- package/dist/adapters/ProportionBarChart.config-o0w_Pnlt.js +0 -2
- package/dist/adapters/ProportionBarChart.config-phNohhhY.cjs +0 -1
- package/dist/adapters/RadarChart.config-BmrYBd9x.js +0 -2
- package/dist/adapters/RadarChart.config-Dlt3UflG.cjs +0 -1
- package/dist/adapters/RadialBarChart.config-CeEm8xRb.cjs +0 -1
- package/dist/adapters/RadialBarChart.config-Dishh6bC.js +0 -2
- package/dist/adapters/RetentionCombinedChart.config-BaD4ev85.cjs +0 -1
- package/dist/adapters/RetentionCombinedChart.config-m2FjBUi9.js +0 -2
- package/dist/adapters/RetentionHeatmap.config-DiMplGdk.js +0 -2
- package/dist/adapters/RetentionHeatmap.config-Dp6oYwQZ.cjs +0 -1
- package/dist/adapters/SankeyChart.config-C4Y6qzCS.cjs +0 -1
- package/dist/adapters/SankeyChart.config-CJHqgjQ1.js +0 -2
- package/dist/adapters/ScatterChart.config-C0QqvDrN.cjs +0 -1
- package/dist/adapters/ScatterChart.config-DywOsWPW.js +0 -2
- package/dist/adapters/SunburstChart.config-DE8RxpDR.cjs +0 -1
- package/dist/adapters/SunburstChart.config-DohowrO3.js +0 -2
- package/dist/adapters/TreeMapChart.config-D2gXz-zC.cjs +0 -1
- package/dist/adapters/TreeMapChart.config-HMlI29GG.js +0 -2
- package/dist/adapters/WaterfallChart.config-BO2WV2VB.js +0 -2
- package/dist/adapters/WaterfallChart.config-CzwGiheB.cjs +0 -1
- package/dist/adapters/core-CzFfrJzu.cjs +0 -1
- package/dist/adapters/mcp-transport-B0b27YUB.cjs +0 -40
- package/dist/adapters/mcp-transport-BXyA4dTk.js +0 -603
- package/dist/client/chunks/chart-activity-grid-4jfS8khG.js.map +0 -1
- package/dist/client/chunks/chart-data-table-DoDHQRe7.js.map +0 -1
- package/dist/client/chunks/charts-loader-CwMcOfwT.js +0 -85
- package/dist/client/chunks/nl-NL-DFLVORiD.js.map +0 -1
- package/dist/client/chunks/vendor-Qa1s8oSX.js.map +0 -1
|
@@ -714,6 +714,9 @@ var e = Object.create, t = Object.defineProperty, n = Object.getOwnPropertyDescr
|
|
|
714
714
|
"server.errors.retentionValidationFailed": "Retention validation failed: {errors}",
|
|
715
715
|
"server.errors.cubeRefUnresolved": "{cubeName}.joins.{joinName}: target cube '{targetCube}' is not registered",
|
|
716
716
|
"server.errors.unresolvedCubeRefs": "Unresolved cube references:\n{details}",
|
|
717
|
+
"server.errors.cubeSetIdEmpty": "Cube set id must not be empty — the empty id is reserved for the base cube set",
|
|
718
|
+
"server.errors.cubeSetNotFound": "No cube set registered for '{setId}'",
|
|
719
|
+
"server.errors.attributeIdRequired": "Attribute definitions must have a non-empty id",
|
|
717
720
|
"server.errors.calculatedMeasureValidation": "Calculated measure validation failed for cube '{cubeName}':\n{details}",
|
|
718
721
|
"server.errors.queryValidationFailed": "Query validation failed: {errors}",
|
|
719
722
|
"server.errors.queryContainsMultipleModes": "Query contains multiple query modes: {modes}",
|
|
@@ -6425,13 +6428,13 @@ function Mo(e, t, n) {
|
|
|
6425
6428
|
//#endregion
|
|
6426
6429
|
//#region src/server/query-handlers.ts
|
|
6427
6430
|
var No = fo.messages[0]?.content.text ?? "";
|
|
6428
|
-
async function Po(e, t) {
|
|
6431
|
+
async function Po(e, t, n) {
|
|
6429
6432
|
return {
|
|
6430
|
-
cubes: jo(e.getMetadata(), {
|
|
6431
|
-
topic:
|
|
6432
|
-
intent:
|
|
6433
|
-
limit:
|
|
6434
|
-
minScore:
|
|
6433
|
+
cubes: jo(e.getMetadata(t), {
|
|
6434
|
+
topic: n.topic,
|
|
6435
|
+
intent: n.intent,
|
|
6436
|
+
limit: n.limit,
|
|
6437
|
+
minScore: n.minScore
|
|
6435
6438
|
}),
|
|
6436
6439
|
queryLanguageReference: co,
|
|
6437
6440
|
dateFilteringGuide: No
|
|
@@ -6484,7 +6487,7 @@ function zo(e, t) {
|
|
|
6484
6487
|
return r;
|
|
6485
6488
|
}
|
|
6486
6489
|
async function Bo(e, t, n) {
|
|
6487
|
-
let r = Fo(n.query), i = e.validateQuery(r);
|
|
6490
|
+
let r = Fo(n.query), i = e.validateQuery(r, t);
|
|
6488
6491
|
if (!i.isValid) throw Error(`Query validation failed: ${i.errors.join(", ")}`);
|
|
6489
6492
|
let a = await e.executeMultiCubeQuery(r, t);
|
|
6490
6493
|
return {
|
|
@@ -7218,9 +7221,9 @@ function ys(e, t, n) {
|
|
|
7218
7221
|
return;
|
|
7219
7222
|
}
|
|
7220
7223
|
}
|
|
7221
|
-
function Y(e, t, n) {
|
|
7222
|
-
let
|
|
7223
|
-
if (!
|
|
7224
|
+
function Y(e, t, n, r) {
|
|
7225
|
+
let i = n.validateQuery(e, t);
|
|
7226
|
+
if (!i.isValid) throw Error(`${r} validation failed: ${i.errors.join(", ")}`);
|
|
7224
7227
|
}
|
|
7225
7228
|
async function X(e, t, n) {
|
|
7226
7229
|
return {
|
|
@@ -7293,7 +7296,7 @@ async function ws(e, t, n) {
|
|
|
7293
7296
|
}[vs(e)]();
|
|
7294
7297
|
}
|
|
7295
7298
|
async function Ts(e, t, n) {
|
|
7296
|
-
Y(e, n, "Query");
|
|
7299
|
+
Y(e, t, n, "Query");
|
|
7297
7300
|
let r = bs(e), i = r.length > 1, { sqlResult: a, analysis: o } = await X(e, t, n), s = r.map((t) => ({
|
|
7298
7301
|
cube: t,
|
|
7299
7302
|
query: {
|
|
@@ -7319,7 +7322,7 @@ async function Ts(e, t, n) {
|
|
|
7319
7322
|
});
|
|
7320
7323
|
}
|
|
7321
7324
|
async function Es(e, t, n) {
|
|
7322
|
-
Y(e, n, "Comparison query");
|
|
7325
|
+
Y(e, t, n, "Comparison query");
|
|
7323
7326
|
let r = bs(e), i = r.length > 1, { sqlResult: a, analysis: o } = await X(e, t, n), s = e.timeDimensions?.find((e) => e.compareDateRange && e.compareDateRange.length >= 2), c = s ? {
|
|
7324
7327
|
timeDimension: s.dimension,
|
|
7325
7328
|
granularity: s.granularity || "day",
|
|
@@ -7468,7 +7471,7 @@ async function js(e, t, n, r) {
|
|
|
7468
7471
|
}) };
|
|
7469
7472
|
}
|
|
7470
7473
|
async function Ms(e, t, n) {
|
|
7471
|
-
Y(e, n, "Funnel query");
|
|
7474
|
+
Y(e, t, n, "Funnel query");
|
|
7472
7475
|
let r = xs(e), { sqlResult: i, analysis: a } = await X(e, t, n), o = e.funnel;
|
|
7473
7476
|
return $({
|
|
7474
7477
|
mode: "funnel",
|
|
@@ -7495,7 +7498,7 @@ async function Ms(e, t, n) {
|
|
|
7495
7498
|
});
|
|
7496
7499
|
}
|
|
7497
7500
|
async function Ns(e, t, n) {
|
|
7498
|
-
Y(e, n, "Flow query");
|
|
7501
|
+
Y(e, t, n, "Flow query");
|
|
7499
7502
|
let r = Ss(e), { sqlResult: i, analysis: a } = await X(e, t, n), o = e.flow;
|
|
7500
7503
|
return $({
|
|
7501
7504
|
mode: "flow",
|
|
@@ -7517,7 +7520,7 @@ async function Ns(e, t, n) {
|
|
|
7517
7520
|
});
|
|
7518
7521
|
}
|
|
7519
7522
|
async function Ps(e, t, n) {
|
|
7520
|
-
Y(e, n, "Retention query");
|
|
7523
|
+
Y(e, t, n, "Retention query");
|
|
7521
7524
|
let r = Cs(e), { sqlResult: i, analysis: a } = await X(e, t, n), o = e.retention;
|
|
7522
7525
|
return $({
|
|
7523
7526
|
mode: "retention",
|
|
@@ -7539,13 +7542,13 @@ async function Ps(e, t, n) {
|
|
|
7539
7542
|
}
|
|
7540
7543
|
});
|
|
7541
7544
|
}
|
|
7542
|
-
async function Fs(e, t) {
|
|
7543
|
-
return es(e.getMetadata(),
|
|
7545
|
+
async function Fs(e, t, n) {
|
|
7546
|
+
return es(e.getMetadata(t), n.naturalLanguage, n.cube);
|
|
7544
7547
|
}
|
|
7545
7548
|
async function Is(e, t, n) {
|
|
7546
|
-
let r = e.getMetadata(), i = await fs(
|
|
7547
|
-
if (i.isValid
|
|
7548
|
-
let r = Fo(i.correctedQuery ??
|
|
7549
|
+
let r = e.getMetadata(t), i = await fs(n.query, r);
|
|
7550
|
+
if (i.isValid) try {
|
|
7551
|
+
let r = Fo(i.correctedQuery ?? n.query), a = await e.dryRun(r, t);
|
|
7549
7552
|
return {
|
|
7550
7553
|
...i,
|
|
7551
7554
|
sql: a
|
package/dist/adapters/utils.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./utils-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./utils-BY0-KFyI.cjs");exports.buildTransformedQuery=e.t,exports.calculateQueryComplexity=e.n,exports.formatCubeResponse=e.r,exports.formatErrorResponse=e.i,exports.formatMetaResponse=e.a,exports.formatSqlResponse=e.o,exports.formatSqlString=e.S,exports.generateRequestId=e.s,exports.getDatabaseType=e.c,exports.handleBatchRequest=e.l,exports.handleDiscover=e.p,exports.handleDryRun=e.u,exports.handleLoad=e.m,exports.handleSuggest=e.d,exports.handleValidate=e.f,exports.normalizeQueryFields=e.h;
|
package/dist/adapters/utils.d.ts
CHANGED
|
@@ -354,11 +354,11 @@ export interface ValidateRequest {
|
|
|
354
354
|
/**
|
|
355
355
|
* Handle /suggest endpoint - generate query from natural language
|
|
356
356
|
*/
|
|
357
|
-
export declare function handleSuggest(semanticLayer: SemanticLayerCompiler, body: SuggestRequest): Promise<QuerySuggestion>;
|
|
357
|
+
export declare function handleSuggest(semanticLayer: SemanticLayerCompiler, securityContext: SecurityContext, body: SuggestRequest): Promise<QuerySuggestion>;
|
|
358
358
|
/**
|
|
359
359
|
* Handle /validate endpoint - validate query with corrections
|
|
360
360
|
*/
|
|
361
|
-
export declare function handleValidate(semanticLayer: SemanticLayerCompiler,
|
|
361
|
+
export declare function handleValidate(semanticLayer: SemanticLayerCompiler, securityContext: SecurityContext, body: ValidateRequest): Promise<AIValidationResult & {
|
|
362
362
|
sql?: {
|
|
363
363
|
sql: string;
|
|
364
364
|
params?: any[];
|
package/dist/adapters/utils.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { S as e, a as t, c as n, d as r, f as i, h as a, i as o, l as s, m as c, n as l, o as u, p as d, r as f, s as p, t as m, u as h } from "./utils-
|
|
1
|
+
import { S as e, a as t, c as n, d as r, f as i, h as a, i as o, l as s, m as c, n as l, o as u, p as d, r as f, s as p, t as m, u as h } from "./utils-DkmShl5f.js";
|
|
2
2
|
export { m as buildTransformedQuery, l as calculateQueryComplexity, f as formatCubeResponse, o as formatErrorResponse, t as formatMetaResponse, u as formatSqlResponse, e as formatSqlString, p as generateRequestId, n as getDatabaseType, s as handleBatchRequest, d as handleDiscover, h as handleDryRun, c as handleLoad, r as handleSuggest, i as handleValidate, a as normalizeQueryFields };
|
|
@@ -7,8 +7,16 @@
|
|
|
7
7
|
* (Hono/Next.js). Implementations are constructed per request by each adapter.
|
|
8
8
|
*
|
|
9
9
|
* This interface is public — third parties implement it to build adapters for
|
|
10
|
-
* other frameworks.
|
|
11
|
-
*
|
|
10
|
+
* other frameworks. Prefer optional members or a separate extension interface
|
|
11
|
+
* for new capabilities, because a new required member is a breaking change for
|
|
12
|
+
* those adapters.
|
|
13
|
+
*
|
|
14
|
+
* `setHeader` was promoted from {@link McpHttpPort} to this interface in the
|
|
15
|
+
* per-tenant cube sets release, so that the core can stamp `Cache-Control` on
|
|
16
|
+
* every REST response (see {@link withRestCacheHeaders}). Every REST body is now
|
|
17
|
+
* tenant-scoped, and that guarantee cannot be left to each adapter. The break is
|
|
18
|
+
* accepted for this release: third-party REST-only adapters must add
|
|
19
|
+
* `setHeader`, which all four first-party adapters already implemented.
|
|
12
20
|
*/
|
|
13
21
|
export interface HttpPort<TRes> {
|
|
14
22
|
/** Read a request header by (case-insensitive) name. Synchronous. */
|
|
@@ -17,23 +25,42 @@ export interface HttpPort<TRes> {
|
|
|
17
25
|
getBody(): Promise<unknown>;
|
|
18
26
|
/** Read a raw query-string value by name (used by GET). */
|
|
19
27
|
getQueryParam(name: string): string | undefined;
|
|
28
|
+
/** Set a response header. Must be called before `send`/`sendSse`/`sendEmpty`. */
|
|
29
|
+
setHeader(name: string, value: string): void;
|
|
20
30
|
/** Send a response with the given status and JSON body; returns the framework's response value. */
|
|
21
31
|
send(status: number, body: unknown): TRes;
|
|
22
32
|
}
|
|
23
33
|
/**
|
|
24
|
-
* Extension of {@link HttpPort} for the MCP POST handler, which needs to
|
|
25
|
-
* response
|
|
26
|
-
*
|
|
34
|
+
* Extension of {@link HttpPort} for the MCP POST handler, which needs to emit a
|
|
35
|
+
* single-event SSE response and send an empty-body acknowledgement (202 for
|
|
36
|
+
* notifications).
|
|
27
37
|
*
|
|
28
38
|
* Kept separate from the minimal REST port so third-party adapters only
|
|
29
39
|
* implement these when they wire up MCP. New required members on this interface
|
|
30
40
|
* are still a breaking change for MCP-capable adapters.
|
|
31
41
|
*/
|
|
32
42
|
export interface McpHttpPort<TRes> extends HttpPort<TRes> {
|
|
33
|
-
/** Set a response header. Must be called before `send`/`sendSse`/`sendEmpty`. */
|
|
34
|
-
setHeader(name: string, value: string): void;
|
|
35
43
|
/** Send a single-event SSE response (status 200): write the pre-serialized body, then end. */
|
|
36
44
|
sendSse(status: number, body: string): TRes;
|
|
37
45
|
/** Send an empty-body response (no JSON), e.g. a 202 notification acknowledgement. */
|
|
38
46
|
sendEmpty(status: number): TRes;
|
|
39
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* `Cache-Control` stamped on every REST response.
|
|
50
|
+
*
|
|
51
|
+
* Every REST body varies by tenant: `/meta` returns the caller's cube set, and
|
|
52
|
+
* `/load`, `/sql`, `/dry-run`, `/batch` and `/explain` return that tenant's data
|
|
53
|
+
* or SQL. With no `Cache-Control` a shared cache may store and reuse these
|
|
54
|
+
* responses heuristically, which would cross-serve one tenant's cubes to
|
|
55
|
+
* another. `private` bars shared caches; `no-store` bars storage entirely.
|
|
56
|
+
*/
|
|
57
|
+
export declare const REST_CACHE_CONTROL = "private, no-store";
|
|
58
|
+
/**
|
|
59
|
+
* Wrap a port so every response it sends carries {@link REST_CACHE_CONTROL}.
|
|
60
|
+
*
|
|
61
|
+
* Applied once over the whole REST surface in `createCubeHttpHandler`, not per
|
|
62
|
+
* route, so no endpoint can forget it — including the 400/500 error paths.
|
|
63
|
+
* Deliberately NOT applied to MCP: its SSE responses set their own
|
|
64
|
+
* `Cache-Control`, and JSON-RPC POSTs are not heuristically cacheable.
|
|
65
|
+
*/
|
|
66
|
+
export declare function withRestCacheHeaders<TRes>(port: HttpPort<TRes>): HttpPort<TRes>;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* {@link createCubeHttpHandler}.
|
|
7
7
|
*/
|
|
8
8
|
export type { HttpPort, McpHttpPort } from './http-port.js';
|
|
9
|
+
export { withRestCacheHeaders, REST_CACHE_CONTROL } from './http-port.js';
|
|
9
10
|
export { withLocaleFromHeaders, resolveSecurityContext, type HeaderReader, type BaseSecurityContextThunk } from './security-context.js';
|
|
10
11
|
export { createCubeHttpHandler, type CubeHttpHandler, type CubeHttpHandlerOptions } from './cube-http-handler.js';
|
|
11
12
|
export type { RestHandlers } from './rest-handlers.js';
|
|
@@ -3,7 +3,7 @@ import { HttpPort } from './http-port.js';
|
|
|
3
3
|
import { BaseSecurityContextThunk } from './security-context.js';
|
|
4
4
|
/** REST handlers keyed by endpoint; each closes over the shared semantic layer. */
|
|
5
5
|
export interface RestHandlers {
|
|
6
|
-
handleMetaGet<TRes>(port: HttpPort<TRes
|
|
6
|
+
handleMetaGet<TRes>(port: HttpPort<TRes>, getBaseSecurityContext: BaseSecurityContextThunk): Promise<TRes>;
|
|
7
7
|
handleSqlGet<TRes>(port: HttpPort<TRes>, getBaseSecurityContext: BaseSecurityContextThunk): Promise<TRes>;
|
|
8
8
|
handleSqlPost<TRes>(port: HttpPort<TRes>, getBaseSecurityContext: BaseSecurityContextThunk): Promise<TRes>;
|
|
9
9
|
handleDryRunGet<TRes>(port: HttpPort<TRes>, getBaseSecurityContext: BaseSecurityContextThunk): Promise<TRes>;
|
|
@@ -2,15 +2,24 @@ import { Router, Request, Response, Express } from 'express';
|
|
|
2
2
|
import { CorsOptions } from 'cors';
|
|
3
3
|
import { SemanticQuery, SecurityContext, DatabaseExecutor, DrizzleDatabase, Cube, CacheConfig, RLSSetupFn } from '../../server/index.js';
|
|
4
4
|
import { AgentConfig } from '../../server/agent/types.js';
|
|
5
|
+
import { SemanticLayerCompiler } from '../../server/compiler.js';
|
|
5
6
|
import { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
|
|
6
7
|
import { MySql2Database } from 'drizzle-orm/mysql2';
|
|
7
8
|
import { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
|
|
8
9
|
import { MCPOptions } from '../utils.js';
|
|
9
10
|
export interface ExpressAdapterOptions {
|
|
10
11
|
/**
|
|
11
|
-
*
|
|
12
|
+
* Pre-configured SemanticLayerCompiler instance.
|
|
13
|
+
* When provided, skips creating a new compiler and cube registration (caller
|
|
14
|
+
* manages it). Required to use per-tenant cube sets, since the caller must own
|
|
15
|
+
* the compiler to call `registerCubeSet` — see docs/per-tenant-cube-sets.md.
|
|
12
16
|
*/
|
|
13
|
-
|
|
17
|
+
semanticLayer?: SemanticLayerCompiler;
|
|
18
|
+
/**
|
|
19
|
+
* Array of cube definitions to register.
|
|
20
|
+
* Required unless `semanticLayer` is provided.
|
|
21
|
+
*/
|
|
22
|
+
cubes?: Cube[];
|
|
14
23
|
/**
|
|
15
24
|
* Drizzle database instance (REQUIRED)
|
|
16
25
|
* This is the core of drizzle-cube - Drizzle ORM integration
|
|
@@ -2,15 +2,24 @@ import { FastifyPluginCallback, FastifyRequest, FastifyInstance } from 'fastify'
|
|
|
2
2
|
import { FastifyCorsOptions } from '@fastify/cors';
|
|
3
3
|
import { SemanticQuery, SecurityContext, DatabaseExecutor, DrizzleDatabase, Cube, CacheConfig, RLSSetupFn } from '../../server/index.js';
|
|
4
4
|
import { AgentConfig } from '../../server/agent/types.js';
|
|
5
|
+
import { SemanticLayerCompiler } from '../../server/compiler.js';
|
|
5
6
|
import { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
|
|
6
7
|
import { MySql2Database } from 'drizzle-orm/mysql2';
|
|
7
8
|
import { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
|
|
8
9
|
import { MCPOptions } from '../utils.js';
|
|
9
10
|
export interface FastifyAdapterOptions {
|
|
10
11
|
/**
|
|
11
|
-
*
|
|
12
|
+
* Pre-configured SemanticLayerCompiler instance.
|
|
13
|
+
* When provided, skips creating a new compiler and cube registration (caller
|
|
14
|
+
* manages it). Required to use per-tenant cube sets, since the caller must own
|
|
15
|
+
* the compiler to call `registerCubeSet` — see docs/per-tenant-cube-sets.md.
|
|
12
16
|
*/
|
|
13
|
-
|
|
17
|
+
semanticLayer?: SemanticLayerCompiler;
|
|
18
|
+
/**
|
|
19
|
+
* Array of cube definitions to register.
|
|
20
|
+
* Required unless `semanticLayer` is provided.
|
|
21
|
+
*/
|
|
22
|
+
cubes?: Cube[];
|
|
14
23
|
/**
|
|
15
24
|
* Drizzle database instance (REQUIRED)
|
|
16
25
|
* This is the core of drizzle-cube - Drizzle ORM integration
|
|
@@ -6,9 +6,16 @@ export interface CubeToolHandlerDeps {
|
|
|
6
6
|
wrapContent: (result: unknown) => MCPToolResult;
|
|
7
7
|
wrapError: (error: unknown) => MCPToolResult;
|
|
8
8
|
}
|
|
9
|
-
/**
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Execute the `discover` tool. Reads the caller's cube set, so it resolves a
|
|
11
|
+
* security context first — discovery has no unauthenticated mode.
|
|
12
|
+
*/
|
|
13
|
+
export declare function runDiscoverTool(deps: CubeToolHandlerDeps, args: unknown, meta?: unknown): Promise<MCPToolResult>;
|
|
14
|
+
/**
|
|
15
|
+
* Execute the `validate` tool. The security context is required: validation is
|
|
16
|
+
* against the caller's cube set, so a caller whose context cannot be resolved
|
|
17
|
+
* gets an error rather than a base-set answer with the SQL omitted.
|
|
18
|
+
*/
|
|
12
19
|
export declare function runValidateTool(deps: CubeToolHandlerDeps, args: unknown, meta?: unknown): Promise<MCPToolResult>;
|
|
13
20
|
/**
|
|
14
21
|
* Execute the `load` / `chart` tools. Both run the same query path; `chart`
|
|
@@ -172,5 +172,16 @@ export declare function resolveMcpResources(resources?: MCPResourceResolver): MC
|
|
|
172
172
|
* project-specific guidance like custom cube semantics).
|
|
173
173
|
*/
|
|
174
174
|
export declare function resolveMcpInstructions(instructions?: MCPInstructionsResolver): string;
|
|
175
|
-
|
|
176
|
-
|
|
175
|
+
/**
|
|
176
|
+
* The `drizzle-cube://schema` resource: this caller's cube metadata as JSON.
|
|
177
|
+
*
|
|
178
|
+
* Its body is tenant-specific, so it must be built per request under the
|
|
179
|
+
* caller's security context. Building it once at handler construction — as this
|
|
180
|
+
* used to be — would freeze every tenant's view to the base set.
|
|
181
|
+
*/
|
|
182
|
+
export declare function buildMcpSchemaResource(semanticLayer: SemanticLayerCompiler, securityContext: SecurityContext): MCPResource;
|
|
183
|
+
/**
|
|
184
|
+
* Static resources plus this caller's schema resource. Call per request, never
|
|
185
|
+
* at setup time — see {@link buildMcpSchemaResource}.
|
|
186
|
+
*/
|
|
187
|
+
export declare function buildMcpResources(semanticLayer: SemanticLayerCompiler, securityContext: SecurityContext, resources?: MCPResourceResolver): MCPResource[];
|
|
@@ -26,9 +26,12 @@ export interface NextCorsOptions {
|
|
|
26
26
|
}
|
|
27
27
|
export interface NextAdapterOptions {
|
|
28
28
|
/**
|
|
29
|
-
* Array of cube definitions to register
|
|
29
|
+
* Array of cube definitions to register.
|
|
30
|
+
* Required unless `semanticLayer` is provided — `createSemanticLayer` returns
|
|
31
|
+
* an injected compiler untouched, so a caller managing their own (which
|
|
32
|
+
* per-tenant cube sets require) supplies no cubes here.
|
|
30
33
|
*/
|
|
31
|
-
cubes
|
|
34
|
+
cubes?: Cube[];
|
|
32
35
|
/**
|
|
33
36
|
* Drizzle database instance (REQUIRED)
|
|
34
37
|
* This is the core of drizzle-cube - Drizzle ORM integration
|
|
@@ -354,11 +354,11 @@ export interface ValidateRequest {
|
|
|
354
354
|
/**
|
|
355
355
|
* Handle /suggest endpoint - generate query from natural language
|
|
356
356
|
*/
|
|
357
|
-
export declare function handleSuggest(semanticLayer: SemanticLayerCompiler, body: SuggestRequest): Promise<QuerySuggestion>;
|
|
357
|
+
export declare function handleSuggest(semanticLayer: SemanticLayerCompiler, securityContext: SecurityContext, body: SuggestRequest): Promise<QuerySuggestion>;
|
|
358
358
|
/**
|
|
359
359
|
* Handle /validate endpoint - validate query with corrections
|
|
360
360
|
*/
|
|
361
|
-
export declare function handleValidate(semanticLayer: SemanticLayerCompiler,
|
|
361
|
+
export declare function handleValidate(semanticLayer: SemanticLayerCompiler, securityContext: SecurityContext, body: ValidateRequest): Promise<AIValidationResult & {
|
|
362
362
|
sql?: {
|
|
363
363
|
sql: string;
|
|
364
364
|
params?: any[];
|
|
@@ -111,6 +111,17 @@ export interface DatabaseAdapter {
|
|
|
111
111
|
* @returns SQL expression with type casting
|
|
112
112
|
*/
|
|
113
113
|
castToType(fieldExpr: AnyColumn | SQL, targetType: 'timestamp' | 'decimal' | 'integer'): SQL;
|
|
114
|
+
/**
|
|
115
|
+
* Cast expression to specific database type, tolerantly: unparseable input yields NULL
|
|
116
|
+
* instead of raising an error (PostgreSQL's `::`/`CAST` on bad input) or silently producing
|
|
117
|
+
* 0 (MySQL/SQLite `CAST` on non-numeric text). Intended for EAV-style schemas where a text
|
|
118
|
+
* column holds numbers/timestamps for some attributes and free text for others, so one dirty
|
|
119
|
+
* value doesn't fail the whole query or masquerade as a real 0.
|
|
120
|
+
* @param fieldExpr - The field expression to cast
|
|
121
|
+
* @param targetType - Target database type
|
|
122
|
+
* @returns SQL expression with tolerant type casting; unparseable/NULL input yields NULL
|
|
123
|
+
*/
|
|
124
|
+
tryCastToType(fieldExpr: AnyColumn | SQL, targetType: 'timestamp' | 'decimal' | 'integer'): SQL;
|
|
114
125
|
/**
|
|
115
126
|
* Build AVG aggregation expression with database-specific null handling
|
|
116
127
|
* @param fieldExpr - The field expression to average
|
|
@@ -216,6 +227,7 @@ export declare abstract class BaseDatabaseAdapter implements DatabaseAdapter {
|
|
|
216
227
|
abstract buildPeriodSeriesSubquery(maxPeriod: number): SQL;
|
|
217
228
|
abstract buildTimeDimension(granularity: TimeGranularity, fieldExpr: AnyColumn | SQL): SQL;
|
|
218
229
|
abstract castToType(fieldExpr: AnyColumn | SQL, targetType: 'timestamp' | 'decimal' | 'integer'): SQL;
|
|
230
|
+
abstract tryCastToType(fieldExpr: AnyColumn | SQL, targetType: 'timestamp' | 'decimal' | 'integer'): SQL;
|
|
219
231
|
abstract getCapabilities(): DatabaseCapabilities;
|
|
220
232
|
abstract buildPercentile(fieldExpr: AnyColumn | SQL, percentile: number): SQL | null;
|
|
221
233
|
/**
|
|
@@ -303,6 +315,40 @@ export declare abstract class BaseDatabaseAdapter implements DatabaseAdapter {
|
|
|
303
315
|
field: AnyColumn | SQL;
|
|
304
316
|
direction: 'asc' | 'desc';
|
|
305
317
|
}>, config?: WindowFunctionConfig): SQL | null;
|
|
318
|
+
/**
|
|
319
|
+
* Regex pattern for tryCastToType's decimal guard: optional leading sign, digits with an
|
|
320
|
+
* optional fractional part (or a bare fractional part like `.5`), surrounded by optional
|
|
321
|
+
* spaces; rejects everything else. Shared by PostgreSQL (`~`) and MySQL/SingleStore
|
|
322
|
+
* (`REGEXP`).
|
|
323
|
+
*
|
|
324
|
+
* Deliberately written using only POSIX ERE syntax (`[0-9]` instead of `\d`, a literal
|
|
325
|
+
* space instead of `\s`) rather than Perl/ICU shorthands. PostgreSQL's `~` always
|
|
326
|
+
* understands `\d`/`\s`, and MySQL 8.0.4+'s default ICU regex engine does too — but
|
|
327
|
+
* SingleStore's `REGEXP` is dialect-switchable via the `regexp_format` session variable
|
|
328
|
+
* ('extended' = POSIX ERE, 'advanced' = ICU/PCRE-style), and SingleStore's own docs
|
|
329
|
+
* recommend explicitly opting into 'advanced' for new regex logic, implying 'extended'
|
|
330
|
+
* (POSIX, no `\d`/`\s`) is the default. Since SingleStoreAdapter inherits this pattern
|
|
331
|
+
* unchanged from MySQLAdapter and this repo doesn't control session variables for
|
|
332
|
+
* consumers, the pattern is written as the POSIX-ERE/ICU/ARE intersection so it matches
|
|
333
|
+
* correctly regardless of which dialect is active.
|
|
334
|
+
*/
|
|
335
|
+
protected decimalTryCastPattern(): string;
|
|
336
|
+
/**
|
|
337
|
+
* Regex pattern for tryCastToType's integer guard: optional leading sign, digits only,
|
|
338
|
+
* surrounded by optional spaces. Same POSIX-ERE/ICU/ARE-portable rationale as
|
|
339
|
+
* decimalTryCastPattern().
|
|
340
|
+
*/
|
|
341
|
+
protected integerTryCastPattern(): string;
|
|
342
|
+
/**
|
|
343
|
+
* Regex pattern for tryCastToType's timestamp guard: an ISO 8601-shaped date, optionally
|
|
344
|
+
* followed by a time component (with optional seconds, fractional seconds and a UTC/offset
|
|
345
|
+
* suffix), surrounded by optional spaces. This only validates the *shape* of the input —
|
|
346
|
+
* it does not catch calendar-invalid dates (e.g. 2024-02-30) or reject strings that "look"
|
|
347
|
+
* like a timestamp but aren't (that would need engine-side parsing, which is exactly what
|
|
348
|
+
* tryCastToType is avoiding relying on for error-safety). Same POSIX-ERE/ICU/ARE-portable
|
|
349
|
+
* rationale as decimalTryCastPattern().
|
|
350
|
+
*/
|
|
351
|
+
protected timestampTryCastPattern(): string;
|
|
306
352
|
/**
|
|
307
353
|
* Helper method to build pattern for string matching
|
|
308
354
|
* Can be overridden by specific adapters if needed
|
|
@@ -45,6 +45,11 @@ export declare class DatabendAdapter extends BaseDatabaseAdapter {
|
|
|
45
45
|
* Databend supports both :: syntax and CAST() function
|
|
46
46
|
*/
|
|
47
47
|
castToType(fieldExpr: AnyColumn | SQL, targetType: 'timestamp' | 'decimal' | 'integer'): SQL;
|
|
48
|
+
/**
|
|
49
|
+
* Build Databend tolerant type casting using the native TRY_CAST function, which returns
|
|
50
|
+
* NULL on conversion failure instead of raising an error (unlike `::`/CAST).
|
|
51
|
+
*/
|
|
52
|
+
tryCastToType(fieldExpr: AnyColumn | SQL, targetType: 'timestamp' | 'decimal' | 'integer'): SQL;
|
|
48
53
|
/**
|
|
49
54
|
* Databend capabilities - start conservative
|
|
50
55
|
*/
|
|
@@ -52,6 +52,11 @@ export declare class DuckDBAdapter extends BaseDatabaseAdapter {
|
|
|
52
52
|
* DuckDB supports both :: syntax and CAST() function
|
|
53
53
|
*/
|
|
54
54
|
castToType(fieldExpr: AnyColumn | SQL, targetType: 'timestamp' | 'decimal' | 'integer'): SQL;
|
|
55
|
+
/**
|
|
56
|
+
* Build DuckDB tolerant type casting using the native TRY_CAST function, which returns
|
|
57
|
+
* NULL on conversion failure instead of raising an error (unlike `::`/CAST).
|
|
58
|
+
*/
|
|
59
|
+
tryCastToType(fieldExpr: AnyColumn | SQL, targetType: 'timestamp' | 'decimal' | 'integer'): SQL;
|
|
55
60
|
/**
|
|
56
61
|
* DuckDB has full support for statistical and window functions
|
|
57
62
|
* Note: supportsPercentileSubqueries is false because DuckDB's QUANTILE_CONT
|
|
@@ -47,6 +47,20 @@ export declare class MySQLAdapter extends BaseDatabaseAdapter {
|
|
|
47
47
|
* MySQL equivalent to PostgreSQL's :: casting syntax
|
|
48
48
|
*/
|
|
49
49
|
castToType(fieldExpr: AnyColumn | SQL, targetType: 'timestamp' | 'decimal' | 'integer'): SQL;
|
|
50
|
+
/**
|
|
51
|
+
* Build MySQL tolerant type casting: NULL on unparseable input instead of MySQL's usual
|
|
52
|
+
* lenient-but-wrong behaviour. `CAST(x AS DECIMAL/SIGNED)` parses a leading numeric prefix
|
|
53
|
+
* (or returns 0 with a warning if there's no numeric prefix at all) rather than erroring —
|
|
54
|
+
* so a dirty value like 'n/a' silently becomes 0. `CAST(x AS DATETIME)` on a string that
|
|
55
|
+
* merely looks date-shaped but is calendar-invalid can, depending on sql_mode, raise an
|
|
56
|
+
* error (strict mode, the MySQL 8 default) rather than returning NULL. Guard all three with
|
|
57
|
+
* REGEXP so we only ever attempt the cast on input that already looks like the target type;
|
|
58
|
+
* anything else short-circuits to NULL first.
|
|
59
|
+
*
|
|
60
|
+
* The timestamp guard only validates ISO 8601 *shape* — it will not catch calendar-invalid
|
|
61
|
+
* dates like 2024-02-30, which could still error under strict SQL mode.
|
|
62
|
+
*/
|
|
63
|
+
tryCastToType(fieldExpr: AnyColumn | SQL, targetType: 'timestamp' | 'decimal' | 'integer'): SQL;
|
|
50
64
|
/**
|
|
51
65
|
* MySQL AVG/STDDEV/VARIANCE use IFNULL (no COALESCE-for-zero idiom mismatch,
|
|
52
66
|
* but IFNULL is the MySQL-idiomatic null guard).
|
|
@@ -43,6 +43,21 @@ export declare class PostgresAdapter extends BaseDatabaseAdapter {
|
|
|
43
43
|
* Extracted from various locations where ::timestamp was used
|
|
44
44
|
*/
|
|
45
45
|
castToType(fieldExpr: AnyColumn | SQL, targetType: 'timestamp' | 'decimal' | 'integer'): SQL;
|
|
46
|
+
/**
|
|
47
|
+
* Build PostgreSQL tolerant type casting: NULL on unparseable input instead of an error.
|
|
48
|
+
* PostgreSQL has no TRY_CAST, and `CAST(x AS type DEFAULT NULL ON ERROR)` (added in a
|
|
49
|
+
* recent PostgreSQL release) requires a minimum server version. This repo pins no minimum
|
|
50
|
+
* PostgreSQL version anywhere (CI/dev docker-compose both run `postgres:18`, but nothing
|
|
51
|
+
* documents that as a floor for consumers), so we don't assume newer syntax is available.
|
|
52
|
+
* Instead, guard the cast with a POSIX regex (`~`) so we only ever attempt to cast values
|
|
53
|
+
* that already look like the target type; anything else short-circuits to NULL before the
|
|
54
|
+
* cast runs, so PostgreSQL never gets a chance to raise.
|
|
55
|
+
*
|
|
56
|
+
* The timestamp guard only validates ISO 8601 *shape* (see timestampTryCastPattern) — it
|
|
57
|
+
* will not catch calendar-invalid dates like 2024-02-30, which would still error. A full
|
|
58
|
+
* guarantee would need a helper SQL function (out of scope here).
|
|
59
|
+
*/
|
|
60
|
+
tryCastToType(fieldExpr: AnyColumn | SQL, targetType: 'timestamp' | 'decimal' | 'integer'): SQL;
|
|
46
61
|
/**
|
|
47
62
|
* PostgreSQL has full support for statistical and window functions
|
|
48
63
|
*/
|
|
@@ -41,6 +41,12 @@ export declare class SnowflakeAdapter extends BaseDatabaseAdapter {
|
|
|
41
41
|
* Snowflake supports both :: syntax and CAST() function
|
|
42
42
|
*/
|
|
43
43
|
castToType(fieldExpr: AnyColumn | SQL, targetType: 'timestamp' | 'decimal' | 'integer'): SQL;
|
|
44
|
+
/**
|
|
45
|
+
* Build Snowflake tolerant type casting using the native TRY_CAST function, which returns
|
|
46
|
+
* NULL on conversion failure instead of raising an error (unlike `::`/CAST). Snowflake's
|
|
47
|
+
* TRY_CAST supports VARCHAR, NUMBER-family types (including DECIMAL) and TIMESTAMP.
|
|
48
|
+
*/
|
|
49
|
+
tryCastToType(fieldExpr: AnyColumn | SQL, targetType: 'timestamp' | 'decimal' | 'integer'): SQL;
|
|
44
50
|
/**
|
|
45
51
|
* Snowflake capabilities - full SQL support
|
|
46
52
|
*/
|
|
@@ -51,6 +51,27 @@ export declare class SQLiteAdapter extends BaseDatabaseAdapter {
|
|
|
51
51
|
* SQLite has dynamic typing but supports CAST for consistency
|
|
52
52
|
*/
|
|
53
53
|
castToType(fieldExpr: AnyColumn | SQL, targetType: 'timestamp' | 'decimal' | 'integer'): SQL;
|
|
54
|
+
/**
|
|
55
|
+
* Build SQLite tolerant type casting: NULL on unparseable input instead of SQLite's usual
|
|
56
|
+
* dynamic-typing behaviour. SQLite's CAST-to-numeric applies "prefix" conversion — the
|
|
57
|
+
* longest numeric prefix of the string is used, or 0 if there is none — so `CAST('n/a' AS
|
|
58
|
+
* REAL)` silently yields 0.0 rather than erroring or returning NULL.
|
|
59
|
+
*
|
|
60
|
+
* SQLite has no REGEXP operator by default (it requires loading an extension, same
|
|
61
|
+
* limitation regexCondition() works around with GLOB). GLOB's `*`/`?`/`[...]` syntax can't
|
|
62
|
+
* express "one or more digits" directly, but the standard SQLite idiom for "string contains
|
|
63
|
+
* only characters from a set" is `NOT x GLOB '*[^set]*'` — true only if no character outside
|
|
64
|
+
* the set appears anywhere. That's what's used below to validate the trimmed value contains
|
|
65
|
+
* only the characters a valid decimal/integer/epoch-ms value could use, before attempting
|
|
66
|
+
* the cast; empty/whitespace-only strings are excluded separately.
|
|
67
|
+
*
|
|
68
|
+
* Known limitation: this is a character-set check, not a full grammar check, so a malformed
|
|
69
|
+
* value that still only uses allowed characters (e.g. '1.2.3' or '+-5') passes the guard and
|
|
70
|
+
* is then handled by SQLite's own prefix-based numeric parsing (never an error, but not
|
|
71
|
+
* necessarily NULL either). Clearly non-numeric input (letters, 'n/a', punctuation outside
|
|
72
|
+
* the allowed set) is reliably rejected to NULL, which is the case this method exists for.
|
|
73
|
+
*/
|
|
74
|
+
tryCastToType(fieldExpr: AnyColumn | SQL, targetType: 'timestamp' | 'decimal' | 'integer'): SQL;
|
|
54
75
|
/**
|
|
55
76
|
* SQLite AVG uses IFNULL rather than COALESCE for null-to-zero handling.
|
|
56
77
|
*/
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { AnyColumn, SQL } from 'drizzle-orm';
|
|
2
|
+
import { Dimension, QueryContext } from './types/index.js';
|
|
3
|
+
/** The value types a generated attribute dimension can be cast to. */
|
|
4
|
+
export type AttributeValueType = 'string' | 'number' | 'time';
|
|
5
|
+
/** One admin-defined attribute, as loaded from the application's own table. */
|
|
6
|
+
export interface AttributeDefinition {
|
|
7
|
+
/**
|
|
8
|
+
* Stable identifier. The dimension's member name is derived from this, never
|
|
9
|
+
* from the attribute's name — so renaming an attribute updates every table
|
|
10
|
+
* header without breaking saved dashboards, drill state or share links.
|
|
11
|
+
*/
|
|
12
|
+
id: string | number;
|
|
13
|
+
/** Display name. Becomes the dimension's `title`, which the client renders. */
|
|
14
|
+
name: string;
|
|
15
|
+
/**
|
|
16
|
+
* Value type, if the application's attribute table records one. Filtering and
|
|
17
|
+
* sorting happen in SQL over the whole table before any row reaches the
|
|
18
|
+
* browser, so this is not cosmetic — see {@link buildAttributeDimensions}.
|
|
19
|
+
*/
|
|
20
|
+
valueType?: AttributeValueType;
|
|
21
|
+
}
|
|
22
|
+
export interface BuildAttributeDimensionsOptions {
|
|
23
|
+
/** The attributes to generate a dimension for. */
|
|
24
|
+
attributes: AttributeDefinition[];
|
|
25
|
+
/** The junction table holding one row per (record, attribute). */
|
|
26
|
+
valueTable: unknown;
|
|
27
|
+
/** Primary key of the record being extended — e.g. `employees.id`. */
|
|
28
|
+
recordKey: AnyColumn;
|
|
29
|
+
/** Column on the junction table pointing back at the record. */
|
|
30
|
+
foreignKey: AnyColumn;
|
|
31
|
+
/** Column on the junction table identifying the attribute. */
|
|
32
|
+
attributeKey: AnyColumn;
|
|
33
|
+
/** Column on the junction table holding the value. */
|
|
34
|
+
valueColumn: AnyColumn;
|
|
35
|
+
/**
|
|
36
|
+
* Row-level security for the junction table. **Required**: the subquery reads
|
|
37
|
+
* the junction table directly, so without this a tenant sees every tenant's
|
|
38
|
+
* attribute values. It is a parameter rather than an option so that omitting
|
|
39
|
+
* it is impossible rather than merely inadvisable.
|
|
40
|
+
*/
|
|
41
|
+
security: (ctx: QueryContext) => SQL;
|
|
42
|
+
/**
|
|
43
|
+
* Per-attribute type overrides, keyed by attribute id. Wins over
|
|
44
|
+
* `AttributeDefinition.valueType`.
|
|
45
|
+
*/
|
|
46
|
+
types?: Record<string, AttributeValueType>;
|
|
47
|
+
/** Member-name prefix. Defaults to `attr_`. */
|
|
48
|
+
namePrefix?: string;
|
|
49
|
+
/** Passed through to each generated dimension's `shown`. */
|
|
50
|
+
shown?: boolean;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Build one dimension per attribute, each backed by a correlated scalar
|
|
54
|
+
* subquery against the junction table.
|
|
55
|
+
*
|
|
56
|
+
* ```ts
|
|
57
|
+
* dimensions: {
|
|
58
|
+
* ...baseDimensions,
|
|
59
|
+
* ...buildAttributeDimensions({
|
|
60
|
+
* attributes: attrs,
|
|
61
|
+
* valueTable: employeeAttributeValues,
|
|
62
|
+
* recordKey: employees.id,
|
|
63
|
+
* foreignKey: employeeAttributeValues.employeeId,
|
|
64
|
+
* attributeKey: employeeAttributeValues.attributeId,
|
|
65
|
+
* valueColumn: employeeAttributeValues.value,
|
|
66
|
+
* security: (ctx) => eq(employeeAttributeValues.organisationId, ctx.securityContext.organisationId)
|
|
67
|
+
* })
|
|
68
|
+
* }
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* Three details that are easy to get wrong, and are handled here:
|
|
72
|
+
*
|
|
73
|
+
* - **Typing is mandatory, not cosmetic.** Sorting and filtering run in SQL
|
|
74
|
+
* over the whole table before a page reaches the browser, so client-side
|
|
75
|
+
* conversion cannot repair them: sorted as text, `100` sorts below `9`, and
|
|
76
|
+
* `> 50` admits `'9'` while rejecting `'100'`. A `number` attribute is cast
|
|
77
|
+
* in SQL — tolerantly, so one `n/a` yields NULL for that row instead of
|
|
78
|
+
* failing the whole query.
|
|
79
|
+
* - **`LIMIT 1`.** EAV tables rarely carry a unique constraint on
|
|
80
|
+
* (record, attribute); without it a duplicate row raises "more than one row
|
|
81
|
+
* returned by a subquery" on Postgres.
|
|
82
|
+
* - **Security inside the subquery**, not merely on the outer query.
|
|
83
|
+
*
|
|
84
|
+
* **Grouping limitation.** The subquery correlates on the record key, so a
|
|
85
|
+
* *grouped* query must also group by that key — `dimensions: ['Employees.id',
|
|
86
|
+
* 'Employees.attr_1']` is fine, `dimensions: ['Employees.attr_1']` with a
|
|
87
|
+
* measure is not. Postgres rejects the latter with "subquery uses ungrouped
|
|
88
|
+
* column … from outer query", and MySQL with `only_full_group_by`; SQLite
|
|
89
|
+
* permits it. Record-grain listings (`ungrouped: true`) — the case this exists
|
|
90
|
+
* for — are unaffected. If you need to aggregate freely by an attribute, pivot
|
|
91
|
+
* it into a real column with a view (see the performance ladder below).
|
|
92
|
+
*
|
|
93
|
+
* Performance: projection is cheap (a page of 25 rows is 25 indexed lookups per
|
|
94
|
+
* attribute), but `ORDER BY (SELECT …)` and `WHERE (SELECT …) = …` are
|
|
95
|
+
* proportional to the base table because no index serves them. At tens of
|
|
96
|
+
* thousands of rows that is fine; beyond it, pivot the attributes into real
|
|
97
|
+
* indexable columns via a view.
|
|
98
|
+
*/
|
|
99
|
+
export declare function buildAttributeDimensions(options: BuildAttributeDimensionsOptions): Record<string, Dimension>;
|