@finos/legend-cube-builder 0.0.4 → 0.0.5

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.
Files changed (609) hide show
  1. package/README.md +9 -3
  2. package/docs/adding-an-operation.md +22 -12
  3. package/docs/demo/DEMO-FAST-NOTES.md +67 -0
  4. package/docs/demo/README.md +102 -0
  5. package/docs/demo/specs/duckdb-sales-pivot.cube.json +110 -0
  6. package/docs/demo/specs/trades-desks-1-joined.cube.json +123 -0
  7. package/docs/demo/specs/trades-desks-2-grouped.cube.json +140 -0
  8. package/docs/demo/specs/trades-desks-3-ranked.cube.json +158 -0
  9. package/docs/demo/specs/trades-desks-4-extended.cube.json +208 -0
  10. package/docs/demo/specs/trades-desks-5-final.cube.json +248 -0
  11. package/docs/hosting.md +50 -3
  12. package/docs/testing.md +32 -0
  13. package/lib/__lib__/LegendCubeCommand.d.ts +2 -0
  14. package/lib/__lib__/LegendCubeCommand.d.ts.map +1 -1
  15. package/lib/__lib__/LegendCubeCommand.js +7 -0
  16. package/lib/__lib__/LegendCubeCommand.js.map +1 -1
  17. package/lib/__lib__/LegendCubeFunctionLabels.d.ts +29 -0
  18. package/lib/__lib__/LegendCubeFunctionLabels.d.ts.map +1 -0
  19. package/lib/__lib__/LegendCubeFunctionLabels.js +31 -0
  20. package/lib/__lib__/LegendCubeFunctionLabels.js.map +1 -0
  21. package/lib/__lib__/LegendCubeHelpText.d.ts +5 -1
  22. package/lib/__lib__/LegendCubeHelpText.d.ts.map +1 -1
  23. package/lib/__lib__/LegendCubeHelpText.js +14 -2
  24. package/lib/__lib__/LegendCubeHelpText.js.map +1 -1
  25. package/lib/__lib__/LegendCubeLabels.d.ts +100 -8
  26. package/lib/__lib__/LegendCubeLabels.d.ts.map +1 -1
  27. package/lib/__lib__/LegendCubeLabels.js +129 -14
  28. package/lib/__lib__/LegendCubeLabels.js.map +1 -1
  29. package/lib/__lib__/LegendCubeProjectSourceLabels.d.ts +26 -0
  30. package/lib/__lib__/LegendCubeProjectSourceLabels.d.ts.map +1 -0
  31. package/lib/__lib__/LegendCubeProjectSourceLabels.js +26 -0
  32. package/lib/__lib__/LegendCubeProjectSourceLabels.js.map +1 -0
  33. package/lib/__lib__/LegendCubeServiceLabels.d.ts +27 -0
  34. package/lib/__lib__/LegendCubeServiceLabels.d.ts.map +1 -0
  35. package/lib/__lib__/LegendCubeServiceLabels.js +32 -0
  36. package/lib/__lib__/LegendCubeServiceLabels.js.map +1 -0
  37. package/lib/__lib__/LegendCubeTesting.d.ts +7 -0
  38. package/lib/__lib__/LegendCubeTesting.d.ts.map +1 -1
  39. package/lib/__lib__/LegendCubeTesting.js +7 -0
  40. package/lib/__lib__/LegendCubeTesting.js.map +1 -1
  41. package/lib/__test-utils__/CubeEngineTestSupport.d.ts +1 -1
  42. package/lib/__test-utils__/CubeEngineTestSupport.d.ts.map +1 -1
  43. package/lib/__test-utils__/CubeEngineTestSupport.js +2 -2
  44. package/lib/__test-utils__/CubeEngineTestSupport.js.map +1 -1
  45. package/lib/__test-utils__/CubeExpressionTestUtils.d.ts +8 -1
  46. package/lib/__test-utils__/CubeExpressionTestUtils.d.ts.map +1 -1
  47. package/lib/__test-utils__/CubeExpressionTestUtils.js +20 -3
  48. package/lib/__test-utils__/CubeExpressionTestUtils.js.map +1 -1
  49. package/lib/__test-utils__/CubeFunctionTestOutline.d.ts +26 -0
  50. package/lib/__test-utils__/CubeFunctionTestOutline.d.ts.map +1 -0
  51. package/lib/__test-utils__/CubeFunctionTestOutline.js +56 -0
  52. package/lib/__test-utils__/CubeFunctionTestOutline.js.map +1 -0
  53. package/lib/__test-utils__/CubeLambdaCorpus.d.ts +36 -0
  54. package/lib/__test-utils__/CubeLambdaCorpus.d.ts.map +1 -0
  55. package/lib/__test-utils__/CubeLambdaCorpus.js +83 -0
  56. package/lib/__test-utils__/CubeLambdaCorpus.js.map +1 -0
  57. package/lib/__test-utils__/CubePageTestUtils.d.ts +6 -0
  58. package/lib/__test-utils__/CubePageTestUtils.d.ts.map +1 -1
  59. package/lib/__test-utils__/CubePageTestUtils.js +21 -0
  60. package/lib/__test-utils__/CubePageTestUtils.js.map +1 -1
  61. package/lib/__test-utils__/CubeTestApplication.d.ts +9 -0
  62. package/lib/__test-utils__/CubeTestApplication.d.ts.map +1 -1
  63. package/lib/__test-utils__/CubeTestApplication.js +16 -0
  64. package/lib/__test-utils__/CubeTestApplication.js.map +1 -1
  65. package/lib/__test-utils__/FakeCubeEngine.d.ts +5 -0
  66. package/lib/__test-utils__/FakeCubeEngine.d.ts.map +1 -1
  67. package/lib/__test-utils__/FakeCubeEngine.js +17 -0
  68. package/lib/__test-utils__/FakeCubeEngine.js.map +1 -1
  69. package/lib/__test-utils__/FakeCubeIngestCatalog.d.ts +7 -1
  70. package/lib/__test-utils__/FakeCubeIngestCatalog.d.ts.map +1 -1
  71. package/lib/__test-utils__/FakeCubeIngestCatalog.js +16 -0
  72. package/lib/__test-utils__/FakeCubeIngestCatalog.js.map +1 -1
  73. package/lib/__test-utils__/FakeCubeServiceCatalog.d.ts +26 -0
  74. package/lib/__test-utils__/FakeCubeServiceCatalog.d.ts.map +1 -0
  75. package/lib/__test-utils__/FakeCubeServiceCatalog.js +40 -0
  76. package/lib/__test-utils__/FakeCubeServiceCatalog.js.map +1 -0
  77. package/lib/components/CubeAddItems.d.ts.map +1 -1
  78. package/lib/components/CubeAddItems.js +9 -6
  79. package/lib/components/CubeAddItems.js.map +1 -1
  80. package/lib/components/CubeDialogTheme.d.ts +25 -0
  81. package/lib/components/CubeDialogTheme.d.ts.map +1 -0
  82. package/lib/components/CubeDialogTheme.js +25 -0
  83. package/lib/components/CubeDialogTheme.js.map +1 -0
  84. package/lib/components/CubeEditor.d.ts +12 -1
  85. package/lib/components/CubeEditor.d.ts.map +1 -1
  86. package/lib/components/CubeEditor.js +16 -14
  87. package/lib/components/CubeEditor.js.map +1 -1
  88. package/lib/components/CubeFileMenu.d.ts +28 -0
  89. package/lib/components/CubeFileMenu.d.ts.map +1 -0
  90. package/lib/components/CubeFileMenu.js +77 -0
  91. package/lib/components/CubeFileMenu.js.map +1 -0
  92. package/lib/components/CubeLambdaImportBanner.d.ts +26 -0
  93. package/lib/components/CubeLambdaImportBanner.d.ts.map +1 -0
  94. package/lib/components/CubeLambdaImportBanner.js +47 -0
  95. package/lib/components/CubeLambdaImportBanner.js.map +1 -0
  96. package/lib/components/CubeNodeIcon.d.ts.map +1 -1
  97. package/lib/components/CubeNodeIcon.js +5 -1
  98. package/lib/components/CubeNodeIcon.js.map +1 -1
  99. package/lib/components/CubeSchemaColumnsTable.d.ts.map +1 -1
  100. package/lib/components/CubeSchemaColumnsTable.js +2 -2
  101. package/lib/components/CubeSchemaColumnsTable.js.map +1 -1
  102. package/lib/components/canvas/CubeCanvas.d.ts.map +1 -1
  103. package/lib/components/canvas/CubeCanvas.js +38 -5
  104. package/lib/components/canvas/CubeCanvas.js.map +1 -1
  105. package/lib/components/canvas/CubeCanvasContextMenu.d.ts.map +1 -1
  106. package/lib/components/canvas/CubeCanvasContextMenu.js +2 -1
  107. package/lib/components/canvas/CubeCanvasContextMenu.js.map +1 -1
  108. package/lib/components/canvas/CubeCanvasElements.d.ts +18 -1
  109. package/lib/components/canvas/CubeCanvasElements.d.ts.map +1 -1
  110. package/lib/components/canvas/CubeCanvasElements.js +58 -3
  111. package/lib/components/canvas/CubeCanvasElements.js.map +1 -1
  112. package/lib/components/canvas/CubeCanvasLayout.js +1 -1
  113. package/lib/components/canvas/CubeCanvasNode.d.ts.map +1 -1
  114. package/lib/components/canvas/CubeCanvasNode.js +8 -4
  115. package/lib/components/canvas/CubeCanvasNode.js.map +1 -1
  116. package/lib/components/dev-settings/CubeDevSettings.d.ts +35 -0
  117. package/lib/components/dev-settings/CubeDevSettings.d.ts.map +1 -0
  118. package/lib/components/dev-settings/CubeDevSettings.js +50 -0
  119. package/lib/components/dev-settings/CubeDevSettings.js.map +1 -0
  120. package/lib/components/editors/CubeColumnChecklist.d.ts.map +1 -1
  121. package/lib/components/editors/CubeColumnChecklist.js +2 -2
  122. package/lib/components/editors/CubeColumnChecklist.js.map +1 -1
  123. package/lib/components/editors/CubeColumnPicker.d.ts.map +1 -1
  124. package/lib/components/editors/CubeColumnPicker.js +3 -3
  125. package/lib/components/editors/CubeColumnPicker.js.map +1 -1
  126. package/lib/components/editors/CubeConcatEditor.js +2 -2
  127. package/lib/components/editors/CubeConcatEditor.js.map +1 -1
  128. package/lib/components/editors/CubeExpressionFilterEditor.d.ts +25 -0
  129. package/lib/components/editors/CubeExpressionFilterEditor.d.ts.map +1 -0
  130. package/lib/components/editors/CubeExpressionFilterEditor.js +83 -0
  131. package/lib/components/editors/CubeExpressionFilterEditor.js.map +1 -0
  132. package/lib/components/editors/CubeExtendEditor.d.ts +2 -0
  133. package/lib/components/editors/CubeExtendEditor.d.ts.map +1 -1
  134. package/lib/components/editors/CubeExtendEditor.js +3 -3
  135. package/lib/components/editors/CubeExtendEditor.js.map +1 -1
  136. package/lib/components/editors/CubeFilterEditor.d.ts.map +1 -1
  137. package/lib/components/editors/CubeFilterEditor.js +13 -2
  138. package/lib/components/editors/CubeFilterEditor.js.map +1 -1
  139. package/lib/components/editors/CubeFunctionSourceEditor.d.ts +25 -0
  140. package/lib/components/editors/CubeFunctionSourceEditor.d.ts.map +1 -0
  141. package/lib/components/editors/CubeFunctionSourceEditor.js +55 -0
  142. package/lib/components/editors/CubeFunctionSourceEditor.js.map +1 -0
  143. package/lib/components/editors/CubeJoinEditor.d.ts.map +1 -1
  144. package/lib/components/editors/CubeJoinEditor.js +16 -4
  145. package/lib/components/editors/CubeJoinEditor.js.map +1 -1
  146. package/lib/components/editors/CubeNodeEditorPanel.d.ts.map +1 -1
  147. package/lib/components/editors/CubeNodeEditorPanel.js +18 -8
  148. package/lib/components/editors/CubeNodeEditorPanel.js.map +1 -1
  149. package/lib/components/editors/CubeNodeEditorPopper.d.ts +5 -1
  150. package/lib/components/editors/CubeNodeEditorPopper.d.ts.map +1 -1
  151. package/lib/components/editors/CubeNodeEditorPopper.js +10 -2
  152. package/lib/components/editors/CubeNodeEditorPopper.js.map +1 -1
  153. package/lib/components/editors/CubeNodeEditorRegistry.d.ts.map +1 -1
  154. package/lib/components/editors/CubeNodeEditorRegistry.js +9 -1
  155. package/lib/components/editors/CubeNodeEditorRegistry.js.map +1 -1
  156. package/lib/components/editors/CubePivotEditor.d.ts +26 -0
  157. package/lib/components/editors/CubePivotEditor.d.ts.map +1 -0
  158. package/lib/components/editors/CubePivotEditor.js +93 -0
  159. package/lib/components/editors/CubePivotEditor.js.map +1 -0
  160. package/lib/components/editors/CubeRestrictEditor.d.ts.map +1 -1
  161. package/lib/components/editors/CubeRestrictEditor.js +2 -2
  162. package/lib/components/editors/CubeRestrictEditor.js.map +1 -1
  163. package/lib/components/editors/CubeServiceSourceEditor.d.ts +25 -0
  164. package/lib/components/editors/CubeServiceSourceEditor.d.ts.map +1 -0
  165. package/lib/components/editors/CubeServiceSourceEditor.js +41 -0
  166. package/lib/components/editors/CubeServiceSourceEditor.js.map +1 -0
  167. package/lib/components/grid/CubeColumnFormatDialog.d.ts +28 -0
  168. package/lib/components/grid/CubeColumnFormatDialog.d.ts.map +1 -0
  169. package/lib/components/grid/CubeColumnFormatDialog.js +94 -0
  170. package/lib/components/grid/CubeColumnFormatDialog.js.map +1 -0
  171. package/lib/components/grid/CubeDrilldownBar.d.ts +37 -0
  172. package/lib/components/grid/CubeDrilldownBar.d.ts.map +1 -0
  173. package/lib/components/grid/CubeDrilldownBar.js +77 -0
  174. package/lib/components/grid/CubeDrilldownBar.js.map +1 -0
  175. package/lib/components/grid/CubeGridRegion.d.ts.map +1 -1
  176. package/lib/components/grid/CubeGridRegion.js +40 -26
  177. package/lib/components/grid/CubeGridRegion.js.map +1 -1
  178. package/lib/components/grid/CubeGridValues.d.ts +31 -1
  179. package/lib/components/grid/CubeGridValues.d.ts.map +1 -1
  180. package/lib/components/grid/CubeGridValues.js +108 -1
  181. package/lib/components/grid/CubeGridValues.js.map +1 -1
  182. package/lib/components/grid/CubeResultGrid.d.ts +68 -5
  183. package/lib/components/grid/CubeResultGrid.d.ts.map +1 -1
  184. package/lib/components/grid/CubeResultGrid.js +308 -35
  185. package/lib/components/grid/CubeResultGrid.js.map +1 -1
  186. package/lib/components/grid/CubeRunStatsPanel.d.ts +28 -0
  187. package/lib/components/grid/CubeRunStatsPanel.d.ts.map +1 -0
  188. package/lib/components/grid/CubeRunStatsPanel.js +61 -0
  189. package/lib/components/grid/CubeRunStatsPanel.js.map +1 -0
  190. package/lib/components/grid/CubeServerSideGrid.d.ts +36 -0
  191. package/lib/components/grid/CubeServerSideGrid.d.ts.map +1 -0
  192. package/lib/components/grid/CubeServerSideGrid.js +114 -0
  193. package/lib/components/grid/CubeServerSideGrid.js.map +1 -0
  194. package/lib/components/grid/CubeSqlDialog.d.ts +24 -0
  195. package/lib/components/grid/CubeSqlDialog.d.ts.map +1 -0
  196. package/lib/components/grid/CubeSqlDialog.js +39 -0
  197. package/lib/components/grid/CubeSqlDialog.js.map +1 -0
  198. package/lib/components/grid/CubeSqlFormat.d.ts +20 -0
  199. package/lib/components/grid/CubeSqlFormat.d.ts.map +1 -0
  200. package/lib/components/grid/CubeSqlFormat.js +32 -0
  201. package/lib/components/grid/CubeSqlFormat.js.map +1 -0
  202. package/lib/components/palette/CubePalette.d.ts.map +1 -1
  203. package/lib/components/palette/CubePalette.js +32 -13
  204. package/lib/components/palette/CubePalette.js.map +1 -1
  205. package/lib/components/show-pure/CubeShowPureDialog.d.ts +4 -1
  206. package/lib/components/show-pure/CubeShowPureDialog.d.ts.map +1 -1
  207. package/lib/components/show-pure/CubeShowPureDialog.js +8 -4
  208. package/lib/components/show-pure/CubeShowPureDialog.js.map +1 -1
  209. package/lib/components/source-picker/CubeDataProductTab.d.ts.map +1 -1
  210. package/lib/components/source-picker/CubeDataProductTab.js +37 -16
  211. package/lib/components/source-picker/CubeDataProductTab.js.map +1 -1
  212. package/lib/components/source-picker/CubeDirectConnectionTab.d.ts.map +1 -1
  213. package/lib/components/source-picker/CubeDirectConnectionTab.js +6 -4
  214. package/lib/components/source-picker/CubeDirectConnectionTab.js.map +1 -1
  215. package/lib/components/source-picker/CubeFunctionSteps.d.ts +36 -0
  216. package/lib/components/source-picker/CubeFunctionSteps.d.ts.map +1 -0
  217. package/lib/components/source-picker/CubeFunctionSteps.js +76 -0
  218. package/lib/components/source-picker/CubeFunctionSteps.js.map +1 -0
  219. package/lib/components/source-picker/CubeIngestTab.d.ts.map +1 -1
  220. package/lib/components/source-picker/CubeIngestTab.js +39 -16
  221. package/lib/components/source-picker/CubeIngestTab.js.map +1 -1
  222. package/lib/components/source-picker/CubeInlineModelTab.d.ts +3 -2
  223. package/lib/components/source-picker/CubeInlineModelTab.d.ts.map +1 -1
  224. package/lib/components/source-picker/CubeInlineModelTab.js +23 -13
  225. package/lib/components/source-picker/CubeInlineModelTab.js.map +1 -1
  226. package/lib/components/source-picker/CubePickerListItem.d.ts +47 -0
  227. package/lib/components/source-picker/CubePickerListItem.d.ts.map +1 -0
  228. package/lib/components/source-picker/CubePickerListItem.js +62 -0
  229. package/lib/components/source-picker/CubePickerListItem.js.map +1 -0
  230. package/lib/components/source-picker/CubeProjectTab.d.ts +4 -3
  231. package/lib/components/source-picker/CubeProjectTab.d.ts.map +1 -1
  232. package/lib/components/source-picker/CubeProjectTab.js +7 -4
  233. package/lib/components/source-picker/CubeProjectTab.js.map +1 -1
  234. package/lib/components/source-picker/CubeServiceTab.d.ts +27 -0
  235. package/lib/components/source-picker/CubeServiceTab.d.ts.map +1 -0
  236. package/lib/components/source-picker/CubeServiceTab.js +36 -0
  237. package/lib/components/source-picker/CubeServiceTab.js.map +1 -0
  238. package/lib/components/source-picker/CubeSourcePicker.d.ts.map +1 -1
  239. package/lib/components/source-picker/CubeSourcePicker.js +16 -3
  240. package/lib/components/source-picker/CubeSourcePicker.js.map +1 -1
  241. package/lib/components/source-picker/CubeTablePreview.d.ts +29 -0
  242. package/lib/components/source-picker/CubeTablePreview.d.ts.map +1 -0
  243. package/lib/components/source-picker/CubeTablePreview.js +10 -0
  244. package/lib/components/source-picker/CubeTablePreview.js.map +1 -0
  245. package/lib/components/spec-transfer/CubeImportPureDialog.d.ts +27 -0
  246. package/lib/components/spec-transfer/CubeImportPureDialog.d.ts.map +1 -0
  247. package/lib/components/spec-transfer/CubeImportPureDialog.js +38 -0
  248. package/lib/components/spec-transfer/CubeImportPureDialog.js.map +1 -0
  249. package/lib/components/spec-transfer/CubeSpecTransferDialog.d.ts.map +1 -1
  250. package/lib/components/spec-transfer/CubeSpecTransferDialog.js +9 -3
  251. package/lib/components/spec-transfer/CubeSpecTransferDialog.js.map +1 -1
  252. package/lib/graph-manager/CubeDataProductCatalog.d.ts +10 -0
  253. package/lib/graph-manager/CubeDataProductCatalog.d.ts.map +1 -1
  254. package/lib/graph-manager/CubeDataProductCatalog.js.map +1 -1
  255. package/lib/graph-manager/CubeEngine.d.ts +46 -1
  256. package/lib/graph-manager/CubeEngine.d.ts.map +1 -1
  257. package/lib/graph-manager/CubeEngine.js.map +1 -1
  258. package/lib/graph-manager/CubeEngineClientSettings.d.ts +43 -0
  259. package/lib/graph-manager/CubeEngineClientSettings.d.ts.map +1 -0
  260. package/lib/graph-manager/CubeEngineClientSettings.js +51 -0
  261. package/lib/graph-manager/CubeEngineClientSettings.js.map +1 -0
  262. package/lib/graph-manager/CubeIngest.d.ts +5 -0
  263. package/lib/graph-manager/CubeIngest.d.ts.map +1 -1
  264. package/lib/graph-manager/CubeIngest.js +10 -0
  265. package/lib/graph-manager/CubeIngest.js.map +1 -1
  266. package/lib/graph-manager/CubeIngestCatalog.d.ts +26 -0
  267. package/lib/graph-manager/CubeIngestCatalog.d.ts.map +1 -1
  268. package/lib/graph-manager/CubeIngestCatalog.js +6 -0
  269. package/lib/graph-manager/CubeIngestCatalog.js.map +1 -1
  270. package/lib/graph-manager/CubeLakehouseRuntime.d.ts +29 -0
  271. package/lib/graph-manager/CubeLakehouseRuntime.d.ts.map +1 -0
  272. package/lib/graph-manager/CubeLakehouseRuntime.js +40 -0
  273. package/lib/graph-manager/CubeLakehouseRuntime.js.map +1 -0
  274. package/lib/graph-manager/CubeProjectCatalog.d.ts +3 -3
  275. package/lib/graph-manager/CubeService.d.ts +20 -0
  276. package/lib/graph-manager/CubeService.d.ts.map +1 -0
  277. package/lib/graph-manager/CubeService.js +22 -0
  278. package/lib/graph-manager/CubeService.js.map +1 -0
  279. package/lib/graph-manager/CubeServiceCatalog.d.ts +31 -0
  280. package/lib/graph-manager/CubeServiceCatalog.d.ts.map +1 -0
  281. package/lib/graph-manager/CubeServiceCatalog.js +17 -0
  282. package/lib/graph-manager/CubeServiceCatalog.js.map +1 -0
  283. package/lib/graph-manager/protocol/pure/CubeEngineBuilder.d.ts +52 -5
  284. package/lib/graph-manager/protocol/pure/CubeEngineBuilder.d.ts.map +1 -1
  285. package/lib/graph-manager/protocol/pure/CubeEngineBuilder.js +63 -5
  286. package/lib/graph-manager/protocol/pure/CubeEngineBuilder.js.map +1 -1
  287. package/lib/graph-manager/protocol/pure/v1/V1_CubeDataProductModel.d.ts +9 -6
  288. package/lib/graph-manager/protocol/pure/v1/V1_CubeDataProductModel.d.ts.map +1 -1
  289. package/lib/graph-manager/protocol/pure/v1/V1_CubeDataProductModel.js +12 -8
  290. package/lib/graph-manager/protocol/pure/v1/V1_CubeDataProductModel.js.map +1 -1
  291. package/lib/graph-manager/protocol/pure/v1/V1_CubeFunctionOutlineBuilder.d.ts +30 -0
  292. package/lib/graph-manager/protocol/pure/v1/V1_CubeFunctionOutlineBuilder.d.ts.map +1 -0
  293. package/lib/graph-manager/protocol/pure/v1/V1_CubeFunctionOutlineBuilder.js +229 -0
  294. package/lib/graph-manager/protocol/pure/v1/V1_CubeFunctionOutlineBuilder.js.map +1 -0
  295. package/lib/graph-manager/protocol/pure/v1/V1_CubeIngestDefinition.d.ts.map +1 -1
  296. package/lib/graph-manager/protocol/pure/v1/V1_CubeIngestDefinition.js +18 -9
  297. package/lib/graph-manager/protocol/pure/v1/V1_CubeIngestDefinition.js.map +1 -1
  298. package/lib/graph-manager/protocol/pure/v1/V1_CubeIngestModel.d.ts +4 -9
  299. package/lib/graph-manager/protocol/pure/v1/V1_CubeIngestModel.d.ts.map +1 -1
  300. package/lib/graph-manager/protocol/pure/v1/V1_CubeIngestModel.js +2 -1
  301. package/lib/graph-manager/protocol/pure/v1/V1_CubeIngestModel.js.map +1 -1
  302. package/lib/graph-manager/protocol/pure/v1/V1_CubeLambdaReader.d.ts +34 -0
  303. package/lib/graph-manager/protocol/pure/v1/V1_CubeLambdaReader.d.ts.map +1 -0
  304. package/lib/graph-manager/protocol/pure/v1/V1_CubeLambdaReader.js +332 -0
  305. package/lib/graph-manager/protocol/pure/v1/V1_CubeLambdaReader.js.map +1 -0
  306. package/lib/graph-manager/protocol/pure/v1/V1_CubeLambdaSerializer.d.ts.map +1 -1
  307. package/lib/graph-manager/protocol/pure/v1/V1_CubeLambdaSerializer.js +49 -10
  308. package/lib/graph-manager/protocol/pure/v1/V1_CubeLambdaSerializer.js.map +1 -1
  309. package/lib/graph-manager/protocol/pure/v1/V1_CubeModelOutlineBuilder.d.ts +1 -1
  310. package/lib/graph-manager/protocol/pure/v1/V1_CubeModelOutlineBuilder.d.ts.map +1 -1
  311. package/lib/graph-manager/protocol/pure/v1/V1_CubeModelOutlineBuilder.js +3 -1
  312. package/lib/graph-manager/protocol/pure/v1/V1_CubeModelOutlineBuilder.js.map +1 -1
  313. package/lib/graph-manager/protocol/pure/v1/V1_LegendCubeConnectionExplorer.d.ts +2 -1
  314. package/lib/graph-manager/protocol/pure/v1/V1_LegendCubeConnectionExplorer.d.ts.map +1 -1
  315. package/lib/graph-manager/protocol/pure/v1/V1_LegendCubeConnectionExplorer.js +2 -1
  316. package/lib/graph-manager/protocol/pure/v1/V1_LegendCubeConnectionExplorer.js.map +1 -1
  317. package/lib/graph-manager/protocol/pure/v1/V1_LegendCubeEngine.d.ts +18 -0
  318. package/lib/graph-manager/protocol/pure/v1/V1_LegendCubeEngine.d.ts.map +1 -1
  319. package/lib/graph-manager/protocol/pure/v1/V1_LegendCubeEngine.js +74 -6
  320. package/lib/graph-manager/protocol/pure/v1/V1_LegendCubeEngine.js.map +1 -1
  321. package/lib/graph-manager/protocol/pure/v1/V1_LegendCubeProjectCatalog.d.ts.map +1 -1
  322. package/lib/graph-manager/protocol/pure/v1/V1_LegendCubeProjectCatalog.js +7 -4
  323. package/lib/graph-manager/protocol/pure/v1/V1_LegendCubeProjectCatalog.js.map +1 -1
  324. package/lib/graph-manager/protocol/pure/v1/V1_LegendCubeServiceCatalog.d.ts +31 -0
  325. package/lib/graph-manager/protocol/pure/v1/V1_LegendCubeServiceCatalog.d.ts.map +1 -0
  326. package/lib/graph-manager/protocol/pure/v1/V1_LegendCubeServiceCatalog.js +69 -0
  327. package/lib/graph-manager/protocol/pure/v1/V1_LegendCubeServiceCatalog.js.map +1 -0
  328. package/lib/graph-manager/protocol/pure/v1/__test-utils__/V1_CubeEngineTestUtils.d.ts.map +1 -1
  329. package/lib/graph-manager/protocol/pure/v1/__test-utils__/V1_CubeEngineTestUtils.js +6 -2
  330. package/lib/graph-manager/protocol/pure/v1/__test-utils__/V1_CubeEngineTestUtils.js.map +1 -1
  331. package/lib/index.css +2 -2
  332. package/lib/index.css.map +1 -1
  333. package/lib/index.d.ts +12 -3
  334. package/lib/index.d.ts.map +1 -1
  335. package/lib/index.js +10 -1
  336. package/lib/index.js.map +1 -1
  337. package/lib/stores/CubeAddPlacement.d.ts +10 -3
  338. package/lib/stores/CubeAddPlacement.d.ts.map +1 -1
  339. package/lib/stores/CubeAddPlacement.js +16 -5
  340. package/lib/stores/CubeAddPlacement.js.map +1 -1
  341. package/lib/stores/CubeDevSettingsState.d.ts +47 -0
  342. package/lib/stores/CubeDevSettingsState.d.ts.map +1 -0
  343. package/lib/stores/CubeDevSettingsState.js +99 -0
  344. package/lib/stores/CubeDevSettingsState.js.map +1 -0
  345. package/lib/stores/CubeEditorState.d.ts +173 -43
  346. package/lib/stores/CubeEditorState.d.ts.map +1 -1
  347. package/lib/stores/CubeEditorState.js +498 -113
  348. package/lib/stores/CubeEditorState.js.map +1 -1
  349. package/lib/stores/CubeEngineChecks.d.ts +59 -0
  350. package/lib/stores/CubeEngineChecks.d.ts.map +1 -0
  351. package/lib/stores/CubeEngineChecks.js +100 -0
  352. package/lib/stores/CubeEngineChecks.js.map +1 -0
  353. package/lib/stores/CubeExamples.d.ts.map +1 -1
  354. package/lib/stores/CubeExamples.js +39 -2
  355. package/lib/stores/CubeExamples.js.map +1 -1
  356. package/lib/stores/CubeExamplesState.d.ts +1 -1
  357. package/lib/stores/CubeExamplesState.d.ts.map +1 -1
  358. package/lib/stores/CubeExamplesState.js +2 -2
  359. package/lib/stores/CubeExamplesState.js.map +1 -1
  360. package/lib/stores/CubeExecutionState.d.ts.map +1 -1
  361. package/lib/stores/CubeExecutionState.js +24 -33
  362. package/lib/stores/CubeExecutionState.js.map +1 -1
  363. package/lib/stores/CubeExportState.d.ts +41 -0
  364. package/lib/stores/CubeExportState.d.ts.map +1 -0
  365. package/lib/stores/CubeExportState.js +134 -0
  366. package/lib/stores/CubeExportState.js.map +1 -0
  367. package/lib/stores/CubeExpressionFilterCheck.d.ts +51 -0
  368. package/lib/stores/CubeExpressionFilterCheck.d.ts.map +1 -0
  369. package/lib/stores/CubeExpressionFilterCheck.js +134 -0
  370. package/lib/stores/CubeExpressionFilterCheck.js.map +1 -0
  371. package/lib/stores/CubeExtendTyping.d.ts +6 -14
  372. package/lib/stores/CubeExtendTyping.d.ts.map +1 -1
  373. package/lib/stores/CubeExtendTyping.js +6 -33
  374. package/lib/stores/CubeExtendTyping.js.map +1 -1
  375. package/lib/stores/CubeFunctionRecheck.d.ts +30 -0
  376. package/lib/stores/CubeFunctionRecheck.d.ts.map +1 -0
  377. package/lib/stores/CubeFunctionRecheck.js +67 -0
  378. package/lib/stores/CubeFunctionRecheck.js.map +1 -0
  379. package/lib/stores/CubeGridFetcher.d.ts +75 -0
  380. package/lib/stores/CubeGridFetcher.d.ts.map +1 -0
  381. package/lib/stores/CubeGridFetcher.js +197 -0
  382. package/lib/stores/CubeGridFetcher.js.map +1 -0
  383. package/lib/stores/CubeGridQuickActions.d.ts +18 -6
  384. package/lib/stores/CubeGridQuickActions.d.ts.map +1 -1
  385. package/lib/stores/CubeGridQuickActions.js +32 -12
  386. package/lib/stores/CubeGridQuickActions.js.map +1 -1
  387. package/lib/stores/CubeGridState.d.ts +136 -0
  388. package/lib/stores/CubeGridState.d.ts.map +1 -0
  389. package/lib/stores/CubeGridState.js +317 -0
  390. package/lib/stores/CubeGridState.js.map +1 -0
  391. package/lib/stores/CubeHost.d.ts +42 -0
  392. package/lib/stores/CubeHost.d.ts.map +1 -1
  393. package/lib/stores/CubeHost.js +4 -0
  394. package/lib/stores/CubeHost.js.map +1 -1
  395. package/lib/stores/CubeLambdaImportState.d.ts +118 -0
  396. package/lib/stores/CubeLambdaImportState.d.ts.map +1 -0
  397. package/lib/stores/CubeLambdaImportState.js +302 -0
  398. package/lib/stores/CubeLambdaImportState.js.map +1 -0
  399. package/lib/stores/CubeLambdaSources.d.ts +45 -0
  400. package/lib/stores/CubeLambdaSources.d.ts.map +1 -0
  401. package/lib/stores/CubeLambdaSources.js +261 -0
  402. package/lib/stores/CubeLambdaSources.js.map +1 -0
  403. package/lib/stores/CubeQueryRun.d.ts +59 -0
  404. package/lib/stores/CubeQueryRun.d.ts.map +1 -0
  405. package/lib/stores/CubeQueryRun.js +101 -0
  406. package/lib/stores/CubeQueryRun.js.map +1 -0
  407. package/lib/stores/CubeRunStatsState.d.ts +61 -0
  408. package/lib/stores/CubeRunStatsState.d.ts.map +1 -0
  409. package/lib/stores/CubeRunStatsState.js +54 -0
  410. package/lib/stores/CubeRunStatsState.js.map +1 -0
  411. package/lib/stores/CubeRunningStepLambda.d.ts +25 -0
  412. package/lib/stores/CubeRunningStepLambda.d.ts.map +1 -0
  413. package/lib/stores/CubeRunningStepLambda.js +45 -0
  414. package/lib/stores/CubeRunningStepLambda.js.map +1 -0
  415. package/lib/stores/CubeServiceRecheck.d.ts +29 -0
  416. package/lib/stores/CubeServiceRecheck.d.ts.map +1 -0
  417. package/lib/stores/CubeServiceRecheck.js +33 -0
  418. package/lib/stores/CubeServiceRecheck.js.map +1 -0
  419. package/lib/stores/CubeShowPureState.d.ts +14 -1
  420. package/lib/stores/CubeShowPureState.d.ts.map +1 -1
  421. package/lib/stores/CubeShowPureState.js +41 -11
  422. package/lib/stores/CubeShowPureState.js.map +1 -1
  423. package/lib/stores/CubeSourcePickerState.d.ts +20 -4
  424. package/lib/stores/CubeSourcePickerState.d.ts.map +1 -1
  425. package/lib/stores/CubeSourcePickerState.js +75 -14
  426. package/lib/stores/CubeSourcePickerState.js.map +1 -1
  427. package/lib/stores/LocalModelCatalog.d.ts.map +1 -1
  428. package/lib/stores/LocalModelCatalog.js +3 -1
  429. package/lib/stores/LocalModelCatalog.js.map +1 -1
  430. package/lib/stores/editors/CubeExpressionFilterDraft.d.ts +91 -0
  431. package/lib/stores/editors/CubeExpressionFilterDraft.d.ts.map +1 -0
  432. package/lib/stores/editors/CubeExpressionFilterDraft.js +254 -0
  433. package/lib/stores/editors/CubeExpressionFilterDraft.js.map +1 -0
  434. package/lib/stores/editors/CubeFunctionDraft.d.ts +34 -0
  435. package/lib/stores/editors/CubeFunctionDraft.d.ts.map +1 -0
  436. package/lib/stores/editors/CubeFunctionDraft.js +69 -0
  437. package/lib/stores/editors/CubeFunctionDraft.js.map +1 -0
  438. package/lib/stores/editors/CubeNodeDraftRegistry.d.ts +4 -2
  439. package/lib/stores/editors/CubeNodeDraftRegistry.d.ts.map +1 -1
  440. package/lib/stores/editors/CubeNodeDraftRegistry.js +20 -3
  441. package/lib/stores/editors/CubeNodeDraftRegistry.js.map +1 -1
  442. package/lib/stores/editors/CubePivotDraft.d.ts +93 -0
  443. package/lib/stores/editors/CubePivotDraft.d.ts.map +1 -0
  444. package/lib/stores/editors/CubePivotDraft.js +267 -0
  445. package/lib/stores/editors/CubePivotDraft.js.map +1 -0
  446. package/lib/stores/fixtures/CubeSalesDuckDbModel.d.ts +26 -0
  447. package/lib/stores/fixtures/CubeSalesDuckDbModel.d.ts.map +1 -0
  448. package/lib/stores/fixtures/CubeSalesDuckDbModel.js +46 -0
  449. package/lib/stores/fixtures/CubeSalesDuckDbModel.js.map +1 -0
  450. package/lib/stores/fixtures/CubeTradesModel.d.ts +4 -0
  451. package/lib/stores/fixtures/CubeTradesModel.d.ts.map +1 -1
  452. package/lib/stores/fixtures/CubeTradesModel.js +31 -1
  453. package/lib/stores/fixtures/CubeTradesModel.js.map +1 -1
  454. package/lib/stores/source-picker/CubeDataProductTabState.d.ts +34 -5
  455. package/lib/stores/source-picker/CubeDataProductTabState.d.ts.map +1 -1
  456. package/lib/stores/source-picker/CubeDataProductTabState.js +111 -26
  457. package/lib/stores/source-picker/CubeDataProductTabState.js.map +1 -1
  458. package/lib/stores/source-picker/CubeDirectConnectionTabState.d.ts +25 -2
  459. package/lib/stores/source-picker/CubeDirectConnectionTabState.d.ts.map +1 -1
  460. package/lib/stores/source-picker/CubeDirectConnectionTabState.js +183 -31
  461. package/lib/stores/source-picker/CubeDirectConnectionTabState.js.map +1 -1
  462. package/lib/stores/source-picker/CubeIngestTabState.d.ts +22 -9
  463. package/lib/stores/source-picker/CubeIngestTabState.d.ts.map +1 -1
  464. package/lib/stores/source-picker/CubeIngestTabState.js +84 -29
  465. package/lib/stores/source-picker/CubeIngestTabState.js.map +1 -1
  466. package/lib/stores/source-picker/CubeInlineModelTabState.d.ts +100 -4
  467. package/lib/stores/source-picker/CubeInlineModelTabState.d.ts.map +1 -1
  468. package/lib/stores/source-picker/CubeInlineModelTabState.js +415 -28
  469. package/lib/stores/source-picker/CubeInlineModelTabState.js.map +1 -1
  470. package/lib/stores/source-picker/CubeProjectTabState.d.ts +18 -3
  471. package/lib/stores/source-picker/CubeProjectTabState.d.ts.map +1 -1
  472. package/lib/stores/source-picker/CubeProjectTabState.js +26 -1
  473. package/lib/stores/source-picker/CubeProjectTabState.js.map +1 -1
  474. package/lib/stores/source-picker/CubeServiceTabState.d.ts +74 -0
  475. package/lib/stores/source-picker/CubeServiceTabState.d.ts.map +1 -0
  476. package/lib/stores/source-picker/CubeServiceTabState.js +216 -0
  477. package/lib/stores/source-picker/CubeServiceTabState.js.map +1 -0
  478. package/lib/stores/source-picker/CubeSourcePickerTab.d.ts +15 -3
  479. package/lib/stores/source-picker/CubeSourcePickerTab.d.ts.map +1 -1
  480. package/lib/stores/source-picker/CubeSourcePickerTab.js +21 -0
  481. package/lib/stores/source-picker/CubeSourcePickerTab.js.map +1 -1
  482. package/package.json +10 -9
  483. package/src/__lib__/LegendCubeCommand.ts +7 -0
  484. package/src/__lib__/LegendCubeFunctionLabels.ts +41 -0
  485. package/src/__lib__/LegendCubeHelpText.ts +23 -1
  486. package/src/__lib__/LegendCubeLabels.ts +170 -13
  487. package/src/__lib__/LegendCubeProjectSourceLabels.ts +26 -0
  488. package/src/__lib__/LegendCubeServiceLabels.ts +41 -0
  489. package/src/__lib__/LegendCubeTesting.ts +7 -0
  490. package/src/__test-utils__/CubeEngineTestSupport.ts +2 -1
  491. package/src/__test-utils__/CubeExpressionTestUtils.ts +29 -2
  492. package/src/__test-utils__/CubeFunctionTestOutline.ts +78 -0
  493. package/src/__test-utils__/CubeLambdaCorpus.ts +137 -0
  494. package/src/__test-utils__/CubePageTestUtils.tsx +34 -0
  495. package/src/__test-utils__/CubeTestApplication.ts +25 -0
  496. package/src/__test-utils__/FakeCubeEngine.ts +27 -0
  497. package/src/__test-utils__/FakeCubeIngestCatalog.ts +18 -0
  498. package/src/__test-utils__/FakeCubeServiceCatalog.ts +57 -0
  499. package/src/components/CubeAddItems.tsx +13 -6
  500. package/src/components/CubeDialogTheme.ts +25 -0
  501. package/src/components/CubeEditor.tsx +155 -129
  502. package/src/components/CubeFileMenu.tsx +127 -0
  503. package/src/components/CubeLambdaImportBanner.tsx +97 -0
  504. package/src/components/CubeNodeIcon.tsx +7 -0
  505. package/src/components/CubeSchemaColumnsTable.tsx +7 -2
  506. package/src/components/canvas/CubeCanvas.tsx +52 -13
  507. package/src/components/canvas/CubeCanvasContextMenu.tsx +33 -2
  508. package/src/components/canvas/CubeCanvasElements.ts +76 -3
  509. package/src/components/canvas/CubeCanvasLayout.ts +1 -1
  510. package/src/components/canvas/CubeCanvasNode.tsx +30 -3
  511. package/src/components/dev-settings/CubeDevSettings.tsx +154 -0
  512. package/src/components/editors/CubeColumnChecklist.tsx +8 -2
  513. package/src/components/editors/CubeColumnPicker.tsx +6 -3
  514. package/src/components/editors/CubeConcatEditor.tsx +2 -2
  515. package/src/components/editors/CubeExpressionFilterEditor.tsx +193 -0
  516. package/src/components/editors/CubeExtendEditor.tsx +3 -3
  517. package/src/components/editors/CubeFilterEditor.tsx +13 -1
  518. package/src/components/editors/CubeFunctionSourceEditor.tsx +140 -0
  519. package/src/components/editors/CubeJoinEditor.tsx +23 -4
  520. package/src/components/editors/CubeNodeEditorPanel.tsx +22 -10
  521. package/src/components/editors/CubeNodeEditorPopper.tsx +9 -1
  522. package/src/components/editors/CubeNodeEditorRegistry.ts +12 -0
  523. package/src/components/editors/CubePivotEditor.tsx +277 -0
  524. package/src/components/editors/CubeRestrictEditor.tsx +8 -2
  525. package/src/components/editors/CubeServiceSourceEditor.tsx +77 -0
  526. package/src/components/grid/CubeColumnFormatDialog.tsx +289 -0
  527. package/src/components/grid/CubeDrilldownBar.tsx +219 -0
  528. package/src/components/grid/CubeGridRegion.tsx +170 -54
  529. package/src/components/grid/CubeGridValues.ts +146 -1
  530. package/src/components/grid/CubeResultGrid.tsx +443 -41
  531. package/src/components/grid/CubeRunStatsPanel.tsx +156 -0
  532. package/src/components/grid/CubeServerSideGrid.tsx +200 -0
  533. package/src/components/grid/CubeSqlDialog.tsx +90 -0
  534. package/src/components/grid/CubeSqlFormat.ts +37 -0
  535. package/src/components/palette/CubePalette.tsx +45 -12
  536. package/src/components/show-pure/CubeShowPureDialog.tsx +19 -5
  537. package/src/components/source-picker/CubeDataProductTab.tsx +169 -75
  538. package/src/components/source-picker/CubeDirectConnectionTab.tsx +42 -30
  539. package/src/components/source-picker/CubeFunctionSteps.tsx +244 -0
  540. package/src/components/source-picker/CubeIngestTab.tsx +159 -79
  541. package/src/components/source-picker/CubeInlineModelTab.tsx +110 -81
  542. package/src/components/source-picker/CubePickerListItem.tsx +118 -0
  543. package/src/components/source-picker/CubeProjectTab.tsx +6 -3
  544. package/src/components/source-picker/CubeServiceTab.tsx +151 -0
  545. package/src/components/source-picker/CubeSourcePicker.tsx +54 -18
  546. package/src/components/source-picker/CubeTablePreview.tsx +49 -0
  547. package/src/components/spec-transfer/CubeImportPureDialog.tsx +122 -0
  548. package/src/components/spec-transfer/CubeSpecTransferDialog.tsx +21 -8
  549. package/src/graph-manager/CubeDataProductCatalog.ts +11 -0
  550. package/src/graph-manager/CubeEngine.ts +51 -1
  551. package/src/graph-manager/CubeEngineClientSettings.ts +64 -0
  552. package/src/graph-manager/CubeIngest.ts +15 -0
  553. package/src/graph-manager/CubeIngestCatalog.ts +33 -0
  554. package/src/graph-manager/CubeLakehouseRuntime.ts +43 -0
  555. package/src/graph-manager/CubeProjectCatalog.ts +3 -3
  556. package/src/graph-manager/CubeService.ts +29 -0
  557. package/src/graph-manager/CubeServiceCatalog.ts +35 -0
  558. package/src/graph-manager/protocol/pure/CubeEngineBuilder.ts +115 -5
  559. package/src/graph-manager/protocol/pure/v1/V1_CubeDataProductModel.ts +13 -7
  560. package/src/graph-manager/protocol/pure/v1/V1_CubeFunctionOutlineBuilder.ts +312 -0
  561. package/src/graph-manager/protocol/pure/v1/V1_CubeIngestDefinition.ts +35 -9
  562. package/src/graph-manager/protocol/pure/v1/V1_CubeIngestModel.ts +6 -15
  563. package/src/graph-manager/protocol/pure/v1/V1_CubeLambdaReader.ts +471 -0
  564. package/src/graph-manager/protocol/pure/v1/V1_CubeLambdaSerializer.ts +70 -15
  565. package/src/graph-manager/protocol/pure/v1/V1_CubeModelOutlineBuilder.ts +3 -1
  566. package/src/graph-manager/protocol/pure/v1/V1_LegendCubeConnectionExplorer.ts +7 -1
  567. package/src/graph-manager/protocol/pure/v1/V1_LegendCubeEngine.ts +122 -7
  568. package/src/graph-manager/protocol/pure/v1/V1_LegendCubeProjectCatalog.ts +9 -4
  569. package/src/graph-manager/protocol/pure/v1/V1_LegendCubeServiceCatalog.ts +92 -0
  570. package/src/graph-manager/protocol/pure/v1/__test-utils__/V1_CubeEngineTestUtils.ts +6 -1
  571. package/src/index.ts +32 -2
  572. package/src/stores/CubeAddPlacement.ts +25 -5
  573. package/src/stores/CubeDevSettingsState.ts +117 -0
  574. package/src/stores/CubeEditorState.ts +687 -197
  575. package/src/stores/CubeEngineChecks.ts +240 -0
  576. package/src/stores/CubeExamples.ts +70 -1
  577. package/src/stores/CubeExamplesState.ts +4 -2
  578. package/src/stores/CubeExecutionState.ts +26 -57
  579. package/src/stores/CubeExportState.ts +196 -0
  580. package/src/stores/CubeExpressionFilterCheck.ts +218 -0
  581. package/src/stores/CubeExtendTyping.ts +6 -46
  582. package/src/stores/CubeFunctionRecheck.ts +97 -0
  583. package/src/stores/CubeGridFetcher.ts +302 -0
  584. package/src/stores/CubeGridQuickActions.ts +33 -11
  585. package/src/stores/CubeGridState.ts +450 -0
  586. package/src/stores/CubeHost.ts +48 -0
  587. package/src/stores/CubeLambdaImportState.ts +434 -0
  588. package/src/stores/CubeLambdaSources.ts +390 -0
  589. package/src/stores/CubeQueryRun.ts +169 -0
  590. package/src/stores/CubeRunStatsState.ts +91 -0
  591. package/src/stores/CubeRunningStepLambda.ts +62 -0
  592. package/src/stores/CubeServiceRecheck.ts +53 -0
  593. package/src/stores/CubeShowPureState.ts +51 -12
  594. package/src/stores/CubeSourcePickerState.ts +89 -13
  595. package/src/stores/LocalModelCatalog.ts +6 -1
  596. package/src/stores/editors/CubeExpressionFilterDraft.ts +385 -0
  597. package/src/stores/editors/CubeFunctionDraft.ts +92 -0
  598. package/src/stores/editors/CubeNodeDraftRegistry.ts +27 -2
  599. package/src/stores/editors/CubePivotDraft.ts +355 -0
  600. package/src/stores/fixtures/CubeSalesDuckDbModel.ts +54 -0
  601. package/src/stores/fixtures/CubeTradesModel.ts +36 -1
  602. package/src/stores/source-picker/CubeDataProductTabState.ts +162 -35
  603. package/src/stores/source-picker/CubeDirectConnectionTabState.ts +246 -47
  604. package/src/stores/source-picker/CubeIngestTabState.ts +112 -38
  605. package/src/stores/source-picker/CubeInlineModelTabState.ts +514 -34
  606. package/src/stores/source-picker/CubeProjectTabState.ts +35 -3
  607. package/src/stores/source-picker/CubeServiceTabState.ts +288 -0
  608. package/src/stores/source-picker/CubeSourcePickerTab.ts +31 -2
  609. package/tsconfig.json +50 -0
