@finos/legend-application-query 13.7.205 → 13.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/__lib__/LegendQueryNavigation.d.ts +16 -10
- package/lib/__lib__/LegendQueryNavigation.d.ts.map +1 -1
- package/lib/__lib__/LegendQueryNavigation.js +17 -12
- package/lib/__lib__/LegendQueryNavigation.js.map +1 -1
- package/lib/__lib__/LegendQueryUserDataHelper.d.ts +25 -7
- package/lib/__lib__/LegendQueryUserDataHelper.d.ts.map +1 -1
- package/lib/__lib__/LegendQueryUserDataHelper.js +81 -6
- package/lib/__lib__/LegendQueryUserDataHelper.js.map +1 -1
- package/lib/__lib__/LegendQueryUserDataSpaceHelper.d.ts +21 -4
- package/lib/__lib__/LegendQueryUserDataSpaceHelper.d.ts.map +1 -1
- package/lib/__lib__/LegendQueryUserDataSpaceHelper.js +17 -0
- package/lib/__lib__/LegendQueryUserDataSpaceHelper.js.map +1 -1
- package/lib/application/LegendQueryApplicationConfig.d.ts +10 -0
- package/lib/application/LegendQueryApplicationConfig.d.ts.map +1 -1
- package/lib/application/LegendQueryApplicationConfig.js +16 -0
- package/lib/application/LegendQueryApplicationConfig.js.map +1 -1
- package/lib/components/Core_LegendQueryApplicationPlugin.d.ts.map +1 -1
- package/lib/components/Core_LegendQueryApplicationPlugin.js +7 -3
- package/lib/components/Core_LegendQueryApplicationPlugin.js.map +1 -1
- package/lib/components/LegendQueryWebApplication.d.ts.map +1 -1
- package/lib/components/LegendQueryWebApplication.js +2 -2
- package/lib/components/LegendQueryWebApplication.js.map +1 -1
- package/lib/components/QueryEditor.d.ts.map +1 -1
- package/lib/components/QueryEditor.js +5 -2
- package/lib/components/QueryEditor.js.map +1 -1
- package/lib/components/__test-utils__/QueryEditorComponentTestUtils.d.ts +8 -0
- package/lib/components/__test-utils__/QueryEditorComponentTestUtils.d.ts.map +1 -1
- package/lib/components/__test-utils__/QueryEditorComponentTestUtils.js +190 -8
- package/lib/components/__test-utils__/QueryEditorComponentTestUtils.js.map +1 -1
- package/lib/components/data-product/DataProductInfo.d.ts +28 -0
- package/lib/components/data-product/DataProductInfo.d.ts.map +1 -0
- package/lib/components/data-product/DataProductInfo.js +89 -0
- package/lib/components/data-product/DataProductInfo.js.map +1 -0
- package/lib/components/{data-space/DataSpaceQueryCreator.d.ts → data-product/LegendQueryDataProductQueryBuilder.d.ts} +3 -4
- package/lib/components/data-product/LegendQueryDataProductQueryBuilder.d.ts.map +1 -0
- package/lib/components/data-product/LegendQueryDataProductQueryBuilder.js +98 -0
- package/lib/components/data-product/LegendQueryDataProductQueryBuilder.js.map +1 -0
- package/lib/components/data-space/DataProductQueryCreator.d.ts +36 -0
- package/lib/components/data-space/DataProductQueryCreator.d.ts.map +1 -0
- package/lib/components/data-space/DataProductQueryCreator.js +76 -0
- package/lib/components/data-space/DataProductQueryCreator.js.map +1 -0
- package/lib/index.css +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/light-mode.css +1 -1
- package/lib/package.json +2 -1
- package/lib/stores/QueryEditorStore.d.ts +46 -2
- package/lib/stores/QueryEditorStore.d.ts.map +1 -1
- package/lib/stores/QueryEditorStore.js +251 -5
- package/lib/stores/QueryEditorStore.js.map +1 -1
- package/lib/stores/data-product/query-builder/DataProductArtifactHelper.d.ts +21 -0
- package/lib/stores/data-product/query-builder/DataProductArtifactHelper.d.ts.map +1 -0
- package/lib/stores/data-product/query-builder/DataProductArtifactHelper.js +35 -0
- package/lib/stores/data-product/query-builder/DataProductArtifactHelper.js.map +1 -0
- package/lib/stores/data-product/query-builder/LegendQueryDataProductQueryBuilderState.d.ts +11 -3
- package/lib/stores/data-product/query-builder/LegendQueryDataProductQueryBuilderState.d.ts.map +1 -1
- package/lib/stores/data-product/query-builder/LegendQueryDataProductQueryBuilderState.js +50 -8
- package/lib/stores/data-product/query-builder/LegendQueryDataProductQueryBuilderState.js.map +1 -1
- package/lib/stores/data-space/DataProductQueryCreatorStore.d.ts +94 -0
- package/lib/stores/data-space/DataProductQueryCreatorStore.d.ts.map +1 -0
- package/lib/stores/data-space/DataProductQueryCreatorStore.js +388 -0
- package/lib/stores/data-space/DataProductQueryCreatorStore.js.map +1 -0
- package/lib/stores/data-space/DataProductSelectorState.d.ts +44 -0
- package/lib/stores/data-space/DataProductSelectorState.d.ts.map +1 -0
- package/lib/stores/data-space/DataProductSelectorState.js +111 -0
- package/lib/stores/data-space/DataProductSelectorState.js.map +1 -0
- package/lib/stores/data-space/DataSpaceTemplateQueryCreatorStore.d.ts.map +1 -1
- package/lib/stores/data-space/DataSpaceTemplateQueryCreatorStore.js +3 -0
- package/lib/stores/data-space/DataSpaceTemplateQueryCreatorStore.js.map +1 -1
- package/lib/stores/data-space/LegendQueryBareQueryBuilderState.d.ts +1 -1
- package/lib/stores/data-space/LegendQueryBareQueryBuilderState.d.ts.map +1 -1
- package/lib/stores/data-space/LegendQueryBareQueryBuilderState.js +1 -1
- package/lib/stores/data-space/LegendQueryBareQueryBuilderState.js.map +1 -1
- package/lib/stores/data-space/query-builder/LegendQueryDataSpaceQueryBuilderState.d.ts +4 -3
- package/lib/stores/data-space/query-builder/LegendQueryDataSpaceQueryBuilderState.d.ts.map +1 -1
- package/lib/stores/data-space/query-builder/LegendQueryDataSpaceQueryBuilderState.js +24 -29
- package/lib/stores/data-space/query-builder/LegendQueryDataSpaceQueryBuilderState.js.map +1 -1
- package/package.json +8 -7
- package/src/__lib__/LegendQueryNavigation.ts +76 -18
- package/src/__lib__/LegendQueryUserDataHelper.ts +177 -12
- package/src/__lib__/LegendQueryUserDataSpaceHelper.ts +54 -4
- package/src/application/LegendQueryApplicationConfig.ts +31 -0
- package/src/components/Core_LegendQueryApplicationPlugin.tsx +8 -2
- package/src/components/LegendQueryWebApplication.tsx +8 -4
- package/src/components/QueryEditor.tsx +13 -0
- package/src/components/__test-utils__/QueryEditorComponentTestUtils.tsx +418 -5
- package/src/components/data-product/DataProductInfo.tsx +297 -0
- package/src/components/data-product/LegendQueryDataProductQueryBuilder.tsx +268 -0
- package/src/components/data-space/DataProductQueryCreator.tsx +167 -0
- package/src/components/data-space/DataSpaceQuerySetup.tsx +1 -1
- package/src/index.ts +6 -0
- package/src/stores/QueryEditorStore.ts +485 -2
- package/src/stores/data-product/query-builder/DataProductArtifactHelper.ts +48 -0
- package/src/stores/data-product/query-builder/LegendQueryDataProductQueryBuilderState.ts +77 -16
- package/src/stores/data-space/DataProductQueryCreatorStore.ts +765 -0
- package/src/stores/data-space/DataProductSelectorState.ts +164 -0
- package/src/stores/data-space/DataSpaceTemplateQueryCreatorStore.ts +10 -0
- package/src/stores/data-space/LegendQueryBareQueryBuilderState.ts +1 -1
- package/src/stores/data-space/query-builder/LegendQueryDataSpaceQueryBuilderState.ts +27 -54
- package/tsconfig.json +6 -2
- package/lib/components/data-space/DataSpaceQueryCreator.d.ts.map +0 -1
- package/lib/components/data-space/DataSpaceQueryCreator.js +0 -62
- package/lib/components/data-space/DataSpaceQueryCreator.js.map +0 -1
- package/lib/stores/data-space/DataSpaceQueryCreatorStore.d.ts +0 -92
- package/lib/stores/data-space/DataSpaceQueryCreatorStore.d.ts.map +0 -1
- package/lib/stores/data-space/DataSpaceQueryCreatorStore.js +0 -400
- package/lib/stores/data-space/DataSpaceQueryCreatorStore.js.map +0 -1
- package/src/components/data-space/DataSpaceQueryCreator.tsx +0 -119
- package/src/stores/data-space/DataSpaceQueryCreatorStore.ts +0 -697
|
@@ -42,13 +42,14 @@ import {
|
|
|
42
42
|
} from '@finos/legend-shared';
|
|
43
43
|
import {
|
|
44
44
|
type LightQuery,
|
|
45
|
+
NativeModelExecutionContext,
|
|
45
46
|
type RawLambda,
|
|
46
47
|
type Runtime,
|
|
47
48
|
type Service,
|
|
48
49
|
type QueryGridConfig,
|
|
49
50
|
type ValueSpecification,
|
|
50
51
|
type GraphInitializationReport,
|
|
51
|
-
|
|
52
|
+
PackageableRuntime,
|
|
52
53
|
type QueryInfo,
|
|
53
54
|
GraphManagerState,
|
|
54
55
|
Query,
|
|
@@ -75,6 +76,16 @@ import {
|
|
|
75
76
|
QUERY_PROFILE_PATH,
|
|
76
77
|
QueryDataSpaceExecutionContextInfo,
|
|
77
78
|
QueryExplicitExecutionContextInfo,
|
|
79
|
+
QueryDataProductNativeExecutionContextInfo,
|
|
80
|
+
QueryDataProductModelAccessExecutionContextInfo,
|
|
81
|
+
ModelAccessPointGroup,
|
|
82
|
+
type DataProduct,
|
|
83
|
+
LakehouseRuntime,
|
|
84
|
+
V1_DATA_PRODUCT_ELEMENT_PROTOCOL_TYPE,
|
|
85
|
+
V1_DataProductArtifact,
|
|
86
|
+
V1_ModelAccessPointGroupInfo,
|
|
87
|
+
DataProductAccessType,
|
|
88
|
+
type DataProductAnalysisQueryResult,
|
|
78
89
|
} from '@finos/legend-graph';
|
|
79
90
|
import {
|
|
80
91
|
generateExistingQueryEditorRoute,
|
|
@@ -86,7 +97,9 @@ import {
|
|
|
86
97
|
type Entity,
|
|
87
98
|
type ProjectGAVCoordinates,
|
|
88
99
|
type EntitiesWithOrigin,
|
|
100
|
+
type DepotEntityWithOrigin,
|
|
89
101
|
parseGACoordinates,
|
|
102
|
+
StoredFileGeneration,
|
|
90
103
|
} from '@finos/legend-storage';
|
|
91
104
|
import {
|
|
92
105
|
type DepotServerClient,
|
|
@@ -95,6 +108,8 @@ import {
|
|
|
95
108
|
LATEST_VERSION_ALIAS,
|
|
96
109
|
VersionedProjectData,
|
|
97
110
|
retrieveProjectEntitiesWithClassifier,
|
|
111
|
+
isSnapshotVersion,
|
|
112
|
+
SNAPSHOT_VERSION_ALIAS,
|
|
98
113
|
} from '@finos/legend-server-depot';
|
|
99
114
|
import {
|
|
100
115
|
ActionAlertActionType,
|
|
@@ -116,6 +131,8 @@ import {
|
|
|
116
131
|
QueryBuilderDataBrowserWorkflow,
|
|
117
132
|
QueryBuilderActionConfig,
|
|
118
133
|
QUERY_LOADER_DEFAULT_QUERY_SEARCH_LIMIT,
|
|
134
|
+
NativeModelDataProductExecutionState,
|
|
135
|
+
ModelAccessPointDataProductExecutionState,
|
|
119
136
|
} from '@finos/legend-query-builder';
|
|
120
137
|
import { LegendQueryUserDataHelper } from '../__lib__/LegendQueryUserDataHelper.js';
|
|
121
138
|
import { LegendQueryTelemetryHelper } from '../__lib__/LegendQueryTelemetryHelper.js';
|
|
@@ -133,6 +150,13 @@ import {
|
|
|
133
150
|
import { generateDataSpaceQueryCreatorRoute } from '../__lib__/DSL_DataSpace_LegendQueryNavigation.js';
|
|
134
151
|
import { hasDataSpaceInfoBeenVisited } from '../__lib__/LegendQueryUserDataSpaceHelper.js';
|
|
135
152
|
import { LegendQueryDataSpaceQueryBuilderState } from './data-space/query-builder/LegendQueryDataSpaceQueryBuilderState.js';
|
|
153
|
+
import { LegendQueryDataProductQueryBuilderState } from './data-product/query-builder/LegendQueryDataProductQueryBuilderState.js';
|
|
154
|
+
import { DataProductSelectorState } from './data-space/DataProductSelectorState.js';
|
|
155
|
+
import {
|
|
156
|
+
decorateEnvWithRealm,
|
|
157
|
+
LakehouseContractServerClient,
|
|
158
|
+
LakehouseEnvironmentType,
|
|
159
|
+
} from '@finos/legend-server-lakehouse';
|
|
136
160
|
|
|
137
161
|
export interface QueryPersistConfiguration {
|
|
138
162
|
defaultName?: string | undefined;
|
|
@@ -266,12 +290,21 @@ export class QueryCreatorState {
|
|
|
266
290
|
}
|
|
267
291
|
}
|
|
268
292
|
|
|
293
|
+
export class LegendQueryLakehouseState {
|
|
294
|
+
readonly contractServerClient: LakehouseContractServerClient;
|
|
295
|
+
|
|
296
|
+
constructor(contractServerClient: LakehouseContractServerClient) {
|
|
297
|
+
this.contractServerClient = contractServerClient;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
269
301
|
export abstract class QueryEditorStore {
|
|
270
302
|
readonly applicationStore: LegendQueryApplicationStore;
|
|
271
303
|
readonly depotServerClient: DepotServerClient;
|
|
272
304
|
readonly pluginManager: LegendQueryPluginManager;
|
|
273
305
|
readonly graphManagerState: GraphManagerState;
|
|
274
306
|
readonly queryLoaderState: QueryLoaderState;
|
|
307
|
+
readonly lakehouseState?: LegendQueryLakehouseState | undefined;
|
|
275
308
|
|
|
276
309
|
readonly initState = ActionState.create();
|
|
277
310
|
|
|
@@ -281,6 +314,7 @@ export abstract class QueryEditorStore {
|
|
|
281
314
|
showRegisterServiceModal = false;
|
|
282
315
|
showAppInfo = false;
|
|
283
316
|
showDataspaceInfo = false;
|
|
317
|
+
showDataProductInfo = false;
|
|
284
318
|
enableMinialGraphForDataSpaceLoadingPerformance = true;
|
|
285
319
|
|
|
286
320
|
constructor(
|
|
@@ -294,6 +328,7 @@ export abstract class QueryEditorStore {
|
|
|
294
328
|
showRegisterServiceModal: observable,
|
|
295
329
|
showAppInfo: observable,
|
|
296
330
|
showDataspaceInfo: observable,
|
|
331
|
+
showDataProductInfo: observable,
|
|
297
332
|
queryBuilderState: observable,
|
|
298
333
|
enableMinialGraphForDataSpaceLoadingPerformance: observable,
|
|
299
334
|
isPerformingBlockingAction: computed,
|
|
@@ -301,6 +336,7 @@ export abstract class QueryEditorStore {
|
|
|
301
336
|
setShowRegisterServiceModal: action,
|
|
302
337
|
setShowAppInfo: action,
|
|
303
338
|
setShowDataspaceInfo: action,
|
|
339
|
+
setShowDataProductInfo: action,
|
|
304
340
|
setEnableMinialGraphForDataSpaceLoadingPerformance: action,
|
|
305
341
|
initialize: flow,
|
|
306
342
|
buildGraph: flow,
|
|
@@ -315,6 +351,15 @@ export abstract class QueryEditorStore {
|
|
|
315
351
|
applicationStore.pluginManager,
|
|
316
352
|
applicationStore.logService,
|
|
317
353
|
);
|
|
354
|
+
|
|
355
|
+
// lakehouse
|
|
356
|
+
if (applicationStore.config.lakehouseContractUrl) {
|
|
357
|
+
const contractServerClient = new LakehouseContractServerClient({
|
|
358
|
+
baseUrl: applicationStore.config.lakehouseContractUrl,
|
|
359
|
+
});
|
|
360
|
+
contractServerClient.setTracerService(applicationStore.tracerService);
|
|
361
|
+
this.lakehouseState = new LegendQueryLakehouseState(contractServerClient);
|
|
362
|
+
}
|
|
318
363
|
this.queryLoaderState = new QueryLoaderState(
|
|
319
364
|
applicationStore,
|
|
320
365
|
this.graphManagerState.graphManager,
|
|
@@ -402,6 +447,10 @@ export abstract class QueryEditorStore {
|
|
|
402
447
|
this.showDataspaceInfo = val;
|
|
403
448
|
}
|
|
404
449
|
|
|
450
|
+
setShowDataProductInfo(val: boolean): void {
|
|
451
|
+
this.showDataProductInfo = val;
|
|
452
|
+
}
|
|
453
|
+
|
|
405
454
|
setShowRegisterServiceModal(val: boolean): void {
|
|
406
455
|
this.showRegisterServiceModal = val;
|
|
407
456
|
}
|
|
@@ -827,6 +876,394 @@ export abstract class QueryEditorStore {
|
|
|
827
876
|
isLightGraphEnabled,
|
|
828
877
|
};
|
|
829
878
|
}
|
|
879
|
+
|
|
880
|
+
async fetchDataProductArtifact(
|
|
881
|
+
groupId: string,
|
|
882
|
+
artifactId: string,
|
|
883
|
+
versionId: string,
|
|
884
|
+
dataProductPath: string,
|
|
885
|
+
): Promise<V1_DataProductArtifact> {
|
|
886
|
+
const project = StoreProjectData.serialization.fromJson(
|
|
887
|
+
await this.depotServerClient.getProject(groupId, artifactId),
|
|
888
|
+
);
|
|
889
|
+
const files = (
|
|
890
|
+
await this.depotServerClient.getGenerationFilesByType(
|
|
891
|
+
project,
|
|
892
|
+
versionId,
|
|
893
|
+
V1_DATA_PRODUCT_ELEMENT_PROTOCOL_TYPE,
|
|
894
|
+
)
|
|
895
|
+
).map((rawFile) => StoredFileGeneration.serialization.fromJson(rawFile));
|
|
896
|
+
const fileContent = guaranteeNonNullable(
|
|
897
|
+
files.find((e) => e.path === dataProductPath)?.file.content,
|
|
898
|
+
`Artifact generation not found for data product: ${groupId}:${artifactId}:${versionId}/${dataProductPath}`,
|
|
899
|
+
);
|
|
900
|
+
const result = V1_DataProductArtifact.serialization.fromJson(
|
|
901
|
+
JSON.parse(fileContent) as PlainObject,
|
|
902
|
+
);
|
|
903
|
+
return result;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
resolveDataProductMappingPath(
|
|
907
|
+
artifact: V1_DataProductArtifact,
|
|
908
|
+
executionContextId: string | undefined,
|
|
909
|
+
): string {
|
|
910
|
+
// Try native execution contexts first
|
|
911
|
+
if (artifact.nativeModelAccess) {
|
|
912
|
+
const native = artifact.nativeModelAccess;
|
|
913
|
+
if (executionContextId) {
|
|
914
|
+
const matchingContext = native.nativeModelExecutionContexts.find(
|
|
915
|
+
(ctx) => ctx.key === executionContextId,
|
|
916
|
+
);
|
|
917
|
+
if (matchingContext) {
|
|
918
|
+
return matchingContext.mapping;
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
// Fall back to default execution context
|
|
922
|
+
const defaultContext = native.nativeModelExecutionContexts.find(
|
|
923
|
+
(ctx) => ctx.key === native.defaultExecutionContext,
|
|
924
|
+
);
|
|
925
|
+
if (defaultContext) {
|
|
926
|
+
return defaultContext.mapping;
|
|
927
|
+
}
|
|
928
|
+
// Fall back to first context
|
|
929
|
+
const firstContext = native.nativeModelExecutionContexts[0];
|
|
930
|
+
if (firstContext) {
|
|
931
|
+
return firstContext.mapping;
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
// Try model access point groups
|
|
936
|
+
const modelGroups = artifact.accessPointGroups.filter(
|
|
937
|
+
(g): g is V1_ModelAccessPointGroupInfo =>
|
|
938
|
+
g instanceof V1_ModelAccessPointGroupInfo,
|
|
939
|
+
);
|
|
940
|
+
if (executionContextId) {
|
|
941
|
+
const matchingGroup = modelGroups.find(
|
|
942
|
+
(g) => g.id === executionContextId,
|
|
943
|
+
);
|
|
944
|
+
if (matchingGroup) {
|
|
945
|
+
return matchingGroup.mappingGeneration.path;
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
// Fall back to first model access point group
|
|
949
|
+
const firstGroup = modelGroups[0];
|
|
950
|
+
if (firstGroup) {
|
|
951
|
+
return firstGroup.mappingGeneration.path;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
throw new UnsupportedOperationError(
|
|
955
|
+
`Can't resolve mapping path for data product artifact`,
|
|
956
|
+
);
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
async buildGraphAndDataproductAnalyticsResult(
|
|
960
|
+
groupId: string,
|
|
961
|
+
artifactId: string,
|
|
962
|
+
versionId: string,
|
|
963
|
+
dataProductPath: string,
|
|
964
|
+
dataProductAccessType: DataProductAccessType,
|
|
965
|
+
accessPointId: string,
|
|
966
|
+
preFetchedArtifact?: V1_DataProductArtifact | undefined,
|
|
967
|
+
): Promise<DataProductAnalysisQueryResult> {
|
|
968
|
+
this.initState.setMessage('Fetching data product analysis result...');
|
|
969
|
+
const project = StoreProjectData.serialization.fromJson(
|
|
970
|
+
await this.depotServerClient.getProject(groupId, artifactId),
|
|
971
|
+
);
|
|
972
|
+
const graph_buildReport = createGraphBuilderReport();
|
|
973
|
+
const stopWatch = new StopWatch();
|
|
974
|
+
|
|
975
|
+
// initialize system
|
|
976
|
+
stopWatch.record();
|
|
977
|
+
await this.graphManagerState.initializeSystem();
|
|
978
|
+
stopWatch.record(GRAPH_MANAGER_EVENT.INITIALIZE_GRAPH_SYSTEM__SUCCESS);
|
|
979
|
+
|
|
980
|
+
const dependency_buildReport = createGraphBuilderReport();
|
|
981
|
+
const dataProductAnalysisResult = preFetchedArtifact
|
|
982
|
+
? await this.graphManagerState.graphManager.buildDataProductAnalysis(
|
|
983
|
+
preFetchedArtifact,
|
|
984
|
+
dataProductPath,
|
|
985
|
+
this.graphManagerState.graph,
|
|
986
|
+
accessPointId,
|
|
987
|
+
dataProductAccessType,
|
|
988
|
+
{ groupId, artifactId, versionId },
|
|
989
|
+
graph_buildReport,
|
|
990
|
+
)
|
|
991
|
+
: await this.graphManagerState.graphManager.analyzeDataProductAndBuildMinimalGraph(
|
|
992
|
+
dataProductPath,
|
|
993
|
+
async () => {
|
|
994
|
+
const files = (
|
|
995
|
+
await this.depotServerClient.getGenerationFilesByType(
|
|
996
|
+
project,
|
|
997
|
+
versionId,
|
|
998
|
+
V1_DATA_PRODUCT_ELEMENT_PROTOCOL_TYPE,
|
|
999
|
+
)
|
|
1000
|
+
).map((rawFile) =>
|
|
1001
|
+
StoredFileGeneration.serialization.fromJson(rawFile),
|
|
1002
|
+
);
|
|
1003
|
+
const fileContent = guaranteeNonNullable(
|
|
1004
|
+
files.find((e) => e.path === dataProductPath)?.file.content,
|
|
1005
|
+
`Artifact generation not found for data product: ${groupId}:${artifactId}:${versionId}/${dataProductPath}`,
|
|
1006
|
+
);
|
|
1007
|
+
return JSON.parse(fileContent) as PlainObject;
|
|
1008
|
+
},
|
|
1009
|
+
this.graphManagerState.graph,
|
|
1010
|
+
accessPointId,
|
|
1011
|
+
dataProductAccessType,
|
|
1012
|
+
{ groupId, artifactId, versionId },
|
|
1013
|
+
undefined,
|
|
1014
|
+
graph_buildReport,
|
|
1015
|
+
);
|
|
1016
|
+
|
|
1017
|
+
// report
|
|
1018
|
+
stopWatch.record(GRAPH_MANAGER_EVENT.INITIALIZE_GRAPH__SUCCESS);
|
|
1019
|
+
const graphBuilderReportData = {
|
|
1020
|
+
timings:
|
|
1021
|
+
this.applicationStore.timeService.finalizeTimingsRecord(stopWatch),
|
|
1022
|
+
dependencies: dependency_buildReport,
|
|
1023
|
+
dependenciesCount:
|
|
1024
|
+
this.graphManagerState.graph.dependencyManager.numberOfDependencies,
|
|
1025
|
+
graph: graph_buildReport,
|
|
1026
|
+
isLightGraphEnabled: true,
|
|
1027
|
+
};
|
|
1028
|
+
this.logBuildGraphMetrics(graphBuilderReportData);
|
|
1029
|
+
this.applicationStore.logService.info(
|
|
1030
|
+
LogEvent.create(GRAPH_MANAGER_EVENT.INITIALIZE_GRAPH__SUCCESS),
|
|
1031
|
+
graphBuilderReportData,
|
|
1032
|
+
);
|
|
1033
|
+
|
|
1034
|
+
return dataProductAnalysisResult;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
/**
|
|
1038
|
+
* Resolves the execution state for a data product by looking up `accessId`
|
|
1039
|
+
* in both model access point groups (by `id`) and native execution contexts
|
|
1040
|
+
* (by `key`). Throws if no matching state is found.
|
|
1041
|
+
*/
|
|
1042
|
+
resolveDataProductExecutionState(
|
|
1043
|
+
dataProduct: DataProduct,
|
|
1044
|
+
accessId: string | undefined,
|
|
1045
|
+
): NativeModelExecutionContext | ModelAccessPointGroup {
|
|
1046
|
+
// Search model access point groups
|
|
1047
|
+
const modelGroups = dataProduct.accessPointGroups.filter(
|
|
1048
|
+
filterByType(ModelAccessPointGroup),
|
|
1049
|
+
);
|
|
1050
|
+
if (accessId) {
|
|
1051
|
+
const matchingGroup = modelGroups.find((g) => g.id === accessId);
|
|
1052
|
+
if (matchingGroup) {
|
|
1053
|
+
return matchingGroup;
|
|
1054
|
+
}
|
|
1055
|
+
// Search native execution contexts
|
|
1056
|
+
const matchingNative =
|
|
1057
|
+
dataProduct.nativeModelAccess?.nativeModelExecutionContexts.find(
|
|
1058
|
+
(ctx) => ctx.key === accessId,
|
|
1059
|
+
);
|
|
1060
|
+
if (matchingNative) {
|
|
1061
|
+
return matchingNative;
|
|
1062
|
+
}
|
|
1063
|
+
} else {
|
|
1064
|
+
// No accessId: fall back to defaults
|
|
1065
|
+
if (dataProduct.nativeModelAccess) {
|
|
1066
|
+
return dataProduct.nativeModelAccess.defaultExecutionContext;
|
|
1067
|
+
}
|
|
1068
|
+
if (modelGroups.length > 0) {
|
|
1069
|
+
return guaranteeNonNullable(modelGroups[0]);
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
throw new UnsupportedOperationError(
|
|
1073
|
+
`Can't resolve execution state for data product '${dataProduct.path}'${accessId ? ` with access ID '${accessId}'` : ''}`,
|
|
1074
|
+
);
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
/**
|
|
1078
|
+
* Resolves the user's lakehouse environment and warehouse, creates a
|
|
1079
|
+
* `LakehouseRuntime`, and wraps it in a `PackageableRuntime`.
|
|
1080
|
+
*
|
|
1081
|
+
* Resolution order:
|
|
1082
|
+
* 1. Check local storage (`LakehouseUserInfo`) for a previously persisted value.
|
|
1083
|
+
* 2. If not found, fetch from the lakehouse contract server via
|
|
1084
|
+
* `getUserEntitlementEnvs()` and persist the result to local storage.
|
|
1085
|
+
*/
|
|
1086
|
+
async createLakehousePackageableRuntime(
|
|
1087
|
+
dataProductPath: string,
|
|
1088
|
+
gav: {
|
|
1089
|
+
groupId: string;
|
|
1090
|
+
artifactId: string;
|
|
1091
|
+
versionId: string;
|
|
1092
|
+
},
|
|
1093
|
+
): Promise<PackageableRuntime> {
|
|
1094
|
+
// 1. Check local storage for persisted lakehouse user info
|
|
1095
|
+
const persistedInfo = LegendQueryUserDataHelper.getLakehouseUserInfo(
|
|
1096
|
+
this.applicationStore.userDataService,
|
|
1097
|
+
);
|
|
1098
|
+
|
|
1099
|
+
let userEnvironment: string | undefined = persistedInfo?.env;
|
|
1100
|
+
const userWarehouse: string | undefined =
|
|
1101
|
+
persistedInfo?.snowflakeWarehouse ?? 'LAKEHOUSE_CONSUMER_DEFAULT_WH';
|
|
1102
|
+
// 2. If no persisted environment, fetch from the server
|
|
1103
|
+
if (userEnvironment === undefined && this.lakehouseState) {
|
|
1104
|
+
try {
|
|
1105
|
+
const entitlementEnvs =
|
|
1106
|
+
await this.lakehouseState.contractServerClient.getUserEntitlementEnvs(
|
|
1107
|
+
this.applicationStore.identityService.currentUser,
|
|
1108
|
+
this.applicationStore.getAccessToken(),
|
|
1109
|
+
);
|
|
1110
|
+
userEnvironment = entitlementEnvs.users
|
|
1111
|
+
.map((e) => e.lakehouseEnvironment)
|
|
1112
|
+
.at(0);
|
|
1113
|
+
// Persist to local storage for future use
|
|
1114
|
+
LegendQueryUserDataHelper.persistLakehouseUserInfo(
|
|
1115
|
+
this.applicationStore.userDataService,
|
|
1116
|
+
{
|
|
1117
|
+
env: userEnvironment,
|
|
1118
|
+
snowflakeWarehouse: userWarehouse,
|
|
1119
|
+
},
|
|
1120
|
+
);
|
|
1121
|
+
} catch (error) {
|
|
1122
|
+
assertErrorThrown(error);
|
|
1123
|
+
this.applicationStore.logService.warn(
|
|
1124
|
+
LogEvent.create(LEGEND_QUERY_APP_EVENT.GENERIC_FAILURE),
|
|
1125
|
+
`Unable to fetch user lakehouse environment: ${error.message}`,
|
|
1126
|
+
);
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
if (userEnvironment === undefined) {
|
|
1131
|
+
throw new Error(
|
|
1132
|
+
`Can't query data product '${dataProductPath}': unable to resolve lakehouse user environment. ` +
|
|
1133
|
+
`Please ensure your lakehouse entitlements are configured.`,
|
|
1134
|
+
);
|
|
1135
|
+
}
|
|
1136
|
+
if (
|
|
1137
|
+
isSnapshotVersion(gav.versionId) ||
|
|
1138
|
+
gav.versionId === SNAPSHOT_VERSION_ALIAS
|
|
1139
|
+
) {
|
|
1140
|
+
userEnvironment = decorateEnvWithRealm(
|
|
1141
|
+
userEnvironment,
|
|
1142
|
+
LakehouseEnvironmentType.PRODUCTION_PARALLEL,
|
|
1143
|
+
);
|
|
1144
|
+
}
|
|
1145
|
+
const lakehouseRuntime = new LakehouseRuntime(
|
|
1146
|
+
userEnvironment,
|
|
1147
|
+
userWarehouse,
|
|
1148
|
+
);
|
|
1149
|
+
const packageableRuntime = new PackageableRuntime(
|
|
1150
|
+
`${dataProductPath}_LakehouseRuntime`,
|
|
1151
|
+
);
|
|
1152
|
+
packageableRuntime.runtimeValue = lakehouseRuntime;
|
|
1153
|
+
return packageableRuntime;
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
/**
|
|
1157
|
+
* Centralized method to build a data product query builder state.
|
|
1158
|
+
* Used by both the creator flow (new query from data product route/picker)
|
|
1159
|
+
* and the existing query flow (loading a saved data product query).
|
|
1160
|
+
*
|
|
1161
|
+
* This fetches the data product artifact, resolves the mapping path,
|
|
1162
|
+
* builds the minimal graph via `buildGraphAndDataproductAnalyticsResult`,
|
|
1163
|
+
* creates `LegendQueryDataProductQueryBuilderState`, and wires in
|
|
1164
|
+
* mapping coverage results.
|
|
1165
|
+
*/
|
|
1166
|
+
async buildDataProductQueryBuilderState(
|
|
1167
|
+
groupId: string,
|
|
1168
|
+
artifactId: string,
|
|
1169
|
+
versionId: string,
|
|
1170
|
+
dataProductPath: string,
|
|
1171
|
+
artifact: V1_DataProductArtifact,
|
|
1172
|
+
accessId: string,
|
|
1173
|
+
dataProductAccessType: DataProductAccessType,
|
|
1174
|
+
onDataProductChange: (val: DepotEntityWithOrigin) => Promise<void>,
|
|
1175
|
+
productSelectorState?: DataProductSelectorState | undefined,
|
|
1176
|
+
): Promise<LegendQueryDataProductQueryBuilderState> {
|
|
1177
|
+
// 3. Build minimal graph and get analysis result
|
|
1178
|
+
const dataProductAnalysisResult =
|
|
1179
|
+
await this.buildGraphAndDataproductAnalyticsResult(
|
|
1180
|
+
groupId,
|
|
1181
|
+
artifactId,
|
|
1182
|
+
versionId,
|
|
1183
|
+
dataProductPath,
|
|
1184
|
+
dataProductAccessType,
|
|
1185
|
+
accessId,
|
|
1186
|
+
artifact,
|
|
1187
|
+
);
|
|
1188
|
+
// 3.5. Create a LakehouseRuntime and add it to the graph
|
|
1189
|
+
const packageableRuntime = await this.createLakehousePackageableRuntime(
|
|
1190
|
+
dataProductPath,
|
|
1191
|
+
{
|
|
1192
|
+
groupId,
|
|
1193
|
+
artifactId,
|
|
1194
|
+
versionId,
|
|
1195
|
+
},
|
|
1196
|
+
);
|
|
1197
|
+
this.graphManagerState.graph.addElement(packageableRuntime, '_internal_');
|
|
1198
|
+
// 4. Get the data product from the built graph
|
|
1199
|
+
const dataProduct =
|
|
1200
|
+
this.graphManagerState.graph.getDataProduct(dataProductPath);
|
|
1201
|
+
// 5. Resolve execution state from accessId
|
|
1202
|
+
const resolvedState = this.resolveDataProductExecutionState(
|
|
1203
|
+
dataProduct,
|
|
1204
|
+
accessId,
|
|
1205
|
+
);
|
|
1206
|
+
|
|
1207
|
+
// 6. Create query builder state
|
|
1208
|
+
const projectInfo = { groupId, artifactId, versionId };
|
|
1209
|
+
const sourceInfo = {
|
|
1210
|
+
groupId,
|
|
1211
|
+
artifactId,
|
|
1212
|
+
versionId,
|
|
1213
|
+
dataProduct: dataProductPath,
|
|
1214
|
+
};
|
|
1215
|
+
const queryBuilderState = new LegendQueryDataProductQueryBuilderState(
|
|
1216
|
+
this.applicationStore,
|
|
1217
|
+
this.graphManagerState,
|
|
1218
|
+
QueryBuilderDataBrowserWorkflow.INSTANCE,
|
|
1219
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
1220
|
+
new QueryBuilderActionConfig_QueryApplication(this),
|
|
1221
|
+
dataProduct,
|
|
1222
|
+
artifact,
|
|
1223
|
+
resolvedState,
|
|
1224
|
+
this.depotServerClient,
|
|
1225
|
+
projectInfo,
|
|
1226
|
+
onDataProductChange,
|
|
1227
|
+
productSelectorState ??
|
|
1228
|
+
new DataProductSelectorState(
|
|
1229
|
+
this.depotServerClient,
|
|
1230
|
+
this.applicationStore,
|
|
1231
|
+
),
|
|
1232
|
+
undefined,
|
|
1233
|
+
undefined,
|
|
1234
|
+
this.applicationStore.config.options.queryBuilderConfig,
|
|
1235
|
+
sourceInfo,
|
|
1236
|
+
);
|
|
1237
|
+
// Pass pre-resolved state to avoid double-resolution
|
|
1238
|
+
queryBuilderState.initWithDataProduct(dataProduct, resolvedState);
|
|
1239
|
+
|
|
1240
|
+
// 7. Wire in mapping coverage result
|
|
1241
|
+
const mappingCoverageResult =
|
|
1242
|
+
dataProductAnalysisResult.dataProductAnalysis.mappingToMappingCoverageResult?.get(
|
|
1243
|
+
dataProductAnalysisResult.targetMappingPath,
|
|
1244
|
+
);
|
|
1245
|
+
if (mappingCoverageResult) {
|
|
1246
|
+
queryBuilderState.explorerState.mappingModelCoverageAnalysisResult =
|
|
1247
|
+
mappingCoverageResult;
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
// init
|
|
1251
|
+
const execValue = dataProductAnalysisResult.targetExecState;
|
|
1252
|
+
queryBuilderState.executionState =
|
|
1253
|
+
execValue instanceof NativeModelExecutionContext
|
|
1254
|
+
? new NativeModelDataProductExecutionState(execValue, queryBuilderState)
|
|
1255
|
+
: new ModelAccessPointDataProductExecutionState(
|
|
1256
|
+
execValue,
|
|
1257
|
+
queryBuilderState,
|
|
1258
|
+
).withAdhocRuntime();
|
|
1259
|
+
queryBuilderState.changeMapping(queryBuilderState.executionState.mapping);
|
|
1260
|
+
queryBuilderState.changeRuntime(
|
|
1261
|
+
new RuntimePointer(
|
|
1262
|
+
PackageableElementExplicitReference.create(packageableRuntime),
|
|
1263
|
+
),
|
|
1264
|
+
);
|
|
1265
|
+
return queryBuilderState;
|
|
1266
|
+
}
|
|
830
1267
|
}
|
|
831
1268
|
|
|
832
1269
|
export class QueryBuilderActionConfig_QueryApplication extends QueryBuilderActionConfig {
|
|
@@ -1451,7 +1888,11 @@ export class ExistingQueryEditorStore extends QueryEditorStore {
|
|
|
1451
1888
|
!(
|
|
1452
1889
|
dataSpaceTaggedValue !== undefined ||
|
|
1453
1890
|
queryInfo?.executionContext instanceof
|
|
1454
|
-
QueryDataSpaceExecutionContextInfo
|
|
1891
|
+
QueryDataSpaceExecutionContextInfo ||
|
|
1892
|
+
queryInfo?.executionContext instanceof
|
|
1893
|
+
QueryDataProductNativeExecutionContextInfo ||
|
|
1894
|
+
queryInfo?.executionContext instanceof
|
|
1895
|
+
QueryDataProductModelAccessExecutionContextInfo
|
|
1455
1896
|
)
|
|
1456
1897
|
) {
|
|
1457
1898
|
yield flowResult(this.buildFullGraph());
|
|
@@ -1603,6 +2044,15 @@ export class ExistingQueryEditorStore extends QueryEditorStore {
|
|
|
1603
2044
|
);
|
|
1604
2045
|
}
|
|
1605
2046
|
},
|
|
2047
|
+
new DataProductSelectorState(
|
|
2048
|
+
this.depotServerClient,
|
|
2049
|
+
this.applicationStore,
|
|
2050
|
+
),
|
|
2051
|
+
() => {
|
|
2052
|
+
this.applicationStore.notificationService.notifyWarning(
|
|
2053
|
+
'Switching data products is not supported from the existing query editor. Please open a new query instead.',
|
|
2054
|
+
);
|
|
2055
|
+
},
|
|
1606
2056
|
dataSpaceAnalysisResult,
|
|
1607
2057
|
undefined,
|
|
1608
2058
|
undefined,
|
|
@@ -1667,6 +2117,39 @@ export class ExistingQueryEditorStore extends QueryEditorStore {
|
|
|
1667
2117
|
: undefined,
|
|
1668
2118
|
);
|
|
1669
2119
|
return classQueryBuilderState;
|
|
2120
|
+
} else if (
|
|
2121
|
+
exec instanceof QueryDataProductNativeExecutionContextInfo ||
|
|
2122
|
+
exec instanceof QueryDataProductModelAccessExecutionContextInfo
|
|
2123
|
+
) {
|
|
2124
|
+
const executionContextId =
|
|
2125
|
+
exec instanceof QueryDataProductNativeExecutionContextInfo
|
|
2126
|
+
? exec.executionKey
|
|
2127
|
+
: exec.accessPointGroupId;
|
|
2128
|
+
const accessType =
|
|
2129
|
+
exec instanceof QueryDataProductNativeExecutionContextInfo
|
|
2130
|
+
? DataProductAccessType.NATIVE
|
|
2131
|
+
: DataProductAccessType.MODEL;
|
|
2132
|
+
const artifact = await this.fetchDataProductArtifact(
|
|
2133
|
+
queryInfo.groupId,
|
|
2134
|
+
queryInfo.artifactId,
|
|
2135
|
+
queryInfo.versionId,
|
|
2136
|
+
exec.dataProductPath,
|
|
2137
|
+
);
|
|
2138
|
+
const queryBuilderState = await this.buildDataProductQueryBuilderState(
|
|
2139
|
+
queryInfo.groupId,
|
|
2140
|
+
queryInfo.artifactId,
|
|
2141
|
+
queryInfo.versionId,
|
|
2142
|
+
exec.dataProductPath,
|
|
2143
|
+
artifact,
|
|
2144
|
+
executionContextId,
|
|
2145
|
+
accessType,
|
|
2146
|
+
async () => {
|
|
2147
|
+
this.applicationStore.notificationService.notifyWarning(
|
|
2148
|
+
'Switching data products is not supported from the existing query editor. Please open a new query instead.',
|
|
2149
|
+
);
|
|
2150
|
+
},
|
|
2151
|
+
);
|
|
2152
|
+
return queryBuilderState;
|
|
1670
2153
|
}
|
|
1671
2154
|
throw new UnsupportedOperationError(`Unsupported query execution context`);
|
|
1672
2155
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026-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
|
+
DataProductAccessType,
|
|
19
|
+
V1_ModelAccessPointGroupInfo,
|
|
20
|
+
type V1_DataProductArtifact,
|
|
21
|
+
} from '@finos/legend-graph';
|
|
22
|
+
import { filterByType } from '@finos/legend-shared';
|
|
23
|
+
|
|
24
|
+
export const resolveDefaultDataProductAccessType = (
|
|
25
|
+
dataProductArtifact: V1_DataProductArtifact,
|
|
26
|
+
): { type: DataProductAccessType; id: string } => {
|
|
27
|
+
const modelAcessGroup = dataProductArtifact.accessPointGroups.filter(
|
|
28
|
+
filterByType(V1_ModelAccessPointGroupInfo),
|
|
29
|
+
)[0];
|
|
30
|
+
if (modelAcessGroup) {
|
|
31
|
+
return {
|
|
32
|
+
type: DataProductAccessType.MODEL,
|
|
33
|
+
id: modelAcessGroup.id,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const native =
|
|
38
|
+
dataProductArtifact.nativeModelAccess?.nativeModelExecutionContexts[0];
|
|
39
|
+
if (native) {
|
|
40
|
+
return {
|
|
41
|
+
type: DataProductAccessType.NATIVE,
|
|
42
|
+
id: native.key,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
throw new Error(
|
|
46
|
+
`Data Product not supported for querying on legend query ${dataProductArtifact.dataProduct.path}. Must contain a model access point or native model access.`,
|
|
47
|
+
);
|
|
48
|
+
};
|