@finos/legend-data-cube 0.0.35 → 0.0.37

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 (138) hide show
  1. package/README.md +1 -1
  2. package/lib/__lib__/DataCubeEvent.d.ts +21 -0
  3. package/lib/__lib__/DataCubeEvent.d.ts.map +1 -0
  4. package/lib/__lib__/DataCubeEvent.js +22 -0
  5. package/lib/__lib__/DataCubeEvent.js.map +1 -0
  6. package/lib/components/DataCube.d.ts +3 -1
  7. package/lib/components/DataCube.d.ts.map +1 -1
  8. package/lib/components/DataCube.js +10 -9
  9. package/lib/components/DataCube.js.map +1 -1
  10. package/lib/components/DataCubeProvider.js +1 -1
  11. package/lib/components/DataCubeProvider.js.map +1 -1
  12. package/lib/components/core/DataCubeAlert.d.ts +3 -2
  13. package/lib/components/core/DataCubeAlert.d.ts.map +1 -1
  14. package/lib/components/core/DataCubeAlert.js +4 -2
  15. package/lib/components/core/DataCubeAlert.js.map +1 -1
  16. package/lib/components/core/DataCubeFormUtils.d.ts +26 -0
  17. package/lib/components/core/DataCubeFormUtils.d.ts.map +1 -1
  18. package/lib/components/core/DataCubeFormUtils.js +127 -4
  19. package/lib/components/core/DataCubeFormUtils.js.map +1 -1
  20. package/lib/components/core/DataCubeLayoutManager.js +1 -1
  21. package/lib/components/core/DataCubeLayoutManager.js.map +1 -1
  22. package/lib/components/core/DataCubeSettingsPanel.d.ts.map +1 -1
  23. package/lib/components/core/DataCubeSettingsPanel.js +53 -27
  24. package/lib/components/core/DataCubeSettingsPanel.js.map +1 -1
  25. package/lib/components/view/editor/DataCubeEditor.d.ts.map +1 -1
  26. package/lib/components/view/editor/DataCubeEditor.js +6 -5
  27. package/lib/components/view/editor/DataCubeEditor.js.map +1 -1
  28. package/lib/components/view/editor/DataCubeEditorColumnPropertiesPanel.d.ts.map +1 -1
  29. package/lib/components/view/editor/DataCubeEditorColumnPropertiesPanel.js +4 -4
  30. package/lib/components/view/editor/DataCubeEditorColumnPropertiesPanel.js.map +1 -1
  31. package/lib/components/view/editor/DataCubeEditorGeneralPropertiesPanel.d.ts.map +1 -1
  32. package/lib/components/view/editor/DataCubeEditorGeneralPropertiesPanel.js +2 -2
  33. package/lib/components/view/editor/DataCubeEditorGeneralPropertiesPanel.js.map +1 -1
  34. package/lib/components/view/extend/DataCubeColumnEditor.d.ts.map +1 -1
  35. package/lib/components/view/extend/DataCubeColumnEditor.js +12 -12
  36. package/lib/components/view/extend/DataCubeColumnEditor.js.map +1 -1
  37. package/lib/components/view/filter/DataCubeFilterEditor.d.ts.map +1 -1
  38. package/lib/components/view/filter/DataCubeFilterEditor.js +4 -4
  39. package/lib/components/view/filter/DataCubeFilterEditor.js.map +1 -1
  40. package/lib/components/view/grid/DataCubeGrid.d.ts.map +1 -1
  41. package/lib/components/view/grid/DataCubeGrid.js +7 -7
  42. package/lib/components/view/grid/DataCubeGrid.js.map +1 -1
  43. package/lib/index.css +1 -1
  44. package/lib/index.d.ts +7 -2
  45. package/lib/index.d.ts.map +1 -1
  46. package/lib/index.js +7 -2
  47. package/lib/index.js.map +1 -1
  48. package/lib/package.json +2 -2
  49. package/lib/stores/DataCubeOptions.d.ts +6 -5
  50. package/lib/stores/DataCubeOptions.d.ts.map +1 -1
  51. package/lib/stores/DataCubeSettings.d.ts +25 -22
  52. package/lib/stores/DataCubeSettings.d.ts.map +1 -1
  53. package/lib/stores/DataCubeSettings.js +250 -62
  54. package/lib/stores/DataCubeSettings.js.map +1 -1
  55. package/lib/stores/DataCubeState.d.ts +8 -5
  56. package/lib/stores/DataCubeState.d.ts.map +1 -1
  57. package/lib/stores/DataCubeState.js +27 -42
  58. package/lib/stores/DataCubeState.js.map +1 -1
  59. package/lib/stores/core/DataCubeEngine.d.ts +15 -18
  60. package/lib/stores/core/DataCubeEngine.d.ts.map +1 -1
  61. package/lib/stores/core/DataCubeEngine.js +5 -16
  62. package/lib/stores/core/DataCubeEngine.js.map +1 -1
  63. package/lib/stores/core/DataCubeQueryBuilder.d.ts +1 -0
  64. package/lib/stores/core/DataCubeQueryBuilder.d.ts.map +1 -1
  65. package/lib/stores/core/DataCubeQueryBuilder.js.map +1 -1
  66. package/lib/stores/core/DataCubeQueryBuilderUtils.d.ts +3 -0
  67. package/lib/stores/core/DataCubeQueryBuilderUtils.d.ts.map +1 -1
  68. package/lib/stores/core/DataCubeQueryBuilderUtils.js +12 -1
  69. package/lib/stores/core/DataCubeQueryBuilderUtils.js.map +1 -1
  70. package/lib/stores/core/DataCubeQuerySnapshotBuilder.d.ts.map +1 -1
  71. package/lib/stores/core/DataCubeQuerySnapshotBuilder.js +46 -30
  72. package/lib/stores/core/DataCubeQuerySnapshotBuilder.js.map +1 -1
  73. package/lib/stores/core/DataCubeSetting.d.ts +51 -0
  74. package/lib/stores/core/DataCubeSetting.d.ts.map +1 -0
  75. package/lib/stores/core/DataCubeSetting.js +36 -0
  76. package/lib/stores/core/DataCubeSetting.js.map +1 -0
  77. package/lib/stores/core/models/AdhocQueryDataCubeSource.d.ts +29 -0
  78. package/lib/stores/core/models/AdhocQueryDataCubeSource.d.ts.map +1 -0
  79. package/lib/stores/core/models/AdhocQueryDataCubeSource.js +35 -0
  80. package/lib/stores/core/models/AdhocQueryDataCubeSource.js.map +1 -0
  81. package/lib/stores/core/models/DataCubeSource.d.ts +1 -1
  82. package/lib/stores/core/models/DataCubeSource.d.ts.map +1 -1
  83. package/lib/stores/core/models/DataCubeSource.js +1 -1
  84. package/lib/stores/core/models/DataCubeSource.js.map +1 -1
  85. package/lib/stores/view/DataCubeQuerySnapshotManager.d.ts.map +1 -1
  86. package/lib/stores/view/DataCubeQuerySnapshotManager.js +9 -2
  87. package/lib/stores/view/DataCubeQuerySnapshotManager.js.map +1 -1
  88. package/lib/stores/view/DataCubeViewState.d.ts +1 -1
  89. package/lib/stores/view/DataCubeViewState.d.ts.map +1 -1
  90. package/lib/stores/view/DataCubeViewState.js +5 -14
  91. package/lib/stores/view/DataCubeViewState.js.map +1 -1
  92. package/lib/stores/view/extend/DataCubeColumnEditorState.d.ts.map +1 -1
  93. package/lib/stores/view/extend/DataCubeColumnEditorState.js +5 -5
  94. package/lib/stores/view/extend/DataCubeColumnEditorState.js.map +1 -1
  95. package/lib/stores/view/grid/DataCubeGridClientEngine.d.ts +1 -1
  96. package/lib/stores/view/grid/DataCubeGridClientEngine.d.ts.map +1 -1
  97. package/lib/stores/view/grid/DataCubeGridClientEngine.js +11 -7
  98. package/lib/stores/view/grid/DataCubeGridClientEngine.js.map +1 -1
  99. package/lib/stores/view/grid/DataCubeGridQueryBuilder.d.ts.map +1 -1
  100. package/lib/stores/view/grid/DataCubeGridQueryBuilder.js +2 -2
  101. package/lib/stores/view/grid/DataCubeGridQueryBuilder.js.map +1 -1
  102. package/lib/stores/view/grid/DataCubeGridState.d.ts +1 -0
  103. package/lib/stores/view/grid/DataCubeGridState.d.ts.map +1 -1
  104. package/lib/stores/view/grid/DataCubeGridState.js +8 -3
  105. package/lib/stores/view/grid/DataCubeGridState.js.map +1 -1
  106. package/package.json +6 -6
  107. package/src/__lib__/DataCubeEvent.ts +21 -0
  108. package/src/components/DataCube.tsx +14 -8
  109. package/src/components/DataCubeProvider.tsx +1 -1
  110. package/src/components/core/DataCubeAlert.tsx +12 -7
  111. package/src/components/core/DataCubeFormUtils.tsx +245 -16
  112. package/src/components/core/DataCubeLayoutManager.tsx +1 -1
  113. package/src/components/core/DataCubeSettingsPanel.tsx +166 -134
  114. package/src/components/view/editor/DataCubeEditor.tsx +12 -16
  115. package/src/components/view/editor/DataCubeEditorColumnPropertiesPanel.tsx +6 -5
  116. package/src/components/view/editor/DataCubeEditorGeneralPropertiesPanel.tsx +4 -3
  117. package/src/components/view/extend/DataCubeColumnEditor.tsx +24 -28
  118. package/src/components/view/filter/DataCubeFilterEditor.tsx +10 -18
  119. package/src/components/view/grid/DataCubeGrid.tsx +8 -7
  120. package/src/index.tsx +13 -2
  121. package/src/stores/DataCubeOptions.ts +14 -10
  122. package/src/stores/DataCubeSettings.tsx +421 -0
  123. package/src/stores/DataCubeState.tsx +38 -51
  124. package/src/stores/core/DataCubeEngine.tsx +45 -62
  125. package/src/stores/core/DataCubeQueryBuilder.ts +1 -0
  126. package/src/stores/core/DataCubeQueryBuilderUtils.ts +17 -0
  127. package/src/stores/core/DataCubeQuerySnapshotBuilder.ts +59 -30
  128. package/src/stores/core/DataCubeSetting.ts +63 -0
  129. package/src/stores/core/models/AdhocQueryDataCubeSource.ts +45 -0
  130. package/src/stores/core/models/DataCubeSource.ts +1 -1
  131. package/src/stores/view/DataCubeQuerySnapshotManager.ts +16 -4
  132. package/src/stores/view/DataCubeViewState.ts +8 -17
  133. package/src/stores/view/extend/DataCubeColumnEditorState.tsx +8 -6
  134. package/src/stores/view/grid/DataCubeGridClientEngine.ts +22 -11
  135. package/src/stores/view/grid/DataCubeGridQueryBuilder.ts +7 -1
  136. package/src/stores/view/grid/DataCubeGridState.ts +17 -3
  137. package/tsconfig.json +4 -1
  138. package/src/stores/DataCubeSettings.ts +0 -107