@@ -21,10 +21,11 @@ import {
21
21
  createNodeRegistry,
22
22
  CubeDocument,
23
23
  diffSchemas,
24
- Extend,
24
+ dependsOnDatabaseType,
25
25
  findLostSortOrders,
26
+ getDatabaseProblemOfType,
27
+ getDatabaseProblems,
26
28
  isTypingError,
27
- type JsonObject,
28
29
  MESSAGE_SORT_COLUMNS_CUT,
29
30
  MESSAGE_SORT_COLUMNS_DROPPED,
30
31
  MESSAGE_SORT_ORDER_LOST,
@@ -38,7 +39,13 @@ import {
38
39
  rereadQueryFilterValues,
39
40
  type Schema,
40
41
  type SchemaInferenceResult,
42
+ ServiceSource,
41
43
  type SourceDefinition,
44
+ foldColumnName,
45
+ FunctionSource,
46
+ copyQueryNode,
47
+ type CubeContext,
48
+ SourceNode,
42
49
  } from '@finos/legend-cube';
43
50
  import type { CommandRegistrar } from '@finos/legend-application';
44
51
  import type { GeneratorFn } from '@finos/legend-shared';
@@ -58,7 +65,6 @@ import {
58
65
  CUBE_EDITOR_CLOSED_REASON,
59
66
  DEFAULT_ROW_LIMIT,
60
67
  getSchemaDriftWarning,
61
- getExtendRetypeWarning,
62
68
  getSourceRecheckWarning,
63
69
  LEGEND_CUBE_USER_DATA_KEY,
64
70
  MAX_UNDO_STEPS,
@@ -75,31 +81,49 @@ import {
75
81
  } from '../__lib__/LegendCubeIngestLabels.js';
76
82
  import { isCubeDataProductModel } from '../graph-manager/CubeDataProduct.js';
77
83
  import { isCubeIngestModel } from '../graph-manager/CubeIngest.js';
84
+ import { isCubeServiceModel } from '../graph-manager/CubeService.js';
78
85
  import {
79
86
  CubeEngineError,
80
87
  CubeEngineErrorKind,
81
88
  type CubeModelOutline,
82
89
  type NodeId,
83
90
  } from '../graph-manager/CubeEngine.js';
91
+ import {
92
+ CUBE_LAKEHOUSE_RUNTIME_KIND,
93
+ getLakehouseDatabaseType,
94
+ } from '../graph-manager/CubeLakehouseRuntime.js';
84
95
  import { getDatabaseType } from '../graph-manager/CubeModelOutlineHelper.js';
85
96
  import { recheckCubeDataProductSources } from './CubeDataProductRecheck.js';
86
97
  import { recheckCubeIngestSources } from './CubeIngestRecheck.js';
98
+ import { recheckCubeServiceSources } from './CubeServiceRecheck.js';
99
+ import {
100
+ CUBE_FUNCTION_MESSAGE,
101
+ getFunctionDriftWarning,
102
+ getFunctionRecheckWarning,
103
+ } from '../__lib__/LegendCubeFunctionLabels.js';
104
+ import { recheckCubeFunctionSources } from './CubeFunctionRecheck.js';
87
105
  import { CubeDataProductRuntimeState } from './CubeDataProductRuntimeState.js';
88
106
  import { CubeExamplesState } from './CubeExamplesState.js';
107
+ import { CubeExportState } from './CubeExportState.js';
108
+ import { CubeGridFetcher } from './CubeGridFetcher.js';
109
+ import { CubeGridState } from './CubeGridState.js';
110
+ import { CubeDevSettingsState } from './CubeDevSettingsState.js';
111
+ import { CubeRunStatsState } from './CubeRunStatsState.js';
89
112
  import { CubeExecutionState } from './CubeExecutionState.js';
113
+ import { CubeExpressionFilterDraft } from './editors/CubeExpressionFilterDraft.js';
90
114
  import { CubeExtendDraft } from './editors/CubeExtendDraft.js';
91
115
  import {
92
- buildCubeExtendTypingLambdas,
93
- createStaleCubeExtendTypingRule,
94
- getCubeExtendTypingUpstream,
95
- getCubeExtendUpstream,
96
- isCubeExtendTypingCurrent,
97
- isSameCubeExtendTyping,
98
- readCubeExtendTyping,
99
- } from './CubeExtendTyping.js';
116
+ buildCubeEngineCheckRequest,
117
+ type CubeEngineCheckedNode,
118
+ createStaleCubeEngineCheckRule,
119
+ getCubeEngineCheckUpstream,
120
+ isCubeEngineCheckedNode,
121
+ } from './CubeEngineChecks.js';
122
+ import { getCubeExtendUpstream } from './CubeExtendTyping.js';
100
123
  import { type CubeHost, loadCubeModelOutline } from './CubeHost.js';
101
124
  import { CubeNodeEditorState } from './CubeNodeEditorState.js';
102
125
  import { CubeShowPureState } from './CubeShowPureState.js';
126
+ import { CubeLambdaImportState } from './CubeLambdaImportState.js';
103
127
  import { CubeSourcePickerState } from './CubeSourcePickerState.js';
104
128
  import { CubeSpecTransferState } from './CubeSpecTransferState.js';
105
129
 
@@ -128,11 +152,13 @@ const isFocusInNodeEditor = (): boolean =>
128
152
  `[data-testid="${LEGEND_CUBE_TEST_ID.NODE_EDITOR}"]`,
129
153
  ) !== null && document.activeElement !== null;
