drizzle-cube 0.4.40 → 0.4.42
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/cli/index.cjs +439 -0
- package/dist/client/charts/ChartLoader.d.ts +18 -3
- package/dist/client/charts/chartConfigRegistry.d.ts +11 -1
- package/dist/client/charts/chartPlugin.d.ts +74 -0
- package/dist/client/charts/lazyChartConfigRegistry.d.ts +10 -0
- package/dist/client/charts.js +13 -15
- package/dist/client/chunks/{DashboardEditModal-iGhIvNP6.js → DashboardEditModal-4zzjtZRR.js} +683 -685
- package/dist/client/chunks/DashboardEditModal-4zzjtZRR.js.map +1 -0
- package/dist/client/chunks/{FieldSearchModal-BxQ5JhWz.js → FieldSearchModal-trURu9Sa.js} +15 -16
- package/dist/client/chunks/{FieldSearchModal-BxQ5JhWz.js.map → FieldSearchModal-trURu9Sa.js.map} +1 -1
- package/dist/client/chunks/{RetentionCombinedChart-D4Yf1TnQ.js → RetentionCombinedChart-B1hUYaXt.js} +2 -2
- package/dist/client/chunks/{RetentionCombinedChart-D4Yf1TnQ.js.map → RetentionCombinedChart-B1hUYaXt.js.map} +1 -1
- package/dist/client/chunks/{RetentionHeatmap-BoGY6mlZ.js → RetentionHeatmap-Dn2ocjVf.js} +2 -2
- package/dist/client/chunks/{RetentionHeatmap-BoGY6mlZ.js.map → RetentionHeatmap-Dn2ocjVf.js.map} +1 -1
- package/dist/client/chunks/{analysis-builder-DEGG5NwE.js → analysis-builder-B7XSIMkr.js} +1474 -1523
- package/dist/client/chunks/analysis-builder-B7XSIMkr.js.map +1 -0
- package/dist/client/chunks/{analysis-builder-shared-BxHYfTzo.js → analysis-builder-shared-DaqtrLxd.js} +762 -778
- package/dist/client/chunks/analysis-builder-shared-DaqtrLxd.js.map +1 -0
- package/dist/client/chunks/{chart-bar-Bx4oKlqo.js → chart-bar-CPt67rLR.js} +1 -1
- package/dist/client/chunks/{chart-bar-Bx4oKlqo.js.map → chart-bar-CPt67rLR.js.map} +1 -1
- package/dist/client/chunks/{chart-box-plot-CVIi1aM5.js → chart-box-plot-Dp_nqQen.js} +1 -1
- package/dist/client/chunks/{chart-box-plot-CVIi1aM5.js.map → chart-box-plot-Dp_nqQen.js.map} +1 -1
- package/dist/client/chunks/{chart-bubble-DvyG15UB.js → chart-bubble-CYQ8loeS.js} +1 -1
- package/dist/client/chunks/{chart-bubble-DvyG15UB.js.map → chart-bubble-CYQ8loeS.js.map} +1 -1
- package/dist/client/chunks/{chart-candlestick-caHyxB9O.js → chart-candlestick-DTeSf7C5.js} +1 -1
- package/dist/client/chunks/{chart-candlestick-caHyxB9O.js.map → chart-candlestick-DTeSf7C5.js.map} +1 -1
- package/dist/client/chunks/{chart-config-activity-grid-USo7JrPh.js → chart-config-activity-grid-BSWS08cI.js} +1 -1
- package/dist/client/chunks/{chart-config-activity-grid-USo7JrPh.js.map → chart-config-activity-grid-BSWS08cI.js.map} +1 -1
- package/dist/client/chunks/{chart-config-area-D_ZufYzg.js → chart-config-area-DKwgcHp4.js} +1 -1
- package/dist/client/chunks/{chart-config-area-D_ZufYzg.js.map → chart-config-area-DKwgcHp4.js.map} +1 -1
- package/dist/client/chunks/{chart-config-bar-BCi2Wmd6.js → chart-config-bar-deTjEhap.js} +1 -1
- package/dist/client/chunks/{chart-config-bar-BCi2Wmd6.js.map → chart-config-bar-deTjEhap.js.map} +1 -1
- package/dist/client/chunks/{chart-config-box-plot-afKLzJSp.js → chart-config-box-plot-DU4iWk3V.js} +1 -1
- package/dist/client/chunks/{chart-config-box-plot-afKLzJSp.js.map → chart-config-box-plot-DU4iWk3V.js.map} +1 -1
- package/dist/client/chunks/{chart-config-bubble-CgbBjPv8.js → chart-config-bubble-B8FSHSW-.js} +1 -1
- package/dist/client/chunks/{chart-config-bubble-CgbBjPv8.js.map → chart-config-bubble-B8FSHSW-.js.map} +1 -1
- package/dist/client/chunks/{chart-config-candlestick-7boGjZ-A.js → chart-config-candlestick-BGfyWFft.js} +1 -1
- package/dist/client/chunks/{chart-config-candlestick-7boGjZ-A.js.map → chart-config-candlestick-BGfyWFft.js.map} +1 -1
- package/dist/client/chunks/{chart-config-data-table-Cl7sBasW.js → chart-config-data-table-DKRcGa8t.js} +1 -1
- package/dist/client/chunks/{chart-config-data-table-Cl7sBasW.js.map → chart-config-data-table-DKRcGa8t.js.map} +1 -1
- package/dist/client/chunks/{chart-config-funnel-CXPYQtTl.js → chart-config-funnel-Bt4iGFo_.js} +1 -1
- package/dist/client/chunks/{chart-config-funnel-CXPYQtTl.js.map → chart-config-funnel-Bt4iGFo_.js.map} +1 -1
- package/dist/client/chunks/{chart-config-gauge-DUNEUCvh.js → chart-config-gauge-Bk4Jjp3W.js} +1 -1
- package/dist/client/chunks/{chart-config-gauge-DUNEUCvh.js.map → chart-config-gauge-Bk4Jjp3W.js.map} +1 -1
- package/dist/client/chunks/{chart-config-heat-map-BFf1tO11.js → chart-config-heat-map-CkHsqkrY.js} +1 -1
- package/dist/client/chunks/{chart-config-heat-map-BFf1tO11.js.map → chart-config-heat-map-CkHsqkrY.js.map} +1 -1
- package/dist/client/chunks/{chart-config-kpi-delta-C5k2waIJ.js → chart-config-kpi-delta-CkUX98JV.js} +1 -1
- package/dist/client/chunks/{chart-config-kpi-delta-C5k2waIJ.js.map → chart-config-kpi-delta-CkUX98JV.js.map} +1 -1
- package/dist/client/chunks/{chart-config-kpi-number-DptOyhk0.js → chart-config-kpi-number-DcxyiUgs.js} +1 -1
- package/dist/client/chunks/{chart-config-kpi-number-DptOyhk0.js.map → chart-config-kpi-number-DcxyiUgs.js.map} +1 -1
- package/dist/client/chunks/{chart-config-kpi-text-D9DdVWqd.js → chart-config-kpi-text-DI4mj8CN.js} +1 -1
- package/dist/client/chunks/{chart-config-kpi-text-D9DdVWqd.js.map → chart-config-kpi-text-DI4mj8CN.js.map} +1 -1
- package/dist/client/chunks/{chart-config-line-B3NgLF7K.js → chart-config-line--j7-dLue.js} +1 -1
- package/dist/client/chunks/{chart-config-line-B3NgLF7K.js.map → chart-config-line--j7-dLue.js.map} +1 -1
- package/dist/client/chunks/{chart-config-markdown-tlfivQTt.js → chart-config-markdown-DUjvVjV4.js} +1 -1
- package/dist/client/chunks/{chart-config-markdown-tlfivQTt.js.map → chart-config-markdown-DUjvVjV4.js.map} +1 -1
- package/dist/client/chunks/{chart-config-measure-profile-D7XDwrU2.js → chart-config-measure-profile-B9FKBNGc.js} +1 -1
- package/dist/client/chunks/{chart-config-measure-profile-D7XDwrU2.js.map → chart-config-measure-profile-B9FKBNGc.js.map} +1 -1
- package/dist/client/chunks/{chart-config-pie-wY0B52PC.js → chart-config-pie-yU4jipl9.js} +1 -1
- package/dist/client/chunks/{chart-config-pie-wY0B52PC.js.map → chart-config-pie-yU4jipl9.js.map} +1 -1
- package/dist/client/chunks/{chart-config-radar-DRpJBy1M.js → chart-config-radar-R9Fkc8wL.js} +1 -1
- package/dist/client/chunks/{chart-config-radar-DRpJBy1M.js.map → chart-config-radar-R9Fkc8wL.js.map} +1 -1
- package/dist/client/chunks/{chart-config-radial-bar-DCUpXv9G.js → chart-config-radial-bar-DeoXfpIp.js} +1 -1
- package/dist/client/chunks/{chart-config-radial-bar-DCUpXv9G.js.map → chart-config-radial-bar-DeoXfpIp.js.map} +1 -1
- package/dist/client/chunks/{chart-config-sankey-CdOhlm4h.js → chart-config-sankey-CXEsxo6s.js} +1 -1
- package/dist/client/chunks/{chart-config-sankey-CdOhlm4h.js.map → chart-config-sankey-CXEsxo6s.js.map} +1 -1
- package/dist/client/chunks/{chart-config-scatter-B2su_x8f.js → chart-config-scatter-MVUFupub.js} +1 -1
- package/dist/client/chunks/{chart-config-scatter-B2su_x8f.js.map → chart-config-scatter-MVUFupub.js.map} +1 -1
- package/dist/client/chunks/{chart-config-sunburst-BPdjbk18.js → chart-config-sunburst-Z_gqIY5u.js} +1 -1
- package/dist/client/chunks/{chart-config-sunburst-BPdjbk18.js.map → chart-config-sunburst-Z_gqIY5u.js.map} +1 -1
- package/dist/client/chunks/{chart-config-tree-map-Cbsh2fe2.js → chart-config-tree-map-BD-xAeIy.js} +1 -1
- package/dist/client/chunks/{chart-config-tree-map-Cbsh2fe2.js.map → chart-config-tree-map-BD-xAeIy.js.map} +1 -1
- package/dist/client/chunks/{chart-config-waterfall-DGmuZfQF.js → chart-config-waterfall-CHwVkXZc.js} +1 -1
- package/dist/client/chunks/{chart-config-waterfall-DGmuZfQF.js.map → chart-config-waterfall-CHwVkXZc.js.map} +1 -1
- package/dist/client/chunks/{chart-data-table-CW_qZDpt.js → chart-data-table-BZ7StNWv.js} +1452 -826
- package/dist/client/chunks/chart-data-table-BZ7StNWv.js.map +1 -0
- package/dist/client/chunks/{chart-gauge-BLLJqeXo.js → chart-gauge-_Xdgk_qI.js} +1 -1
- package/dist/client/chunks/{chart-gauge-BLLJqeXo.js.map → chart-gauge-_Xdgk_qI.js.map} +1 -1
- package/dist/client/chunks/{chart-heat-map-f2fM2mDC.js → chart-heat-map-BOMQeUDL.js} +1 -1
- package/dist/client/chunks/{chart-heat-map-f2fM2mDC.js.map → chart-heat-map-BOMQeUDL.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-delta-BPexzOe7.js → chart-kpi-delta-C2tdpWki.js} +4 -4
- package/dist/client/chunks/{chart-kpi-delta-BPexzOe7.js.map → chart-kpi-delta-C2tdpWki.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-number-BBtGBtZL.js → chart-kpi-number-BUNKM7yg.js} +5 -5
- package/dist/client/chunks/{chart-kpi-number-BBtGBtZL.js.map → chart-kpi-number-BUNKM7yg.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-text-BqHhmJEB.js → chart-kpi-text-COF8iN0K.js} +2 -2
- package/dist/client/chunks/{chart-kpi-text-BqHhmJEB.js.map → chart-kpi-text-COF8iN0K.js.map} +1 -1
- package/dist/client/chunks/{chart-line-CPhQRMZ7.js → chart-line-D3SEwXDS.js} +1 -1
- package/dist/client/chunks/{chart-line-CPhQRMZ7.js.map → chart-line-D3SEwXDS.js.map} +1 -1
- package/dist/client/chunks/{chart-markdown-B2X4IwLO.js → chart-markdown-DMekYkKz.js} +647 -644
- package/dist/client/chunks/chart-markdown-DMekYkKz.js.map +1 -0
- package/dist/client/chunks/{chart-measure-profile-CVlqGslU.js → chart-measure-profile-BPhI1Z9s.js} +1 -1
- package/dist/client/chunks/{chart-measure-profile-CVlqGslU.js.map → chart-measure-profile-BPhI1Z9s.js.map} +1 -1
- package/dist/client/chunks/{chart-pie-DafSc9sE.js → chart-pie-COl3Rmdk.js} +1 -1
- package/dist/client/chunks/{chart-pie-DafSc9sE.js.map → chart-pie-COl3Rmdk.js.map} +1 -1
- package/dist/client/chunks/{chart-radar-Dz9F5k-B.js → chart-radar-BKZXylBB.js} +1 -1
- package/dist/client/chunks/{chart-radar-Dz9F5k-B.js.map → chart-radar-BKZXylBB.js.map} +1 -1
- package/dist/client/chunks/{chart-radial-bar-N3MNUL7o.js → chart-radial-bar-CMfC7SPd.js} +1 -1
- package/dist/client/chunks/{chart-radial-bar-N3MNUL7o.js.map → chart-radial-bar-CMfC7SPd.js.map} +1 -1
- package/dist/client/chunks/{chart-scatter-J2JNi88S.js → chart-scatter-xQMa3dUt.js} +1 -1
- package/dist/client/chunks/{chart-scatter-J2JNi88S.js.map → chart-scatter-xQMa3dUt.js.map} +1 -1
- package/dist/client/chunks/{chart-sunburst-D1NFQjqk.js → chart-sunburst-BGhJ4fui.js} +1 -1
- package/dist/client/chunks/{chart-sunburst-D1NFQjqk.js.map → chart-sunburst-BGhJ4fui.js.map} +1 -1
- package/dist/client/chunks/{chart-tree-map-CbYjko2s.js → chart-tree-map-Cn1pmrAw.js} +1 -1
- package/dist/client/chunks/{chart-tree-map-CbYjko2s.js.map → chart-tree-map-Cn1pmrAw.js.map} +1 -1
- package/dist/client/chunks/{chart-waterfall-Z65TGMUO.js → chart-waterfall-C2nVN4pn.js} +1 -1
- package/dist/client/chunks/{chart-waterfall-Z65TGMUO.js.map → chart-waterfall-C2nVN4pn.js.map} +1 -1
- package/dist/client/chunks/{charts-core-CJlGzwsW.js → charts-core-Cy3rHADX.js} +1 -1
- package/dist/client/chunks/{charts-core-CJlGzwsW.js.map → charts-core-Cy3rHADX.js.map} +1 -1
- package/dist/client/chunks/{core-DJrniqct.js → core-BdWfCZ3y.js} +1 -1
- package/dist/client/chunks/{core-DJrniqct.js.map → core-BdWfCZ3y.js.map} +1 -1
- package/dist/client/chunks/{dist-DDBeV_JI.js → dist-BWPE2m_X.js} +1 -1
- package/dist/client/chunks/{dist-DDBeV_JI.js.map → dist-BWPE2m_X.js.map} +1 -1
- package/dist/client/chunks/{javascript-BBwTSo6e.js → javascript-O1RIRkZr.js} +1 -1
- package/dist/client/chunks/{javascript-BBwTSo6e.js.map → javascript-O1RIRkZr.js.map} +1 -1
- package/dist/client/chunks/{json-BpTrLZSh.js → json-C5bX2tt1.js} +1 -1
- package/dist/client/chunks/{json-BpTrLZSh.js.map → json-C5bX2tt1.js.map} +1 -1
- package/dist/client/chunks/{retention-UEXlSdZ-.js → retention-YhT1Oohi.js} +1 -1
- package/dist/client/chunks/{retention-UEXlSdZ-.js.map → retention-YhT1Oohi.js.map} +1 -1
- package/dist/client/chunks/{schema-visualization-CwiEtwdu.js → schema-visualization-DVdfx6N8.js} +92 -96
- package/dist/client/chunks/schema-visualization-DVdfx6N8.js.map +1 -0
- package/dist/client/chunks/{sql-B0chxcEK.js → sql-D2qikO5q.js} +1 -1
- package/dist/client/chunks/{sql-B0chxcEK.js.map → sql-D2qikO5q.js.map} +1 -1
- package/dist/client/chunks/{syntaxHighlighting-BLl0ch4A.js → syntaxHighlighting-BYYWYmjr.js} +2 -2
- package/dist/client/chunks/{syntaxHighlighting-BLl0ch4A.js.map → syntaxHighlighting-BYYWYmjr.js.map} +1 -1
- package/dist/client/chunks/{useDebounce-C_wstEud.js → useDebounce-Bel8J05v.js} +12 -12
- package/dist/client/chunks/{useDebounce-C_wstEud.js.map → useDebounce-Bel8J05v.js.map} +1 -1
- package/dist/client/chunks/{useDirtyStateTracking-CgKZWkel.js → useDirtyStateTracking-KAjwj1Ht.js} +1 -1
- package/dist/client/chunks/{useDirtyStateTracking-CgKZWkel.js.map → useDirtyStateTracking-KAjwj1Ht.js.map} +1 -1
- package/dist/client/chunks/{useExplainAI-C9ytXRIC.js → useExplainAI-CxdzY2N0.js} +14 -14
- package/dist/client/chunks/{useExplainAI-C9ytXRIC.js.map → useExplainAI-CxdzY2N0.js.map} +1 -1
- package/dist/client/chunks/{useNotebookLayout-BFZ_33Kb.js → useNotebookLayout-DKkMenhj.js} +1 -1
- package/dist/client/chunks/{useNotebookLayout-BFZ_33Kb.js.map → useNotebookLayout-DKkMenhj.js.map} +1 -1
- package/dist/client/chunks/{utils-3FNmeZJR.js → utils-CMkS7h9x.js} +2 -2
- package/dist/client/chunks/{utils-3FNmeZJR.js.map → utils-CMkS7h9x.js.map} +1 -1
- package/dist/client/chunks/{vendor-BPRWulB7.js → vendor-BoWEubRu.js} +40 -40
- package/dist/client/chunks/{vendor-BPRWulB7.js.map → vendor-BoWEubRu.js.map} +1 -1
- package/dist/client/components.js +3 -3
- package/dist/client/hooks.js +5 -5
- package/dist/client/icons/registry.d.ts +6 -0
- package/dist/client/icons.js +2 -2
- package/dist/client/index.d.ts +3 -2
- package/dist/client/index.js +39 -41
- package/dist/client/index.js.map +1 -1
- package/dist/client/providers/CubeProvider.d.ts +4 -1
- package/dist/client/providers.js +2 -2
- package/dist/client/schema.d.ts +13 -0
- package/dist/client/schema.js +2 -0
- package/dist/client/styles.css +1 -1
- package/dist/client/types.d.ts +2 -1
- package/dist/client/utils.js +6 -6
- package/dist/client-bundle-stats.html +1 -1
- package/package.json +10 -2
- package/dist/client/chunks/DashboardEditModal-iGhIvNP6.js.map +0 -1
- package/dist/client/chunks/RetentionCombinedChart.config-DprbXd1N.js +0 -56
- package/dist/client/chunks/RetentionCombinedChart.config-DprbXd1N.js.map +0 -1
- package/dist/client/chunks/RetentionHeatmap.config-cbaNExVy.js +0 -25
- package/dist/client/chunks/RetentionHeatmap.config-cbaNExVy.js.map +0 -1
- package/dist/client/chunks/analysis-builder-DEGG5NwE.js.map +0 -1
- package/dist/client/chunks/analysis-builder-shared-BxHYfTzo.js.map +0 -1
- package/dist/client/chunks/chart-data-table-CW_qZDpt.js.map +0 -1
- package/dist/client/chunks/chart-markdown-B2X4IwLO.js.map +0 -1
- package/dist/client/chunks/charts-loader-gZjOqZwG.js +0 -259
- package/dist/client/chunks/charts-loader-gZjOqZwG.js.map +0 -1
- package/dist/client/chunks/lazyChartConfigRegistry-BjhxDaSf.js +0 -149
- package/dist/client/chunks/lazyChartConfigRegistry-BjhxDaSf.js.map +0 -1
- package/dist/client/chunks/schema-visualization-CwiEtwdu.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retention-UEXlSdZ-.js","names":[],"sources":["../../../src/client/types/retention.ts"],"sourcesContent":["/**\n * Retention Analysis Types\n *\n * Types for Retention analysis mode which tracks cohort-based retention over time.\n * Retention analysis measures what percentage of users from each cohort return\n * in subsequent time periods.\n */\n\nimport type { Filter } from '../types'\nimport type { FunnelBindingKey } from './funnel'\n\n// ============================================================================\n// Date Range Types\n// ============================================================================\n\n/**\n * Date range for cohort analysis (REQUIRED)\n * Matches server's RetentionDateRange interface\n */\nexport interface DateRange {\n /** Start date (inclusive), ISO 8601 format (YYYY-MM-DD) */\n start: string\n /** End date (inclusive), ISO 8601 format (YYYY-MM-DD) */\n end: string\n}\n\n/**\n * Preset date range type\n */\nexport type DateRangePreset =\n | 'last_30_days'\n | 'last_3_months'\n | 'last_6_months'\n | 'last_12_months'\n | 'this_year'\n | 'last_year'\n | 'custom'\n\n/**\n * Preset date range options for the UI\n */\nexport const RETENTION_DATE_RANGE_PRESETS: { value: DateRangePreset; label: string }[] = [\n { value: 'last_30_days', label: 'Last 30 days' },\n { value: 'last_3_months', label: 'Last 3 months' },\n { value: 'last_6_months', label: 'Last 6 months' },\n { value: 'last_12_months', label: 'Last 12 months' },\n { value: 'this_year', label: 'This year' },\n { value: 'last_year', label: 'Last year' },\n { value: 'custom', label: 'Custom range' },\n]\n\n/**\n * Default preset for retention date range\n */\nexport const DEFAULT_DATE_RANGE_PRESET: DateRangePreset = 'last_3_months'\n\n/**\n * Calculate date range from a preset value\n * Returns ISO date strings (YYYY-MM-DD)\n */\nexport function getDateRangeFromPreset(preset: DateRangePreset): DateRange {\n const now = new Date()\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate())\n\n switch (preset) {\n case 'last_30_days': {\n const start = new Date(today)\n start.setDate(start.getDate() - 30)\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(today),\n }\n }\n case 'last_3_months': {\n // Start of 3 months ago to end of last month\n const start = new Date(today.getFullYear(), today.getMonth() - 3, 1)\n const end = new Date(today.getFullYear(), today.getMonth(), 0) // Last day of previous month\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(end),\n }\n }\n case 'last_6_months': {\n const start = new Date(today.getFullYear(), today.getMonth() - 6, 1)\n const end = new Date(today.getFullYear(), today.getMonth(), 0)\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(end),\n }\n }\n case 'last_12_months': {\n const start = new Date(today.getFullYear(), today.getMonth() - 12, 1)\n const end = new Date(today.getFullYear(), today.getMonth(), 0)\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(end),\n }\n }\n case 'this_year': {\n const start = new Date(today.getFullYear(), 0, 1)\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(today),\n }\n }\n case 'last_year': {\n const start = new Date(today.getFullYear() - 1, 0, 1)\n const end = new Date(today.getFullYear() - 1, 11, 31)\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(end),\n }\n }\n case 'custom':\n default:\n // For custom, return last 3 months as fallback\n return getDateRangeFromPreset('last_3_months')\n }\n}\n\n/**\n * Format a Date object to ISO date string (YYYY-MM-DD)\n */\nfunction formatDateToISO(date: Date): string {\n const year = date.getFullYear()\n const month = String(date.getMonth() + 1).padStart(2, '0')\n const day = String(date.getDate()).padStart(2, '0')\n return `${year}-${month}-${day}`\n}\n\n/**\n * Detect which preset a date range matches, if any\n */\nexport function detectDateRangePreset(range: DateRange): DateRangePreset {\n for (const preset of RETENTION_DATE_RANGE_PRESETS) {\n if (preset.value === 'custom') continue\n const presetRange = getDateRangeFromPreset(preset.value)\n if (presetRange.start === range.start && presetRange.end === range.end) {\n return preset.value\n }\n }\n return 'custom'\n}\n\n// ============================================================================\n// Server Query Format\n// ============================================================================\n\n/**\n * Server retention query format\n * This is the shape sent to the server for execution\n * Wrapped in { retention: {...} } similar to funnel queries\n */\nexport interface ServerRetentionQuery {\n retention: RetentionQueryConfig\n}\n\n/**\n * Retention query configuration\n * Contains all parameters needed for server-side retention analysis\n *\n * Simplified Mixpanel-style format:\n * - Single cube and timestamp dimension\n * - Single cohort (date range defines the cohort, not granularity)\n * - Optional breakdown dimension for segmentation\n */\nexport interface RetentionQueryConfig {\n /**\n * Single timestamp dimension for the analysis.\n * String format (e.g., 'Events.timestamp'),\n * Object format for multi-cube with explicit cube reference.\n */\n timeDimension: string | { cube: string; dimension: string }\n\n /**\n * Binding key - dimension that links users across events.\n * This is typically a user ID or other entity identifier.\n * String for single-cube (e.g., 'Events.userId'),\n * Array for multi-cube with different column names per cube.\n */\n bindingKey: string | { cube: string; dimension: string }[]\n\n /**\n * Date range for cohort analysis (REQUIRED).\n * Users who first performed the cohort action within this range are included.\n */\n dateRange: DateRange\n\n /**\n * Granularity for viewing retention periods.\n * Determines how retention periods are measured (day/week/month).\n */\n granularity: RetentionGranularity\n\n /**\n * Number of periods to calculate (e.g., 12 for 12 weeks).\n * Period 0 is always the cohort entry period.\n */\n periods: number\n\n /**\n * Retention type:\n * - 'classic': User returned exactly in period N (bounded)\n * - 'rolling': User returned in period N or any later period (unbounded)\n */\n retentionType: RetentionType\n\n /**\n * Optional filters on cohort entry events.\n * Applied when identifying which users enter the cohort.\n */\n cohortFilters?: Filter | Filter[]\n\n /**\n * Optional filters on return activity events.\n * Applied when checking for user activity in each period.\n */\n activityFilters?: Filter | Filter[]\n\n /**\n * Optional breakdown dimensions for segmenting the cohort.\n * When provided, retention is calculated per breakdown value combination.\n * e.g., [\"Events.country\"] or [\"Events.country\", \"Events.plan\"]\n */\n breakdownDimensions?: string[]\n}\n\n// ============================================================================\n// Enums and Unions\n// ============================================================================\n\n/**\n * Supported granularity levels for retention analysis\n */\nexport type RetentionGranularity = 'day' | 'week' | 'month'\n\n/**\n * Retention calculation types\n * - classic: User active exactly in period N\n * - rolling: User active in period N or any later period\n */\nexport type RetentionType = 'classic' | 'rolling'\n\n// ============================================================================\n// Result Types\n// ============================================================================\n\n/**\n * Single retention data point returned from server\n * Results are returned as a flat array; client transforms to matrix if needed\n */\nexport interface RetentionResultRow {\n /** Period number (0 = cohort entry, 1 = first retention period, etc.) */\n period: number\n\n /** Number of users in the cohort */\n cohortSize: number\n\n /** Number of users retained in this period */\n retainedUsers: number\n\n /** Retention rate as decimal (0-1), e.g., 0.45 for 45% */\n retentionRate: number\n\n /** Breakdown value when breakdown dimension is specified (e.g., \"US\", \"UK\") */\n breakdownValue?: string | null\n}\n\n/**\n * Retention chart data format for visualization\n * Supports both heatmap and line chart modes\n */\nexport interface RetentionChartData {\n rows: RetentionResultRow[]\n /** Period numbers (0 to periods) */\n periods: number[]\n /** Breakdown values when breakdown dimension is specified */\n breakdownValues?: string[]\n /** Summary statistics */\n summary?: RetentionSummary\n /** Granularity of retention periods (day/week/month) for period label formatting */\n granularity?: RetentionGranularity\n /** Human-readable label extracted from the binding key dimension (e.g., \"userId\" from \"Users.userId\") */\n bindingKeyLabel?: string\n}\n\n/**\n * Summary statistics for retention analysis\n */\nexport interface RetentionSummary {\n /** Total unique users in the cohort */\n totalUsers: number\n /** Average retention rate across all periods for period 1 */\n avgPeriod1Retention: number\n /** Highest retention rate for period 1 */\n maxPeriod1Retention: number\n /** Lowest retention rate for period 1 */\n minPeriod1Retention: number\n /** Number of breakdown segments (1 if no breakdown) */\n segmentCount?: number\n}\n\n// ============================================================================\n// Breakdown Types\n// ============================================================================\n\n/**\n * Breakdown item for retention analysis (single dimension)\n * Follows Mixpanel pattern - one breakdown dimension only\n */\nexport interface RetentionBreakdownItem {\n /** Full dimension name (e.g., \"Events.country\") */\n field: string\n /** Display label for the dimension */\n label?: string\n}\n\n// ============================================================================\n// Slice State (for Zustand store)\n// ============================================================================\n\n/**\n * Retention mode state for the AnalysisBuilder store\n * Simplified Mixpanel-style with single global configuration\n *\n * Key simplifications from previous version:\n * - Single cube for all (no separate cohort/activity cubes)\n * - Single timestamp dimension\n * - Single cohort with breakdown support (no cohort explosion)\n * - Granularity = viewing periods only\n */\nexport interface RetentionSliceState {\n /** Single cube for retention analysis */\n retentionCube: string | null\n\n /** Binding key that identifies entities (reuses funnel binding key type) */\n retentionBindingKey: FunnelBindingKey | null\n\n /** Single timestamp dimension for both cohort entry and activity */\n retentionTimeDimension: string | null\n\n /** Date range for cohort analysis (REQUIRED) */\n retentionDateRange: DateRange\n\n /** Filters that define who enters the cohort */\n retentionCohortFilters: Filter[]\n\n /** Filters that define what counts as a return */\n retentionActivityFilters: Filter[]\n\n /** Optional breakdown dimensions for segmenting the cohort */\n retentionBreakdowns: RetentionBreakdownItem[]\n\n /** Granularity for viewing retention periods (day/week/month) */\n retentionViewGranularity: RetentionGranularity\n\n /** Number of periods to analyze (1-52) */\n retentionPeriods: number\n\n /** Type of retention calculation */\n retentionType: RetentionType\n}\n\n/**\n * Retention slice actions for the store\n */\nexport interface RetentionSliceActions {\n /** Set the single cube for retention analysis */\n setRetentionCube: (cube: string | null) => void\n /** Set the retention binding key */\n setRetentionBindingKey: (key: FunnelBindingKey | null) => void\n /** Set the single timestamp dimension */\n setRetentionTimeDimension: (dim: string | null) => void\n /** Set the date range (REQUIRED) */\n setRetentionDateRange: (range: DateRange) => void\n /** Set all cohort filters at once */\n setRetentionCohortFilters: (filters: Filter[]) => void\n /** Add a cohort filter */\n addRetentionCohortFilter: (filter: Filter) => void\n /** Remove a cohort filter by index */\n removeRetentionCohortFilter: (index: number) => void\n /** Update a cohort filter by index */\n updateRetentionCohortFilter: (index: number, filter: Filter) => void\n /** Set all activity filters at once */\n setRetentionActivityFilters: (filters: Filter[]) => void\n /** Add an activity filter */\n addRetentionActivityFilter: (filter: Filter) => void\n /** Remove an activity filter by index */\n removeRetentionActivityFilter: (index: number) => void\n /** Update an activity filter by index */\n updateRetentionActivityFilter: (index: number, filter: Filter) => void\n /** Set all breakdown dimensions */\n setRetentionBreakdowns: (breakdowns: RetentionBreakdownItem[]) => void\n /** Add a breakdown dimension */\n addRetentionBreakdown: (breakdown: RetentionBreakdownItem) => void\n /** Remove a breakdown dimension by field name */\n removeRetentionBreakdown: (field: string) => void\n /** Set the view granularity */\n setRetentionViewGranularity: (granularity: RetentionGranularity) => void\n /** Set the number of periods */\n setRetentionPeriods: (periods: number) => void\n /** Set the retention type */\n setRetentionType: (type: RetentionType) => void\n /** Check if in retention mode (analysisType === 'retention') */\n isRetentionMode: () => boolean\n /** Check if retention mode is properly configured and ready for execution */\n isRetentionModeEnabled: () => boolean\n /** Build ServerRetentionQuery from retention state */\n buildRetentionQuery: () => ServerRetentionQuery | null\n /** Get validation errors explaining why retention query cannot be built */\n getRetentionValidation: () => { isValid: boolean; errors: string[]; warnings: string[] }\n}\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Type guard to check if data is retention chart data\n */\nexport function isRetentionData(data: unknown): data is RetentionChartData {\n if (!data || typeof data !== 'object') return false\n const d = data as Record<string, unknown>\n return (\n Array.isArray(d.rows) &&\n Array.isArray(d.periods)\n )\n}\n\n/**\n * Type guard to detect server retention query format\n * Used to distinguish { retention: {...} } from CubeQuery, etc.\n */\nexport function isServerRetentionQuery(obj: unknown): obj is ServerRetentionQuery {\n return (\n typeof obj === 'object' &&\n obj !== null &&\n 'retention' in obj &&\n typeof (obj as { retention: unknown }).retention === 'object'\n )\n}\n\n/**\n * Type guard for retention result row\n */\nexport function isRetentionResultRow(row: unknown): row is RetentionResultRow {\n if (!row || typeof row !== 'object') return false\n const r = row as Record<string, unknown>\n return (\n typeof r.cohortPeriod === 'string' &&\n typeof r.period === 'number' &&\n typeof r.cohortSize === 'number' &&\n typeof r.retainedUsers === 'number' &&\n typeof r.retentionRate === 'number'\n )\n}\n\n// ============================================================================\n// Default Values\n// ============================================================================\n\n/**\n * Default retention slice state for store initialization\n */\nexport const defaultRetentionSliceState: RetentionSliceState = {\n retentionCube: null,\n retentionBindingKey: null,\n retentionTimeDimension: null,\n retentionDateRange: getDateRangeFromPreset(DEFAULT_DATE_RANGE_PRESET),\n retentionCohortFilters: [],\n retentionActivityFilters: [],\n retentionBreakdowns: [],\n retentionViewGranularity: 'week',\n retentionPeriods: 12,\n retentionType: 'classic',\n}\n\n/**\n * Minimum and maximum values for retention periods\n */\nexport const RETENTION_MIN_PERIODS = 1\nexport const RETENTION_MAX_PERIODS = 52\n\n/**\n * Available granularity options\n */\nexport const RETENTION_GRANULARITY_OPTIONS: { value: RetentionGranularity; label: string }[] = [\n { value: 'day', label: 'Daily' },\n { value: 'week', label: 'Weekly' },\n { value: 'month', label: 'Monthly' },\n]\n\n/**\n * Available retention type options\n */\nexport const RETENTION_TYPE_OPTIONS: { value: RetentionType; label: string; description: string }[] = [\n {\n value: 'classic',\n label: 'Classic',\n description: 'User was active in exactly period N',\n },\n {\n value: 'rolling',\n label: 'Rolling',\n description: 'User was active in period N or later',\n },\n]\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"retention-YhT1Oohi.js","names":[],"sources":["../../../src/client/types/retention.ts"],"sourcesContent":["/**\n * Retention Analysis Types\n *\n * Types for Retention analysis mode which tracks cohort-based retention over time.\n * Retention analysis measures what percentage of users from each cohort return\n * in subsequent time periods.\n */\n\nimport type { Filter } from '../types'\nimport type { FunnelBindingKey } from './funnel'\n\n// ============================================================================\n// Date Range Types\n// ============================================================================\n\n/**\n * Date range for cohort analysis (REQUIRED)\n * Matches server's RetentionDateRange interface\n */\nexport interface DateRange {\n /** Start date (inclusive), ISO 8601 format (YYYY-MM-DD) */\n start: string\n /** End date (inclusive), ISO 8601 format (YYYY-MM-DD) */\n end: string\n}\n\n/**\n * Preset date range type\n */\nexport type DateRangePreset =\n | 'last_30_days'\n | 'last_3_months'\n | 'last_6_months'\n | 'last_12_months'\n | 'this_year'\n | 'last_year'\n | 'custom'\n\n/**\n * Preset date range options for the UI\n */\nexport const RETENTION_DATE_RANGE_PRESETS: { value: DateRangePreset; label: string }[] = [\n { value: 'last_30_days', label: 'Last 30 days' },\n { value: 'last_3_months', label: 'Last 3 months' },\n { value: 'last_6_months', label: 'Last 6 months' },\n { value: 'last_12_months', label: 'Last 12 months' },\n { value: 'this_year', label: 'This year' },\n { value: 'last_year', label: 'Last year' },\n { value: 'custom', label: 'Custom range' },\n]\n\n/**\n * Default preset for retention date range\n */\nexport const DEFAULT_DATE_RANGE_PRESET: DateRangePreset = 'last_3_months'\n\n/**\n * Calculate date range from a preset value\n * Returns ISO date strings (YYYY-MM-DD)\n */\nexport function getDateRangeFromPreset(preset: DateRangePreset): DateRange {\n const now = new Date()\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate())\n\n switch (preset) {\n case 'last_30_days': {\n const start = new Date(today)\n start.setDate(start.getDate() - 30)\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(today),\n }\n }\n case 'last_3_months': {\n // Start of 3 months ago to end of last month\n const start = new Date(today.getFullYear(), today.getMonth() - 3, 1)\n const end = new Date(today.getFullYear(), today.getMonth(), 0) // Last day of previous month\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(end),\n }\n }\n case 'last_6_months': {\n const start = new Date(today.getFullYear(), today.getMonth() - 6, 1)\n const end = new Date(today.getFullYear(), today.getMonth(), 0)\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(end),\n }\n }\n case 'last_12_months': {\n const start = new Date(today.getFullYear(), today.getMonth() - 12, 1)\n const end = new Date(today.getFullYear(), today.getMonth(), 0)\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(end),\n }\n }\n case 'this_year': {\n const start = new Date(today.getFullYear(), 0, 1)\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(today),\n }\n }\n case 'last_year': {\n const start = new Date(today.getFullYear() - 1, 0, 1)\n const end = new Date(today.getFullYear() - 1, 11, 31)\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(end),\n }\n }\n case 'custom':\n default:\n // For custom, return last 3 months as fallback\n return getDateRangeFromPreset('last_3_months')\n }\n}\n\n/**\n * Format a Date object to ISO date string (YYYY-MM-DD)\n */\nfunction formatDateToISO(date: Date): string {\n const year = date.getFullYear()\n const month = String(date.getMonth() + 1).padStart(2, '0')\n const day = String(date.getDate()).padStart(2, '0')\n return `${year}-${month}-${day}`\n}\n\n/**\n * Detect which preset a date range matches, if any\n */\nexport function detectDateRangePreset(range: DateRange): DateRangePreset {\n for (const preset of RETENTION_DATE_RANGE_PRESETS) {\n if (preset.value === 'custom') continue\n const presetRange = getDateRangeFromPreset(preset.value)\n if (presetRange.start === range.start && presetRange.end === range.end) {\n return preset.value\n }\n }\n return 'custom'\n}\n\n// ============================================================================\n// Server Query Format\n// ============================================================================\n\n/**\n * Server retention query format\n * This is the shape sent to the server for execution\n * Wrapped in { retention: {...} } similar to funnel queries\n */\nexport interface ServerRetentionQuery {\n retention: RetentionQueryConfig\n}\n\n/**\n * Retention query configuration\n * Contains all parameters needed for server-side retention analysis\n *\n * Simplified Mixpanel-style format:\n * - Single cube and timestamp dimension\n * - Single cohort (date range defines the cohort, not granularity)\n * - Optional breakdown dimension for segmentation\n */\nexport interface RetentionQueryConfig {\n /**\n * Single timestamp dimension for the analysis.\n * String format (e.g., 'Events.timestamp'),\n * Object format for multi-cube with explicit cube reference.\n */\n timeDimension: string | { cube: string; dimension: string }\n\n /**\n * Binding key - dimension that links users across events.\n * This is typically a user ID or other entity identifier.\n * String for single-cube (e.g., 'Events.userId'),\n * Array for multi-cube with different column names per cube.\n */\n bindingKey: string | { cube: string; dimension: string }[]\n\n /**\n * Date range for cohort analysis (REQUIRED).\n * Users who first performed the cohort action within this range are included.\n */\n dateRange: DateRange\n\n /**\n * Granularity for viewing retention periods.\n * Determines how retention periods are measured (day/week/month).\n */\n granularity: RetentionGranularity\n\n /**\n * Number of periods to calculate (e.g., 12 for 12 weeks).\n * Period 0 is always the cohort entry period.\n */\n periods: number\n\n /**\n * Retention type:\n * - 'classic': User returned exactly in period N (bounded)\n * - 'rolling': User returned in period N or any later period (unbounded)\n */\n retentionType: RetentionType\n\n /**\n * Optional filters on cohort entry events.\n * Applied when identifying which users enter the cohort.\n */\n cohortFilters?: Filter | Filter[]\n\n /**\n * Optional filters on return activity events.\n * Applied when checking for user activity in each period.\n */\n activityFilters?: Filter | Filter[]\n\n /**\n * Optional breakdown dimensions for segmenting the cohort.\n * When provided, retention is calculated per breakdown value combination.\n * e.g., [\"Events.country\"] or [\"Events.country\", \"Events.plan\"]\n */\n breakdownDimensions?: string[]\n}\n\n// ============================================================================\n// Enums and Unions\n// ============================================================================\n\n/**\n * Supported granularity levels for retention analysis\n */\nexport type RetentionGranularity = 'day' | 'week' | 'month'\n\n/**\n * Retention calculation types\n * - classic: User active exactly in period N\n * - rolling: User active in period N or any later period\n */\nexport type RetentionType = 'classic' | 'rolling'\n\n// ============================================================================\n// Result Types\n// ============================================================================\n\n/**\n * Single retention data point returned from server\n * Results are returned as a flat array; client transforms to matrix if needed\n */\nexport interface RetentionResultRow {\n /** Period number (0 = cohort entry, 1 = first retention period, etc.) */\n period: number\n\n /** Number of users in the cohort */\n cohortSize: number\n\n /** Number of users retained in this period */\n retainedUsers: number\n\n /** Retention rate as decimal (0-1), e.g., 0.45 for 45% */\n retentionRate: number\n\n /** Breakdown value when breakdown dimension is specified (e.g., \"US\", \"UK\") */\n breakdownValue?: string | null\n}\n\n/**\n * Retention chart data format for visualization\n * Supports both heatmap and line chart modes\n */\nexport interface RetentionChartData {\n rows: RetentionResultRow[]\n /** Period numbers (0 to periods) */\n periods: number[]\n /** Breakdown values when breakdown dimension is specified */\n breakdownValues?: string[]\n /** Summary statistics */\n summary?: RetentionSummary\n /** Granularity of retention periods (day/week/month) for period label formatting */\n granularity?: RetentionGranularity\n /** Human-readable label extracted from the binding key dimension (e.g., \"userId\" from \"Users.userId\") */\n bindingKeyLabel?: string\n}\n\n/**\n * Summary statistics for retention analysis\n */\nexport interface RetentionSummary {\n /** Total unique users in the cohort */\n totalUsers: number\n /** Average retention rate across all periods for period 1 */\n avgPeriod1Retention: number\n /** Highest retention rate for period 1 */\n maxPeriod1Retention: number\n /** Lowest retention rate for period 1 */\n minPeriod1Retention: number\n /** Number of breakdown segments (1 if no breakdown) */\n segmentCount?: number\n}\n\n// ============================================================================\n// Breakdown Types\n// ============================================================================\n\n/**\n * Breakdown item for retention analysis (single dimension)\n * Follows Mixpanel pattern - one breakdown dimension only\n */\nexport interface RetentionBreakdownItem {\n /** Full dimension name (e.g., \"Events.country\") */\n field: string\n /** Display label for the dimension */\n label?: string\n}\n\n// ============================================================================\n// Slice State (for Zustand store)\n// ============================================================================\n\n/**\n * Retention mode state for the AnalysisBuilder store\n * Simplified Mixpanel-style with single global configuration\n *\n * Key simplifications from previous version:\n * - Single cube for all (no separate cohort/activity cubes)\n * - Single timestamp dimension\n * - Single cohort with breakdown support (no cohort explosion)\n * - Granularity = viewing periods only\n */\nexport interface RetentionSliceState {\n /** Single cube for retention analysis */\n retentionCube: string | null\n\n /** Binding key that identifies entities (reuses funnel binding key type) */\n retentionBindingKey: FunnelBindingKey | null\n\n /** Single timestamp dimension for both cohort entry and activity */\n retentionTimeDimension: string | null\n\n /** Date range for cohort analysis (REQUIRED) */\n retentionDateRange: DateRange\n\n /** Filters that define who enters the cohort */\n retentionCohortFilters: Filter[]\n\n /** Filters that define what counts as a return */\n retentionActivityFilters: Filter[]\n\n /** Optional breakdown dimensions for segmenting the cohort */\n retentionBreakdowns: RetentionBreakdownItem[]\n\n /** Granularity for viewing retention periods (day/week/month) */\n retentionViewGranularity: RetentionGranularity\n\n /** Number of periods to analyze (1-52) */\n retentionPeriods: number\n\n /** Type of retention calculation */\n retentionType: RetentionType\n}\n\n/**\n * Retention slice actions for the store\n */\nexport interface RetentionSliceActions {\n /** Set the single cube for retention analysis */\n setRetentionCube: (cube: string | null) => void\n /** Set the retention binding key */\n setRetentionBindingKey: (key: FunnelBindingKey | null) => void\n /** Set the single timestamp dimension */\n setRetentionTimeDimension: (dim: string | null) => void\n /** Set the date range (REQUIRED) */\n setRetentionDateRange: (range: DateRange) => void\n /** Set all cohort filters at once */\n setRetentionCohortFilters: (filters: Filter[]) => void\n /** Add a cohort filter */\n addRetentionCohortFilter: (filter: Filter) => void\n /** Remove a cohort filter by index */\n removeRetentionCohortFilter: (index: number) => void\n /** Update a cohort filter by index */\n updateRetentionCohortFilter: (index: number, filter: Filter) => void\n /** Set all activity filters at once */\n setRetentionActivityFilters: (filters: Filter[]) => void\n /** Add an activity filter */\n addRetentionActivityFilter: (filter: Filter) => void\n /** Remove an activity filter by index */\n removeRetentionActivityFilter: (index: number) => void\n /** Update an activity filter by index */\n updateRetentionActivityFilter: (index: number, filter: Filter) => void\n /** Set all breakdown dimensions */\n setRetentionBreakdowns: (breakdowns: RetentionBreakdownItem[]) => void\n /** Add a breakdown dimension */\n addRetentionBreakdown: (breakdown: RetentionBreakdownItem) => void\n /** Remove a breakdown dimension by field name */\n removeRetentionBreakdown: (field: string) => void\n /** Set the view granularity */\n setRetentionViewGranularity: (granularity: RetentionGranularity) => void\n /** Set the number of periods */\n setRetentionPeriods: (periods: number) => void\n /** Set the retention type */\n setRetentionType: (type: RetentionType) => void\n /** Check if in retention mode (analysisType === 'retention') */\n isRetentionMode: () => boolean\n /** Check if retention mode is properly configured and ready for execution */\n isRetentionModeEnabled: () => boolean\n /** Build ServerRetentionQuery from retention state */\n buildRetentionQuery: () => ServerRetentionQuery | null\n /** Get validation errors explaining why retention query cannot be built */\n getRetentionValidation: () => { isValid: boolean; errors: string[]; warnings: string[] }\n}\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Type guard to check if data is retention chart data\n */\nexport function isRetentionData(data: unknown): data is RetentionChartData {\n if (!data || typeof data !== 'object') return false\n const d = data as Record<string, unknown>\n return (\n Array.isArray(d.rows) &&\n Array.isArray(d.periods)\n )\n}\n\n/**\n * Type guard to detect server retention query format\n * Used to distinguish { retention: {...} } from CubeQuery, etc.\n */\nexport function isServerRetentionQuery(obj: unknown): obj is ServerRetentionQuery {\n return (\n typeof obj === 'object' &&\n obj !== null &&\n 'retention' in obj &&\n typeof (obj as { retention: unknown }).retention === 'object'\n )\n}\n\n/**\n * Type guard for retention result row\n */\nexport function isRetentionResultRow(row: unknown): row is RetentionResultRow {\n if (!row || typeof row !== 'object') return false\n const r = row as Record<string, unknown>\n return (\n typeof r.cohortPeriod === 'string' &&\n typeof r.period === 'number' &&\n typeof r.cohortSize === 'number' &&\n typeof r.retainedUsers === 'number' &&\n typeof r.retentionRate === 'number'\n )\n}\n\n// ============================================================================\n// Default Values\n// ============================================================================\n\n/**\n * Default retention slice state for store initialization\n */\nexport const defaultRetentionSliceState: RetentionSliceState = {\n retentionCube: null,\n retentionBindingKey: null,\n retentionTimeDimension: null,\n retentionDateRange: getDateRangeFromPreset(DEFAULT_DATE_RANGE_PRESET),\n retentionCohortFilters: [],\n retentionActivityFilters: [],\n retentionBreakdowns: [],\n retentionViewGranularity: 'week',\n retentionPeriods: 12,\n retentionType: 'classic',\n}\n\n/**\n * Minimum and maximum values for retention periods\n */\nexport const RETENTION_MIN_PERIODS = 1\nexport const RETENTION_MAX_PERIODS = 52\n\n/**\n * Available granularity options\n */\nexport const RETENTION_GRANULARITY_OPTIONS: { value: RetentionGranularity; label: string }[] = [\n { value: 'day', label: 'Daily' },\n { value: 'week', label: 'Weekly' },\n { value: 'month', label: 'Monthly' },\n]\n\n/**\n * Available retention type options\n */\nexport const RETENTION_TYPE_OPTIONS: { value: RetentionType; label: string; description: string }[] = [\n {\n value: 'classic',\n label: 'Classic',\n description: 'User was active in exactly period N',\n },\n {\n value: 'rolling',\n label: 'Rolling',\n description: 'User was active in period N or later',\n },\n]\n"],"mappings":";AAyCA,IAAa,IAA4E;CACvF;EAAE,OAAO;EAAgB,OAAO;EAAgB;CAChD;EAAE,OAAO;EAAiB,OAAO;EAAiB;CAClD;EAAE,OAAO;EAAiB,OAAO;EAAiB;CAClD;EAAE,OAAO;EAAkB,OAAO;EAAkB;CACpD;EAAE,OAAO;EAAa,OAAO;EAAa;CAC1C;EAAE,OAAO;EAAa,OAAO;EAAa;CAC1C;EAAE,OAAO;EAAU,OAAO;EAAgB;CAC3C,EAKY,IAA6C;AAM1D,SAAgB,EAAuB,GAAoC;CACzE,IAAM,oBAAM,IAAI,MAAM,EAChB,IAAQ,IAAI,KAAK,EAAI,aAAa,EAAE,EAAI,UAAU,EAAE,EAAI,SAAS,CAAC;AAExE,SAAQ,GAAR;EACE,KAAK,gBAAgB;GACnB,IAAM,IAAQ,IAAI,KAAK,EAAM;AAE7B,UADA,EAAM,QAAQ,EAAM,SAAS,GAAG,GAAG,EAC5B;IACL,OAAO,EAAgB,EAAM;IAC7B,KAAK,EAAgB,EAAM;IAC5B;;EAEH,KAAK,iBAAiB;GAEpB,IAAM,IAAQ,IAAI,KAAK,EAAM,aAAa,EAAE,EAAM,UAAU,GAAG,GAAG,EAAE,EAC9D,IAAM,IAAI,KAAK,EAAM,aAAa,EAAE,EAAM,UAAU,EAAE,EAAE;AAC9D,UAAO;IACL,OAAO,EAAgB,EAAM;IAC7B,KAAK,EAAgB,EAAI;IAC1B;;EAEH,KAAK,iBAAiB;GACpB,IAAM,IAAQ,IAAI,KAAK,EAAM,aAAa,EAAE,EAAM,UAAU,GAAG,GAAG,EAAE,EAC9D,IAAM,IAAI,KAAK,EAAM,aAAa,EAAE,EAAM,UAAU,EAAE,EAAE;AAC9D,UAAO;IACL,OAAO,EAAgB,EAAM;IAC7B,KAAK,EAAgB,EAAI;IAC1B;;EAEH,KAAK,kBAAkB;GACrB,IAAM,IAAQ,IAAI,KAAK,EAAM,aAAa,EAAE,EAAM,UAAU,GAAG,IAAI,EAAE,EAC/D,IAAM,IAAI,KAAK,EAAM,aAAa,EAAE,EAAM,UAAU,EAAE,EAAE;AAC9D,UAAO;IACL,OAAO,EAAgB,EAAM;IAC7B,KAAK,EAAgB,EAAI;IAC1B;;EAEH,KAAK,YAEH,QAAO;GACL,OAAO,EAFK,IAAI,KAAK,EAAM,aAAa,EAAE,GAAG,EAAE,CAElB;GAC7B,KAAK,EAAgB,EAAM;GAC5B;EAEH,KAAK,aAAa;GAChB,IAAM,IAAQ,IAAI,KAAK,EAAM,aAAa,GAAG,GAAG,GAAG,EAAE,EAC/C,IAAM,IAAI,KAAK,EAAM,aAAa,GAAG,GAAG,IAAI,GAAG;AACrD,UAAO;IACL,OAAO,EAAgB,EAAM;IAC7B,KAAK,EAAgB,EAAI;IAC1B;;EAGH,QAEE,QAAO,EAAuB,gBAAgB;;;AAOpD,SAAS,EAAgB,GAAoB;AAI3C,QAAO,GAHM,EAAK,aAAa,CAGhB,GAFD,OAAO,EAAK,UAAU,GAAG,EAAE,CAAC,SAAS,GAAG,IAAI,CAElC,GADZ,OAAO,EAAK,SAAS,CAAC,CAAC,SAAS,GAAG,IAAI;;AAOrD,SAAgB,EAAsB,GAAmC;AACvE,MAAK,IAAM,KAAU,GAA8B;AACjD,MAAI,EAAO,UAAU,SAAU;EAC/B,IAAM,IAAc,EAAuB,EAAO,MAAM;AACxD,MAAI,EAAY,UAAU,EAAM,SAAS,EAAY,QAAQ,EAAM,IACjE,QAAO,EAAO;;AAGlB,QAAO;;AAuRT,SAAgB,EAAgB,GAA2C;AACzE,KAAI,CAAC,KAAQ,OAAO,KAAS,SAAU,QAAO;CAC9C,IAAM,IAAI;AACV,QACE,MAAM,QAAQ,EAAE,KAAK,IACrB,MAAM,QAAQ,EAAE,QAAQ;;AAQ5B,SAAgB,EAAuB,GAA2C;AAChF,QACE,OAAO,KAAQ,cACf,KACA,eAAe,KACf,OAAQ,EAA+B,aAAc;;AA0BzD,IAAa,IAAkD;CAC7D,eAAe;CACf,qBAAqB;CACrB,wBAAwB;CACxB,oBAAoB,EAAuB,EAA0B;CACrE,wBAAwB,EAAE;CAC1B,0BAA0B,EAAE;CAC5B,qBAAqB,EAAE;CACvB,0BAA0B;CAC1B,kBAAkB;CAClB,eAAe;CAChB,EAWY,IAAkF;CAC7F;EAAE,OAAO;EAAO,OAAO;EAAS;CAChC;EAAE,OAAO;EAAQ,OAAO;EAAU;CAClC;EAAE,OAAO;EAAS,OAAO;EAAW;CACrC,EAKY,IAAyF,CACpG;CACE,OAAO;CACP,OAAO;CACP,aAAa;CACd,EACD;CACE,OAAO;CACP,OAAO;CACP,aAAa;CACd,CACF"}
|
package/dist/client/chunks/{schema-visualization-CwiEtwdu.js → schema-visualization-DVdfx6N8.js}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as e } from "./rolldown-runtime-lc2dmIiU.js";
|
|
2
|
-
import {
|
|
2
|
+
import { A as t, c as n } from "./chart-data-table-BZ7StNWv.js";
|
|
3
3
|
import { Suspense as r, createContext as i, lazy as a, useCallback as o, useContext as s, useEffect as c, useMemo as l, useRef as u, useState as d } from "react";
|
|
4
4
|
import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
5
5
|
//#region src/client/components/SchemaVisualization/xyflowContext.tsx
|
|
@@ -11,8 +11,8 @@ function _() {
|
|
|
11
11
|
}
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region src/client/components/SchemaVisualization/SchemaVisualizationLazy.tsx
|
|
14
|
-
var v = !1;
|
|
15
|
-
function
|
|
14
|
+
var v = /* @__PURE__ */ e({ SchemaVisualizationLazy: () => C }), y = !1;
|
|
15
|
+
function b(e) {
|
|
16
16
|
return /* @__PURE__ */ p("div", {
|
|
17
17
|
className: "dc:flex dc:items-center dc:justify-center dc:h-full dc:p-8",
|
|
18
18
|
children: /* @__PURE__ */ m("div", {
|
|
@@ -38,7 +38,7 @@ function y(e) {
|
|
|
38
38
|
})
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
|
-
function
|
|
41
|
+
function x() {
|
|
42
42
|
return /* @__PURE__ */ p("div", {
|
|
43
43
|
className: "dc:flex dc:items-center dc:justify-center dc:h-full",
|
|
44
44
|
children: /* @__PURE__ */ m("div", {
|
|
@@ -50,36 +50,36 @@ function b() {
|
|
|
50
50
|
})
|
|
51
51
|
});
|
|
52
52
|
}
|
|
53
|
-
var
|
|
54
|
-
function
|
|
55
|
-
let [t, n] = d(null), [i, a] = d(
|
|
53
|
+
var S = a(async () => ({ default: (await Promise.resolve().then(() => R)).SchemaVisualization }));
|
|
54
|
+
function C(e) {
|
|
55
|
+
let [t, n] = d(null), [i, a] = d(y);
|
|
56
56
|
return c(() => {
|
|
57
|
-
if (
|
|
57
|
+
if (y) return;
|
|
58
58
|
let e = !1;
|
|
59
|
-
return import(
|
|
59
|
+
return import("@xyflow/react").then((t) => {
|
|
60
60
|
e || n(t);
|
|
61
61
|
}).catch(() => {
|
|
62
|
-
|
|
62
|
+
y = !0, e || a(!0);
|
|
63
63
|
}), () => {
|
|
64
64
|
e = !0;
|
|
65
65
|
};
|
|
66
|
-
}, []), i ? /* @__PURE__ */ p(
|
|
66
|
+
}, []), i ? /* @__PURE__ */ p(b, { ...e }) : t ? /* @__PURE__ */ p(g, {
|
|
67
67
|
value: t,
|
|
68
68
|
children: /* @__PURE__ */ p(r, {
|
|
69
|
-
fallback: /* @__PURE__ */ p(
|
|
70
|
-
children: /* @__PURE__ */ p(
|
|
69
|
+
fallback: /* @__PURE__ */ p(x, {}),
|
|
70
|
+
children: /* @__PURE__ */ p(S, { ...e })
|
|
71
71
|
})
|
|
72
|
-
}) : /* @__PURE__ */ p(
|
|
72
|
+
}) : /* @__PURE__ */ p(x, {});
|
|
73
73
|
}
|
|
74
74
|
//#endregion
|
|
75
75
|
//#region src/client/components/SchemaVisualization/CubeNode.tsx
|
|
76
|
-
function
|
|
77
|
-
let { Handle:
|
|
76
|
+
function w({ data: e }) {
|
|
77
|
+
let { Handle: n, Position: r } = _(), { cube: i, onFieldClick: a, onCubeClick: o, isHighlighted: s, highlightedFields: c, searchTerm: l, selectedField: u } = e, d = (e, t, n) => {
|
|
78
78
|
a && a(i.name, t, n, {
|
|
79
79
|
x: e.clientX,
|
|
80
80
|
y: e.clientY
|
|
81
81
|
});
|
|
82
|
-
}, f =
|
|
82
|
+
}, f = t("info"), h = (e) => {
|
|
83
83
|
e.stopPropagation(), o && o(i.name, {
|
|
84
84
|
x: e.clientX,
|
|
85
85
|
y: e.clientY
|
|
@@ -233,28 +233,28 @@ function C({ data: e }) {
|
|
|
233
233
|
})
|
|
234
234
|
})]
|
|
235
235
|
}),
|
|
236
|
-
/* @__PURE__ */ p(
|
|
236
|
+
/* @__PURE__ */ p(n, {
|
|
237
237
|
type: "source",
|
|
238
238
|
position: r.Right,
|
|
239
239
|
id: "right",
|
|
240
240
|
className: "dc:opacity-0",
|
|
241
241
|
isConnectable: !1
|
|
242
242
|
}),
|
|
243
|
-
/* @__PURE__ */ p(
|
|
243
|
+
/* @__PURE__ */ p(n, {
|
|
244
244
|
type: "target",
|
|
245
245
|
position: r.Left,
|
|
246
246
|
id: "left",
|
|
247
247
|
className: "dc:opacity-0",
|
|
248
248
|
isConnectable: !1
|
|
249
249
|
}),
|
|
250
|
-
/* @__PURE__ */ p(
|
|
250
|
+
/* @__PURE__ */ p(n, {
|
|
251
251
|
type: "source",
|
|
252
252
|
position: r.Bottom,
|
|
253
253
|
id: "bottom",
|
|
254
254
|
className: "dc:opacity-0",
|
|
255
255
|
isConnectable: !1
|
|
256
256
|
}),
|
|
257
|
-
/* @__PURE__ */ p(
|
|
257
|
+
/* @__PURE__ */ p(n, {
|
|
258
258
|
type: "target",
|
|
259
259
|
position: r.Top,
|
|
260
260
|
id: "top",
|
|
@@ -266,7 +266,7 @@ function C({ data: e }) {
|
|
|
266
266
|
}
|
|
267
267
|
//#endregion
|
|
268
268
|
//#region src/client/components/SchemaVisualization/RelationshipEdge.tsx
|
|
269
|
-
function
|
|
269
|
+
function T({ sourceX: e, sourceY: t, targetX: n, targetY: r, sourcePosition: i, targetPosition: a, style: o = {}, data: s, markerEnd: c }) {
|
|
270
270
|
let { getBezierPath: l, BaseEdge: u, EdgeLabelRenderer: d } = _(), [h, g, v] = l({
|
|
271
271
|
sourceX: e,
|
|
272
272
|
sourceY: t,
|
|
@@ -337,7 +337,7 @@ function w({ sourceX: e, sourceY: t, targetX: n, targetY: r, sourcePosition: i,
|
|
|
337
337
|
}
|
|
338
338
|
//#endregion
|
|
339
339
|
//#region src/client/components/SchemaVisualization/FieldDetailPanel.tsx
|
|
340
|
-
function
|
|
340
|
+
function E({ label: e, children: t }) {
|
|
341
341
|
return /* @__PURE__ */ m("div", {
|
|
342
342
|
className: "dc:flex dc:items-start dc:gap-2 dc:text-xs",
|
|
343
343
|
children: [/* @__PURE__ */ p("span", {
|
|
@@ -349,7 +349,7 @@ function T({ label: e, children: t }) {
|
|
|
349
349
|
})]
|
|
350
350
|
});
|
|
351
351
|
}
|
|
352
|
-
function
|
|
352
|
+
function D({ type: e, color: t }) {
|
|
353
353
|
return /* @__PURE__ */ p("span", {
|
|
354
354
|
className: "dc:inline-flex dc:items-center dc:px-1.5 dc:py-0.5 dc:rounded dc:text-[10px] dc:font-medium dc:uppercase",
|
|
355
355
|
style: {
|
|
@@ -359,17 +359,17 @@ function E({ type: e, color: t }) {
|
|
|
359
359
|
children: e
|
|
360
360
|
});
|
|
361
361
|
}
|
|
362
|
-
function
|
|
362
|
+
function O({ measure: e, cube: t }) {
|
|
363
363
|
return /* @__PURE__ */ m("div", {
|
|
364
364
|
className: "dc:flex dc:flex-col dc:gap-2",
|
|
365
365
|
children: [
|
|
366
|
-
/* @__PURE__ */ p(
|
|
366
|
+
/* @__PURE__ */ p(E, {
|
|
367
367
|
label: "Cube",
|
|
368
368
|
children: t.title || t.name
|
|
369
369
|
}),
|
|
370
|
-
/* @__PURE__ */ p(
|
|
370
|
+
/* @__PURE__ */ p(E, {
|
|
371
371
|
label: "Type",
|
|
372
|
-
children: /* @__PURE__ */ p(
|
|
372
|
+
children: /* @__PURE__ */ p(D, {
|
|
373
373
|
type: e.type,
|
|
374
374
|
color: {
|
|
375
375
|
count: "#f59e0b",
|
|
@@ -384,11 +384,11 @@ function D({ measure: e, cube: t }) {
|
|
|
384
384
|
}[e.type] || "#6b7280"
|
|
385
385
|
})
|
|
386
386
|
}),
|
|
387
|
-
e.title && e.title !== e.shortTitle && /* @__PURE__ */ p(
|
|
387
|
+
e.title && e.title !== e.shortTitle && /* @__PURE__ */ p(E, {
|
|
388
388
|
label: "Title",
|
|
389
389
|
children: e.title
|
|
390
390
|
}),
|
|
391
|
-
e.drillMembers && e.drillMembers.length > 0 && /* @__PURE__ */ p(
|
|
391
|
+
e.drillMembers && e.drillMembers.length > 0 && /* @__PURE__ */ p(E, {
|
|
392
392
|
label: "Drill into",
|
|
393
393
|
children: /* @__PURE__ */ p("div", {
|
|
394
394
|
className: "dc:flex dc:flex-wrap dc:gap-1",
|
|
@@ -401,27 +401,27 @@ function D({ measure: e, cube: t }) {
|
|
|
401
401
|
]
|
|
402
402
|
});
|
|
403
403
|
}
|
|
404
|
-
function
|
|
404
|
+
function k({ dimension: e, cube: t }) {
|
|
405
405
|
let n = e.type === "time" ? "#3b82f6" : "#10b981", r = t.hierarchies?.filter((n) => n.levels.some((n) => n === e.name || n === `${t.name}.${e.name.split(".")[1]}`)) || [];
|
|
406
406
|
return /* @__PURE__ */ m("div", {
|
|
407
407
|
className: "dc:flex dc:flex-col dc:gap-2",
|
|
408
408
|
children: [
|
|
409
|
-
/* @__PURE__ */ p(
|
|
409
|
+
/* @__PURE__ */ p(E, {
|
|
410
410
|
label: "Cube",
|
|
411
411
|
children: t.title || t.name
|
|
412
412
|
}),
|
|
413
|
-
/* @__PURE__ */ p(
|
|
413
|
+
/* @__PURE__ */ p(E, {
|
|
414
414
|
label: "Type",
|
|
415
|
-
children: /* @__PURE__ */ p(
|
|
415
|
+
children: /* @__PURE__ */ p(D, {
|
|
416
416
|
type: e.type,
|
|
417
417
|
color: n
|
|
418
418
|
})
|
|
419
419
|
}),
|
|
420
|
-
e.title && e.title !== e.shortTitle && /* @__PURE__ */ p(
|
|
420
|
+
e.title && e.title !== e.shortTitle && /* @__PURE__ */ p(E, {
|
|
421
421
|
label: "Title",
|
|
422
422
|
children: e.title
|
|
423
423
|
}),
|
|
424
|
-
e.type === "time" && e.granularities && e.granularities.length > 0 && /* @__PURE__ */ p(
|
|
424
|
+
e.type === "time" && e.granularities && e.granularities.length > 0 && /* @__PURE__ */ p(E, {
|
|
425
425
|
label: "Granularity",
|
|
426
426
|
children: /* @__PURE__ */ p("div", {
|
|
427
427
|
className: "dc:flex dc:flex-wrap dc:gap-1",
|
|
@@ -431,7 +431,7 @@ function O({ dimension: e, cube: t }) {
|
|
|
431
431
|
}, e))
|
|
432
432
|
})
|
|
433
433
|
}),
|
|
434
|
-
r.length > 0 && /* @__PURE__ */ p(
|
|
434
|
+
r.length > 0 && /* @__PURE__ */ p(E, {
|
|
435
435
|
label: "Hierarchy",
|
|
436
436
|
children: r.map((e) => /* @__PURE__ */ m("div", {
|
|
437
437
|
className: "dc:text-[10px]",
|
|
@@ -451,7 +451,7 @@ function O({ dimension: e, cube: t }) {
|
|
|
451
451
|
]
|
|
452
452
|
});
|
|
453
453
|
}
|
|
454
|
-
function
|
|
454
|
+
function ee({ cube: e }) {
|
|
455
455
|
let t = {
|
|
456
456
|
belongsTo: "#10b981",
|
|
457
457
|
hasOne: "#3b82f6",
|
|
@@ -461,11 +461,11 @@ function k({ cube: e }) {
|
|
|
461
461
|
return /* @__PURE__ */ m("div", {
|
|
462
462
|
className: "dc:flex dc:flex-col dc:gap-2",
|
|
463
463
|
children: [
|
|
464
|
-
e.description && /* @__PURE__ */ p(
|
|
464
|
+
e.description && /* @__PURE__ */ p(E, {
|
|
465
465
|
label: "Description",
|
|
466
466
|
children: e.description
|
|
467
467
|
}),
|
|
468
|
-
/* @__PURE__ */ m(
|
|
468
|
+
/* @__PURE__ */ m(E, {
|
|
469
469
|
label: "Measures",
|
|
470
470
|
children: [/* @__PURE__ */ p("span", {
|
|
471
471
|
className: "dc:font-mono",
|
|
@@ -479,7 +479,7 @@ function k({ cube: e }) {
|
|
|
479
479
|
]
|
|
480
480
|
})]
|
|
481
481
|
}),
|
|
482
|
-
/* @__PURE__ */ m(
|
|
482
|
+
/* @__PURE__ */ m(E, {
|
|
483
483
|
label: "Dimensions",
|
|
484
484
|
children: [/* @__PURE__ */ p("span", {
|
|
485
485
|
className: "dc:font-mono",
|
|
@@ -493,13 +493,13 @@ function k({ cube: e }) {
|
|
|
493
493
|
]
|
|
494
494
|
})]
|
|
495
495
|
}),
|
|
496
|
-
e.relationships && e.relationships.length > 0 && /* @__PURE__ */ p(
|
|
496
|
+
e.relationships && e.relationships.length > 0 && /* @__PURE__ */ p(E, {
|
|
497
497
|
label: "Joins",
|
|
498
498
|
children: /* @__PURE__ */ p("div", {
|
|
499
499
|
className: "dc:flex dc:flex-col dc:gap-1",
|
|
500
500
|
children: e.relationships.map((e, n) => /* @__PURE__ */ m("div", {
|
|
501
501
|
className: "dc:flex dc:items-center dc:gap-1.5 dc:text-[10px]",
|
|
502
|
-
children: [/* @__PURE__ */ p(
|
|
502
|
+
children: [/* @__PURE__ */ p(D, {
|
|
503
503
|
type: e.relationship,
|
|
504
504
|
color: t[e.relationship] || "#6b7280"
|
|
505
505
|
}), /* @__PURE__ */ p("span", {
|
|
@@ -509,7 +509,7 @@ function k({ cube: e }) {
|
|
|
509
509
|
}, n))
|
|
510
510
|
})
|
|
511
511
|
}),
|
|
512
|
-
e.hierarchies && e.hierarchies.length > 0 && /* @__PURE__ */ p(
|
|
512
|
+
e.hierarchies && e.hierarchies.length > 0 && /* @__PURE__ */ p(E, {
|
|
513
513
|
label: "Hierarchies",
|
|
514
514
|
children: /* @__PURE__ */ p("div", {
|
|
515
515
|
className: "dc:flex dc:flex-col dc:gap-1",
|
|
@@ -529,7 +529,7 @@ function k({ cube: e }) {
|
|
|
529
529
|
}, e.name))
|
|
530
530
|
})
|
|
531
531
|
}),
|
|
532
|
-
e.meta?.eventStream && /* @__PURE__ */ p(
|
|
532
|
+
e.meta?.eventStream && /* @__PURE__ */ p(E, {
|
|
533
533
|
label: "Event Stream",
|
|
534
534
|
children: /* @__PURE__ */ m("div", {
|
|
535
535
|
className: "dc:text-[10px]",
|
|
@@ -556,22 +556,22 @@ function k({ cube: e }) {
|
|
|
556
556
|
]
|
|
557
557
|
});
|
|
558
558
|
}
|
|
559
|
-
function
|
|
560
|
-
let i =
|
|
559
|
+
function te({ selection: e, meta: n, onClose: r }) {
|
|
560
|
+
let i = t("close"), a = n.cubes.find((t) => t.name === e.cubeName);
|
|
561
561
|
if (!a) return null;
|
|
562
562
|
let o, s, c, l;
|
|
563
|
-
if (e.fieldType === "cube" || !e.fieldName) o = a.title || a.name, s = "var(--dc-accent)", c = "color-mix(in srgb, var(--dc-accent) 10%, var(--dc-surface))", l = /* @__PURE__ */ p(
|
|
563
|
+
if (e.fieldType === "cube" || !e.fieldName) o = a.title || a.name, s = "var(--dc-accent)", c = "color-mix(in srgb, var(--dc-accent) 10%, var(--dc-surface))", l = /* @__PURE__ */ p(ee, { cube: a });
|
|
564
564
|
else if (e.fieldType === "measure") {
|
|
565
565
|
let t = a.measures.find((t) => (t.name.split(".")[1] || t.name) === e.fieldName || t.name === e.fieldName);
|
|
566
566
|
if (!t) return null;
|
|
567
|
-
o = t.shortTitle || t.title || e.fieldName, s = "var(--dc-warning)", c = "color-mix(in srgb, var(--dc-warning) 10%, var(--dc-surface))", l = /* @__PURE__ */ p(
|
|
567
|
+
o = t.shortTitle || t.title || e.fieldName, s = "var(--dc-warning)", c = "color-mix(in srgb, var(--dc-warning) 10%, var(--dc-surface))", l = /* @__PURE__ */ p(O, {
|
|
568
568
|
measure: t,
|
|
569
569
|
cube: a
|
|
570
570
|
});
|
|
571
571
|
} else {
|
|
572
572
|
let t = a.dimensions.find((t) => (t.name.split(".")[1] || t.name) === e.fieldName || t.name === e.fieldName);
|
|
573
573
|
if (!t) return null;
|
|
574
|
-
o = t.shortTitle || t.title || e.fieldName, s = t.type === "time" ? "var(--dc-accent)" : "var(--dc-success)", c = t.type === "time" ? "color-mix(in srgb, var(--dc-accent) 10%, var(--dc-surface))" : "color-mix(in srgb, var(--dc-success) 10%, var(--dc-surface))", l = /* @__PURE__ */ p(
|
|
574
|
+
o = t.shortTitle || t.title || e.fieldName, s = t.type === "time" ? "var(--dc-accent)" : "var(--dc-success)", c = t.type === "time" ? "color-mix(in srgb, var(--dc-accent) 10%, var(--dc-surface))" : "color-mix(in srgb, var(--dc-success) 10%, var(--dc-surface))", l = /* @__PURE__ */ p(k, {
|
|
575
575
|
dimension: t,
|
|
576
576
|
cube: a
|
|
577
577
|
});
|
|
@@ -604,7 +604,7 @@ function ee({ selection: e, meta: t, onClose: r }) {
|
|
|
604
604
|
}
|
|
605
605
|
//#endregion
|
|
606
606
|
//#region src/client/components/SchemaVisualization/useERDLayout.ts
|
|
607
|
-
var
|
|
607
|
+
var ne = {
|
|
608
608
|
direction: "LR",
|
|
609
609
|
nodeWidth: 340,
|
|
610
610
|
nodeSep: 150,
|
|
@@ -632,11 +632,7 @@ function M(e) {
|
|
|
632
632
|
}
|
|
633
633
|
var N = null, P = null;
|
|
634
634
|
function F() {
|
|
635
|
-
return P || (P = import(
|
|
636
|
-
"elkjs",
|
|
637
|
-
"lib",
|
|
638
|
-
"elk.bundled.js"
|
|
639
|
-
].join("/")).then((e) => (N = new (e.default || e)(), N)).catch(() => null), P);
|
|
635
|
+
return P || (P = import("elkjs/lib/elk.bundled.js").then((e) => (N = new (e.default || e)(), N)).catch(() => null), P);
|
|
640
636
|
}
|
|
641
637
|
async function I(e, t, n) {
|
|
642
638
|
if (await F(), !N) return {
|
|
@@ -715,9 +711,9 @@ function L(e, t) {
|
|
|
715
711
|
};
|
|
716
712
|
});
|
|
717
713
|
}
|
|
718
|
-
function
|
|
714
|
+
function re(e, t, n = {}) {
|
|
719
715
|
let r = l(() => ({
|
|
720
|
-
...
|
|
716
|
+
...ne,
|
|
721
717
|
...n
|
|
722
718
|
}), [
|
|
723
719
|
n.direction,
|
|
@@ -756,8 +752,8 @@ function ne(e, t, n = {}) {
|
|
|
756
752
|
var R = /* @__PURE__ */ e({
|
|
757
753
|
SchemaVisualization: () => B,
|
|
758
754
|
default: () => B
|
|
759
|
-
}),
|
|
760
|
-
function
|
|
755
|
+
}), ie = { cubeNode: w }, ae = { relationshipEdge: T };
|
|
756
|
+
function oe({ token: e }) {
|
|
761
757
|
let { useNodesInitialized: t, useReactFlow: n } = _(), r = t(), { fitView: i } = n(), a = u(0);
|
|
762
758
|
return c(() => {
|
|
763
759
|
e === 0 || e === a.current || r && (a.current = e, i({ padding: .1 }));
|
|
@@ -768,7 +764,7 @@ function ae({ token: e }) {
|
|
|
768
764
|
]), null;
|
|
769
765
|
}
|
|
770
766
|
var z = [];
|
|
771
|
-
function
|
|
767
|
+
function se(e) {
|
|
772
768
|
switch (e) {
|
|
773
769
|
case "belongsTo": return "#10b981";
|
|
774
770
|
case "hasOne": return "#3b82f6";
|
|
@@ -778,13 +774,13 @@ function oe(e) {
|
|
|
778
774
|
}
|
|
779
775
|
}
|
|
780
776
|
function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlightedFields: a, searchTerm: s, height: f = "100%" }) {
|
|
781
|
-
let { ReactFlow: h, Controls: g, MiniMap: v, Background: y, applyNodeChanges: b } = _(), { meta: x, metaLoading: S, metaError: C } =
|
|
777
|
+
let { ReactFlow: h, Controls: g, MiniMap: v, Background: y, applyNodeChanges: b } = _(), { meta: x, metaLoading: S, metaError: C } = n(), w = i || z, T = a || z, [E, D] = d(null), [O, k] = d(s || ""), [ee, ne] = d(0), [A, j] = d(null), [M, N] = d(null), P = u(null), F = !r, [I, L] = d({}), [R, B] = d(!1), ce = t("search"), le = t("close"), V = s === void 0 ? O : s;
|
|
782
778
|
c(() => {
|
|
783
779
|
try {
|
|
784
780
|
let e = localStorage.getItem("drizzle-cube-erd-node-positions");
|
|
785
|
-
e &&
|
|
781
|
+
e && L(JSON.parse(e));
|
|
786
782
|
} catch {}
|
|
787
|
-
|
|
783
|
+
B(!0);
|
|
788
784
|
}, []);
|
|
789
785
|
let { structuralNodes: H, structuralEdges: U } = l(() => {
|
|
790
786
|
if (!x) return {
|
|
@@ -813,7 +809,7 @@ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
|
|
|
813
809
|
},
|
|
814
810
|
animated: !1,
|
|
815
811
|
style: {
|
|
816
|
-
stroke:
|
|
812
|
+
stroke: se(n.relationship),
|
|
817
813
|
strokeWidth: 2
|
|
818
814
|
}
|
|
819
815
|
});
|
|
@@ -822,13 +818,13 @@ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
|
|
|
822
818
|
structuralNodes: e,
|
|
823
819
|
structuralEdges: t
|
|
824
820
|
};
|
|
825
|
-
}, [x]), W =
|
|
821
|
+
}, [x]), W = ee > 0 || R && Object.keys(I).length === 0, { nodes: G, edges: K, phase: ue } = re(W ? H : [], W ? U : [], {
|
|
826
822
|
direction: "LR",
|
|
827
823
|
nodeWidth: 340,
|
|
828
824
|
nodeSep: 150,
|
|
829
825
|
rankSep: 350
|
|
830
826
|
}), q = o((e, t) => {
|
|
831
|
-
let n =
|
|
827
|
+
let n = P.current?.getBoundingClientRect();
|
|
832
828
|
if (!n) return {
|
|
833
829
|
x: e,
|
|
834
830
|
y: t
|
|
@@ -839,48 +835,48 @@ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
|
|
|
839
835
|
y: i
|
|
840
836
|
};
|
|
841
837
|
}, []), de = o((e, t, n, r) => {
|
|
842
|
-
|
|
838
|
+
j((i) => i && i.cubeName === e && i.fieldName === t ? (N(null), null) : (r && N(q(r.x, r.y)), {
|
|
843
839
|
cubeName: e,
|
|
844
840
|
fieldName: t,
|
|
845
841
|
fieldType: n
|
|
846
842
|
}));
|
|
847
843
|
}, [q]), fe = o((e, t) => {
|
|
848
|
-
|
|
844
|
+
j((n) => n && n.cubeName === e && n.fieldName === null ? (N(null), null) : (t && N(q(t.x, t.y)), {
|
|
849
845
|
cubeName: e,
|
|
850
846
|
fieldName: null,
|
|
851
847
|
fieldType: "cube"
|
|
852
848
|
}));
|
|
853
|
-
}, [q]), pe =
|
|
849
|
+
}, [q]), pe = F ? de : r, me = F ? fe : void 0, J = o((e) => ({
|
|
854
850
|
cube: e,
|
|
855
851
|
onFieldClick: pe,
|
|
856
852
|
onCubeClick: me,
|
|
857
853
|
isHighlighted: w.includes(e.name),
|
|
858
854
|
highlightedFields: T,
|
|
859
855
|
searchTerm: V,
|
|
860
|
-
selectedField:
|
|
856
|
+
selectedField: F ? A : null
|
|
861
857
|
}), [
|
|
862
858
|
pe,
|
|
863
859
|
me,
|
|
864
860
|
w,
|
|
865
861
|
T,
|
|
866
862
|
V,
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
]), Y = !W || ue === "ready", X = l(() => !x || !Y || !
|
|
863
|
+
F,
|
|
864
|
+
A
|
|
865
|
+
]), Y = !W || ue === "ready", X = l(() => !x || !Y || !R ? [] : W && G.length > 0 ? G.map((e) => ({
|
|
870
866
|
...e,
|
|
871
867
|
data: J(e.data?.cube || x.cubes.find((t) => t.name === e.id))
|
|
872
868
|
})) : H.map((e) => ({
|
|
873
869
|
...e,
|
|
874
|
-
position:
|
|
870
|
+
position: I[e.id] || e.position,
|
|
875
871
|
data: J(e.data?.cube)
|
|
876
872
|
})), [
|
|
877
873
|
x,
|
|
878
874
|
Y,
|
|
879
|
-
|
|
875
|
+
R,
|
|
880
876
|
W,
|
|
881
877
|
G,
|
|
882
878
|
H,
|
|
883
|
-
|
|
879
|
+
I,
|
|
884
880
|
J
|
|
885
881
|
]), he = l(() => !x || !Y ? [] : W && K.length > 0 ? K : U, [
|
|
886
882
|
x,
|
|
@@ -898,7 +894,7 @@ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
|
|
|
898
894
|
}, [X, he]);
|
|
899
895
|
let be = u("");
|
|
900
896
|
c(() => {
|
|
901
|
-
let e =
|
|
897
|
+
let e = A ? `${A.cubeName}.${A.fieldName}` : "", t = `${w.join(",")}|${T.join(",")}|${V}|${String(r)}|${e}`;
|
|
902
898
|
t !== be.current && (be.current = t, !(Z.length === 0 || !x) && Q((e) => e.map((e) => {
|
|
903
899
|
let t = x.cubes.find((t) => t.name === e.id);
|
|
904
900
|
return t ? {
|
|
@@ -911,7 +907,7 @@ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
|
|
|
911
907
|
T,
|
|
912
908
|
V,
|
|
913
909
|
r,
|
|
914
|
-
|
|
910
|
+
A,
|
|
915
911
|
Z.length,
|
|
916
912
|
x,
|
|
917
913
|
J
|
|
@@ -925,7 +921,7 @@ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
|
|
|
925
921
|
try {
|
|
926
922
|
localStorage.setItem("drizzle-cube-erd-node-positions", JSON.stringify(t));
|
|
927
923
|
} catch {}
|
|
928
|
-
return
|
|
924
|
+
return L(t), e;
|
|
929
925
|
});
|
|
930
926
|
}, []), Se = o((e) => {}, []), Ce = o((e) => {
|
|
931
927
|
e.preventDefault(), e.stopPropagation(), D({
|
|
@@ -933,13 +929,13 @@ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
|
|
|
933
929
|
y: e.clientY
|
|
934
930
|
});
|
|
935
931
|
}, []), we = o(() => {
|
|
936
|
-
E && D(null),
|
|
937
|
-
}, [E,
|
|
938
|
-
|
|
932
|
+
E && D(null), A && (j(null), N(null));
|
|
933
|
+
}, [E, A]), Te = o(() => {
|
|
934
|
+
L({}), $.current = "";
|
|
939
935
|
try {
|
|
940
936
|
localStorage.removeItem("drizzle-cube-erd-node-positions");
|
|
941
937
|
} catch {}
|
|
942
|
-
|
|
938
|
+
ne((e) => e + 1), D(null);
|
|
943
939
|
}, []);
|
|
944
940
|
return S ? /* @__PURE__ */ p("div", {
|
|
945
941
|
className: `dc:flex dc:items-center dc:justify-center dc:h-96 ${e}`,
|
|
@@ -1000,7 +996,7 @@ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
|
|
|
1000
996
|
]
|
|
1001
997
|
}),
|
|
1002
998
|
/* @__PURE__ */ m("div", {
|
|
1003
|
-
ref:
|
|
999
|
+
ref: P,
|
|
1004
1000
|
className: "dc:relative dc:flex-1 dc:min-h-0",
|
|
1005
1001
|
children: [/* @__PURE__ */ p("div", {
|
|
1006
1002
|
style: {
|
|
@@ -1012,8 +1008,8 @@ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
|
|
|
1012
1008
|
edges: ge,
|
|
1013
1009
|
onNodesChange: xe,
|
|
1014
1010
|
onEdgesChange: Se,
|
|
1015
|
-
nodeTypes:
|
|
1016
|
-
edgeTypes:
|
|
1011
|
+
nodeTypes: ie,
|
|
1012
|
+
edgeTypes: ae,
|
|
1017
1013
|
connectionMode: "loose",
|
|
1018
1014
|
minZoom: .1,
|
|
1019
1015
|
maxZoom: 2,
|
|
@@ -1031,20 +1027,20 @@ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
|
|
|
1031
1027
|
gap: 12,
|
|
1032
1028
|
size: 1
|
|
1033
1029
|
}),
|
|
1034
|
-
/* @__PURE__ */ p(
|
|
1030
|
+
/* @__PURE__ */ p(oe, { token: ve })
|
|
1035
1031
|
]
|
|
1036
1032
|
})
|
|
1037
|
-
}),
|
|
1033
|
+
}), F && A && M && x && /* @__PURE__ */ p("div", {
|
|
1038
1034
|
className: "dc:absolute dc:z-20",
|
|
1039
1035
|
style: {
|
|
1040
|
-
left:
|
|
1041
|
-
top:
|
|
1036
|
+
left: M.x,
|
|
1037
|
+
top: M.y
|
|
1042
1038
|
},
|
|
1043
|
-
children: /* @__PURE__ */ p(
|
|
1044
|
-
selection:
|
|
1039
|
+
children: /* @__PURE__ */ p(te, {
|
|
1040
|
+
selection: A,
|
|
1045
1041
|
meta: x,
|
|
1046
1042
|
onClose: () => {
|
|
1047
|
-
|
|
1043
|
+
j(null), N(null);
|
|
1048
1044
|
}
|
|
1049
1045
|
})
|
|
1050
1046
|
})]
|
|
@@ -1074,6 +1070,6 @@ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
|
|
|
1074
1070
|
});
|
|
1075
1071
|
}
|
|
1076
1072
|
//#endregion
|
|
1077
|
-
export {
|
|
1073
|
+
export { C as n, v as r, R as t };
|
|
1078
1074
|
|
|
1079
|
-
//# sourceMappingURL=schema-visualization-
|
|
1075
|
+
//# sourceMappingURL=schema-visualization-DVdfx6N8.js.map
|