@finos/legend-query-builder 4.17.85 → 4.17.87

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 (28) hide show
  1. package/lib/components/workflows/DataProductQueryBuilder.d.ts.map +1 -1
  2. package/lib/components/workflows/DataProductQueryBuilder.js +59 -16
  3. package/lib/components/workflows/DataProductQueryBuilder.js.map +1 -1
  4. package/lib/data-access-overview.css +1 -1
  5. package/lib/index.css +1 -1
  6. package/lib/index.d.ts +1 -1
  7. package/lib/index.d.ts.map +1 -1
  8. package/lib/index.js +1 -1
  9. package/lib/index.js.map +1 -1
  10. package/lib/package.json +1 -1
  11. package/lib/stores/QueryBuilderState.d.ts +6 -1
  12. package/lib/stores/QueryBuilderState.d.ts.map +1 -1
  13. package/lib/stores/QueryBuilderState.js +9 -1
  14. package/lib/stores/QueryBuilderState.js.map +1 -1
  15. package/lib/stores/QueryBuilderValueSpecificationBuilder.d.ts +2 -0
  16. package/lib/stores/QueryBuilderValueSpecificationBuilder.d.ts.map +1 -1
  17. package/lib/stores/QueryBuilderValueSpecificationBuilder.js +2 -2
  18. package/lib/stores/QueryBuilderValueSpecificationBuilder.js.map +1 -1
  19. package/lib/stores/workflows/dataProduct/DataProductQueryBuilderState.d.ts +46 -5
  20. package/lib/stores/workflows/dataProduct/DataProductQueryBuilderState.d.ts.map +1 -1
  21. package/lib/stores/workflows/dataProduct/DataProductQueryBuilderState.js +182 -15
  22. package/lib/stores/workflows/dataProduct/DataProductQueryBuilderState.js.map +1 -1
  23. package/package.json +7 -7
  24. package/src/components/workflows/DataProductQueryBuilder.tsx +147 -24
  25. package/src/index.ts +7 -1
  26. package/src/stores/QueryBuilderState.ts +19 -1
  27. package/src/stores/QueryBuilderValueSpecificationBuilder.ts +2 -5
  28. package/src/stores/workflows/dataProduct/DataProductQueryBuilderState.ts +278 -16
@@ -20,12 +20,26 @@ import {
20
20
  DataProduct,
21
21
  type V1_DataProductArtifact,
22
22
  ModelAccessPointGroup,
23
- type NativeModelExecutionContext,
23
+ NativeModelExecutionContext,
24
24
  CORE_PURE_PATH,
25
25
  type NativeModelAccess,
26
+ type Mapping,
27
+ type DataProductElementScope,
28
+ PackageableRuntime,
26
29
  resolveUsableDataProductClasses,
30
+ LakehouseRuntime,
31
+ type LambdaFunction,
32
+ SimpleFunctionExpression,
33
+ InstanceValue,
34
+ Multiplicity,
35
+ extractElementNameFromPath,
36
+ SUPPORTED_FUNCTIONS,
37
+ PackageableElementExplicitReference,
38
+ resolveDataProductExecutionState,
39
+ RuntimePointer,
27
40
  } from '@finos/legend-graph';
28
41
  import { QueryBuilderState } from '../../QueryBuilderState.js';
42
+
29
43
  import { type GenericLegendApplicationStore } from '@finos/legend-application';