130
154
 
131
- /** A source Cube types again to see drift: a table, or a data product's access point */
155
+ /** A source Cube types again to see drift: a table, a function, an access point, an ingest data set or a service */
132
156
  type RecheckedSource =
133
157
  | RelationalTableSource
158
+ | FunctionSource
134
159
  | DataProductAccessPointSource
135
- | IngestDatasetSource;
160
+ | IngestDatasetSource
161
+ | ServiceSource;
136
162
 
137
163
  /**
138
164
  * The state of one Cube page (PLAN §7.8). The document is immutable: every
@@ -144,20 +170,59 @@ export class CubeEditorState implements CommandRegistrar {
144
170
  readonly host: CubeHost;
145
171
  /** One registry for inference, emission and the saved spec */
146
172
  readonly registry: NodeRegistry;
147
- /** The editor's own query rule: an Extend typed for another input than its own waits to be typed again (PLAN §11.7) */
148
- private readonly staleExtendTyping: QueryRule;
173
+ /**
174
+ * The editor's own query rule: an Extend typed, or a Filter by Expression
175
+ * checked, for another input than its own waits to be checked again (PLAN
176
+ * §11.7, §11.11)
177
+ */
178
+ private readonly staleEngineChecks: QueryRule;
179
+ /**
180
+ * The editor's query rule for the database a node runs on: `%` or `_`
181
+ * given to a pattern on DuckDB (PLAN §11.11), once the model's outline
182
+ * tells the database
183
+ */
184
+ private readonly databaseRefusals: QueryRule;
149
185
  readonly execution: CubeExecutionState;