@@ -69,22 +69,16 @@ import {
69
69
  configureCodeEditor,
70
70
  setupPureLanguageService,
71
71
  } from '@finos/legend-code-editor';
72
- import { DataCubeFont, DataCubeFunction } from './DataCubeQueryEngine.js';
72
+ import { DataCubeFont } from './DataCubeQueryEngine.js';
73
73
  import type { DataCubeQuerySnapshot } from './DataCubeQuerySnapshot.js';
74
74
  import { buildExecutableQuery } from './DataCubeQueryBuilder.js';
75
75
  import type { DataCubeColumn } from './models/DataCubeColumn.js';
76
76
  import { LicenseManager } from 'ag-grid-enterprise';
77
- import type { DataCubeQuery } from './models/DataCubeQuery.js';
78
77
  import {
79
78
  type DataCubeSource,
80
79
  INTERNAL__DataCubeSource,
81
80
  } from './models/DataCubeSource.js';
82
- import {
83
- _cols,
84
- _colSpec,
85
- _function,
86
- _primitiveValue,
87
- } from './DataCubeQueryBuilderUtils.js';
81
+ import { _primitiveValue } from './DataCubeQueryBuilderUtils.js';
88
82
  import {
89
83
  uuid,
90
84
  type DocumentationEntry,
@@ -105,27 +99,26 @@ import {
105
99
  } from './DataCubeLayoutManagerState.js';
106
100
  import { editor as monacoEditorAPI, Uri } from 'monaco-editor';
107
101
  import { DataCubeCodeCheckErrorAlert } from '../../components/core/DataCubeCodeCheckErrorAlert.js';
108
- import type { DataCubeAPI } from '../DataCubeAPI.js';
109
102
 
110
103
  export type CompletionItem = {
111
104
  completion: string;
112
105
  display: string;
113
106
  };
114
107
 
115
- export type RelationType = {
108
+ export type DataCubeRelationType = {
116
109
  columns: DataCubeColumn[];
117
110
  };
118
111
 
112
+ export type DataCubeExecutionOptions = {
113
+ debug?: boolean | undefined;
114
+ };
115
+
119
116
  export type DataCubeExecutionResult = {
120
117
  result: TDSExecutionResult;
121
118
  executedQuery: string;
122
119
  executedSQL: string;
123
120
  };
124
121
 
125
- export type DataCubeEngineConfiguration = {
126
- gridClientLicense?: string | undefined;
127
- };
128
-
129
122
  export abstract class DataCubeEngine {
130
123
  readonly layout = new LayoutManagerState();
131
124
  readonly filterOperations = [
@@ -176,16 +169,11 @@ export abstract class DataCubeEngine {
176
169
  new DataCubeQueryAggregateOperation__JoinStrings(),
177
170
  ];
178
171
 
179
- protected async fetchConfiguration(): Promise<DataCubeEngineConfiguration> {
180
- return {
181
- gridClientLicense: undefined,
182
- };
183
- }
184
-
185
- async initialize(): Promise<void> {
186
- const config = await this.fetchConfiguration();
187
- if (config.gridClientLicense) {
188
- LicenseManager.setLicenseKey(config.gridClientLicense);
172
+ async initialize(options?: {
173
+ gridClientLicense?: string | undefined;
174
+ }): Promise<void> {
175
+ if (options?.gridClientLicense) {
176
+ LicenseManager.setLicenseKey(options.gridClientLicense);
189
177
  }
190
178
  await configureCodeEditor(DataCubeFont.ROBOTO_MONO, (error) => {
191
179
  throw error;
@@ -203,7 +191,36 @@ export abstract class DataCubeEngine {
203
191
  return getAggregateOperation(value, this.aggregateOperations);
204
192
  }
205
193
 
206
- abstract getBaseQuery(): Promise<DataCubeQuery | undefined>;
194
+ /**
195
+ * By default, for a function chain, Pure grammar composer will extract the first parameter of the first function
196
+ * and render it as the caller of that function rather than a parameter
197
+ * e.g. fx(fy(p1, p2), p3) will be rendered as p1->fy(p2)->fx(p3) instead of fy(p1, p2)-> fx(p3)
198
+ *
199
+ * We do a hack to get around this by setting a dummy value as the first parameter of the first function in the chain.
200
+ * Then remove this dummy value from the final code.
201
+ */
202
+ async getPartialQueryCode(
203
+ snapshot: DataCubeQuerySnapshot,
204
+ pretty?: boolean | undefined,
205
+ ) {
206
+ const source = new INTERNAL__DataCubeSource();
207
+ source.query = _primitiveValue(PRIMITIVE_TYPE.STRING, '');
208
+ return (
209
+ await this.getValueSpecificationCode(
210
+ buildExecutableQuery(
211
+ snapshot,
212
+ source,
213
+ () => undefined,
214
+ this.filterOperations,
215
+ this.aggregateOperations,
216
+ ),
217
+ pretty,
218
+ )
219
+ ).substring(`''->`.length);
220
+ }
221
+
222
+ // ---------------------------------- INTERFACE ----------------------------------
223
+
207
224
  abstract processQuerySource(value: PlainObject): Promise<DataCubeSource>;
208
225
 
209
226
  abstract parseValueSpecification(
@@ -225,58 +242,24 @@ export abstract class DataCubeEngine {
225
242
  abstract getQueryRelationType(
226
243
  query: V1_Lambda,
227
244
  source: DataCubeSource,
228
- ): Promise<RelationType>;
245
+ ): Promise<DataCubeRelationType>;
229
246
 
230
247
  abstract getQueryCodeRelationReturnType(
231
248
  code: string,
232
249
  baseQuery: V1_ValueSpecification,
233
250
  source: DataCubeSource,
234
- ): Promise<RelationType>;
251
+ ): Promise<DataCubeRelationType>;
235
252
 
236
253
  abstract executeQuery(
237
254
  query: V1_Lambda,
238
255
  source: DataCubeSource,
239
- api: DataCubeAPI,
256
+ options?: DataCubeExecutionOptions | undefined,
240
257
  ): Promise<DataCubeExecutionResult>;
241
258
 
242
259
  abstract buildExecutionContext(
243
260
  source: DataCubeSource,
244
261
  ): V1_AppliedFunction | undefined;
245
262
 
246
- /**
247
- * By default, for a function chain, Pure grammar composer will extract the first parameter of the first function
248
- * and render it as the caller of that function rather than a parameter
249
- * e.g. fx(fy(p1, p2), p3) will be rendered as p1->fy(p2)->fx(p3) instead of fy(p1, p2)-> fx(p3)
250
- *
251
- * We do a hack to get around this by setting a dummy value as the first parameter of the first function in the chain.
252
- * Then remove this dummy value from the final code.
253
- */
254
- async getPartialQueryCode(
255
- snapshot: DataCubeQuerySnapshot,
256
- pretty?: boolean | undefined,
257
- ) {
258
- const source = new INTERNAL__DataCubeSource();
259
- source.query = _primitiveValue(PRIMITIVE_TYPE.STRING, '');
260
- return (
261
- await this.getValueSpecificationCode(
262
- buildExecutableQuery(
263
- snapshot,
264
- source,
265
- () => undefined,
266
- this.filterOperations,
267
- this.aggregateOperations,
268
- ),
269
- pretty,
270
- )
271
- ).substring(`''->`.length);
272
- }
273
-
274
- generateInitialQuery(snapshot: DataCubeQuerySnapshot): V1_AppliedFunction {
275
- return _function(DataCubeFunction.SELECT, [
276
- _cols(snapshot.data.sourceColumns.map((col) => _colSpec(col.name))),
277
- ]);
278
- }
279
-
280
263
  // ---------------------------------- DOCUMENTATION ----------------------------------
281
264
 
282
265
  getDocumentationURL(): string | undefined {
@@ -79,6 +79,7 @@ export function buildExecutableQuery(
79
79
  end: number;
80
80
  }
81
81
  | undefined;
82
+ skipExecutionContext?: boolean;
82
83
  },
83
84
  ) {
84
85
  const data = snapshot.data;
@@ -53,6 +53,7 @@ import {
53
53
  V1_createGenericTypeWithRawType,
54
54
  V1_createRelationType,
55
55
  V1_createRelationTypeColumn,
56
+ V1_serializeValueSpecification,
56
57
  } from '@finos/legend-graph';
57
58
  import {
58
59
  type DataCubeQuerySnapshotFilterCondition,
@@ -117,6 +118,16 @@ export function _deserializeLambda(json: PlainObject<V1_Lambda>) {
117
118
  return guaranteeType(V1_deserializeValueSpecification(json, []), V1_Lambda);
118
119
  }
119
120
 
121
+ export function _deserializeValueSpecification(
122
+ json: PlainObject<V1_ValueSpecification>,
123
+ ) {
124
+ return V1_deserializeValueSpecification(json, []);
125
+ }
126
+
127
+ export function _serializeValueSpecification(protocol: V1_ValueSpecification) {
128
+ return V1_serializeValueSpecification(protocol, []);
129
+ }
130
+
120
131
  export function _deserializeFunction(json: PlainObject<V1_Lambda>) {
121
132
  return guaranteeType(
122
133
  V1_deserializeValueSpecification(json, []),
@@ -304,6 +315,12 @@ export function _not(fn: V1_AppliedFunction) {
304
315
  return _function(_functionName(DataCubeFunction.NOT), [fn]);
305
316
  }
306
317
 
318
+ export function _selectFunction(columns: DataCubeColumn[]) {
319
+ return _function(DataCubeFunction.SELECT, [
320
+ _cols(columns.map((col) => _colSpec(col.name))),
321
+ ]);
322
+ }
323
+
307
324
  // --------------------------------- BUILDING BLOCKS ---------------------------------
308
325
 
309
326
  export function _col(
@@ -301,12 +301,12 @@ export function validateAndBuildQuerySnapshot(
301
301
  return _toCol(column);
302
302
  };
303
303
 
304
- // --------------------------------- SOURCE ---------------------------------
304
+ // -------------------------------- SOURCE --------------------------------
305
305
 
306
- data.sourceColumns = source.sourceColumns;
306
+ data.sourceColumns = source.columns;
307
307
  data.sourceColumns.forEach((col) => colsMap.set(col.name, col));
308
308
 
309
- // --------------------------------- LEAF-LEVEL EXTEND ---------------------------------
309
+ // --------------------------- LEAF-LEVEL EXTEND ---------------------------
310
310
  /** TODO: @datacube roundtrip */
311
311
 
312
312
  // --------------------------------- FILTER ---------------------------------
@@ -336,7 +336,7 @@ export function validateAndBuildQuerySnapshot(
336
336
  };
337
337
  }
338
338
 
339
- // --------------------------------- GROUP-LEVEL EXTEND ---------------------------------
339
+ // --------------------------- GROUP-LEVEL EXTEND ---------------------------
340
340
  /** TODO: @datacube roundtrip */
341
341
 
342
342
  // --------------------------------- SORT ---------------------------------
@@ -368,41 +368,70 @@ export function validateAndBuildQuerySnapshot(
368
368
  }
369
369
 
370
370
  // --------------------------------- CONFIGURATION ---------------------------------
371
- // NOTE: we aim to keep the data query a Pure query instead of a specification object
372
- // so this configuration holds mostly layout and styling customization.
373
- // But there are overlaps, i.e. certain data query configuration are stored in the
374
- // configuration, e.g. column aggregation type, this is because a column
375
- // aggregation's preference can be populated even when there's no aggregation specified
376
- // in the data query.
377
371
  //
378
- // Arguably, the query should be the single source for these information, but when
379
- // the configuration for a particular data query function coming from multiple sources
380
- // conflict, we need to do some reconciliation (or throw error). Some examples include:
381
- // - missing/extra columns present in the configuration
372
+ // A data-cube conceptually consists of a data query, in form of a Pure query, instead
373
+ // of a particular specification object format, and this configuration, that holds mostly
374
+ // layout and styling customization. But there are overlaps, i.e. certain "meta" query
375
+ // configuration are stored in this configuration, e.g. column aggregation type, because
376
+ // a column aggregation's preference needs to be specified even when there's no aggregation
377
+ // specified over that column in the data query.
378
+ //
379
+ // But in the example above, if the column is part of an aggregation, we have to ensure
380
+ // the configuration is consistent with the query. Conflicts can happen, for example:
382
381
  // - column kind and type conflict with aggregation
383
382
  // - column kind and type conflict with the column configuration
384
383
  //
385
- // In certain cases, configuration needs to be generated from default presets. This
386
- // helps with use cases where the query might comes from a different source, such as
387
- // Studio or Query, or another part of Engine.
384
+ // In those cases, we need to reconcile to make sure the query and the configuration to agree.
385
+ // The query will take precedence when conflicts happen, and if the conflict cannot be resolved
386
+ // somehow, we will throw a validation error. We decide so because in certain cases, configuration
387
+ // needs to be generated from default presets, such as for use cases where the query comes from a
388
+ // different source, such as Studio or Query, or another part of Engine, where the layout
389
+ // configuration is not specified.
390
+ //
391
+ // ----------------------------------------------------------------------------------
392
+
393
+ const configuration = validateAndBuildConfiguration(
394
+ snapshot,
395
+ funcMap,
396
+ baseQuery,
397
+ );
398
+ data.configuration = configuration.serialize();
399
+
400
+ return snapshot.finalize();
401
+ }
402
+
403
+ /**
404
+ * TODO: @datacube roundtrip - implement the logic to reconcile the configuration with the query
405
+ * - [ ] disallow naming an extended column the same as a source column/leaf-level extended column
406
+ * even if the column is not selected
407
+ * - [ ] columns (missing/extra columns - remove or generate default column configuration)
408
+ * - [ ] column kind
409
+ * - [ ] column type
410
+ * - [ ] base off the type, check the settings
411
+ * - [ ] aggregation
412
+ * - [ ] verify groupBy agg columns, pivot agg columns and configuration agree
413
+ * - [ ] verify groupBy sort columns and tree column sort direction configuration agree
414
+ */
415
+ function validateAndBuildConfiguration(
416
+ snapshot: DataCubeQuerySnapshot,
417
+ funcMap: DataCubeQueryFunctionMap,
418
+ baseQuery: DataCubeQuery,
419
+ ) {
420
+ const data = snapshot.data;
388
421
  const configuration =
389
422
  baseQuery.configuration?.clone() ??
390
423
  buildDefaultConfiguration([
391
- ...source.sourceColumns,
424
+ ...data.sourceColumns,
392
425
  ...data.leafExtendedColumns,
393
426
  ...data.groupExtendedColumns,
394
427
  ]);
395
- data.configuration = configuration.serialize();
396
- /**
397
- * TODO: @datacube roundtrip - implement the logic to reconcile the configuration with the query
398
- * - [ ] columns (missing/extra columns - remove or generate default column configuration)
399
- * - [ ] column kind
400
- * - [ ] column type
401
- * - [ ] base off the type, check the settings
402
- * - [ ] aggregation
403
- * - [ ] verify groupBy agg columns, pivot agg columns and configuration agree
404
- * - [ ] verify groupBy sort columns and tree column sort direction configuration agree
405
- */
406
428
 
407
- return snapshot.finalize();
429
+ // column selection
430
+ configuration.columns.forEach((column) => {
431
+ column.isSelected = Boolean(
432
+ data.groupExtendedColumns.find((col) => col.name === column.name) ??
433
+ data.selectColumns.find((col) => col.name === column.name),
434
+ );
435
+ });
436
+ return configuration;
408
437
  }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Copyright (c) 2020-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ export type DataCubeSettingValue =
18
+ | string
19
+ | number
20
+ | boolean
21
+ | object
22
+ | undefined;
23
+
24
+ export type DataCubeSettingValues = {
25
+ [key: string]: DataCubeSettingValue;
26
+ };
27
+
28
+ export enum DataCubeSettingGroup {
29
+ DEBUG = 'Debug',
30
+ GRID = 'Grid',
31
+ }
32
+
33
+ export enum DataCubeSettingType {
34
+ BOOLEAN = 'boolean',
35
+ NUMERIC = 'numeric',
36
+ STRING = 'string',
37
+ ACTION = 'action',
38
+ }
39
+
40
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
41
+ export type DataCubeSetting<T extends DataCubeSettingValue = any> = {
42
+ key: string;
43
+ title: string;
44
+ group: string;
45
+ type: DataCubeSettingType;
46
+ defaultValue: T;
47
+ action?: ((newValue: T) => void) | undefined;
48
+ description?: string | undefined;
49
+ valueOptional?: boolean | undefined;
50
+ requiresReload?: boolean | undefined;
51
+ // numeric value specifics - TODO: we might want to break these downw to separate types
52
+ numericValueMin?: number | undefined;
53
+ numericValueMax?: number | undefined;
54
+ numericValueStep?: number | undefined;
55
+ };
56
+
57
+ export enum DataCubeSettingKey {
58
+ DEBUGGER__ENABLE_DEBUG_MODE = 'dataCube.debugger.enableDebugMode',
59
+ GRID_CLIENT__ROW_BUFFER = 'dataCube.grid-client.rowBuffer',
60
+ GRID_CLIENT__PURGE_CLOSED_ROW_NODES = 'dataCube.grid-client.purgeClosedRowNodes',
61
+ GRID_CLIENT__SUPPRESS_LARGE_DATASET_WARNING = 'dataCube.grid-client.suppressLargeDatasetWarning',
62
+ GRID_CLIENT__ACTION__REFRESH_FAILED_DATA_FETCHES = 'dataCube.grid-client.action.refreshFailedDataFetches',
63
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Copyright (c) 2020-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import {
18
+ SerializationFactory,
19
+ usingConstantValueSchema,
20
+ type PlainObject,
21
+ } from '@finos/legend-shared';
22
+ import { DataCubeSource } from './DataCubeSource.js';
23
+ import { createModelSchema, primitive, raw } from 'serializr';
24
+
25
+ export class AdhocQueryDataCubeSource extends DataCubeSource {
26
+ runtime!: string;
27
+ model!: PlainObject;
28
+ }
29
+
30
+ export const ADHOC_QUERY_DATA_CUBE_SOURCE_TYPE = 'adhocQuery';
31
+
32
+ export class RawAdhocQueryDataCubeSource {
33
+ query!: string;
34
+ runtime!: string;
35
+ model!: PlainObject;
36
+
37
+ static readonly serialization = new SerializationFactory(
38
+ createModelSchema(RawAdhocQueryDataCubeSource, {
39
+ _type: usingConstantValueSchema(ADHOC_QUERY_DATA_CUBE_SOURCE_TYPE),
40
+ model: raw(),
41
+ query: primitive(),
42
+ runtime: primitive(),
43
+ }),
44
+ );
45
+ }
@@ -18,7 +18,7 @@ import type { V1_ValueSpecification } from '@finos/legend-graph';
18
18
  import type { DataCubeColumn } from './DataCubeColumn.js';
19
19
 
20
20
  export abstract class DataCubeSource {
21
- sourceColumns: DataCubeColumn[] = [];
21
+ columns: DataCubeColumn[] = [];
22
22
  query!: V1_ValueSpecification;
23
23
  }
24
24
 
@@ -23,6 +23,7 @@ import {
23
23
  guaranteeNonNullable,
24
24
  } from '@finos/legend-shared';
25
25
  import type { DataCubeQuery } from '../core/models/DataCubeQuery.js';
26
+ import { DataCubeSettingKey } from '../core/DataCubeSetting.js';
26
27
 
27
28
  // TODO: set a stack depth when we implement undo/redo
28
29
  // const DATA_CUBE_MAX_SNAPSHOT_COUNT = 100;
@@ -64,7 +65,11 @@ export abstract class DataCubeQuerySnapshotController
64
65
  const previousSnapshot = this.latestSnapshot;
65
66
  this.latestSnapshot = snapshot;
66
67
 
67
- if (this.view.dataCube.settings.enableDebugMode) {
68
+ if (
69
+ this.view.dataCube.settings.getBooleanValue(
70
+ DataCubeSettingKey.DEBUGGER__ENABLE_DEBUG_MODE,
71
+ )
72
+ ) {
68
73
  this.view.engine.debugProcess(
69
74
  `New Snapshot`,
70
75
  ['Publisher', this.getSnapshotSubscriberName()],
@@ -105,9 +110,16 @@ export class DataCubeQuerySnapshotManager {
105
110
  subscriber.getSnapshotSubscriberName(),
106
111
  );
107
112
  if (existingSubscriber) {
108
- throw new IllegalStateError(
109
- `Subscriber with name '${subscriber.getSnapshotSubscriberName()}' already exists`,
110
- );
113
+ // eslint-disable-next-line no-process-env
114
+ if (process.env.NODE_ENV === 'development') {
115
+ this.view.engine.logDebug(
116
+ `Subscriber with name '${subscriber.getSnapshotSubscriberName()}' already exists`,
117
+ );
118
+ } else {
119
+ throw new IllegalStateError(
120
+ `Subscriber with name '${subscriber.getSnapshotSubscriberName()}' already exists`,
121
+ );
122
+ }
111
123
  }
112
124
  this.subscribers.push(subscriber);
113
125
  }
@@ -57,7 +57,6 @@ class DataCubeTask {
57
57
  export class DataCubeViewState {
58
58
  readonly dataCube: DataCubeState;
59
59
  readonly engine: DataCubeEngine;
60
-
61
60
  readonly snapshotManager: DataCubeQuerySnapshotManager;
62
61
 
63
62
  readonly info: DataCubeInfoState;
@@ -79,6 +78,8 @@ export class DataCubeViewState {
79
78
  runningTasks: observable,
80
79
  newTask: action,
81
80
  endTask: action,
81
+
82
+ initialize: action,
82
83
  });
83
84
 
84
85
  this.dataCube = dataCube;
@@ -118,7 +119,7 @@ export class DataCubeViewState {
118
119
  return task;
119
120
  }
120
121
 
121
- async initialize(initialQuery?: DataCubeQuery | undefined) {
122
+ async initialize(query: DataCubeQuery) {
122
123
  const task = this.newTask('Initializing');
123
124
  try {
124
125
  await Promise.all(
@@ -133,30 +134,20 @@ export class DataCubeViewState {
133
134
  this.snapshotManager.registerSubscriber(state);
134
135
  }),
135
136
  );
136
- const baseQuery = initialQuery ?? (await this.engine.getBaseQuery());
137
- if (!baseQuery) {
138
- this.dataCube.alertAction({
139
- message: `Initialization Failure: No initial input provided`,
140
- prompt: `Make sure to either specify the initial input when setting up DataCube or the initial input getter in engine.`,
141
- type: AlertType.ERROR,
142
- actions: [],
143
- });
144
- return;
145
- }
146
- const source = await this.engine.processQuerySource(baseQuery.source);
137
+ const source = await this.engine.processQuerySource(query.source);
147
138
  runInAction(() => {
148
139
  this._source = source;
149
140
  });
150
141
  const partialQuery = await this.engine.parseValueSpecification(
151
- baseQuery.query,
142
+ query.query,
152
143
  );
153
144
  const initialSnapshot = validateAndBuildQuerySnapshot(
154
145
  partialQuery,
155
- this.source,
156
- baseQuery,
146
+ source,
147
+ query,
157
148
  );
158
149
  this.snapshotManager.broadcastSnapshot(initialSnapshot);
159
- } catch (error: unknown) {
150
+ } catch (error) {
160
151
  assertErrorThrown(error);
161
152
  this.dataCube.alertAction({
162
153
  message: `Initialization Failure: ${error.message}`,
@@ -42,14 +42,16 @@ import type { DataCubeExtendManagerState } from './DataCubeExtendManagerState.js
42
42
  import {
43
43
  EngineError,
44
44
  PRIMITIVE_TYPE,
45
- V1_deserializeValueSpecification,
46
45
  V1_Lambda,
47
- V1_serializeValueSpecification,
48
46
  type V1_ValueSpecification,
49
47
  } from '@finos/legend-graph';
50
48
  import type { DataCubeColumnConfiguration } from '../../core/models/DataCubeConfiguration.js';
51
49
  import type { DataCubeQuerySnapshotExtendedColumn } from '../../core/DataCubeQuerySnapshot.js';
52
- import { _lambda } from '../../core/DataCubeQueryBuilderUtils.js';
50
+ import {
51
+ _lambda,
52
+ _serializeValueSpecification,
53
+ _deserializeValueSpecification,
54
+ } from '../../core/DataCubeQueryBuilderUtils.js';
53
55
 
54
56
  export abstract class DataCubeColumnBaseEditorState {
55
57
  readonly uuid = uuid();
@@ -392,7 +394,7 @@ export class DataCubeNewColumnState extends DataCubeColumnBaseEditorState {
392
394
  {
393
395
  name: this.name,
394
396
  type: returnType,
395
- mapFn: V1_serializeValueSpecification(query, []),
397
+ mapFn: _serializeValueSpecification(query),
396
398
  },
397
399
  this.isGroupLevel,
398
400
  this.columnKind,
@@ -442,7 +444,7 @@ export class DataCubeExistingColumnEditorState extends DataCubeColumnBaseEditorS
442
444
 
443
445
  override async getInitialCode(): Promise<string> {
444
446
  return this.view.engine.getValueSpecificationCode(
445
- V1_deserializeValueSpecification(this.initialData.mapFn, []),
447
+ _deserializeValueSpecification(this.initialData.mapFn),
446
448
  true,
447
449
  );
448
450
  }
@@ -518,7 +520,7 @@ export class DataCubeExistingColumnEditorState extends DataCubeColumnBaseEditorS
518
520
  {
519
521
  name: this.name,
520
522
  type: returnType,
521
- mapFn: V1_serializeValueSpecification(query, []),
523
+ mapFn: _serializeValueSpecification(query),
522
524
  },
523
525
  this.isGroupLevel,
524
526
  this.columnKind,