UNPKG

@finos/legend-application-studio

Version:
553 lines 31.7 kB
/** * Copyright (c) 2020-present, Goldman Sachs * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { action, computed, flow, flowResult, makeObservable, observable, } from 'mobx'; import { GRAPH_EDITOR_MODE } from './EditorConfig.js'; import { LogEvent, UnsupportedOperationError, assertErrorThrown, assertTrue, isNonNullable, NetworkClientError, guaranteeNonNullable, StopWatch, filterByType, ActionState, } from '@finos/legend-shared'; import { ElementEditorState } from './editor-state/element-editor-state/ElementEditorState.js'; import { GraphGenerationState } from './editor-state/GraphGenerationState.js'; import { MODEL_IMPORT_NATIVE_INPUT_TYPE } from './editor-state/ModelImporterState.js'; import { EntitiesWithOrigin } from '@finos/legend-storage'; import { ProjectConfiguration, applyEntityChanges, } from '@finos/legend-server-sdlc'; import { ProjectVersionEntities, ProjectDependencyCoordinates, RawProjectDependencyReport, buildDependencyReport, } from '@finos/legend-server-depot'; import { GRAPH_MANAGER_EVENT, Package, Profile, PrimitiveType, Enumeration, Class, Association, Mapping, ConcreteFunctionDefinition, Service, FlatData, PackageableConnection, PackageableRuntime, FileGenerationSpecification, GenerationSpecification, Measure, Unit, Database, SectionIndex, DependencyGraphBuilderError, GraphDataDeserializationError, DataElement, createGraphBuilderReport, ExecutionEnvironmentInstance, SnowflakeApp, GraphEntities, HostedService, } from '@finos/legend-graph'; import { CONFIGURATION_EDITOR_TAB } from './editor-state/project-configuration-editor-state/ProjectConfigurationEditorState.js'; import { PACKAGEABLE_ELEMENT_TYPE } from './utils/ModelClassifierUtils.js'; import { LEGEND_STUDIO_APP_EVENT } from '../../__lib__/LegendStudioEvent.js'; import { LEGEND_STUDIO_SETTING_KEY } from '../../__lib__/LegendStudioSetting.js'; import { LegendStudioTelemetryHelper } from '../../__lib__/LegendStudioTelemetryHelper.js'; export var GraphBuilderStatus; (function (GraphBuilderStatus) { GraphBuilderStatus["SUCCEEDED"] = "SUCCEEDED"; GraphBuilderStatus["FAILED"] = "FAILED"; GraphBuilderStatus["REDIRECTED_TO_TEXT_MODE"] = "REDIRECTED_TO_TEXT_MODE"; })(GraphBuilderStatus || (GraphBuilderStatus = {})); export var GraphCompilationOutcome; (function (GraphCompilationOutcome) { GraphCompilationOutcome["SKIPPED"] = "SKIPPED"; GraphCompilationOutcome["SUCCEEDED"] = "SUCCEEDED"; GraphCompilationOutcome["FAILED"] = "FAILED"; })(GraphCompilationOutcome || (GraphCompilationOutcome = {})); export class EditorGraphState { editorStore; graphGenerationState; isInitializingGraph = false; isRunningGlobalCompile = false; isRunningGlobalGenerate = false; isApplicationLeavingGraphEditMode = false; isUpdatingGraph = false; // critical synchronous update to refresh the graph isUpdatingApplication = false; // including graph update and async operations such as change detection functionActivatorConfigurations = []; relationalDatabseTypeConfigurations; warnings = []; error; compilationResultEntities = []; enableStrictMode; mostRecentCompilationGraphHash = undefined; mostRecentCompilationOutcome = undefined; constructor(editorStore) { makeObservable(this, { isInitializingGraph: observable, isRunningGlobalCompile: observable, isRunningGlobalGenerate: observable, isApplicationLeavingGraphEditMode: observable, isUpdatingGraph: observable, isUpdatingApplication: observable, functionActivatorConfigurations: observable, mostRecentCompilationGraphHash: observable, mostRecentCompilationOutcome: observable, warnings: observable, error: observable, enableStrictMode: observable, relationalDatabseTypeConfigurations: observable, problems: computed, areProblemsStale: computed, isApplicationUpdateOperationIsRunning: computed, clearProblems: action, setEnableStrictMode: action, setMostRecentCompilationGraphHash: action, fetchAvailableRelationalDatabseTypeConfigurations: flow, fetchAvailableFunctionActivatorConfigurations: flow, buildGraph: flow, loadEntityChangesToGraph: flow, updateGenerationGraphAndApplication: flow, rebuildDependencies: flow, buildGraphForLazyText: flow, }); this.editorStore = editorStore; this.graphGenerationState = new GraphGenerationState(this.editorStore); this.enableStrictMode = this.editorStore.applicationStore.settingService.getBooleanValue(LEGEND_STUDIO_SETTING_KEY.EDITOR_STRICT_MODE) ?? false; } get problems() { return [this.error, ...this.warnings].filter(isNonNullable); } /** * This function is temporary. There is no good way to detect if a problem not coming from * the main graph at the moment. In text mode, we can rely on the fact that the source information * has line 0 column 0. But this is not the case for form mode, so this is just temporary * to help with text-mode. */ TEMPORARY__removeDependencyProblems(problems) { return problems.filter((problem) => { if (problem.sourceInformation) { return !(problem.sourceInformation.startLine === 0 && problem.sourceInformation.startColumn === 0 && problem.sourceInformation.endLine === 0 && problem.sourceInformation.endColumn === 0); } return true; }); } setMostRecentCompilationGraphHash(val) { this.mostRecentCompilationGraphHash = val; } setMostRecentCompilationOutcome(val) { this.mostRecentCompilationOutcome = val; } get areProblemsStale() { return (this.mostRecentCompilationGraphHash !== this.editorStore.graphEditorMode.getCurrentGraphHash()); } get isApplicationUpdateOperationIsRunning() { return (this.isRunningGlobalCompile || this.isRunningGlobalGenerate || this.isApplicationLeavingGraphEditMode || this.isUpdatingApplication || this.isInitializingGraph); } checkIfApplicationUpdateOperationIsRunning() { if (this.isRunningGlobalGenerate) { this.editorStore.applicationStore.notificationService.notifyWarning('Please wait for model generation to complete'); return true; } if (this.isRunningGlobalCompile) { this.editorStore.applicationStore.notificationService.notifyWarning('Please wait for graph compilation to complete'); return true; } if (this.isApplicationLeavingGraphEditMode) { this.editorStore.applicationStore.notificationService.notifyWarning('Please wait for editor to leave edit mode completely'); return true; } if (this.isUpdatingApplication) { this.editorStore.applicationStore.notificationService.notifyWarning('Please wait for editor state to rebuild'); return true; } if (this.isInitializingGraph) { this.editorStore.applicationStore.notificationService.notifyWarning('Please wait for editor initialization to complete'); return true; } return false; } clearProblems() { this.error = undefined; this.editorStore.tabManagerState.tabs .filter(filterByType(ElementEditorState)) .forEach((editorState) => editorState.clearCompilationError()); this.mostRecentCompilationGraphHash = undefined; this.warnings = []; } setEnableStrictMode(val) { this.enableStrictMode = val; } *fetchAvailableFunctionActivatorConfigurations() { try { this.functionActivatorConfigurations = (yield this.editorStore.graphManagerState.graphManager.getAvailableFunctionActivatorConfigurations(this.editorStore.graphManagerState.coreModel, this.editorStore.graphManagerState.systemModel)); } catch (error) { assertErrorThrown(error); this.editorStore.applicationStore.logService.error(LogEvent.create(LEGEND_STUDIO_APP_EVENT.GENERIC_FAILURE), error); this.editorStore.applicationStore.notificationService.notifyError(error); } } *fetchAvailableRelationalDatabseTypeConfigurations() { try { this.relationalDatabseTypeConfigurations = (yield this.editorStore.graphManagerState.graphManager.getAvailableRelationalDatabaseTypeConfigurations()); } catch (error) { assertErrorThrown(error); this.editorStore.applicationStore.logService.error(LogEvent.create(LEGEND_STUDIO_APP_EVENT.GENERIC_FAILURE), error); this.editorStore.applicationStore.notificationService.notifyError(error); } } findRelationalDatabaseTypeConfiguration(type) { return this.relationalDatabseTypeConfigurations?.find((aFlow) => aFlow.type === type); } *buildGraph(entities) { try { this.isInitializingGraph = true; const stopWatch = new StopWatch(); // reset this.editorStore.graphManagerState.resetGraph(); // fetch and build dependencies stopWatch.record(); const dependencyManager = this.editorStore.graphManagerState.graphManager.createDependencyManager(); this.editorStore.graphManagerState.graph.dependencyManager = dependencyManager; this.editorStore.graphManagerState.dependenciesBuildState.setMessage(`Fetching dependencies...`); const dependencyEntitiesIndex = (yield flowResult(this.getIndexedDependencyEntities())); stopWatch.record(GRAPH_MANAGER_EVENT.FETCH_GRAPH_DEPENDENCIES__SUCCESS); const dependency_buildReport = createGraphBuilderReport(); yield this.editorStore.graphManagerState.graphManager.buildDependencies(this.editorStore.graphManagerState.coreModel, this.editorStore.graphManagerState.systemModel, dependencyManager, dependencyEntitiesIndex, this.editorStore.graphManagerState.dependenciesBuildState, {}, dependency_buildReport); dependency_buildReport.timings[GRAPH_MANAGER_EVENT.FETCH_GRAPH_DEPENDENCIES__SUCCESS] = stopWatch.getRecord(GRAPH_MANAGER_EVENT.FETCH_GRAPH_DEPENDENCIES__SUCCESS); // build graph const graph_buildReport = createGraphBuilderReport(); yield this.editorStore.graphManagerState.graphManager.buildGraph(this.editorStore.graphManagerState.graph, entities, this.editorStore.graphManagerState.graphBuildState, { TEMPORARY__preserveSectionIndex: this.editorStore.applicationStore.config.options .TEMPORARY__preserveSectionIndex, strict: this.enableStrictMode, }, graph_buildReport); // build generations const generation_buildReport = createGraphBuilderReport(); yield this.editorStore.graphManagerState.graphManager.buildGenerations(this.editorStore.graphManagerState.graph, this.graphGenerationState.generatedEntities, this.editorStore.graphManagerState.generationsBuildState, {}, generation_buildReport); // report stopWatch.record(GRAPH_MANAGER_EVENT.INITIALIZE_GRAPH__SUCCESS); const graphBuilderReportData = { timings: this.editorStore.applicationStore.timeService.finalizeTimingsRecord(stopWatch), dependencies: dependency_buildReport, dependenciesCount: this.editorStore.graphManagerState.graph.dependencyManager .numberOfDependencies, graph: graph_buildReport, generations: generation_buildReport, generationsCount: this.graphGenerationState.generatedEntities.size, }; LegendStudioTelemetryHelper.logEvent_GraphInitializationSucceeded(this.editorStore.applicationStore.telemetryService, graphBuilderReportData); this.editorStore.applicationStore.logService.info(LogEvent.create(GRAPH_MANAGER_EVENT.INITIALIZE_GRAPH__SUCCESS), graphBuilderReportData); // add generation specification if model generation elements exists in graph and no generation specification yield flowResult(this.graphGenerationState.possiblyAddMissingGenerationSpecifications()); return { status: GraphBuilderStatus.SUCCEEDED, }; } catch (error) { assertErrorThrown(error); this.editorStore.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.GRAPH_BUILDER_FAILURE), error); if (error instanceof DependencyGraphBuilderError) { this.editorStore.graphManagerState.graphBuildState.fail(); // no recovery if dependency models cannot be built, this makes assumption that all dependencies models are compiled successfully // TODO: we might want to handle this more gracefully when we can show people the dependency model element in the future this.editorStore.applicationStore.notificationService.notifyError(`Can't initialize dependency models. Error: ${error.message}`); const projectConfigurationEditorState = this.editorStore.projectConfigurationEditorState; projectConfigurationEditorState.setSelectedTab(CONFIGURATION_EDITOR_TAB.PROJECT_DEPENDENCIES); this.editorStore.tabManagerState.openTab(projectConfigurationEditorState); } else if (error instanceof GraphDataDeserializationError) { // if something goes wrong with de-serialization, redirect to model importer to fix this.redirectToModelImporterForDebugging(error); } else if (error instanceof NetworkClientError) { this.editorStore.graphManagerState.graphBuildState.fail(); this.editorStore.applicationStore.notificationService.notifyWarning(`Can't build graph. Error: ${error.message}`); } else { // TODO: we should split this into 2 notifications when we support multiple notifications this.editorStore.applicationStore.notificationService.notifyError(`Can't build graph. Redirected to text mode for debugging. Error: ${error.message}`); this.editorStore.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.GRAPH_BUILDER_FAILURE), error); try { yield flowResult(this.editorStore.switchModes(GRAPH_EDITOR_MODE.GRAMMAR_TEXT, { isGraphBuildFailure: true, })); } catch (error2) { assertErrorThrown(error2); this.editorStore.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.GRAPH_BUILDER_FAILURE), error2); if (error2 instanceof NetworkClientError) { // in case the server cannot even transform the JSON due to corrupted protocol, we can redirect to model importer this.redirectToModelImporterForDebugging(error2); return { status: GraphBuilderStatus.FAILED, error: error2, }; } if (error2 instanceof Error) { return { status: GraphBuilderStatus.FAILED, error: error2, }; } } return { status: GraphBuilderStatus.REDIRECTED_TO_TEXT_MODE, error, }; } return { status: GraphBuilderStatus.FAILED, error, }; } finally { this.isInitializingGraph = false; } } *buildGraphForLazyText() { this.isInitializingGraph = true; const stopWatch = new StopWatch(); // reset this.editorStore.graphManagerState.resetGraph(); // fetch and build dependencies stopWatch.record(); const dependencyManager = this.editorStore.graphManagerState.graphManager.createDependencyManager(); this.editorStore.graphManagerState.graph.dependencyManager = dependencyManager; this.editorStore.graphManagerState.dependenciesBuildState.setMessage(`Fetching dependencies...`); const dependencyEntitiesIndex = (yield flowResult(this.getIndexedDependencyEntities())); stopWatch.record(GRAPH_MANAGER_EVENT.FETCH_GRAPH_DEPENDENCIES__SUCCESS); dependencyManager.initialize(dependencyEntitiesIndex); // set dependency manager graph origin to entities if (dependencyManager.origin === undefined) { dependencyManager.setOrigin(new GraphEntities(Array.from(dependencyEntitiesIndex.values()) .map((e) => e.entities) .flat())); } this.isInitializingGraph = false; this.editorStore.graphManagerState.dependenciesBuildState.sync(ActionState.create().pass()); } redirectToModelImporterForDebugging(error) { if (this.editorStore.isInConflictResolutionMode) { this.editorStore.applicationStore.alertService.setBlockingAlert({ message: `Can't de-serialize graph model from entities`, prompt: `Please refresh the application and abort conflict resolution`, }); return; } this.editorStore.applicationStore.notificationService.notifyWarning(`Can't de-serialize graph model from entities. Redirected to model importer for debugging. Error: ${error.message}`); const nativeImporterState = this.editorStore.modelImporterState.setNativeImportType(MODEL_IMPORT_NATIVE_INPUT_TYPE.ENTITIES); // Making an async call nativeImporterState.loadCurrentProjectEntities(); this.editorStore.tabManagerState.openTab(this.editorStore.modelImporterState); } /** * Loads entity changes to graph and updates application. */ *loadEntityChangesToGraph(changes, baseEntities) { try { assertTrue(this.editorStore.graphEditorMode.mode === GRAPH_EDITOR_MODE.FORM, `Can't apply entity changes: operation only supported in form mode`); const entities = baseEntities ?? this.editorStore.graphManagerState.graph.allOwnElements.map((element) => this.editorStore.graphManagerState.graphManager.elementToEntity(element)); const modifiedEntities = applyEntityChanges(entities, changes); yield flowResult(this.editorStore.graphEditorMode.updateGraphAndApplication(modifiedEntities)); } catch (error) { assertErrorThrown(error); this.editorStore.applicationStore.notificationService.notifyError(`Can't load entity changes: ${error.message}`); } } /** * NOTE: this can post memory-leak issue if we start having immutable elements referencing current graph elements: * e.g. subclass analytics on the immutable class, etc. * * @risk memory-leak */ *rebuildDependencies(newGraph) { if (this.editorStore.graphManagerState.dependenciesBuildState.hasSucceeded) { newGraph.dependencyManager = this.editorStore.graphManagerState.graph.dependencyManager; } else { this.editorStore.projectConfigurationEditorState.setProjectConfiguration(ProjectConfiguration.serialization.fromJson((yield this.editorStore.sdlcServerClient.getConfiguration(this.editorStore.sdlcState.activeProject.projectId, this.editorStore.sdlcState.activeWorkspace)))); const dependencyManager = this.editorStore.graphManagerState.graphManager.createDependencyManager(); newGraph.dependencyManager = dependencyManager; const dependenciesBuildState = ActionState.create(); yield this.editorStore.graphManagerState.graphManager.buildDependencies(this.editorStore.graphManagerState.coreModel, this.editorStore.graphManagerState.systemModel, dependencyManager, (yield flowResult(this.getIndexedDependencyEntities())), dependenciesBuildState); // NOTE: here we don't want to modify the current graph build state directly // instead, we quietly run this in the background and then sync it with the current build state this.editorStore.graphManagerState.dependenciesBuildState.sync(dependenciesBuildState); } } /** * Used to update generation model and generation graph using the generated entities * does not alter the main or dependency model */ *updateGenerationGraphAndApplication() { assertTrue(this.editorStore.graphManagerState.graphBuildState.hasSucceeded && this.editorStore.graphManagerState.dependenciesBuildState.hasSucceeded, 'Both main model and dependencies must be processed to built generation graph'); this.isUpdatingApplication = true; try { this.editorStore.tabManagerState.cacheAndClose({ cacheGeneration: true }); yield flowResult(this.editorStore.graphManagerState.graph.generationModel.dispose()); // we reset the generation model this.editorStore.graphManagerState.graph.generationModel = this.editorStore.graphManagerState.graphManager.createGenerationModel(); yield this.editorStore.graphManagerState.graphManager.buildGenerations(this.editorStore.graphManagerState.graph, this.graphGenerationState.generatedEntities, this.editorStore.graphManagerState.generationsBuildState); this.editorStore.explorerTreeState.reprocess(); this.editorStore.tabManagerState.recoverTabs(); } catch (error) { assertErrorThrown(error); this.editorStore.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.GRAPH_BUILDER_FAILURE), error); this.editorStore.applicationStore.notificationService.notifyError(`Can't build graph: ${error.message}`); } finally { this.isUpdatingApplication = false; } } async getIndexedDependencyEntities() { const dependencyEntitiesIndex = new Map(); const currentConfiguration = this.editorStore.projectConfigurationEditorState .currentProjectConfiguration; try { if (currentConfiguration.projectDependencies.length) { const dependencyCoordinates = await this.buildProjectDependencyCoordinates(currentConfiguration.projectDependencies); // NOTE: if A@v1 is transitive dependencies of 2 or more // direct dependencies, metadata server will take care of deduplication const dependencyEntitiesJson = await this.editorStore.depotServerClient.collectDependencyEntities(dependencyCoordinates.map((e) => ProjectDependencyCoordinates.serialization.toJson(e)), true, true); const dependencyEntities = dependencyEntitiesJson.map((e) => ProjectVersionEntities.serialization.fromJson(e)); const dependencyProjects = new Map(); dependencyEntities.forEach((dependencyInfo) => { const projectId = dependencyInfo.id; // There are a few validations that must be done: // 1. Unlike above, if in the depdendency graph, we have both A@v1 and A@v2 // then we need to throw. Both SDLC and metadata server should handle this // validation, but haven't, so for now, we can do that in Studio. // 2. Same as the previous case, but for version-to-version transformation // This is a special case that needs handling, right now, SDLC does auto // healing, by scanning all the path and convert them into versioned path // e.g. model::someClass -> project1::v1_0_0::model::someClass // But this is a rare and advanced use-case which we will not attempt to handle now. if (dependencyProjects.has(projectId)) { dependencyProjects.get(projectId)?.add(dependencyInfo.versionId); } else { dependencyProjects.set(dependencyInfo.id, new Set([dependencyInfo.versionId])); } dependencyEntitiesIndex.set(dependencyInfo.id, new EntitiesWithOrigin(dependencyInfo.groupId, dependencyInfo.artifactId, dependencyInfo.versionId, dependencyInfo.entities)); }); const hasConflicts = Array.from(dependencyProjects.entries()).find(([k, v]) => v.size > 1); if (hasConflicts) { let dependencyInfo; try { const dependencyTree = await this.editorStore.depotServerClient.analyzeDependencyTree(dependencyCoordinates.map((e) => ProjectDependencyCoordinates.serialization.toJson(e))); const rawReport = RawProjectDependencyReport.serialization.fromJson(dependencyTree); dependencyInfo = buildDependencyReport(rawReport); } catch (error) { assertErrorThrown(error); this.editorStore.applicationStore.logService.error(LogEvent.create(LEGEND_STUDIO_APP_EVENT.DEPOT_MANAGER_FAILURE), error); } const startErrorMessage = 'Depending on multiple versions of a project is not supported. Found conflicts:\n'; if (dependencyInfo?.conflicts.length) { const conflictingProjects = dependencyInfo.conflicts .map((c) => `project: ${c.groupId}:${c.artifactId}\nversions:[${c.versions .map((v) => v.versionId) .join(',')}]`) .join('\n'); throw new UnsupportedOperationError(startErrorMessage + conflictingProjects); } else { const conflictMessages = Array.from(dependencyProjects.entries()) .filter(([, v]) => v.size > 1) .map(([k, v]) => `project: ${k}\n versions: ${Array.from(v.values()).join(',')}`) .join('\n\n'); throw new UnsupportedOperationError(startErrorMessage + conflictMessages); } } } } catch (error) { assertErrorThrown(error); const message = `Can't acquire dependency entitites. Error: ${error.message}`; this.editorStore.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.GRAPH_BUILDER_FAILURE), message); this.editorStore.applicationStore.notificationService.notifyError(error); throw new DependencyGraphBuilderError(error); } return dependencyEntitiesIndex; } async buildProjectDependencyCoordinates(projectDependencies) { return Promise.all(projectDependencies.map(async (dep) => Promise.resolve(new ProjectDependencyCoordinates(guaranteeNonNullable(dep.groupId), guaranteeNonNullable(dep.artifactId), dep.versionId)))); } // -------------------------------------------------- UTILITIES ----------------------------------------------------- getPackageableElementType(element) { if (element instanceof PrimitiveType) { return PACKAGEABLE_ELEMENT_TYPE.PRIMITIVE; } else if (element instanceof Package) { return PACKAGEABLE_ELEMENT_TYPE.PACKAGE; } else if (element instanceof Class) { return PACKAGEABLE_ELEMENT_TYPE.CLASS; } else if (element instanceof Association) { return PACKAGEABLE_ELEMENT_TYPE.ASSOCIATION; } else if (element instanceof Enumeration) { return PACKAGEABLE_ELEMENT_TYPE.ENUMERATION; } else if (element instanceof Measure) { return PACKAGEABLE_ELEMENT_TYPE.MEASURE; } else if (element instanceof Unit) { return PACKAGEABLE_ELEMENT_TYPE.UNIT; } else if (element instanceof Profile) { return PACKAGEABLE_ELEMENT_TYPE.PROFILE; } else if (element instanceof ConcreteFunctionDefinition) { return PACKAGEABLE_ELEMENT_TYPE.FUNCTION; } else if (element instanceof FlatData) { return PACKAGEABLE_ELEMENT_TYPE.FLAT_DATA_STORE; } else if (element instanceof Database) { return PACKAGEABLE_ELEMENT_TYPE.DATABASE; } else if (element instanceof Mapping) { return PACKAGEABLE_ELEMENT_TYPE.MAPPING; } else if (element instanceof Service) { return PACKAGEABLE_ELEMENT_TYPE.SERVICE; } else if (element instanceof PackageableConnection) { return PACKAGEABLE_ELEMENT_TYPE.CONNECTION; } else if (element instanceof PackageableRuntime) { return PACKAGEABLE_ELEMENT_TYPE.RUNTIME; } else if (element instanceof FileGenerationSpecification) { return PACKAGEABLE_ELEMENT_TYPE.FILE_GENERATION; } else if (element instanceof GenerationSpecification) { return PACKAGEABLE_ELEMENT_TYPE.GENERATION_SPECIFICATION; } else if (element instanceof SectionIndex) { return PACKAGEABLE_ELEMENT_TYPE.SECTION_INDEX; } else if (element instanceof DataElement) { return PACKAGEABLE_ELEMENT_TYPE.DATA; } else if (element instanceof ExecutionEnvironmentInstance) { return PACKAGEABLE_ELEMENT_TYPE.EXECUTION_ENVIRONMENT; } else if (element instanceof SnowflakeApp) { return PACKAGEABLE_ELEMENT_TYPE.SNOWFLAKE_APP; } else if (element instanceof HostedService) { return PACKAGEABLE_ELEMENT_TYPE.HOSTED_SERVICE; } const extraElementTypeLabelGetters = this.editorStore.pluginManager .getApplicationPlugins() .flatMap((plugin) => plugin.getExtraElementClassifiers?.() ?? []); for (const labelGetter of extraElementTypeLabelGetters) { const label = labelGetter(element); if (label) { return label; } } return PACKAGEABLE_ELEMENT_TYPE.INTERNAL__UnknownElement; } } //# sourceMappingURL=EditorGraphState.js.map