186
+ /** The latest runs, fetches and exports (spec §12.6) */
187
+ readonly runStats: CubeRunStatsState;
188
+ /** The Dev Settings, at the top left (PLAN §11.16) */
189
+ readonly devSettings: CubeDevSettingsState;
190
+ /** The grid's server-side levels (PLAN §11.10) */
191
+ readonly gridFetcher: CubeGridFetcher;
192
+ /** The grid's mode and its server-side levels (PLAN §11.10) */
193
+ readonly grid: CubeGridState;
194
+ /** The results' export (spec §12.5) */
195
+ readonly export: CubeExportState;
150
196
  /** Where a lakehouse cube runs, a data product's or an ingest one's: its class and warehouse */
151
197
  readonly dataProductRuntime: CubeDataProductRuntimeState;
152
198
  readonly sourcePicker: CubeSourcePickerState;
153
199
  readonly specTransfer: CubeSpecTransferState;
154
200
  readonly examples: CubeExamplesState;
155
201
  readonly showPure: CubeShowPureState;
202
+ /** Import Pure: the lambda the page opened on, read into the cube (PLAN §11.18) */
203
+ readonly lambdaImport: CubeLambdaImportState;
156
204
  readonly nodeEditor: CubeNodeEditorState;
157
205
 
158
206
  document: CubeDocument;