30
44
  import type {
31
45
  QueryBuilderActionConfig,
@@ -35,7 +49,9 @@ import type { QueryBuilderConfig } from '../../../graph-manager/QueryBuilderConf
35
49
  import { renderDataProductQueryBuilderSetupPanelContent } from '../../../components/workflows/DataProductQueryBuilder.js';
36
50
  import {
37
51
  ActionState,
52
+ assertErrorThrown,
38
53
  filterByType,
54
+ guaranteeNonNullable,
39
55
  type GeneratorFn,
40
56
  } from '@finos/legend-shared';
41
57
  import { action, computed, flow, makeObservable, observable } from 'mobx';
@@ -44,6 +60,7 @@ import {
44
60
  type QueryableSourceInfo,
45
61
  } from '@finos/legend-storage';
46
62
  import { compareLabelFn } from '@finos/legend-art';
63
+ import { QueryBuilderEmbeddedFromExecutionContextState } from '../../QueryBuilderExecutionContextState.js';
47
64
 
48
65
  export type DataProductOption = {
49
66
  label: string;
@@ -69,6 +86,113 @@ export const buildExecOptions = (
69
86
  };
70
87
  };
71
88
 
89
+ export type ModelAccessPointGroupOption = {
90
+ label: string;
91
+ value: ModelAccessPointGroup;
92
+ };
93
+
94
+ export const buildModelAccessPointGroupOption = (
95
+ value: ModelAccessPointGroup,
96
+ ): ModelAccessPointGroupOption => ({
97
+ label: value.title ?? value.id,
98
+ value,
99
+ });
100
+
101
+ export abstract class DataProductExecutionState<T> {
102
+ readonly queryBuilderState: DataProductQueryBuilderState;
103
+ exectionValue: T;
104
+
105
+ constructor(
106
+ executionState: T,
107
+ queryBuilderState: DataProductQueryBuilderState,
108
+ ) {
109
+ this.queryBuilderState = queryBuilderState;
110
+ this.exectionValue = executionState;
111
+ }
112
+
113
+ abstract get label(): string;
114
+
115
+ abstract get mapping(): Mapping;
116
+
117
+ abstract get featuredElements(): DataProductElementScope[] | undefined;
118
+
119
+ get selectedOption(): { label: string; value: T } {
120
+ return {
121
+ label: this.label,
122
+ value: this.exectionValue,
123
+ };
124
+ }
125
+ }
126
+
127
+ export class NativeModelDataProductExecutionState extends DataProductExecutionState<NativeModelExecutionContext> {
128
+ nativeModelAccess: NativeModelAccess;
129
+
130
+ constructor(
131
+ executionState: NativeModelExecutionContext,
132
+ queryBuilderState: DataProductQueryBuilderState,
133
+ ) {
134
+ super(executionState, queryBuilderState);
135
+ this.nativeModelAccess = executionState.__owner;
136
+ }
137
+
138
+ override get label(): string {
139
+ return this.exectionValue.key;
140
+ }
141
+
142
+ get mapping(): Mapping {
143
+ return this.exectionValue.mapping.value;
144
+ }
145
+
146
+ get featuredElements(): DataProductElementScope[] | undefined {
147
+ return this.nativeModelAccess.featuredElements;
148
+ }
149
+ }
150
+
151
+ export class ModelAccessPointDataProductExecutionState extends DataProductExecutionState<ModelAccessPointGroup> {
152
+ selectedRuntime: PackageableRuntime | undefined;
153
+
154
+ constructor(
155
+ executionState: ModelAccessPointGroup,
156
+ queryBuilderState: DataProductQueryBuilderState,
157
+ ) {
158
+ super(executionState, queryBuilderState);
159
+ makeObservable(this, {
160
+ selectedRuntime: observable,
161
+ compatibleRuntimes: computed,
162
+ showRuntimeOptions: computed,
163
+ changeSelectedRuntime: action,
164
+ });
165
+ this.selectedRuntime = this.compatibleRuntimes[0];
166
+ }
167
+
168
+ changeSelectedRuntime(val: PackageableRuntime): void {
169
+ this.selectedRuntime = val;
170
+ this.queryBuilderState.changeRuntime(val);
171
+ }
172
+
173
+ override get label(): string {
174
+ return this.exectionValue.title ?? this.exectionValue.id;
175
+ }
176
+
177
+ get mapping(): Mapping {
178
+ return this.exectionValue.mapping.value;
179
+ }
180
+
181
+ get featuredElements(): DataProductElementScope[] | undefined {
182
+ return this.exectionValue.featuredElements;
183
+ }
184
+
185
+ get showRuntimeOptions(): boolean {
186
+ return this.compatibleRuntimes.length > 1;
187
+ }
188
+
189
+ get compatibleRuntimes(): PackageableRuntime[] {
190
+ return this.queryBuilderState.graphManagerState.usableRuntimes.filter(
191
+ (runtime) => runtime.runtimeValue instanceof LakehouseRuntime,
192
+ );
193
+ }
194
+ }
195
+
72
196
  export class DataProductQueryBuilderState extends QueryBuilderState {
73
197
  readonly onClassChange?: ((val: Class) => void) | undefined;
74
198
  readonly onDataProductChange?: (val: DepotEntityWithOrigin) => Promise<void>;
@@ -77,10 +201,11 @@ export class DataProductQueryBuilderState extends QueryBuilderState {
77
201
  | undefined;
78
202
 
79
203
  loadDataProductModelState = ActionState.create();
80
- nativeModelAccess: NativeModelAccess;
81
204
  dataProduct: DataProduct;
82
205
  dataProductArtifact: V1_DataProductArtifact | undefined;
83
- selectedExecContext: NativeModelExecutionContext;
206
+ executionState: DataProductExecutionState<
207
+ NativeModelExecutionContext | ModelAccessPointGroup
208
+ >;
84
209
  entities: DepotEntityWithOrigin[] | undefined;
85
210
 
86
211
  prioritizeEntityFunc?: ((val: DepotEntityWithOrigin) => boolean) | undefined;
@@ -95,8 +220,7 @@ export class DataProductQueryBuilderState extends QueryBuilderState {
95
220
  dataProduct: DataProduct,
96
221
  artifact: V1_DataProductArtifact | undefined,
97
222
  actionConfig: QueryBuilderActionConfig,
98
- nativeNativeModelAccess: NativeModelAccess,
99
- nativeModelExecContext: NativeModelExecutionContext,
223
+ executionState: NativeModelExecutionContext | ModelAccessPointGroup,
100
224
  prioritizeEntityFunc: ((val: DepotEntityWithOrigin) => boolean) | undefined,
101
225
  onDataProductChange: (val: DepotEntityWithOrigin) => Promise<void>,
102
226
  onExecutionContextChange?:
@@ -108,19 +232,31 @@ export class DataProductQueryBuilderState extends QueryBuilderState {
108
232
  ) {
109
233
  super(applicationStore, graphManagerState, workflow, config, sourceInfo);
110
234
  makeObservable(this, {
111
- selectedExecContext: observable,
112
235
  dataProduct: observable,
113
- setExecOptions: action,
236
+ executionState: observable,
237
+ initWithDataProduct: action,
238
+ handleDataProductChange: action,
239
+ setExecutionState: action,
114
240
  selectedDataProductOption: computed,
115
241
  isProductLinkable: computed,
242
+ modelAccessPointGroups: computed,
243
+ hasModelAccessPointGroups: computed,
244
+ modelAccessPointGroupOptions: computed,
245
+ activeMapping: computed,
246
+ activeFeaturedElements: computed,
116
247
  loadEntities: flow,
117
248
  entities: observable,
118
249
  });
250
+ // for queries against data product, we always want to default to from
251
+ this.executionContextState =
252
+ new QueryBuilderEmbeddedFromExecutionContextState(this);
119
253
  this.workflowState.updateActionConfig(actionConfig);
120
254
  this.dataProduct = dataProduct;
121
255
  this.dataProductArtifact = artifact;
122
- this.nativeModelAccess = nativeNativeModelAccess;
123
- this.selectedExecContext = nativeModelExecContext;
256
+ this.executionState =
257
+ executionState instanceof NativeModelExecutionContext
258
+ ? new NativeModelDataProductExecutionState(executionState, this)
259
+ : new ModelAccessPointDataProductExecutionState(executionState, this);
124
260
  this.prioritizeEntityFunc = prioritizeEntityFunc;
125
261
  this.onDataProductChange = onDataProductChange;
126
262
  this.onExecutionContextChange = onExecutionContextChange;
@@ -131,6 +267,63 @@ export class DataProductQueryBuilderState extends QueryBuilderState {
131
267
  return false;
132
268
  }
133
269
 
270
+ handleDataProductChange(val: DepotEntityWithOrigin): void {
271
+ try {
272
+ this.loadDataProductModelState.inProgress();
273
+ const dataProduct = this.graphManagerState.graph.getDataProduct(val.path);
274
+ this.initWithDataProduct(dataProduct);
275
+ } catch (error) {
276
+ assertErrorThrown(error);
277
+ this.applicationStore.notificationService.notifyError(
278
+ `Failed to change Data Product: ${error.message}`,
279
+ );
280
+ }
281
+ }
282
+
283
+ initWithDataProduct(dataProduct: DataProduct): void {
284
+ try {
285
+ const execValue = resolveDataProductExecutionState(dataProduct);
286
+ this.dataProduct = dataProduct;
287
+ this.executionState =
288
+ execValue instanceof NativeModelExecutionContext
289
+ ? new NativeModelDataProductExecutionState(execValue, this)
290
+ : new ModelAccessPointDataProductExecutionState(execValue, this);
291
+ this.changeMapping(this.executionState.mapping);
292
+ if (this.executionState instanceof NativeModelDataProductExecutionState) {
293
+ const runtime = guaranteeNonNullable(
294
+ this.executionState.exectionValue.runtime,
295
+ 'runtime unable to be resolved',
296
+ );
297
+ this.changeRuntime(new RuntimePointer(runtime));
298
+ } else if (
299
+ this.executionState instanceof
300
+ ModelAccessPointDataProductExecutionState &&
301
+ this.executionState.selectedRuntime instanceof PackageableRuntime
302
+ ) {
303
+ this.changeRuntime(this.executionState.selectedRuntime);
304
+ }
305
+ const compatibleClasses = resolveUsableDataProductClasses(
306
+ this.activeFeaturedElements,
307
+ this.executionState.mapping,
308
+ this.graphManagerState,
309
+ undefined,
310
+ );
311
+ // if there is no chosen class or the chosen one is not compatible
312
+ // with the mapping then pick a compatible class if possible
313
+ if (!this.class || !compatibleClasses.includes(this.class)) {
314
+ const possibleNewClass = compatibleClasses[0];
315
+ if (possibleNewClass) {
316
+ this.changeClass(possibleNewClass);
317
+ }
318
+ }
319
+ } catch (error) {
320
+ assertErrorThrown(error);
321
+ this.applicationStore.notificationService.notifyError(
322
+ `Failed to load Data Product: ${error.message}`,
323
+ );
324
+ }
325
+ }
326
+
134
327
  copyDataProductLinkToClipBoard(): void {
135
328
  if (!this.isProductLinkable) {
136
329
  this.applicationStore.notificationService.notifyError(
@@ -143,8 +336,77 @@ export class DataProductQueryBuilderState extends QueryBuilderState {
143
336
  return DataProduct;
144
337
  }
145
338
 
146
- setExecOptions(exec: NativeModelExecutionContext): void {
147
- this.selectedExecContext = exec;
339
+ setExecutionState(
340
+ val: NativeModelExecutionContext | ModelAccessPointGroup,
341
+ ): void {
342
+ this.executionState =
343
+ val instanceof NativeModelExecutionContext
344
+ ? new NativeModelDataProductExecutionState(val, this)
345
+ : new ModelAccessPointDataProductExecutionState(val, this);
346
+ }
347
+
348
+ get modelAccessPointGroups(): ModelAccessPointGroup[] {
349
+ return this.dataProduct.accessPointGroups.filter(
350
+ filterByType(ModelAccessPointGroup),
351
+ );
352
+ }
353
+
354
+ get hasModelAccessPointGroups(): boolean {
355
+ return this.modelAccessPointGroups.length > 0;
356
+ }
357
+
358
+ get modelAccessPointGroupOptions(): ModelAccessPointGroupOption[] {
359
+ return this.modelAccessPointGroups
360
+ .map(buildModelAccessPointGroupOption)
361
+ .sort(compareLabelFn);
362
+ }
363
+
364
+ get activeMapping(): Mapping | undefined {
365
+ return this.executionState.mapping;
366
+ }
367
+
368
+ get activeFeaturedElements(): DataProductElementScope[] | undefined {
369
+ return this.executionState.featuredElements;
370
+ }
371
+
372
+ override buildExecutionContextExpression(
373
+ lambdaFunction: LambdaFunction,
374
+ ): LambdaFunction {
375
+ if (
376
+ this.executionState instanceof ModelAccessPointDataProductExecutionState
377
+ ) {
378
+ // for model access point group with attached ->with(dataProduct)->from(runtime) to execute query
379
+ let precedingExpression = guaranteeNonNullable(
380
+ lambdaFunction.expressionSequence[0],
381
+ `Can't build from() expression: preceding expression is not defined`,
382
+ );
383
+ const withFunc = new SimpleFunctionExpression(
384
+ extractElementNameFromPath(SUPPORTED_FUNCTIONS.WITH),
385
+ );
386
+ const dataProductInstance = new InstanceValue(
387
+ Multiplicity.ONE,
388
+ undefined,
389
+ );
390
+ dataProductInstance.values = [
391
+ PackageableElementExplicitReference.create(this.dataProduct),
392
+ ];
393
+ withFunc.parametersValues = [precedingExpression, dataProductInstance];
394
+ precedingExpression = withFunc;
395
+ const fromFunc = new SimpleFunctionExpression(
396
+ extractElementNameFromPath(SUPPORTED_FUNCTIONS.FROM),
397
+ );
398
+ const runtime = this.executionState.selectedRuntime;
399
+ if (runtime) {
400
+ const runtimeInstance = new InstanceValue(Multiplicity.ONE, undefined);
401
+ runtimeInstance.values = [
402
+ PackageableElementExplicitReference.create(runtime),
403
+ ];
404
+ fromFunc.parametersValues = [precedingExpression, runtimeInstance];
405
+ lambdaFunction.expressionSequence[0] = fromFunc;
406
+ }
407
+ return lambdaFunction;
408
+ }
409
+ return super.buildExecutionContextExpression(lambdaFunction);
148
410
  }
149
411
 
150
412
  *loadEntities(): GeneratorFn<void> {
@@ -216,14 +478,14 @@ export class DataProductQueryBuilderState extends QueryBuilderState {
216
478
  requireReBuildingGraph?: boolean | undefined,
217
479
  ): Promise<void> {
218
480
  const currentMapping = this.executionContextState.mapping;
219
- const execMapping = this.selectedExecContext.mapping.value;
220
- if (execMapping !== currentMapping) {
221
- this.changeMapping(execMapping, {
481
+ const newMapping = this.activeMapping;
482
+ if (newMapping && newMapping !== currentMapping) {
483
+ this.changeMapping(newMapping, {
222
484
  keepQueryContent: true,
223
485
  });
224
486
  const classes = resolveUsableDataProductClasses(
225
- this.nativeModelAccess.featuredElements,
226
- this.selectedExecContext.mapping.value,
487
+ this.activeFeaturedElements,
488
+ newMapping,
227
489
  this.graphManagerState,
228
490
  undefined,
229
491
  );