@finos/legend-application-studio 27.0.0 → 27.1.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__/LegendStudioApplicationNavigationContext.d.ts +9 -1
- package/lib/__lib__/LegendStudioApplicationNavigationContext.d.ts.map +1 -1
- package/lib/__lib__/LegendStudioApplicationNavigationContext.js +11 -1
- package/lib/__lib__/LegendStudioApplicationNavigationContext.js.map +1 -1
- package/lib/application/LegendStudioApplicationConfig.d.ts +6 -0
- package/lib/application/LegendStudioApplicationConfig.d.ts.map +1 -1
- package/lib/application/LegendStudioApplicationConfig.js +7 -0
- package/lib/application/LegendStudioApplicationConfig.js.map +1 -1
- package/lib/components/ElementIconUtils.d.ts.map +1 -1
- package/lib/components/ElementIconUtils.js +3 -1
- package/lib/components/ElementIconUtils.js.map +1 -1
- package/lib/components/editor/editor-group/ModelImporter.d.ts.map +1 -1
- package/lib/components/editor/editor-group/ModelImporter.js +1 -0
- package/lib/components/editor/editor-group/ModelImporter.js.map +1 -1
- package/lib/components/editor/editor-group/connection-editor/DatabaseBuilder.d.ts.map +1 -1
- package/lib/components/editor/editor-group/connection-editor/DatabaseBuilder.js +8 -10
- package/lib/components/editor/editor-group/connection-editor/DatabaseBuilder.js.map +1 -1
- package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.js +5 -0
- package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.js.map +1 -1
- package/lib/components/editor/editor-group/data-editor/RelationalCSVDataEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/data-editor/RelationalCSVDataEditor.js +3 -0
- package/lib/components/editor/editor-group/data-editor/RelationalCSVDataEditor.js.map +1 -1
- package/lib/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_BindingElementEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_BindingElementEditor.js +3 -0
- package/lib/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_BindingElementEditor.js.map +1 -1
- package/lib/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_SchemaSetElementEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_SchemaSetElementEditor.js +3 -0
- package/lib/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_SchemaSetElementEditor.js.map +1 -1
- package/lib/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_SchemaSetModelGenerationEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_SchemaSetModelGenerationEditor.js +3 -0
- package/lib/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_SchemaSetModelGenerationEditor.js.map +1 -1
- package/lib/components/editor/editor-group/mapping-editor/NewMappingElementModal.js +1 -2
- package/lib/components/editor/editor-group/mapping-editor/NewMappingElementModal.js.map +1 -1
- package/lib/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.js +9 -4
- package/lib/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.js.map +1 -1
- package/lib/components/editor/panel-group/SQLPlaygroundPanel.d.ts.map +1 -1
- package/lib/components/editor/panel-group/SQLPlaygroundPanel.js +38 -6
- package/lib/components/editor/panel-group/SQLPlaygroundPanel.js.map +1 -1
- package/lib/components/editor/side-bar/CreateNewElementModal.d.ts +3 -0
- package/lib/components/editor/side-bar/CreateNewElementModal.d.ts.map +1 -1
- package/lib/components/editor/side-bar/CreateNewElementModal.js +43 -1
- package/lib/components/editor/side-bar/CreateNewElementModal.js.map +1 -1
- package/lib/components/extensions/Core_LegendStudioApplicationPlugin.d.ts.map +1 -1
- package/lib/components/extensions/Core_LegendStudioApplicationPlugin.js +10 -0
- package/lib/components/extensions/Core_LegendStudioApplicationPlugin.js.map +1 -1
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/package.json +1 -1
- package/lib/stores/editor/EditorGraphState.js +1 -1
- package/lib/stores/editor/EditorGraphState.js.map +1 -1
- package/lib/stores/editor/EditorStore.d.ts.map +1 -1
- package/lib/stores/editor/EditorStore.js +10 -2
- package/lib/stores/editor/EditorStore.js.map +1 -1
- package/lib/stores/editor/NewElementState.d.ts +0 -1
- package/lib/stores/editor/NewElementState.d.ts.map +1 -1
- package/lib/stores/editor/NewElementState.js +43 -10
- package/lib/stores/editor/NewElementState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.d.ts +0 -1
- package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.js +26 -30
- package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.d.ts +4 -1
- package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.js +5 -1
- package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.js.map +1 -1
- package/lib/stores/editor/panel-group/SQLPlaygroundPanelState.d.ts +9 -0
- package/lib/stores/editor/panel-group/SQLPlaygroundPanelState.d.ts.map +1 -1
- package/lib/stores/editor/panel-group/SQLPlaygroundPanelState.js +149 -3
- package/lib/stores/editor/panel-group/SQLPlaygroundPanelState.js.map +1 -1
- package/lib/stores/editor/utils/ModelClassifierUtils.d.ts +2 -5
- package/lib/stores/editor/utils/ModelClassifierUtils.d.ts.map +1 -1
- package/lib/stores/editor/utils/ModelClassifierUtils.js +2 -6
- package/lib/stores/editor/utils/ModelClassifierUtils.js.map +1 -1
- package/package.json +3 -3
- package/src/__lib__/LegendStudioApplicationNavigationContext.ts +12 -1
- package/src/application/LegendStudioApplicationConfig.ts +8 -0
- package/src/components/ElementIconUtils.tsx +3 -0
- package/src/components/editor/editor-group/ModelImporter.tsx +4 -0
- package/src/components/editor/editor-group/connection-editor/DatabaseBuilder.tsx +12 -13
- package/src/components/editor/editor-group/data-editor/EmbeddedDataEditor.tsx +11 -1
- package/src/components/editor/editor-group/data-editor/RelationalCSVDataEditor.tsx +6 -0
- package/src/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_BindingElementEditor.tsx +7 -0
- package/src/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_SchemaSetElementEditor.tsx +6 -0
- package/src/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_SchemaSetModelGenerationEditor.tsx +6 -0
- package/src/components/editor/editor-group/mapping-editor/NewMappingElementModal.tsx +1 -1
- package/src/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.tsx +12 -7
- package/src/components/editor/panel-group/SQLPlaygroundPanel.tsx +104 -18
- package/src/components/editor/side-bar/CreateNewElementModal.tsx +111 -1
- package/src/components/extensions/Core_LegendStudioApplicationPlugin.tsx +10 -0
- package/src/stores/editor/EditorGraphState.ts +1 -1
- package/src/stores/editor/EditorStore.ts +29 -17
- package/src/stores/editor/NewElementState.ts +109 -20
- package/src/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.ts +33 -40
- package/src/stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.ts +5 -1
- package/src/stores/editor/panel-group/SQLPlaygroundPanelState.ts +224 -1
- package/src/stores/editor/utils/ModelClassifierUtils.ts +2 -6
@@ -929,25 +929,37 @@ export class EditorStore implements CommandRegistrar {
|
|
929
929
|
PACKAGEABLE_ELEMENT_TYPE.ASSOCIATION,
|
930
930
|
PACKAGEABLE_ELEMENT_TYPE.FUNCTION,
|
931
931
|
PACKAGEABLE_ELEMENT_TYPE.MEASURE,
|
932
|
-
PACKAGEABLE_ELEMENT_TYPE.MAPPING,
|
933
|
-
PACKAGEABLE_ELEMENT_TYPE.RUNTIME,
|
934
|
-
PACKAGEABLE_ELEMENT_TYPE.CONNECTION,
|
935
|
-
PACKAGEABLE_ELEMENT_TYPE.SERVICE,
|
936
|
-
PACKAGEABLE_ELEMENT_TYPE.GENERATION_SPECIFICATION,
|
937
|
-
PACKAGEABLE_ELEMENT_TYPE.FILE_GENERATION,
|
938
|
-
PACKAGEABLE_ELEMENT_TYPE.FLAT_DATA_STORE,
|
939
|
-
PACKAGEABLE_ELEMENT_TYPE.DATABASE,
|
940
|
-
PACKAGEABLE_ELEMENT_TYPE.DATA,
|
941
932
|
] as string[]
|
942
933
|
).concat(
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
934
|
+
(
|
935
|
+
[
|
936
|
+
PACKAGEABLE_ELEMENT_TYPE.MAPPING,
|
937
|
+
PACKAGEABLE_ELEMENT_TYPE.RUNTIME,
|
938
|
+
PACKAGEABLE_ELEMENT_TYPE.CONNECTION,
|
939
|
+
PACKAGEABLE_ELEMENT_TYPE.SERVICE,
|
940
|
+
PACKAGEABLE_ELEMENT_TYPE.GENERATION_SPECIFICATION,
|
941
|
+
PACKAGEABLE_ELEMENT_TYPE.FILE_GENERATION,
|
942
|
+
PACKAGEABLE_ELEMENT_TYPE.FLAT_DATA_STORE,
|
943
|
+
PACKAGEABLE_ELEMENT_TYPE.DATABASE,
|
944
|
+
PACKAGEABLE_ELEMENT_TYPE.DATA,
|
945
|
+
this.applicationStore.config.options
|
946
|
+
.TEMPORARY__enableLocalConnectionBuilder
|
947
|
+
? PACKAGEABLE_ELEMENT_TYPE.TEMPORARY__LOCAL_CONNECTION
|
948
|
+
: undefined,
|
949
|
+
] as (string | undefined)[]
|
950
|
+
)
|
951
|
+
.filter(isNonNullable)
|
952
|
+
.concat(
|
953
|
+
this.pluginManager
|
954
|
+
.getApplicationPlugins()
|
955
|
+
.flatMap(
|
956
|
+
(plugin) =>
|
957
|
+
(
|
958
|
+
plugin as DSL_LegendStudioApplicationPlugin_Extension
|
959
|
+
).getExtraSupportedElementTypes?.() ?? [],
|
960
|
+
),
|
961
|
+
)
|
962
|
+
.sort((a, b) => a.localeCompare(b)),
|
951
963
|
);
|
952
964
|
}
|
953
965
|
|
@@ -74,6 +74,12 @@ import {
|
|
74
74
|
Multiplicity,
|
75
75
|
PrimitiveType,
|
76
76
|
LocalH2DatasourceSpecification,
|
77
|
+
SnowflakeDatasourceSpecification,
|
78
|
+
SnowflakePublicAuthenticationStrategy,
|
79
|
+
StoreConnections,
|
80
|
+
ConnectionPointer,
|
81
|
+
IdentifiedConnection,
|
82
|
+
generateIdentifiedConnectionId,
|
77
83
|
} from '@finos/legend-graph';
|
78
84
|
import type { DSL_Mapping_LegendStudioApplicationPlugin_Extension } from '../extensions/DSL_Mapping_LegendStudioApplicationPlugin_Extension.js';
|
79
85
|
import {
|
@@ -646,7 +652,6 @@ export class NewElementState {
|
|
646
652
|
_package: observable,
|
647
653
|
name: observable,
|
648
654
|
newElementDriver: observable,
|
649
|
-
elementAndPackageName: computed,
|
650
655
|
selectedPackage: computed,
|
651
656
|
isValid: computed,
|
652
657
|
setShowModal: action,
|
@@ -665,14 +670,6 @@ export class NewElementState {
|
|
665
670
|
this.type = PACKAGEABLE_ELEMENT_TYPE.PACKAGE;
|
666
671
|
}
|
667
672
|
|
668
|
-
get elementAndPackageName(): [string, string] {
|
669
|
-
return resolvePackageAndElementName(
|
670
|
-
this.selectedPackage,
|
671
|
-
this._package === this.editorStore.graphManagerState.graph.root,
|
672
|
-
this.name,
|
673
|
-
);
|
674
|
-
}
|
675
|
-
|
676
673
|
get selectedPackage(): Package {
|
677
674
|
return this._package
|
678
675
|
? this._package
|
@@ -778,7 +775,11 @@ export class NewElementState {
|
|
778
775
|
|
779
776
|
*save(): GeneratorFn<void> {
|
780
777
|
if (this.name && this.isValid) {
|
781
|
-
const [packagePath, elementName] =
|
778
|
+
const [packagePath, elementName] = resolvePackageAndElementName(
|
779
|
+
this.selectedPackage,
|
780
|
+
this._package === this.editorStore.graphManagerState.graph.root,
|
781
|
+
this.name,
|
782
|
+
);
|
782
783
|
if (
|
783
784
|
this.editorStore.graphManagerState.graph.getNullablePackage(
|
784
785
|
packagePath,
|
@@ -789,17 +790,105 @@ export class NewElementState {
|
|
789
790
|
`Can't create elements for type other than 'package' in root package`,
|
790
791
|
);
|
791
792
|
} else {
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
793
|
+
if (
|
794
|
+
this.editorStore.applicationStore.config.options
|
795
|
+
.TEMPORARY__enableLocalConnectionBuilder &&
|
796
|
+
this.type === PACKAGEABLE_ELEMENT_TYPE.TEMPORARY__LOCAL_CONNECTION
|
797
|
+
) {
|
798
|
+
// NOTE: this is temporary until we have proper support for local connection
|
799
|
+
// For now, we aim to fulfill the PoC for SnowflakeApp use case and will generate
|
800
|
+
// everything: mapping, store, connection, runtime, etc.
|
801
|
+
const store = new Database(`${this.name}_Database`);
|
802
|
+
const mapping = new Mapping(`${this.name}_Mapping`);
|
803
|
+
// connection
|
804
|
+
const connection = new PackageableConnection(
|
805
|
+
`${this.name}_LocalConnection`,
|
806
|
+
);
|
807
|
+
const _suffix = `${packagePath.replaceAll(
|
808
|
+
ELEMENT_PATH_DELIMITER,
|
809
|
+
'-',
|
810
|
+
)}-${connection.name}`;
|
811
|
+
const datasourceSpecification = new SnowflakeDatasourceSpecification(
|
812
|
+
`legend-local-snowflake-accountName-${_suffix}`,
|
813
|
+
`legend-local-snowflake-region-${_suffix}`,
|
814
|
+
`legend-local-snowflake-warehouseName-${_suffix}`,
|
815
|
+
`legend-local-snowflake-databaseName-${_suffix}`,
|
816
|
+
);
|
817
|
+
datasourceSpecification.cloudType = `legend-local-snowflake-cloudType-${_suffix}`;
|
818
|
+
datasourceSpecification.role = `legend-local-snowflake-role-${_suffix}`;
|
819
|
+
const connectionValue = new RelationalDatabaseConnection(
|
820
|
+
PackageableElementExplicitReference.create(store),
|
821
|
+
DatabaseType.Snowflake,
|
822
|
+
datasourceSpecification,
|
823
|
+
new SnowflakePublicAuthenticationStrategy(
|
824
|
+
`legend-local-snowflake-privateKeyVaultReference-${_suffix}`,
|
825
|
+
`legend-local-snowflake-passphraseVaultReference-${_suffix}`,
|
826
|
+
`legend-local-snowflake-publicuserName-${_suffix}`,
|
827
|
+
),
|
828
|
+
);
|
829
|
+
connectionValue.localMode = true;
|
830
|
+
connection.connectionValue = connectionValue;
|
831
|
+
// runtime
|
832
|
+
const runtime = new PackageableRuntime(`${this.name}_Runtime`);
|
833
|
+
const engineRuntime = new EngineRuntime();
|
834
|
+
engineRuntime.mappings = [
|
835
|
+
PackageableElementExplicitReference.create(mapping),
|
836
|
+
];
|
837
|
+
const storeConnections = new StoreConnections(
|
838
|
+
PackageableElementExplicitReference.create(store),
|
839
|
+
);
|
840
|
+
storeConnections.storeConnections = [
|
841
|
+
new IdentifiedConnection(
|
842
|
+
generateIdentifiedConnectionId(engineRuntime),
|
843
|
+
new ConnectionPointer(
|
844
|
+
PackageableElementExplicitReference.create(connection),
|
845
|
+
),
|
846
|
+
),
|
847
|
+
];
|
848
|
+
engineRuntime.connections = [storeConnections];
|
849
|
+
runtime.runtimeValue = engineRuntime;
|
850
|
+
// add the elements
|
851
|
+
yield flowResult(
|
852
|
+
this.editorStore.graphEditorMode.addElement(
|
853
|
+
store,
|
854
|
+
packagePath,
|
855
|
+
false,
|
856
|
+
),
|
857
|
+
);
|
858
|
+
yield flowResult(
|
859
|
+
this.editorStore.graphEditorMode.addElement(
|
860
|
+
connection,
|
861
|
+
packagePath,
|
862
|
+
false,
|
863
|
+
),
|
864
|
+
);
|
865
|
+
yield flowResult(
|
866
|
+
this.editorStore.graphEditorMode.addElement(
|
867
|
+
mapping,
|
868
|
+
packagePath,
|
869
|
+
false,
|
870
|
+
),
|
871
|
+
);
|
872
|
+
yield flowResult(
|
873
|
+
this.editorStore.graphEditorMode.addElement(
|
874
|
+
runtime,
|
875
|
+
packagePath,
|
876
|
+
false,
|
877
|
+
),
|
878
|
+
);
|
879
|
+
} else {
|
880
|
+
const element = this.createElement(elementName);
|
881
|
+
yield flowResult(
|
882
|
+
this.editorStore.graphEditorMode.addElement(
|
883
|
+
element,
|
884
|
+
packagePath,
|
885
|
+
true,
|
886
|
+
),
|
887
|
+
);
|
800
888
|
|
801
|
-
|
802
|
-
|
889
|
+
// post creation handling
|
890
|
+
yield handlePostCreateAction(element, this.editorStore);
|
891
|
+
}
|
803
892
|
}
|
804
893
|
}
|
805
894
|
this.closeModal();
|
package/src/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.ts
CHANGED
@@ -146,8 +146,8 @@ export class DatabaseBuilderState {
|
|
146
146
|
makeObservable<DatabaseBuilderState>(this, {
|
147
147
|
showModal: observable,
|
148
148
|
targetDatabasePath: observable,
|
149
|
-
isBuildingDatabase: observable,
|
150
149
|
databaseGrammarCode: observable,
|
150
|
+
isBuildingDatabase: observable,
|
151
151
|
isSavingDatabase: observable,
|
152
152
|
currentDatabase: computed,
|
153
153
|
setTargetDatabasePath: action,
|
@@ -219,7 +219,7 @@ export class DatabaseBuilderState {
|
|
219
219
|
treeData: DatabaseBuilderTreeData,
|
220
220
|
): DatabaseBuilderTreeNodeData[] | undefined {
|
221
221
|
return node.childrenIds
|
222
|
-
?.map((
|
222
|
+
?.map((childNode) => treeData.nodes.get(childNode))
|
223
223
|
.filter(isNonNullable);
|
224
224
|
}
|
225
225
|
|
@@ -245,7 +245,8 @@ export class DatabaseBuilderState {
|
|
245
245
|
}
|
246
246
|
}
|
247
247
|
}
|
248
|
-
|
248
|
+
|
249
|
+
// TODO: support toggling check for columns
|
249
250
|
this.setTreeData({ ...treeData });
|
250
251
|
}
|
251
252
|
|
@@ -279,6 +280,7 @@ export class DatabaseBuilderState {
|
|
279
280
|
schemaId,
|
280
281
|
schema,
|
281
282
|
);
|
283
|
+
nodes.set(schemaId, schemaNode);
|
282
284
|
|
283
285
|
schemaNode.setChecked(
|
284
286
|
Boolean(
|
@@ -287,7 +289,6 @@ export class DatabaseBuilderState {
|
|
287
289
|
),
|
288
290
|
),
|
289
291
|
);
|
290
|
-
nodes.set(schemaId, schemaNode);
|
291
292
|
});
|
292
293
|
const treeData = { rootIds, nodes, database };
|
293
294
|
this.setTreeData(treeData);
|
@@ -341,6 +342,8 @@ export class DatabaseBuilderState {
|
|
341
342
|
schema,
|
342
343
|
table,
|
343
344
|
);
|
345
|
+
treeData.nodes.set(tableId, tableNode);
|
346
|
+
addUniqueEntry(childrenIds, tableId);
|
344
347
|
|
345
348
|
if (this.currentDatabase) {
|
346
349
|
const matchingSchema = getNullableSchema(
|
@@ -357,9 +360,6 @@ export class DatabaseBuilderState {
|
|
357
360
|
} else {
|
358
361
|
tableNode.setChecked(false);
|
359
362
|
}
|
360
|
-
|
361
|
-
treeData.nodes.set(tableId, tableNode);
|
362
|
-
addUniqueEntry(childrenIds, tableId);
|
363
363
|
});
|
364
364
|
schemaNode.childrenIds = childrenIds;
|
365
365
|
this.setTreeData({ ...treeData });
|
@@ -605,6 +605,8 @@ export class DatabaseBuilderState {
|
|
605
605
|
} else {
|
606
606
|
currentDatabase = this.currentDatabase;
|
607
607
|
}
|
608
|
+
|
609
|
+
// remove undefined schemas
|
608
610
|
const schemas = Array.from(this.treeData.nodes.values())
|
609
611
|
.map((schemaNode) => {
|
610
612
|
if (schemaNode instanceof SchemaDatabaseBuilderTreeNodeData) {
|
@@ -613,11 +615,32 @@ export class DatabaseBuilderState {
|
|
613
615
|
return undefined;
|
614
616
|
})
|
615
617
|
.filter(isNonNullable);
|
616
|
-
|
618
|
+
currentDatabase.schemas = currentDatabase.schemas.filter((schema) => {
|
619
|
+
if (
|
620
|
+
schemas.find((item) => item.name === schema.name) &&
|
621
|
+
!database.schemas.find((s) => s.name === schema.name)
|
622
|
+
) {
|
623
|
+
return false;
|
624
|
+
}
|
625
|
+
return true;
|
626
|
+
});
|
627
|
+
|
628
|
+
// update existing schemas
|
629
|
+
database.schemas.forEach((schema) => {
|
630
|
+
(schema as Writable<Schema>)._OWNER = currentDatabase;
|
631
|
+
const currentSchemaIndex = currentDatabase.schemas.findIndex(
|
632
|
+
(item) => item.name === schema.name,
|
633
|
+
);
|
634
|
+
if (currentSchemaIndex !== -1) {
|
635
|
+
currentDatabase.schemas[currentSchemaIndex] = schema;
|
636
|
+
} else {
|
637
|
+
currentDatabase.schemas.push(schema);
|
638
|
+
}
|
639
|
+
});
|
640
|
+
|
617
641
|
this.editorStore.applicationStore.notificationService.notifySuccess(
|
618
|
-
`Database successfully '${isUpdating ? 'updated' : 'created'}
|
642
|
+
`Database successfully '${isUpdating ? 'updated' : 'created'}`,
|
619
643
|
);
|
620
|
-
this.fetchDatabaseMetadata();
|
621
644
|
if (isUpdating) {
|
622
645
|
yield flowResult(
|
623
646
|
this.editorStore
|
@@ -639,34 +662,4 @@ export class DatabaseBuilderState {
|
|
639
662
|
this.isSavingDatabase = false;
|
640
663
|
}
|
641
664
|
}
|
642
|
-
|
643
|
-
updateDatabase(
|
644
|
-
current: Database,
|
645
|
-
generatedDatabase: Database,
|
646
|
-
allSchemas: Schema[],
|
647
|
-
): void {
|
648
|
-
// remove undefined schemas
|
649
|
-
current.schemas = current.schemas.filter((schema) => {
|
650
|
-
if (
|
651
|
-
allSchemas.find((item) => item.name === schema.name) &&
|
652
|
-
!generatedDatabase.schemas.find((c) => c.name === schema.name)
|
653
|
-
) {
|
654
|
-
return false;
|
655
|
-
}
|
656
|
-
return true;
|
657
|
-
});
|
658
|
-
|
659
|
-
// update existing schemas
|
660
|
-
generatedDatabase.schemas.forEach((schema) => {
|
661
|
-
(schema as Writable<Schema>)._OWNER = current;
|
662
|
-
const currentSchemaIndex = current.schemas.findIndex(
|
663
|
-
(item) => item.name === schema.name,
|
664
|
-
);
|
665
|
-
if (currentSchemaIndex !== -1) {
|
666
|
-
current.schemas[currentSchemaIndex] = schema;
|
667
|
-
} else {
|
668
|
-
current.schemas.push(schema);
|
669
|
-
}
|
670
|
-
});
|
671
|
-
}
|
672
665
|
}
|
@@ -121,7 +121,6 @@ import {
|
|
121
121
|
setImpl_updateRootOnCreate,
|
122
122
|
setImpl_updateRootOnDelete,
|
123
123
|
} from '../../../../graph-modifier/DSL_Mapping_GraphModifierHelper.js';
|
124
|
-
import { BASIC_SET_IMPLEMENTATION_TYPE } from '../../../utils/ModelClassifierUtils.js';
|
125
124
|
import { rootRelationalSetImp_setMainTableAlias } from '../../../../graph-modifier/STO_Relational_GraphModifierHelper.js';
|
126
125
|
import { LambdaEditorState } from '@finos/legend-query-builder';
|
127
126
|
import type { MappingEditorTabState } from './MappingTabManagerState.js';
|
@@ -163,6 +162,11 @@ export enum MAPPING_ELEMENT_TYPE {
|
|
163
162
|
ASSOCIATION = 'ASSOCIATION',
|
164
163
|
}
|
165
164
|
|
165
|
+
export enum BASIC_SET_IMPLEMENTATION_TYPE {
|
166
|
+
OPERATION = 'operation',
|
167
|
+
INSTANCE = 'instance',
|
168
|
+
}
|
169
|
+
|
166
170
|
export type MappingElement =
|
167
171
|
| EnumerationMapping
|
168
172
|
| SetImplementation
|
@@ -25,6 +25,9 @@ import {
|
|
25
25
|
ActionState,
|
26
26
|
getNonNullableEntry,
|
27
27
|
getNullableLastEntry,
|
28
|
+
type Writable,
|
29
|
+
guaranteeNonNullable,
|
30
|
+
IllegalStateError,
|
28
31
|
} from '@finos/legend-shared';
|
29
32
|
import { observable, makeObservable, flow, flowResult, action } from 'mobx';
|
30
33
|
import { editor as monacoEditorAPI } from 'monaco-editor';
|
@@ -40,6 +43,8 @@ import {
|
|
40
43
|
getSchema,
|
41
44
|
guaranteeRelationalDatabaseConnection,
|
42
45
|
GRAPH_MANAGER_EVENT,
|
46
|
+
getNullableSchema,
|
47
|
+
getNullableTable,
|
43
48
|
} from '@finos/legend-graph';
|
44
49
|
import type { EditorStore } from '../EditorStore.js';
|
45
50
|
import { LEGEND_STUDIO_APP_EVENT } from '../../../__lib__/LegendStudioEvent.js';
|
@@ -50,6 +55,8 @@ import {
|
|
50
55
|
import type { CommandRegistrar } from '@finos/legend-application';
|
51
56
|
import { STO_RELATIONAL_LEGEND_STUDIO_COMMAND_KEY } from '../../../__lib__/STO_Relational_LegendStudioCommand.js';
|
52
57
|
import { PANEL_MODE } from '../EditorConfig.js';
|
58
|
+
import type { Entity } from '@finos/legend-storage';
|
59
|
+
import { GraphEditFormModeState } from '../GraphEditFormModeState.js';
|
53
60
|
|
54
61
|
export abstract class DatabaseSchemaExplorerTreeNodeData
|
55
62
|
implements TreeNodeData
|
@@ -59,12 +66,22 @@ export abstract class DatabaseSchemaExplorerTreeNodeData
|
|
59
66
|
label: string;
|
60
67
|
parentId?: string | undefined;
|
61
68
|
childrenIds?: string[] | undefined;
|
69
|
+
isChecked = false;
|
62
70
|
|
63
71
|
constructor(id: string, label: string, parentId: string | undefined) {
|
72
|
+
makeObservable(this, {
|
73
|
+
isChecked: observable,
|
74
|
+
setChecked: action,
|
75
|
+
});
|
76
|
+
|
64
77
|
this.id = id;
|
65
78
|
this.label = label;
|
66
79
|
this.parentId = parentId;
|
67
80
|
}
|
81
|
+
|
82
|
+
setChecked(val: boolean): void {
|
83
|
+
this.isChecked = val;
|
84
|
+
}
|
68
85
|
}
|
69
86
|
|
70
87
|
export class DatabaseSchemaExplorerTreeSchemaNodeData extends DatabaseSchemaExplorerTreeNodeData {
|
@@ -118,6 +135,7 @@ export class SQLPlaygroundPanelState implements CommandRegistrar {
|
|
118
135
|
isExecutingRawSQL = false;
|
119
136
|
|
120
137
|
connection?: PackageableConnection | undefined;
|
138
|
+
database?: Database | undefined;
|
121
139
|
treeData?: DatabaseSchemaExplorerTreeData | undefined;
|
122
140
|
readonly sqlEditorTextModel: monacoEditorAPI.ITextModel;
|
123
141
|
sqlEditor?: monacoEditorAPI.IStandaloneCodeEditor | undefined;
|
@@ -125,17 +143,23 @@ export class SQLPlaygroundPanelState implements CommandRegistrar {
|
|
125
143
|
sqlText = DEFAULT_SQL_TEXT;
|
126
144
|
sqlExecutionResult?: string | undefined;
|
127
145
|
|
146
|
+
isBuildingDatabase = false;
|
147
|
+
isUpdatingDatabase = false;
|
148
|
+
|
128
149
|
constructor(editorStore: EditorStore) {
|
129
150
|
makeObservable(this, {
|
130
151
|
isFetchingSchema: observable,
|
131
152
|
isExecutingRawSQL: observable,
|
132
153
|
connection: observable,
|
154
|
+
database: observable,
|
133
155
|
treeData: observable,
|
134
156
|
sqlText: observable,
|
135
157
|
resetSQL: action,
|
136
158
|
sqlExecutionResult: observable,
|
137
159
|
sqlEditor: observable.ref,
|
138
160
|
sqlEditorViewState: observable.ref,
|
161
|
+
isBuildingDatabase: observable,
|
162
|
+
isUpdatingDatabase: observable,
|
139
163
|
setTreeData: action,
|
140
164
|
setConnection: action,
|
141
165
|
setSQLEditor: action,
|
@@ -146,6 +170,8 @@ export class SQLPlaygroundPanelState implements CommandRegistrar {
|
|
146
170
|
fetchSchemaMetadata: flow,
|
147
171
|
fetchTableMetadata: flow,
|
148
172
|
executeRawSQL: flow,
|
173
|
+
generateDatabase: flow,
|
174
|
+
updateDatabase: flow,
|
149
175
|
});
|
150
176
|
|
151
177
|
this.editorStore = editorStore;
|
@@ -161,6 +187,9 @@ export class SQLPlaygroundPanelState implements CommandRegistrar {
|
|
161
187
|
|
162
188
|
setConnection(val: PackageableConnection | undefined): void {
|
163
189
|
this.connection = val;
|
190
|
+
if (val) {
|
191
|
+
this.database = guaranteeRelationalDatabaseConnection(val).store.value;
|
192
|
+
}
|
164
193
|
this.sqlEditorTextModel.setValue(DEFAULT_SQL_TEXT);
|
165
194
|
}
|
166
195
|
|
@@ -238,10 +267,37 @@ export class SQLPlaygroundPanelState implements CommandRegistrar {
|
|
238
267
|
treeData: DatabaseSchemaExplorerTreeData,
|
239
268
|
): DatabaseSchemaExplorerTreeNodeData[] | undefined {
|
240
269
|
return node.childrenIds
|
241
|
-
?.map((
|
270
|
+
?.map((childNode) => treeData.nodes.get(childNode))
|
242
271
|
.filter(isNonNullable);
|
243
272
|
}
|
244
273
|
|
274
|
+
toggleCheckedNode(
|
275
|
+
node: DatabaseSchemaExplorerTreeNodeData,
|
276
|
+
treeData: DatabaseSchemaExplorerTreeData,
|
277
|
+
): void {
|
278
|
+
node.setChecked(!node.isChecked);
|
279
|
+
if (node instanceof DatabaseSchemaExplorerTreeSchemaNodeData) {
|
280
|
+
this.getChildNodes(node, treeData)?.forEach((childNode) => {
|
281
|
+
childNode.setChecked(node.isChecked);
|
282
|
+
});
|
283
|
+
} else if (node instanceof DatabaseSchemaExplorerTreeTableNodeData) {
|
284
|
+
if (node.parentId) {
|
285
|
+
const parent = treeData.nodes.get(node.parentId);
|
286
|
+
if (
|
287
|
+
parent &&
|
288
|
+
this.getChildNodes(parent, treeData)?.every(
|
289
|
+
(e) => e.isChecked === node.isChecked,
|
290
|
+
)
|
291
|
+
) {
|
292
|
+
parent.setChecked(node.isChecked);
|
293
|
+
}
|
294
|
+
}
|
295
|
+
}
|
296
|
+
|
297
|
+
// TODO: support toggling check for columns
|
298
|
+
this.setTreeData({ ...treeData });
|
299
|
+
}
|
300
|
+
|
245
301
|
*fetchDatabaseMetadata(): GeneratorFn<void> {
|
246
302
|
if (!this.connection) {
|
247
303
|
return;
|
@@ -279,6 +335,14 @@ export class SQLPlaygroundPanelState implements CommandRegistrar {
|
|
279
335
|
dbSchema,
|
280
336
|
);
|
281
337
|
nodes.set(schemaId, schemaNode);
|
338
|
+
|
339
|
+
schemaNode.setChecked(
|
340
|
+
Boolean(
|
341
|
+
this.database?.schemas.find(
|
342
|
+
(schema) => schema.name === dbSchema.name,
|
343
|
+
),
|
344
|
+
),
|
345
|
+
);
|
282
346
|
});
|
283
347
|
const treeData = { rootIds, nodes, database };
|
284
348
|
this.setTreeData(treeData);
|
@@ -339,6 +403,22 @@ export class SQLPlaygroundPanelState implements CommandRegistrar {
|
|
339
403
|
);
|
340
404
|
treeData.nodes.set(tableId, tableNode);
|
341
405
|
addUniqueEntry(childrenIds, tableId);
|
406
|
+
|
407
|
+
if (this.database) {
|
408
|
+
const matchingSchema = getNullableSchema(
|
409
|
+
this.database,
|
410
|
+
schema.name,
|
411
|
+
);
|
412
|
+
tableNode.setChecked(
|
413
|
+
Boolean(
|
414
|
+
matchingSchema
|
415
|
+
? getNullableTable(matchingSchema, table.name)
|
416
|
+
: undefined,
|
417
|
+
),
|
418
|
+
);
|
419
|
+
} else {
|
420
|
+
tableNode.setChecked(false);
|
421
|
+
}
|
342
422
|
});
|
343
423
|
schemaNode.childrenIds = childrenIds;
|
344
424
|
this.setTreeData({ ...treeData });
|
@@ -482,4 +562,147 @@ export class SQLPlaygroundPanelState implements CommandRegistrar {
|
|
482
562
|
this.isExecutingRawSQL = false;
|
483
563
|
}
|
484
564
|
}
|
565
|
+
|
566
|
+
*generateDatabase(): GeneratorFn<Entity> {
|
567
|
+
if (!this.database || !this.connection || !this.treeData) {
|
568
|
+
throw new IllegalStateError(
|
569
|
+
`Can't build database: builder is not properly set up`,
|
570
|
+
);
|
571
|
+
}
|
572
|
+
|
573
|
+
try {
|
574
|
+
this.isBuildingDatabase = true;
|
575
|
+
|
576
|
+
const treeData = this.treeData;
|
577
|
+
const databaseBuilderInput = new DatabaseBuilderInput(
|
578
|
+
guaranteeRelationalDatabaseConnection(this.connection),
|
579
|
+
);
|
580
|
+
const packagePath = guaranteeNonNullable(this.database.package).path;
|
581
|
+
const databaseName = this.database.name;
|
582
|
+
databaseBuilderInput.targetDatabase = new TargetDatabase(
|
583
|
+
packagePath,
|
584
|
+
databaseName,
|
585
|
+
);
|
586
|
+
const config = databaseBuilderInput.config;
|
587
|
+
config.maxTables = undefined;
|
588
|
+
config.enrichTables = true;
|
589
|
+
config.enrichColumns = true;
|
590
|
+
config.enrichPrimaryKeys = true;
|
591
|
+
treeData.rootIds
|
592
|
+
.map((e) => treeData.nodes.get(e))
|
593
|
+
.filter(isNonNullable)
|
594
|
+
.forEach((schemaNode) => {
|
595
|
+
if (schemaNode instanceof DatabaseSchemaExplorerTreeSchemaNodeData) {
|
596
|
+
const tableNodes = this.getChildNodes(schemaNode, treeData);
|
597
|
+
const allChecked = tableNodes?.every((t) => t.isChecked === true);
|
598
|
+
if (
|
599
|
+
allChecked ||
|
600
|
+
(schemaNode.isChecked && !schemaNode.childrenIds)
|
601
|
+
) {
|
602
|
+
config.patterns.push(
|
603
|
+
new DatabasePattern(schemaNode.schema.name, undefined),
|
604
|
+
);
|
605
|
+
} else {
|
606
|
+
tableNodes?.forEach((t) => {
|
607
|
+
if (
|
608
|
+
t instanceof DatabaseSchemaExplorerTreeTableNodeData &&
|
609
|
+
t.isChecked
|
610
|
+
) {
|
611
|
+
config.patterns.push(
|
612
|
+
new DatabasePattern(schemaNode.schema.name, t.table.name),
|
613
|
+
);
|
614
|
+
}
|
615
|
+
});
|
616
|
+
}
|
617
|
+
}
|
618
|
+
});
|
619
|
+
const entities =
|
620
|
+
(yield this.editorStore.graphManagerState.graphManager.buildDatabase(
|
621
|
+
databaseBuilderInput,
|
622
|
+
)) as Entity[];
|
623
|
+
return getNonNullableEntry(
|
624
|
+
entities,
|
625
|
+
0,
|
626
|
+
'Expected a database to be generated',
|
627
|
+
);
|
628
|
+
} finally {
|
629
|
+
this.isBuildingDatabase = false;
|
630
|
+
}
|
631
|
+
}
|
632
|
+
|
633
|
+
*updateDatabase(): GeneratorFn<void> {
|
634
|
+
if (!this.treeData || !this.database || !this.connection) {
|
635
|
+
return;
|
636
|
+
}
|
637
|
+
|
638
|
+
try {
|
639
|
+
this.isUpdatingDatabase = true;
|
640
|
+
|
641
|
+
const graph = this.editorStore.graphManagerState.createNewGraph();
|
642
|
+
(yield this.editorStore.graphManagerState.graphManager.buildGraph(
|
643
|
+
graph,
|
644
|
+
[(yield flowResult(this.generateDatabase())) as Entity],
|
645
|
+
ActionState.create(),
|
646
|
+
)) as Entity[];
|
647
|
+
const generatedDatabase = getNonNullableEntry(
|
648
|
+
graph.ownDatabases,
|
649
|
+
0,
|
650
|
+
'Expected one database to be generated from input',
|
651
|
+
);
|
652
|
+
|
653
|
+
const currentDatabase = this.database;
|
654
|
+
|
655
|
+
// remove undefined schemas
|
656
|
+
const schemas = Array.from(this.treeData.nodes.values())
|
657
|
+
.map((schemaNode) => {
|
658
|
+
if (schemaNode instanceof DatabaseSchemaExplorerTreeSchemaNodeData) {
|
659
|
+
return schemaNode.schema;
|
660
|
+
}
|
661
|
+
return undefined;
|
662
|
+
})
|
663
|
+
.filter(isNonNullable);
|
664
|
+
currentDatabase.schemas = currentDatabase.schemas.filter((schema) => {
|
665
|
+
if (
|
666
|
+
schemas.find((item) => item.name === schema.name) &&
|
667
|
+
!generatedDatabase.schemas.find((s) => s.name === schema.name)
|
668
|
+
) {
|
669
|
+
return false;
|
670
|
+
}
|
671
|
+
return true;
|
672
|
+
});
|
673
|
+
|
674
|
+
// update existing schemas
|
675
|
+
generatedDatabase.schemas.forEach((schema) => {
|
676
|
+
(schema as Writable<Schema>)._OWNER = currentDatabase;
|
677
|
+
const currentSchemaIndex = currentDatabase.schemas.findIndex(
|
678
|
+
(item) => item.name === schema.name,
|
679
|
+
);
|
680
|
+
if (currentSchemaIndex !== -1) {
|
681
|
+
currentDatabase.schemas[currentSchemaIndex] = schema;
|
682
|
+
} else {
|
683
|
+
currentDatabase.schemas.push(schema);
|
684
|
+
}
|
685
|
+
});
|
686
|
+
|
687
|
+
this.editorStore.applicationStore.notificationService.notifySuccess(
|
688
|
+
`Database successfully updated`,
|
689
|
+
);
|
690
|
+
yield flowResult(
|
691
|
+
this.editorStore
|
692
|
+
.getGraphEditorMode(GraphEditFormModeState)
|
693
|
+
.globalCompile({
|
694
|
+
message: `Can't compile graph after editing database. Redirecting you to text mode`,
|
695
|
+
}),
|
696
|
+
);
|
697
|
+
} catch (error) {
|
698
|
+
assertErrorThrown(error);
|
699
|
+
this.editorStore.applicationStore.logService.error(
|
700
|
+
LogEvent.create(LEGEND_STUDIO_APP_EVENT.DATABASE_BUILDER_FAILURE),
|
701
|
+
error,
|
702
|
+
);
|
703
|
+
this.editorStore.applicationStore.notificationService.notifyError(error);
|
704
|
+
} finally {
|
705
|
+
this.isUpdatingDatabase = false;
|
706
|
+
}
|
707
|
+
}
|
485
708
|
}
|