159
207
  /** Earlier documents, oldest first */
160
208
  history: readonly CubeDocument[] = [];
209
+ /**
210
+ * The step copied last, as it was, with the cube's context then, which a
211
+ * pasted source needs; kept for the page, across cubes
212
+ */
213
+ copiedNode:
214
+ | { readonly node: QueryNode; readonly context: CubeContext | undefined }
215
+ | undefined;
216
+ /**
217
+ * The changes undone, the latest last, to redo; a new change clears them.
218
+ * Each keeps whether it was read-only and whether undoing it left another
219
+ * cube (an import), so a redo restores both
220
+ */
221
+ redoStack: readonly {
222
+ readonly document: CubeDocument;
223
+ readonly readOnly: boolean;
224
+ readonly opensAnotherCube: boolean;
225
+ }[] = [];
161
226
  /** Engine errors by node id: shown with the node's own errors, never part of inference */
162
227
  hostIssues: ReadonlyMap<string, CubeHostIssue> = new Map();
163
228
  /**
@@ -166,18 +231,31 @@ export class CubeEditorState implements CommandRegistrar {
166
231
  */
167
232
  warnings: ReadonlyMap<number, readonly string[]> = new Map();
168
233
  /**
169
- * The outline of each model the cube used, loaded when an editor needs it,
170
- * e.g. for the Join's 'type unknown' warning; by reference, never observed
171
- * deeply
234
+ * The outline of each model the cube used, by the model's JSON
235
+ * (`modelKey`): loaded when the cube reads a table, or an editor or a run
236
+ * needs it, e.g. for the Join's 'type unknown' warning or the database a
237
+ * node runs on (PLAN §11.12); by reference, never observed deeply
172
238
  */
173
- private modelOutlines: ReadonlyMap<ModelContext, CubeModelOutline> =
174
- new Map();
239
+ private modelOutlines: ReadonlyMap<string, CubeModelOutline> = new Map();
240
+ /** Each model's key in `modelOutlines`, its JSON, worked out once per model object */
241
+ private readonly modelKeys = new WeakMap<ModelContext, string>();
242
+ /** The outlines on their way, by model key, so a second load waits for the first */
243
+ private readonly loadingOutlines = new Map<
244
+ string,
245
+ Promise<CubeModelOutline>
246
+ >();
175
247
  /** Sources sent to the engine to be typed again, until it answers */
176
248
  private pendingSources: ReadonlySet<QueryNode> = new Set();
177
- /** Extends sent to the engine to be typed, until it answers (PLAN §11.7) */
178
- private typingExtends: ReadonlySet<QueryNode> = new Set();
179
- /** Types the Extends that wait for it, whenever one does (PLAN §11.7 Q4) */
180
- private readonly retyping: IReactionDisposer;
249
+ /** Extends and Filters by Expression sent to the engine to be checked, until it answers (PLAN §11.7, §11.11) */
250
+ private checkingNodes: ReadonlySet<QueryNode> = new Set();
251
+ /** Checks the nodes that wait for the engine, whenever one does (PLAN §11.7 Q4) */
252
+ private readonly rechecking: IReactionDisposer;
253
+ /**
254
+ * Loads the model's outline once the cube reads a table, so the database it
255
+ * runs on is known before any run: some nodes are refused there, or written
256
+ * another way (PLAN §11.4, §11.11, §11.12)
257
+ */
258
+ private readonly outlineLoading: IReactionDisposer;
181
259
  /** The rows a run returns; kept per user, never in the cube */
182
260
  rowLimit: number;
183
261
  /** The palette shows icons only; kept per user, never in the cube */
@@ -195,18 +273,21 @@ export class CubeEditorState implements CommandRegistrar {
195
273
  constructor(host: CubeHost, document = new CubeDocument()) {
196
274
  makeObservable<
197
275
  CubeEditorState,
198
- 'pendingSources' | 'modelOutlines' | 'typingExtends'
276
+ 'pendingSources' | 'modelOutlines' | 'checkingNodes'
199
277
  >(this, {
200
278
  pendingSources: observable.ref,
201
- typingExtends: observable.ref,
202
- extendsToType: computed,
203
- isTypingExtends: computed,
204
- retypeExtends: flow,
279
+ checkingNodes: observable.ref,
280
+ nodesToCheck: computed,
281
+ isCheckingExpressions: computed,
282
+ checkExpressions: flow,
205
283
  modelOutlines: observable.ref,
206
284
  modelOutline: computed,
207
285
  loadModelOutline: flow,
208
286
  document: observable.ref,
209
287
  history: observable.ref,
288
+ redoStack: observable.ref,
289
+ canRedo: computed,
290
+ redo: action,
210
291
  hostIssues: observable.ref,
211
292
  warnings: observable.ref,
212
293
  derivedWarnings: computed,
@@ -220,10 +301,14 @@ export class CubeEditorState implements CommandRegistrar {
220
301
  hasEditsToApply: computed,
221
302
  executeEdited: action,
222
303
  undoEdited: action,
304
+ redoEdited: action,
223
305
  isDialogOpen: computed,
224
306
  applyDocument: action,
225
307
  undo: action,
226
308
  importDocument: action,
309
+ openDocument: action,
310
+ startNewCube: action,
311
+ isEmptyCube: computed,
227
312
  reresolveSources: flow,
228
313
  refreshSource: flow,
229
314
  applyQuery: action,
@@ -233,19 +318,34 @@ export class CubeEditorState implements CommandRegistrar {
233
318
  addConfiguredNode: action,
234
319
  dropNode: action,
235
320
  removeNode: action,
321
+ copiedNode: observable.ref,
322
+ canPaste: computed,
323
+ copyNode: action,
324
+ pasteNode: action,
325
+ duplicateNode: action,
236
326
  swapInputs: action,
237
327
  setShowGraph: action,
238
328
  setPaletteCollapsed: action,
239
329
  setHostIssue: action,
240
330
  clearHostIssues: action,
241
331
  setRowLimit: action,
332
+ setColumnWidth: action,
242
333
  });
243
334
  this.host = host;
244
335
  this.registry = createNodeRegistry();
245
- this.staleExtendTyping = createStaleCubeExtendTypingRule(
336
+ this.staleEngineChecks = createStaleCubeEngineCheckRule(
246
337
  this.registry,
247
338
  () => this.document.context?.model,
248
339
  );
340
+ this.databaseRefusals = (query) =>
341
+ new Map(
342
+ query.nodes
343
+ .map((node): [string, string[]] => [
344
+ node.id,
345
+ this.getNodeDatabaseProblems(query, node),
346
+ ])
347
+ .filter(([, problems]) => problems.length > 0),
348
+ );
249
349
  this.document = document;
250
350
  const storedLimit = host.applicationStore.userDataService.getNumericValue(
251
351
  LEGEND_CUBE_USER_DATA_KEY.ROW_LIMIT,
@@ -258,17 +358,40 @@ export class CubeEditorState implements CommandRegistrar {
258
358
  LEGEND_CUBE_USER_DATA_KEY.PALETTE_COLLAPSED,
259
359
  ) ?? false;
260
360
  this.execution = new CubeExecutionState(this);
361
+ this.runStats = new CubeRunStatsState();
362
+ this.devSettings = new CubeDevSettingsState(host);
363
+ this.gridFetcher = new CubeGridFetcher(this);
364
+ this.grid = new CubeGridState(this);
365
+ this.export = new CubeExportState(this);
261
366
  this.dataProductRuntime = new CubeDataProductRuntimeState(this);
262
367
  this.sourcePicker = new CubeSourcePickerState(this);
263
368
  this.specTransfer = new CubeSpecTransferState(this);
264
369
  this.examples = new CubeExamplesState(this);
265
370
  this.showPure = new CubeShowPureState(this);
371
+ this.lambdaImport = new CubeLambdaImportState(this);
266
372
  this.nodeEditor = new CubeNodeEditorState(this);
267
- this.retyping = reaction(
268
- () => this.extendsToType,
373
+ this.rechecking = reaction(
374
+ () => this.nodesToCheck,
269
375
  (waiting) => {
270
376
  if (waiting.length) {
271
- flowResult(this.retypeExtends(waiting)).catch(
377
+ flowResult(this.checkExpressions(waiting)).catch(
378
+ this.host.applicationStore.alertUnhandledError,
379
+ );
380
+ }
381
+ },
382
+ { fireImmediately: true },
383
+ );
384
+ // the model, while the cube reads a table: another model loads too
385
+ this.outlineLoading = reaction(
386
+ () =>
387
+ this.document.query.nodes.some(
388
+ (node) => node instanceof RelationalTableSource,
389
+ )
390
+ ? this.document.context?.model
391
+ : undefined,
392
+ (model) => {
393
+ if (model !== undefined) {
394
+ flowResult(this.loadModelOutline(model)).catch(
272
395
  this.host.applicationStore.alertUnhandledError,
273
396
  );
274
397
  }
@@ -279,13 +402,15 @@ export class CubeEditorState implements CommandRegistrar {
279
402
 
280
403
  /**
281
404
  * Each node's schema and errors, query-level rules included, as the
282
- * emitter sees them, and an Extend typed for another input than its own
283
- * waiting (`ERR_TYPING`), which only the editor can tell
405
+ * emitter sees them; an Extend or a Filter by Expression checked for
406
+ * another input than its own waiting, and a filter its database would
407
+ * misread refused, which only the editor can tell
284
408
  */
285
409
  get analysis(): SchemaInferenceResult {
286
410
  return buildSchemasAndValidity(this.document.query, [
287
411
  ...this.registry.queryRules,
288
- this.staleExtendTyping,
412
+ this.staleEngineChecks,
413
+ this.databaseRefusals,
289
414
  ]);
290
415
  }
291
416
 
@@ -306,47 +431,50 @@ export class CubeEditorState implements CommandRegistrar {
306
431
  }
307
432
 
308
433
  /**
309
- * The Extends of the cube shown that wait for the engine to type their
310
- * columns, their input valid, and that aren't being typed (PLAN §11.7):
311
- * new expressions, or an input that changed
434
+ * The Extends and Filters by Expression of the cube shown that wait for
435
+ * the engine, their input valid, and that aren't being checked (PLAN §11.7,
436
+ * §11.11): new expressions, or an input that changed
312
437
  */
313
- get extendsToType(): readonly Extend[] {
438
+ get nodesToCheck(): readonly CubeEngineCheckedNode[] {
314
439
  const { validity } = this.analysis;
315
440
  return this.document.query.nodes.filter(
316
- (node): node is Extend =>
317
- node instanceof Extend &&
318
- !this.typingExtends.has(node) &&
441
+ (node): node is CubeEngineCheckedNode =>
442
+ isCubeEngineCheckedNode(node) &&
443
+ !this.checkingNodes.has(node) &&
319
444
  (validity.get(node.id) ?? []).some(isTypingError),
320
445
  );
321
446
  }
322
447
 
323
- /** The cube shown has Extends the engine is typing */
324
- get isTypingExtends(): boolean {
448
+ /** The cube shown has expressions the engine is checking: an Extend's columns, a filter's condition */
449
+ get isCheckingExpressions(): boolean {
325
450
  return this.document.query.nodes.some((node) =>
326
- this.typingExtends.has(node),
451
+ this.checkingNodes.has(node),
327
452
  );
328
453
  }
329
454
 
330
- /** The node waits for the engine to type it, or is being typed: an Extend (PLAN §11.7) */
455
+ /** The node waits for the engine to check it, or is being checked: an Extend or a Filter by Expression (PLAN §11.7, §11.11) */
331
456
  isTypingNode(node: QueryNode): boolean {
332
457
  return (
333
- this.typingExtends.has(node) ||
458
+ this.checkingNodes.has(node) ||
334
459
  (this.analysis.validity.get(node.id) ?? []).some(isTypingError)
335
460
  );
336
461
  }
337
462
 
338
463
  /**
339
- * Types Extends' columns with the engine, in one call, outside the undo
340
- * history (PLAN §11.7 Q4): each for the input it has now, its columns
341
- * after its input's relation, as typing types any node. The typing goes in
342
- * place of the very nodes sent, in the cube shown and the undo snapshots
343
- * that give the engine the same input; one the user changed meanwhile is
344
- * left to type again. Each typing records the input as the engine was given
345
- * it (`upstream`). A typing the engine couldn't give names the column it
346
- * failed on; when the engine can't be reached, a typing still current for
347
- * the input is kept, with a warning, as a source's saved columns are.
464
+ * Checks expressions with the engine, in one call, outside the undo history
465
+ * (PLAN §11.7 Q4, §11.11): an Extend's columns typed, a Filter by
466
+ * Expression's condition checked, each for the input it has now, after its
467
+ * input's relation, as typing types any node. The check goes in place of
468
+ * the very nodes sent, in the cube shown and the undo snapshots that give
469
+ * the engine the same input; one the user changed meanwhile is left to
470
+ * check again. Each check records the input as the engine was given it
471
+ * (`upstream`). A check the engine couldn't give says why; when the engine
472
+ * can't be reached, a check still current for the input is kept, with a
473
+ * warning, as a source's saved columns are.
348
474
  */
349
- *retypeExtends(nodes: readonly Extend[]): GeneratorFn<void> {
475
+ *checkExpressions(
476
+ nodes: readonly CubeEngineCheckedNode[],
477
+ ): GeneratorFn<void> {
350
478
  const { context, query } = this.document;
351
479
  if (!context) {
352
480
  return;
@@ -358,37 +486,25 @@ export class CubeEditorState implements CommandRegistrar {
358
486
  const input = inputId === undefined ? undefined : schemas.get(inputId);
359
487
  if (
360
488
  query.getNode(node.id) !== node ||
361
- this.typingExtends.has(node) ||
362
- !input ||
363
- node.columns.some(({ lambda }) => lambda === undefined)
489
+ this.checkingNodes.has(node) ||
490
+ !input
364
491
  ) {
365
492
  return [];
366
493
  }
367
- const columns = node.columns.map(({ name, lambda }) => ({
368
- name,
369
- lambda: lambda as JsonObject,
370
- }));
371
- return [
372
- {
373
- node,
374
- input,
375
- columns,
376
- upstream: getCubeExtendUpstream(emitter, node.id, context.model),
377
- lambdas: buildCubeExtendTypingLambdas(
378
- query,
379
- node,
380
- columns,
381
- this.registry,
382
- false,
383
- ),
384
- },
385
- ];
494
+ const request = buildCubeEngineCheckRequest(
495
+ query,
496
+ node,
497
+ input,
498
+ getCubeExtendUpstream(emitter, node.id, context.model),
499
+ this.registry,
500
+ );
501
+ return request ? [request] : [];
386
502
  });
387
503
  if (!requests.length) {
388
504
  return;
389
505
  }
390
- const sent = requests.map(({ node }) => node);
391
- this.typingExtends = new Set([...this.typingExtends, ...sent]);
506
+ const sent: readonly QueryNode[] = requests.map(({ node }) => node);
507
+ this.checkingNodes = new Set([...this.checkingNodes, ...sent]);
392
508
  let answers: ReadonlyMap<NodeId, Schema | CubeEngineError>;
393
509
  try {
394
510
  answers = (yield this.host.engine.typeLambdas(
@@ -409,41 +525,31 @@ export class CubeEditorState implements CommandRegistrar {
409
525
  ),
410
526
  );
411
527
  } finally {
412
- this.typingExtends = new Set(
413
- [...this.typingExtends].filter(
414
- (node) => !sent.includes(node as Extend),
415
- ),
528
+ this.checkingNodes = new Set(
529
+ [...this.checkingNodes].filter((node) => !sent.includes(node)),
416
530
  );
417
531
  }
418
- // a typing that comes back the same leaves its node, and the query, alone
532
+ // a check that comes back the same leaves its node, and the query, alone
419
533
  const warnings = new Map(this.warnings);
420
534
  const replacements = new Map<QueryNode, QueryNode>(
421
- requests.flatMap(({ node, input, columns, upstream }) => {
422
- const { typing, error } = readCubeExtendTyping(
423
- answers,
424
- node,
425
- input,
426
- columns,
427
- upstream,
428
- );
429
- if (
430
- error?.kind === CubeEngineErrorKind.NETWORK &&
431
- isCubeExtendTypingCurrent(node, input, upstream)
432
- ) {
433
- warnings.set(node.key, [getExtendRetypeWarning(error.firstLine)]);
535
+ requests.flatMap((request) => {
536
+ const { node } = request;
537
+ const outcome = request.read(answers);
538
+ if (outcome.keptWarning !== undefined) {
539
+ warnings.set(node.key, [outcome.keptWarning]);
434
540
  return [];
435
541
  }
436
542
  warnings.delete(node.key);
437
- return isSameCubeExtendTyping(typing, node.typing)
438
- ? []
439
- : [[node, node.withTyping(typing)] as const];
543
+ return outcome.node ? [[node, outcome.node] as const] : [];
440
544
  }),
441
545
  );
442
546
  this.warnings = warnings;
443
- // an undo snapshot whose input differs keeps the typing it had
547
+ // an undo snapshot whose input differs keeps the check it had
444
548
  const emitters = new Map<Query, QueryEmitter>([[query, emitter]]);
445
549
  this.replaceOutsideHistory(replacements, (snapshot, resolved) => {
446
- const upstream = getCubeExtendTypingUpstream((resolved as Extend).typing);
550
+ const upstream = getCubeEngineCheckUpstream(
551
+ resolved as CubeEngineCheckedNode,
552
+ );
447
553
  if (upstream === undefined) {
448
554
  return true;
449
555
  }
@@ -525,17 +631,31 @@ export class CubeEditorState implements CommandRegistrar {
525
631
  return model === undefined ? undefined : this.getModelOutline(model);
526
632
  }
527
633
 
634
+ /**
635
+ * A model's key for its outline: its JSON, so a cube imported on the same
636
+ * model, a new object with the same content, shares the outline loaded
637
+ */
638
+ private modelKey(model: ModelContext): string {
639
+ let key = this.modelKeys.get(model);
640
+ if (key === undefined) {
641
+ key = JSON.stringify(model);
642
+ this.modelKeys.set(model, key);
643
+ }
644
+ return key;
645
+ }
646
+
528
647
  /** The outline of a model, once loaded */
529
648
  getModelOutline(model: ModelContext): CubeModelOutline | undefined {
530
- return this.modelOutlines.get(model);
649
+ return this.modelOutlines.get(this.modelKey(model));
531
650
  }
532
651
 
533
652
  /**
534
653
  * The database type a run of the query up to the node needs, with the
535
- * model's runtime (PLAN §11.4), from the model's outline once it is loaded
536
- * (`loadModelOutline`): the type of the runtime's connections to the
537
- * databases the node reads. None without an outline, which writes every
538
- * operation the native way.
654
+ * model's runtime (PLAN §11.4): for a data product or ingest cube, the
655
+ * database its lakehouse runtime routes to (§11.12); else, from the model's
656
+ * outline once it is loaded (`loadModelOutline`), the type of the runtime's
657
+ * connections to the databases the node reads. None without an outline,
658
+ * which writes every operation the native way.
539
659
  */
540
660
  getRunDatabaseType(
541
661
  query: Query,
@@ -543,6 +663,9 @@ export class CubeEditorState implements CommandRegistrar {
543
663
  model: ModelContext,
544
664
  runtime: string,
545
665
  ): string | undefined {
666
+ if (isCubeDataProductModel(model) || isCubeIngestModel(model)) {
667
+ return getLakehouseDatabaseType(CUBE_LAKEHOUSE_RUNTIME_KIND);
668
+ }
546
669
  const outline = this.getModelOutline(model);
547
670
  if (!outline) {
548
671
  return undefined;
@@ -552,6 +675,11 @@ export class CubeEditorState implements CommandRegistrar {
552
675
  const node = query.getNode(id);
553
676
  if (node instanceof RelationalTableSource) {
554
677
  databases.add(node.database);
678
+ } else if (node instanceof FunctionSource) {
679
+ // a function reads what Cube can't see: any database of the runtime
680
+ outline.runtimes
681
+ .find(({ path }) => path === runtime)
682
+ ?.connections?.forEach(({ storePath }) => databases.add(storePath));
555
683
  }
556
684
  query
557
685
  .getInputIds(id)
@@ -562,32 +690,85 @@ export class CubeEditorState implements CommandRegistrar {
562
690
  }
563
691
 
564
692
  /**
565
- * Loads the outline of a model, the cube's by default, once per model. It
566
- * only adds warnings and database types, so a model that fails to load
567
- * shows none and runs every operation the native way.
693
+ * A node's problems on the database the query up to it runs on, with the
694
+ * cube's runtime (`getRunDatabaseType`): a Pivot where it can't run (PLAN
695
+ * §11.12); a filter giving `%` or `_` to a pattern on DuckDB, which would
696
+ * match them as wildcards (§11.11). None when the database isn't known.
697
+ */
698
+ getNodeDatabaseProblems(query: Query, node: QueryNode): string[] {
699
+ const { context } = this.document;
700
+ const runtime = context?.runtime;
701
+ if (!context || runtime === undefined || !dependsOnDatabaseType(node)) {
702
+ return [];
703
+ }
704
+ return getDatabaseProblems(
705
+ node,
706
+ this.getRunDatabaseType(query, node.id, context.model, runtime),
707
+ );
708
+ }
709
+
710
+ /**
711
+ * Why a node of the type can't be added after the node, on the database the
712
+ * query up to that node runs on (PLAN §11.12): a Pivot where it can't run.
713
+ * `undefined` when it can, or the database isn't known.
714
+ */
715
+ getAddDatabaseProblem(
716
+ type: string,
717
+ afterId: string | undefined,
718
+ ): string | undefined {
719
+ const { context, query } = this.document;
720
+ const runtime = context?.runtime;
721
+ if (!context || runtime === undefined || afterId === undefined) {
722
+ return undefined;
723
+ }
724
+ return getDatabaseProblemOfType(
725
+ type,
726
+ this.getRunDatabaseType(query, afterId, context.model, runtime),
727
+ );
728
+ }
729
+
730
+ /**
731
+ * Loads the outline of a model, the cube's by default, once per model: a
732
+ * load already on its way is waited for, not started again, e.g. a run's
733
+ * while the cube's opening load is still out. It only adds warnings,
734
+ * database types and a database's refusals (PLAN §11.11, §11.12), so a
735
+ * model that fails to load shows none and runs every operation the native
736
+ * way.
568
737
  */
569
738
  *loadModelOutline(
570
739
  model: ModelContext | undefined = this.document.context?.model,
571
740
  ): GeneratorFn<void> {
572
- if (model === undefined || this.modelOutlines.has(model)) {
741
+ if (model === undefined) {
573
742
  return;
574
743
  }
744
+ const key = this.modelKey(model);
745
+ if (this.modelOutlines.has(key)) {
746
+ return;
747
+ }
748
+ let loading = this.loadingOutlines.get(key);
749
+ if (!loading) {
750
+ loading = loadCubeModelOutline(this.host, model);
751
+ this.loadingOutlines.set(key, loading);
752
+ }
575
753
  try {
576
- const outline = (yield loadCubeModelOutline(
577
- this.host,
578
- model,
579
- )) as CubeModelOutline;
580
- this.modelOutlines = new Map([...this.modelOutlines, [model, outline]]);
754
+ const outline = (yield loading) as CubeModelOutline;
755
+ if (!this.modelOutlines.has(key)) {
756
+ this.modelOutlines = new Map([...this.modelOutlines, [key, outline]]);
757
+ }
581
758
  } catch {
582
759
  // no outline, no warning: nothing is blocked on it
760
+ } finally {
761
+ this.loadingOutlines.delete(key);
583
762
  }
584
763
  }
585
764
 
586
- /** One of Cube's dialogs is open: the source picker, Import or Export, Show Pure */
765
+ /** One of Cube's dialogs is open: the source picker, Examples, the group rows' settings, Import or Export, Show Pure */
587
766
  get isDialogOpen(): boolean {
588
767
  return (
589
768
  this.sourcePicker.isOpen ||
590
769
  this.examples.isOpen ||
770
+ this.grid.isSettingsShown ||
771
+ this.grid.formatColumn !== undefined ||
591
772
  this.specTransfer.mode !== undefined ||
592
773
  this.showPure.isOpen
593
774
  );
@@ -617,7 +798,7 @@ export class CubeEditorState implements CommandRegistrar {
617
798
  isFocusInNodeEditor(),
618
799
  ),
619
800
  });
620
- // F10 in the Extend editor (PLAN §11.7)
801
+ // F10 in the Extend and Filter by Expression editors (PLAN §11.7, §11.11)
621
802
  commandService.registerCommand({
622
803
  key: LEGEND_CUBE_COMMAND_KEY.VALIDATE_EXPRESSIONS,
623
804
  trigger: () => {
@@ -625,19 +806,36 @@ export class CubeEditorState implements CommandRegistrar {
625
806
  return (
626
807
  !this.isDialogOpen &&
627
808
  !this.readOnly &&
628
- draft instanceof CubeExtendDraft &&
809
+ (draft instanceof CubeExtendDraft ||
810
+ draft instanceof CubeExpressionFilterDraft) &&
629
811
  !draft.validating
630
812
  );
631
813
  },
632
814
  action: () => {
633
815
  const { draft } = this.nodeEditor;
634
- if (draft instanceof CubeExtendDraft) {
816
+ if (
817
+ draft instanceof CubeExtendDraft ||
818
+ draft instanceof CubeExpressionFilterDraft
819
+ ) {
635
820
  flowResult(draft.validate()).catch(
636
821
  this.host.applicationStore.alertUnhandledError,
637
822
  );
638
823
  }
639
824
  },
640
825
  });
826
+ commandService.registerCommand({
827
+ key: LEGEND_CUBE_COMMAND_KEY.REDO,
828
+ trigger: () =>
829
+ !this.isDialogOpen &&
830
+ !this.nodeEditor.isHeld &&
831
+ this.canRedo &&
832
+ !isTypingText(),
833
+ action: () =>
834
+ this.nodeEditor.runFromKeyboard(
835
+ () => this.redoEdited(),
836
+ isFocusInNodeEditor(),
837
+ ),
838
+ });
641
839
  commandService.registerCommand({
642
840
  key: LEGEND_CUBE_COMMAND_KEY.UNDO,
643
841
  trigger: () =>
@@ -694,6 +892,10 @@ export class CubeEditorState implements CommandRegistrar {
694
892
  return this.history.length > 0 && !this.readOnly;
695
893
  }
696
894
 
895
+ get canRedo(): boolean {
896
+ return this.redoStack.length > 0;
897
+ }
898
+
697
899
  /** The one way to change the cube; the document before goes to the undo history */
698
900
  applyDocument(next: CubeDocument): void {
699
901
  if (next === this.document) {
@@ -709,6 +911,41 @@ export class CubeEditorState implements CommandRegistrar {
709
911
  * without applying its edits, and drops the last run's rows and errors,
710
912
  * which belong to the cube before. Never runs the cube.
711
913
  */
914
+ /** Whether the cube is a new one: no name, no context, no node */
915
+ get isEmptyCube(): boolean {
916
+ const { document } = this;
917
+ return (
918
+ document.name === undefined &&
919
+ document.context === undefined &&
920
+ document.query.nodes.length === 0
921
+ );
922
+ }
923
+
924
+ /**
925
+ * Replaces the cube with a new, empty one, as an import does (one undo
926
+ * step, so Undo brings the cube back); a cube already new is left as it is
927
+ */
928
+ startNewCube(): void {
929
+ if (!this.isEmptyCube) {
930
+ this.importDocument(new CubeDocument(), false);
931
+ }
932
+ }
933
+
934
+ /**
935
+ * Opens the page on a cube read for it, as `initialDocument` opens one:
936
+ * no undo step, as there was no cube before it (Import Pure's
937
+ * `initialLambda`, PLAN §11.18). Its sources come typed; its expressions
938
+ * are checked as any are.
939
+ */
940
+ openDocument(next: CubeDocument): void {
941
+ this.execution.reset();
942
+ this.sourcePicker.close();
943
+ this.nodeEditor.discard(CUBE_EDITOR_CLOSED_REASON.CUBE_REPLACED);
944
+ this.hostIssues = new Map();
945
+ this.document = next;
946
+ this.readOnly = false;
947
+ }
948
+
712
949
  importDocument(next: CubeDocument, readOnly: boolean): void {
713
950
  this.pushHistory();
714
951
  this.importedOver.add(this.document);
@@ -723,14 +960,10 @@ export class CubeEditorState implements CommandRegistrar {
723
960
  flowResult(this.reresolveSources()).catch(
724
961
  this.host.applicationStore.alertUnhandledError,
725
962
  );
726
- // typed once on load too, as sources are checked again: the model may
727
- // have changed the types of its functions (PLAN §11.7)
963
+ // checked once on load too, as sources are checked again: the model may
964
+ // have changed the types of its functions (PLAN §11.7, §11.11)
728
965
  flowResult(
729
- this.retypeExtends(
730
- next.query.nodes.filter(
731
- (node): node is Extend => node instanceof Extend,
732
- ),
733
- ),
966
+ this.checkExpressions(next.query.nodes.filter(isCubeEngineCheckedNode)),
734
967
  ).catch(this.host.applicationStore.alertUnhandledError);
735
968
  }
736
969
 
@@ -784,10 +1017,27 @@ export class CubeEditorState implements CommandRegistrar {
784
1017
  node instanceof IngestDatasetSource,
785
1018
  )
786
1019
  : [];
1020
+ // a function on another kind of cube is the no-mix rule's to flag
1021
+ const functions =
1022
+ isCubeDataProductModel(context.model) ||
1023
+ isCubeIngestModel(context.model) ||
1024
+ isCubeServiceModel(context.model)
1025
+ ? []
1026
+ : kept.filter(
1027
+ (node): node is FunctionSource => node instanceof FunctionSource,
1028
+ );
1029
+ // services are typed in one place, still to come (PLAN §6.4)
1030
+ const services = isCubeServiceModel(context.model)
1031
+ ? kept.filter(
1032
+ (node): node is ServiceSource => node instanceof ServiceSource,
1033
+ )
1034
+ : [];
787
1035
  const sources: readonly RecheckedSource[] = [
788
1036
  ...tables,
1037
+ ...functions,
789
1038
  ...accessPoints,
790
1039
  ...dataSets,
1040
+ ...services,
791
1041
  ];
792
1042
  if (!sources.length) {
793
1043
  return;
@@ -795,53 +1045,72 @@ export class CubeEditorState implements CommandRegistrar {
795
1045
  this.pendingSources = new Set([...this.pendingSources, ...sources]);
796
1046
  let answers: ReadonlyMap<string, Schema | CubeEngineError>;
797
1047
  try {
798
- const [tableAnswers, accessPointAnswers, dataSetAnswers] =
799
- (yield Promise.all([
800
- tables.length
801
- ? this.host.engine
802
- .resolveSchemas(
803
- context.model,
804
- new Map(
805
- tables.map((source) => [
806
- source.id,
807
- [source.database, source.schema, source.table],
808
- ]),
809
- ),
810
- )
811
- .catch((error: unknown) => {
812
- const failure =
813
- error instanceof CubeEngineError
814
- ? error
815
- : new CubeEngineError(
816
- CubeEngineErrorKind.NETWORK,
817
- error instanceof Error
818
- ? error.message
819
- : String(error),
820
- );
821
- return new Map(tables.map((source) => [source.id, failure]));
822
- })
823
- : new Map(),
824
- accessPoints.length
825
- ? recheckCubeDataProductSources(
826
- this.host.dataProductCatalog,
1048
+ const [
1049
+ tableAnswers,
1050
+ accessPointAnswers,
1051
+ dataSetAnswers,
1052
+ serviceAnswers,
1053
+ functionAnswers,
1054
+ ] = (yield Promise.all([
1055
+ tables.length
1056
+ ? this.host.engine
1057
+ .resolveSchemas(
827
1058
  context.model,
828
- accessPoints,
829
- fresh,
830
- )
831
- : new Map(),
832
- dataSets.length
833
- ? recheckCubeIngestSources(
834
- this.host.ingestCatalog,
835
- context.model,
836
- dataSets,
837
- fresh,
1059
+ new Map(
1060
+ tables.map((source) => [
1061
+ source.id,
1062
+ [source.database, source.schema, source.table],
1063
+ ]),
1064
+ ),
838
1065
  )
839
- : new Map(),
840
- ])) as ReadonlyMap<string, Schema | CubeEngineError>[];
1066
+ .catch((error: unknown) => {
1067
+ const failure =
1068
+ error instanceof CubeEngineError
1069
+ ? error
1070
+ : new CubeEngineError(
1071
+ CubeEngineErrorKind.NETWORK,
1072
+ error instanceof Error ? error.message : String(error),
1073
+ );
1074
+ return new Map(tables.map((source) => [source.id, failure]));
1075
+ })
1076
+ : new Map(),
1077
+ accessPoints.length
1078
+ ? recheckCubeDataProductSources(
1079
+ this.host.dataProductCatalog,
1080
+ context.model,
1081
+ accessPoints,
1082
+ fresh,
1083
+ )
1084
+ : new Map(),
1085
+ dataSets.length
1086
+ ? recheckCubeIngestSources(
1087
+ this.host.ingestCatalog,
1088
+ context.model,
1089
+ dataSets,
1090
+ fresh,
1091
+ )
1092
+ : new Map(),
1093
+ services.length
1094
+ ? recheckCubeServiceSources(
1095
+ this.host.serviceCatalog,
1096
+ context.model,
1097
+ services,
1098
+ )
1099
+ : new Map(),
1100
+ functions.length
1101
+ ? recheckCubeFunctionSources(
1102
+ this.host.engine,
1103
+ context.model,
1104
+ functions,
1105
+ )
1106
+ : new Map(),
1107
+ ])) as ReadonlyMap<string, Schema | CubeEngineError>[];
841
1108
  answers = new Map([
842
1109
  ...(tableAnswers ?? []),
843
1110
  ...(accessPointAnswers ?? []),
844
1111
  ...(dataSetAnswers ?? []),
1112
+ ...(serviceAnswers ?? []),
1113
+ ...(functionAnswers ?? []),
845
1114
  ]);
846
1115
  } finally {
847
1116
  this.pendingSources = new Set(
@@ -856,6 +1125,7 @@ export class CubeEditorState implements CommandRegistrar {
856
1125
  sources.forEach((source) => {
857
1126
  const isAccessPoint = source instanceof DataProductAccessPointSource;
858
1127
  const isDataSet = source instanceof IngestDatasetSource;
1128
+ const isFunction = source instanceof FunctionSource;
859
1129
  const answer =
860
1130
  answers.get(source.id) ??
861
1131
  new CubeEngineError(
@@ -864,7 +1134,9 @@ export class CubeEditorState implements CommandRegistrar {
864
1134
  ? CUBE_DATA_PRODUCT_RECHECK_MESSAGE.NO_ANSWER
865
1135
  : isDataSet
866
1136
  ? CUBE_INGEST_RECHECK_MESSAGE.NO_ANSWER
867
- : 'The engine gave no schema for this table',
1137
+ : isFunction
1138
+ ? CUBE_FUNCTION_MESSAGE.NO_ANSWER
1139
+ : 'The engine gave no schema for this table',
868
1140
  source.id,
869
1141
  );
870
1142
  const saved =
@@ -878,7 +1150,9 @@ export class CubeEditorState implements CommandRegistrar {
878
1150
  ? getAccessPointRecheckWarning(answer.firstLine)
879
1151
  : isDataSet
880
1152
  ? getDataSetRecheckWarning(answer.firstLine)
881
- : getSourceRecheckWarning(answer.firstLine),
1153
+ : isFunction
1154
+ ? getFunctionRecheckWarning(answer.firstLine)
1155
+ : getSourceRecheckWarning(answer.firstLine),
882
1156
  ]);
883
1157
  } else if (
884
1158
  source.resolution.kind !== 'failed' ||
@@ -907,7 +1181,9 @@ export class CubeEditorState implements CommandRegistrar {
907
1181
  ? getAccessPointDriftWarning(diff)
908
1182
  : isDataSet
909
1183
  ? getDataSetDriftWarning(diff)
910
- : getSchemaDriftWarning(diff),
1184
+ : isFunction
1185
+ ? getFunctionDriftWarning(diff)
1186
+ : getSchemaDriftWarning(diff),
911
1187
  ]);
912
1188
  }
913
1189
  replacements.set(source, resolved);
@@ -964,6 +1240,11 @@ export class CubeEditorState implements CommandRegistrar {
964
1240
  return next;
965
1241
  };
966
1242
  this.history = this.history.map(check);
1243
+ // a change undone meanwhile is redone with the checked nodes too
1244
+ this.redoStack = this.redoStack.map((entry) => ({
1245
+ ...entry,
1246
+ document: check(entry.document),
1247
+ }));
967
1248
  const next = check(this.document);
968
1249
  if (next !== this.document) {
969
1250
  this.replaceDocument(next);
@@ -981,7 +1262,9 @@ export class CubeEditorState implements CommandRegistrar {
981
1262
  if (
982
1263
  source instanceof RelationalTableSource ||
983
1264
  source instanceof DataProductAccessPointSource ||
984
- source instanceof IngestDatasetSource
1265
+ source instanceof IngestDatasetSource ||
1266
+ source instanceof ServiceSource ||
1267
+ source instanceof FunctionSource
985
1268
  ) {
986
1269
  // a Refresh reads the deployed artifact or definition again
987
1270
  yield flowResult(this.reresolveSources([source], true));
@@ -1003,25 +1286,91 @@ export class CubeEditorState implements CommandRegistrar {
1003
1286
  return;
1004
1287
  }
1005
1288
  this.history = this.history.slice(0, -1);
1289
+ this.redoStack = [
1290
+ ...this.redoStack,
1291
+ {
1292
+ document: this.document,
1293
+ readOnly: this.readOnly,
1294
+ opensAnotherCube: this.importedOver.has(previous),
1295
+ },
1296
+ ];
1006
1297
  this.readOnly = this.readOnlyDocuments.has(previous);
1007
1298
  if (this.importedOver.has(previous)) {
1008
1299
  // the cube before an import is another cube, as the import was
1009
1300
  this.sourcePicker.close();
1010
1301
  this.nodeEditor.discard(CUBE_EDITOR_CLOSED_REASON.CUBE_REPLACED);
1011
1302
  }
1012
- const { query } = this.document;
1303
+ const { query, meta } = this.document;
1304
+ const restored = previous.withQuery(
1305
+ previous.query === query ? query : previous.query.clone(),
1306
+ );
1307
+ // widths take no undo step, so the same cube keeps the ones set since
1308
+ // (review of M7); the cube before an import keeps its own
1309
+ this.replaceDocument(
1310
+ this.importedOver.has(previous)
1311
+ ? restored
1312
+ : restored.withMeta({
1313
+ ...restored.meta,
1314
+ presentation: {
1315
+ ...restored.meta.presentation,
1316
+ columnWidths: meta.presentation.columnWidths,
1317
+ },
1318
+ }),
1319
+ );
1320
+ }
1321
+
1322
+ /**
1323
+ * Brings back the last change undone, as Ctrl+Shift+Z does: the cube shown
1324
+ * goes back to the undo history, and a change that opened another cube
1325
+ * (an import, New) closes the editor and the source dialog again
1326
+ */
1327
+ redo(): void {
1328
+ const next = this.redoStack.at(-1);
1329
+ if (!next) {
1330
+ return;
1331
+ }
1332
+ this.redoStack = this.redoStack.slice(0, -1);
1333
+ this.pushHistory(true);
1334
+ if (next.opensAnotherCube) {
1335
+ this.importedOver.add(this.history.at(-1) as CubeDocument);
1336
+ this.sourcePicker.close();
1337
+ this.nodeEditor.discard(CUBE_EDITOR_CLOSED_REASON.CUBE_REPLACED);
1338
+ }
1339
+ this.readOnly = next.readOnly;
1340
+ const { query, meta } = this.document;
1341
+ const restored = next.document.withQuery(
1342
+ next.document.query === query ? query : next.document.query.clone(),
1343
+ );
1344
+ // widths take no undo step: the same cube keeps the ones set since
1013
1345
  this.replaceDocument(
1014
- previous.withQuery(
1015
- previous.query === query ? query : previous.query.clone(),
1016
- ),
1346
+ next.opensAnotherCube
1347
+ ? restored
1348
+ : restored.withMeta({
1349
+ ...restored.meta,
1350
+ presentation: {
1351
+ ...restored.meta.presentation,
1352
+ columnWidths: meta.presentation.columnWidths,
1353
+ },
1354
+ }),
1017
1355
  );
1018
1356
  }
1019
1357
 
1020
- private pushHistory(): void {
1358
+ /** Redo, as its button and Ctrl+Shift+Z do: finishes the node editor first */
1359
+ redoEdited(): void {
1360
+ if (this.nodeEditor.finishApplied() && this.canRedo) {
1361
+ this.redo();
1362
+ }
1363
+ }
1364
+
1365
+ /** Keeps the cube shown for undo; a new change, not a redo, drops what was undone */
1366
+ private pushHistory(keepRedo = false): void {
1021
1367
  if (this.readOnly) {
1022
1368
  this.readOnlyDocuments.add(this.document);
1023
1369
  }
1024
1370
  this.history = [...this.history, this.document].slice(-MAX_UNDO_STEPS);
1371
+ if (!keepRedo) {
1372
+ this.redoStack = [];
1373
+ }
1025
1374
  }
1026
1375
 
1027
1376
  /**
@@ -1063,17 +1412,43 @@ export class CubeEditorState implements CommandRegistrar {
1063
1412
  }
1064
1413
 
1065
1414
  /**
1066
- * The kinds of source the host serves: data products and ingest data sets
1067
- * only with their catalogs. The cube's kind may still disable one
1068
- * (`canAddNode`)
1415
+ * The kinds of source the host serves: data products, ingest data sets and
1416
+ * services only with their catalogs, tables and functions only with a tab
1417
+ * that reads them (Studio offers ingest data sets alone). The cube's kind
1418
+ * may still disable one (`canAddNode`)
1069
1419
  */
1070
1420
  get offeredSources(): readonly SourceDefinition[] {
1071
- return this.registry.sources.filter(
1072
- (definition) =>
1073
- (definition.type !== DataProductAccessPointSource.TYPE ||
1074
- this.sourcePicker.dataProductTab.isAvailable) &&
1075
- (definition.type !== IngestDatasetSource.TYPE ||
1076
- this.sourcePicker.ingestTab.isAvailable),
1421
+ const {
1422
+ modelTab,
1423
+ projectTab,
1424
+ projectFunctionTab,
1425
+ directTab,
1426
+ dataProductTab,
1427
+ ingestTab,
1428
+ serviceTab,
1429
+ } = this.sourcePicker;
1430
+ const isServed = (type: string): boolean => {
1431
+ switch (type) {
1432
+ case DataProductAccessPointSource.TYPE:
1433
+ return dataProductTab.isAvailable;
1434
+ case IngestDatasetSource.TYPE:
1435
+ return ingestTab.isAvailable;
1436
+ case ServiceSource.TYPE:
1437
+ return serviceTab.isAvailable;
1438
+ case FunctionSource.TYPE:
1439
+ return modelTab.isAvailable || projectFunctionTab.isAvailable;
1440
+ case RelationalTableSource.TYPE:
1441
+ return (
1442
+ modelTab.isAvailable ||
1443
+ projectTab.isAvailable ||
1444
+ directTab.isAvailable
1445
+ );
1446
+ default:
1447
+ return true;
1448
+ }
1449
+ };
1450
+ return this.registry.sources.filter((definition) =>
1451
+ isServed(definition.type),
1077
1452
  );
1078
1453
  }
1079
1454
 
@@ -1108,19 +1483,19 @@ export class CubeEditorState implements CommandRegistrar {
1108
1483
  * after `afterId`; a source opens the source picker, which adds it once
1109
1484
  * the engine has typed it. Does nothing `canAddNode` refuses.
1110
1485
  */
1111
- addNode(type: string, afterId?: string): void {
1486
+ addNode(type: string, afterId?: string): string | undefined {
1112
1487
  const definition = this.registry.get(type);
1113
1488
  if (!definition || !this.canAddNode(type, afterId)) {
1114
- return;
1489
+ return undefined;
1115
1490
  }
1116
1491
  if (definition.kind === 'source') {
1117
- this.sourcePicker.open(this.sourcePicker.tabForSourceType(type)?.key);
1118
- return;
1492
+ this.sourcePicker.openForSourceType(type);
1493
+ return undefined;
1119
1494
  }
1120
1495
  const { query } = this.document;
1121
- this.applyQuery(
1122
- query.add(definition.create(query.generateId(type)), afterId),
1123
- );
1496
+ const id = query.generateId(type);
1497
+ this.applyQuery(query.add(definition.create(id), afterId));
1498
+ return id;
1124
1499
  }
1125
1500
 
1126
1501
  /**
@@ -1184,6 +1559,95 @@ export class CubeEditorState implements CommandRegistrar {
1184
1559
  );
1185
1560
  }
1186
1561
 
1562
+ /** Whether a step can be copied: a known type's, so its copy reads back */
1563
+ canCopyNode(nodeId: string): boolean {
1564
+ const node = this.document.query.getNode(nodeId);
1565
+ return node !== undefined && this.registry.get(node.type) !== undefined;
1566
+ }
1567
+
1568
+ /** Copies a step, as Cmd/Ctrl+C on it does, for Paste */
1569
+ copyNode(nodeId: string): void {
1570
+ const node = this.document.query.getNode(nodeId);
1571
+ if (node && this.canCopyNode(nodeId)) {
1572
+ this.copiedNode = { node, context: this.document.context };
1573
+ }
1574
+ }
1575
+
1576
+ /**
1577
+ * Whether the step copied can be pasted here: a transform always; a source
1578
+ * only into a cube of the same model and runtime, or an empty cube, which
1579
+ * takes them, as a first table does
1580
+ */
1581
+ get canPaste(): boolean {
1582
+ const copied = this.copiedNode;
1583
+ return (
1584
+ copied !== undefined &&
1585
+ !this.readOnly &&
1586
+ this.canTakeCopy(copied.node, copied.context)
1587
+ );
1588
+ }
1589
+
1590
+ /** Pastes the step copied: after the step given when it takes an input, else on its own; one undo step */
1591
+ pasteNode(afterId?: string): void {
1592
+ const copied = this.copiedNode;
1593
+ if (copied && this.canPaste) {
1594
+ this.addCopy(copied.node, copied.context, afterId);
1595
+ }
1596
+ }
1597
+
1598
+ canDuplicateNode(nodeId: string): boolean {
1599
+ return !this.readOnly && this.canCopyNode(nodeId);
1600
+ }
1601
+
1602
+ /** A copy of the step after it, as Cmd/Ctrl+D does, leaving the step copied for Paste as it was */
1603
+ duplicateNode(nodeId: string): void {
1604
+ const node = this.document.query.getNode(nodeId);
1605
+ if (node && this.canDuplicateNode(nodeId)) {
1606
+ this.addCopy(node, this.document.context, nodeId);
1607
+ }
1608
+ }
1609
+
1610
+ private canTakeCopy(
1611
+ node: QueryNode,
1612
+ context: CubeContext | undefined,
1613
+ ): boolean {
1614
+ if (!(node instanceof SourceNode)) {
1615
+ return true;
1616
+ }
1617
+ const { document } = this;
1618
+ return (
1619
+ document.query.isEmpty ||
1620
+ JSON.stringify(document.context) === JSON.stringify(context)
1621
+ );
1622
+ }
1623
+
1624
+ private addCopy(
1625
+ node: QueryNode,
1626
+ context: CubeContext | undefined,
1627
+ afterId?: string,
1628
+ ): void {
1629
+ const { document } = this;
1630
+ const copy = copyQueryNode(
1631
+ node,
1632
+ document.query.generateId(node.type),
1633
+ this.registry,
1634
+ );
1635
+ if (!copy) {
1636
+ return;
1637
+ }
1638
+ const after =
1639
+ afterId !== undefined && document.query.canAdd(copy, afterId)
1640
+ ? afterId
1641
+ : undefined;
1642
+ const query = document.query.add(copy, after);
1643
+ // a source pasted into an empty cube brings its model and runtime
1644
+ this.applyDocument(
1645
+ copy instanceof SourceNode && document.query.isEmpty && context
1646
+ ? document.withContext(context).withQuery(query)
1647
+ : document.withQuery(query),
1648
+ );
1649
+ }
1650
+
1187
1651
  canSwapInputs(nodeId: string): boolean {
1188
1652
  return !this.readOnly && this.document.query.canSwapInputs(nodeId);
1189
1653
  }
@@ -1211,6 +1675,31 @@ export class CubeEditorState implements CommandRegistrar {
1211
1675
  }
1212
1676
  }
1213
1677
 
1678
+ /**
1679
+ * Keeps a grid column's width, which the cube saves (PLAN §11.10): by the
1680
+ * column's name, in any case. Presentation the user sets by dragging, so
1681
+ * no undo step, and the rows stay current.
1682
+ */
1683
+ setColumnWidth(column: string, width: number): void {
1684
+ if (!Number.isFinite(width) || width <= 0) {
1685
+ return;
1686
+ }
1687
+ const { meta } = this.document;
1688
+ const { presentation } = meta;
1689
+ const others = presentation.columnWidths.filter(
1690
+ (each) => foldColumnName(each.column) !== foldColumnName(column),
1691
+ );
1692
+ this.replaceDocument(
1693
+ this.document.withMeta({
1694
+ ...meta,
1695
+ presentation: {
1696
+ ...presentation,
1697
+ columnWidths: [...others, { column, width: Math.round(width) }],
1698
+ },
1699
+ }),
1700
+ );
1701
+ }
1702
+
1214
1703
  setHostIssue(nodeId: string, error: CubeEngineError): void {
1215
1704
  this.hostIssues = new Map([
1216
1705
  ...this.hostIssues,
@@ -1248,7 +1737,8 @@ export class CubeEditorState implements CommandRegistrar {
1248
1737
 
1249
1738
  /** Stops any run; call when the page closes */
1250
1739
  dispose(): void {
1251
- this.retyping();
1740
+ this.rechecking();
1741
+ this.outlineLoading();
1252
1742
  this.execution.stop();
1253
1743
  this.nodeEditor.dispose();
1254
1744
  }