@flowuent-org/diagramming-core 1.3.10 → 1.4.1
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/.editorconfig +13 -13
- package/.eslintignore +1 -1
- package/.eslintrc.json +35 -35
- package/.prettierignore +3 -3
- package/.prettierrc +3 -3
- package/.vscode/settings.json +6 -6
- package/README.md +95 -95
- package/apps/authentication/tsconfig.app.json +23 -23
- package/apps/authentication/tsconfig.json +21 -21
- package/apps/authentication/tsconfig.spec.json +28 -28
- package/apps/diagramming/.eslintrc.json +18 -18
- package/apps/diagramming/index.html +16 -16
- package/apps/diagramming/project.json +53 -53
- package/apps/diagramming/public/aws-icons/compute/App Runner.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Application Auto Scaling.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Batch.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Bottlerocket.svg +19 -19
- package/apps/diagramming/public/aws-icons/compute/Compute Optimizer.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/EC2 Auto Scaling.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/EC2 Image Builder.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/EC2.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Elastic Beanstalk.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Elastic Fabric Adapter.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Fargate.svg +19 -19
- package/apps/diagramming/public/aws-icons/compute/Genomics CLI.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Lambda.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Local Zones.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/NICE DCV.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/NICE EnginFrame.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Nitro Enclaves.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Outposts family.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Outposts rack.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Outposts servers.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/ParallelCluster.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Serverless Application Repository.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/SimSpace Weaver.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Thinkbox Deadline.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Thinkbox Frost.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Thinkbox Sequoia.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Thinkbox Stoke.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Thinkbox XMesh.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/VMware Cloud on AWS.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Wavelength.svg +17 -17
- package/apps/diagramming/public/aws-icons/container/ECS Anywhere.svg +17 -17
- package/apps/diagramming/public/aws-icons/container/EKS Anywhere.svg +17 -17
- package/apps/diagramming/public/aws-icons/container/EKS Cloud.svg +17 -17
- package/apps/diagramming/public/aws-icons/container/EKS Distro.svg +17 -17
- package/apps/diagramming/public/aws-icons/container/Elastic Container Registry.svg +17 -17
- package/apps/diagramming/public/aws-icons/container/Elastic Container Service.svg +17 -17
- package/apps/diagramming/public/aws-icons/container/Elastic Kubernetes Service.svg +17 -17
- package/apps/diagramming/public/aws-icons/container/Fargate.svg +19 -19
- package/apps/diagramming/public/aws-icons/container/Red Hat OpenShift Service on AWS.svg +17 -17
- package/apps/diagramming/public/aws-icons/database/Aurora.svg +17 -17
- package/apps/diagramming/public/aws-icons/database/Database Migration Service.svg +17 -17
- package/apps/diagramming/public/aws-icons/database/DocumentDB.svg +17 -17
- package/apps/diagramming/public/aws-icons/database/ElastiCache.svg +17 -17
- package/apps/diagramming/public/aws-icons/database/Keyspaces.svg +15 -15
- package/apps/diagramming/public/aws-icons/database/MemoryDB for Redis.svg +17 -17
- package/apps/diagramming/public/aws-icons/database/Neptune.svg +17 -17
- package/apps/diagramming/public/aws-icons/database/RDS on VMware.svg +17 -17
- package/apps/diagramming/public/aws-icons/database/RDS.svg +17 -17
- package/apps/diagramming/public/aws-icons/database/Timestream.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/App Mesh.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Client VPN.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Cloud Directory.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Cloud Map.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Cloud WAN.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/CloudFront.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Direct Connect.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Elastic Load Balancing.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Global Accelerator.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Private 5G.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/PrivateLink.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Route 53.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Site to Site VPN.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Transit Gateway.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/VPC Lattice.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Verified Access.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Virtual Private Cloud.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Artifact.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Audit Manager.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Certificate Manager.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/CloudHSM.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Cognito.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Detective.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Directory Service.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Firewall Manager.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/GuardDuty.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/IAM Identity Center.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Identity and Access Management.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Inspector.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Key Management Service.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Macie.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Network Firewall.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Resource Access Manager.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Secrets Manager.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Security Hub.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Security Lake.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Shield.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Signer.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Verified Permissions.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/WAF.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/Backup.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/EFS.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/Elastic Block Store.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/Elastic Disaster Recovery.svg +15 -15
- package/apps/diagramming/public/aws-icons/storage/FSx for Lustre.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/FSx for NetApp ONTAP.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/FSx for OpenZFS.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/FSx for WFS.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/FSx.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/File Cache.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/S3 on Outposts.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/Simple Storage Service Glacier.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/Simple Storage Service.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/Snowball Edge.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/Snowball.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/Snowcone.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/Snowmobile.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/Storage Gateway.svg +17 -17
- package/apps/diagramming/public/azure-icons/compute/02112-icon-service-Automanaged-VM.svg +1 -1
- package/apps/diagramming/public/azure-icons/databases/02390-icon-service-Azure-SQL.svg +1 -1
- package/apps/diagramming/public/azure-icons/databases/02392-icon-service-SSIS-Lift-And-Shift-IR.svg +1 -1
- package/apps/diagramming/public/azure-icons/networking/02145-icon-service-Resource-Management-Private-Link.svg +1 -1
- package/apps/diagramming/public/azure-icons/security/02247-icon-service-Microsoft-Defender-for-IoT.svg +1 -1
- package/apps/diagramming/public/sample-node-complete.json +63 -63
- package/apps/diagramming/public/sample-node-data.json +63 -63
- package/apps/diagramming/src/AutomationDiagramData.ts +147 -480
- package/apps/diagramming/src/CollaborationDiagramData.ts +127 -127
- package/apps/diagramming/src/CustomIconExamples.ts +233 -233
- package/apps/diagramming/src/DiagramTabs.tsx +205 -205
- package/apps/diagramming/src/Pages/DevPlayground.tsx +3 -3
- package/apps/diagramming/src/Pages/Home.tsx +111 -111
- package/apps/diagramming/src/SequenceDiagramData.ts +215 -215
- package/apps/diagramming/src/StateMachineDiagramData.ts +64 -64
- package/apps/diagramming/src/UseCaseDiagramData.ts +52 -52
- package/apps/diagramming/src/cloud-data.ts +371 -371
- package/apps/diagramming/src/components/AddNodeView.tsx +252 -252
- package/apps/diagramming/src/createSelecors.tsx +17 -17
- package/apps/diagramming/src/index.scss +12 -12
- package/apps/diagramming/src/main.tsx +463 -463
- package/apps/diagramming/src/node-data.ts +664 -664
- package/apps/diagramming/src/sample-workflow-content.ts +55 -55
- package/apps/diagramming/src/stencil-items.ts +31 -31
- package/apps/diagramming/src/style.css +13 -13
- package/apps/diagramming/src/tabsStore.tsx +152 -152
- package/apps/diagramming/src/vite-env.d.ts +1 -1
- package/apps/diagramming/tsconfig.app.json +23 -23
- package/apps/diagramming/tsconfig.json +21 -21
- package/apps/diagramming/tsconfig.spec.json +28 -28
- package/apps/diagramming/vite.config.ts +34 -34
- package/apps/diagramming/webpack.config.js +13 -13
- package/apps/workflow/.eslintrc.json +18 -18
- package/apps/workflow/group/group-form-hooks/index.ts +3 -3
- package/apps/workflow/group/group-form-hooks/useFormValidation.ts +20 -20
- package/apps/workflow/group/group-form-schema/SettingsTabFormSchema.ts +7 -7
- package/apps/workflow/group/group-form-schema/index.ts +3 -3
- package/apps/workflow/i18n.ts +19 -19
- package/apps/workflow/index.html +16 -16
- package/apps/workflow/locales/en/translation.json +713 -713
- package/apps/workflow/project.json +8 -8
- package/apps/workflow/src/app/app.module.css +1 -1
- package/apps/workflow/src/app/app.spec.tsx +15 -15
- package/apps/workflow/src/app/app.tsx +370 -370
- package/apps/workflow/src/main.tsx +13 -13
- package/apps/workflow/src/styles.css +1 -1
- package/apps/workflow/src/theme/index.ts +546 -546
- package/apps/workflow/tsconfig.app.json +23 -23
- package/apps/workflow/tsconfig.json +21 -21
- package/apps/workflow/tsconfig.spec.json +28 -28
- package/apps/workflow/vite.config.ts +51 -51
- package/nx.json +58 -58
- package/package.json +1 -1
- package/packages/api/.babelrc +12 -12
- package/packages/api/.eslintrc.json +18 -18
- package/packages/api/README.md +7 -7
- package/packages/api/project.json +8 -8
- package/packages/api/src/index.ts +3 -3
- package/packages/api/src/lib/jsonPlaceholderService/endpoints.ts +3 -3
- package/packages/api/src/lib/jsonPlaceholderService/service.ts +13 -13
- package/packages/api/tsconfig.json +17 -17
- package/packages/api/tsconfig.lib.json +24 -24
- package/packages/atoms/.babelrc +12 -12
- package/packages/atoms/.eslintrc.json +18 -18
- package/packages/atoms/README.md +7 -7
- package/packages/atoms/forms/AuthenticationTabForm/authenticationTabForm.json +224 -224
- package/packages/atoms/forms/AuthenticationTabForm/index.tsx +255 -255
- package/packages/atoms/forms/SettingsTabForm/index.tsx +85 -85
- package/packages/atoms/forms/SettingsTabForm/settingTabForm.json +27 -27
- package/packages/atoms/forms/index.ts +4 -4
- package/packages/atoms/project.json +8 -8
- package/packages/atoms/src/index.ts +33 -33
- package/packages/atoms/src/lib/Accordion/Accordion.module.css +7 -7
- package/packages/atoms/src/lib/Accordion/Accordion.spec.tsx +13 -13
- package/packages/atoms/src/lib/Accordion/Accordion.tsx +29 -29
- package/packages/atoms/src/lib/Alert/Alert.module.css +7 -7
- package/packages/atoms/src/lib/Alert/Alert.spec.tsx +10 -10
- package/packages/atoms/src/lib/Alert/Alert.tsx +19 -19
- package/packages/atoms/src/lib/Avatar/Avatar.module.css +7 -7
- package/packages/atoms/src/lib/Avatar/Avatar.spec.tsx +10 -10
- package/packages/atoms/src/lib/Avatar/Avatar.tsx +22 -22
- package/packages/atoms/src/lib/Box/Box.module.css +7 -7
- package/packages/atoms/src/lib/Box/Box.spec.tsx +10 -10
- package/packages/atoms/src/lib/Box/Box.tsx +19 -19
- package/packages/atoms/src/lib/BulkEdit/BulkEdit.module.css +7 -7
- package/packages/atoms/src/lib/BulkEdit/BulkEdit.spec.tsx +10 -10
- package/packages/atoms/src/lib/BulkEdit/BulkEdit.tsx +15 -15
- package/packages/atoms/src/lib/Button/Button.module.css +7 -7
- package/packages/atoms/src/lib/Button/Button.spec.tsx +10 -10
- package/packages/atoms/src/lib/Button/Button.tsx +78 -78
- package/packages/atoms/src/lib/Card/Card.module.css +7 -7
- package/packages/atoms/src/lib/Card/Card.spec.tsx +10 -10
- package/packages/atoms/src/lib/Card/Card.tsx +19 -19
- package/packages/atoms/src/lib/CardContent/CardContent.module.css +7 -7
- package/packages/atoms/src/lib/CardContent/CardContent.spec.tsx +10 -10
- package/packages/atoms/src/lib/CardContent/CardContent.tsx +22 -22
- package/packages/atoms/src/lib/FormTextField/FormTextField.module.css +7 -7
- package/packages/atoms/src/lib/FormTextField/FormTextField.spec.tsx +10 -10
- package/packages/atoms/src/lib/FormTextField/FormTextField.tsx +35 -35
- package/packages/atoms/src/lib/Grid/Grid.module.css +7 -7
- package/packages/atoms/src/lib/Grid/Grid.spec.tsx +10 -10
- package/packages/atoms/src/lib/Grid/Grid.tsx +19 -19
- package/packages/atoms/src/lib/Stack/Stack.module.css +7 -7
- package/packages/atoms/src/lib/Stack/Stack.spec.tsx +10 -10
- package/packages/atoms/src/lib/Stack/Stack.tsx +19 -19
- package/packages/atoms/src/lib/Switch/Switch.module.css +7 -7
- package/packages/atoms/src/lib/Switch/Switch.spec.tsx +10 -10
- package/packages/atoms/src/lib/Switch/Switch.tsx +46 -46
- package/packages/atoms/src/lib/TableView/TableView.module.css +7 -7
- package/packages/atoms/src/lib/TableView/TableView.spec.tsx +10 -10
- package/packages/atoms/src/lib/TableView/TableView.tsx +88 -88
- package/packages/atoms/src/lib/TextField/TextField.module.css +7 -7
- package/packages/atoms/src/lib/TextField/TextField.spec.tsx +10 -10
- package/packages/atoms/src/lib/TextField/TextField.tsx +17 -17
- package/packages/atoms/src/lib/Typography/Typography.module.css +7 -7
- package/packages/atoms/src/lib/Typography/Typography.spec.tsx +10 -10
- package/packages/atoms/src/lib/Typography/Typography.tsx +22 -22
- package/packages/atoms/tsconfig.json +17 -17
- package/packages/atoms/tsconfig.lib.json +30 -30
- package/packages/common/.babelrc +12 -12
- package/packages/common/.eslintrc.json +18 -18
- package/packages/common/README.md +7 -7
- package/packages/common/project.json +8 -8
- package/packages/common/src/index.ts +4 -4
- package/packages/common/src/lib/generateRandomProfilePic.ts +3 -3
- package/packages/common/src/lib/generateValidationSchema.ts +46 -46
- package/packages/common/tsconfig.json +17 -17
- package/packages/common/tsconfig.lib.json +24 -24
- package/packages/contexts/.babelrc +12 -12
- package/packages/contexts/.eslintrc.json +18 -18
- package/packages/contexts/README.md +7 -7
- package/packages/contexts/project.json +8 -8
- package/packages/contexts/src/index.ts +2 -2
- package/packages/contexts/tsconfig.json +17 -17
- package/packages/contexts/tsconfig.lib.json +24 -24
- package/packages/diagrams/.babelrc +12 -12
- package/packages/diagrams/.ctirc +208 -208
- package/packages/diagrams/.eslintrc.json +17 -17
- package/packages/diagrams/CUSTOM_ICONS.md +232 -232
- package/packages/diagrams/GOOGLE_SHEETS_IMPLEMENTATION.md +233 -233
- package/packages/diagrams/NODE_DATA_UPDATE_API.md +430 -430
- package/packages/diagrams/README.md +7 -7
- package/packages/diagrams/UNDO_REDO_API.md +306 -306
- package/packages/diagrams/locales/en/translation.json +713 -713
- package/packages/diagrams/package.json +27 -27
- package/packages/diagrams/pnpm-lock.yaml +2606 -2606
- package/packages/diagrams/project.json +42 -42
- package/packages/diagrams/rollup.config.js +26 -26
- package/packages/diagrams/src/DiagramFlow.tsx +7 -7
- package/packages/diagrams/src/declarations.d.ts +7 -7
- package/packages/diagrams/src/index.ts +8 -1
- package/packages/diagrams/src/index.ts.bak +99 -99
- package/packages/diagrams/src/lib/assets/markers/markers.param.tsx +101 -101
- package/packages/diagrams/src/lib/assets/markers/markers.type.ts +10 -10
- package/packages/diagrams/src/lib/atoms/ActorNode.tsx +123 -123
- package/packages/diagrams/src/lib/atoms/AddParallelColButton.tsx +26 -26
- package/packages/diagrams/src/lib/atoms/BendpointNode.tsx +71 -71
- package/packages/diagrams/src/lib/atoms/CardBlockTypeSelector.tsx +35 -35
- package/packages/diagrams/src/lib/atoms/CardEditableTitle.tsx +76 -76
- package/packages/diagrams/src/lib/atoms/CardMainContent.tsx +19 -19
- package/packages/diagrams/src/lib/atoms/ConnectionPoints.tsx +149 -149
- package/packages/diagrams/src/lib/atoms/ContentAssist.tsx +341 -341
- package/packages/diagrams/src/lib/atoms/DiagramControls.tsx +56 -56
- package/packages/diagrams/src/lib/atoms/ExpressionInput.tsx +437 -437
- package/packages/diagrams/src/lib/atoms/FloatingConnectionLine.tsx +73 -73
- package/packages/diagrams/src/lib/atoms/LazyIcon.tsx +31 -31
- package/packages/diagrams/src/lib/atoms/MarkerSelector.tsx +106 -106
- package/packages/diagrams/src/lib/atoms/MultiSelectInput.tsx +87 -87
- package/packages/diagrams/src/lib/atoms/ParameterInput.tsx +199 -199
- package/packages/diagrams/src/lib/atoms/PropertyInput.tsx +114 -114
- package/packages/diagrams/src/lib/atoms/StyledBox.tsx +69 -69
- package/packages/diagrams/src/lib/atoms/ValidationError.tsx +37 -37
- package/packages/diagrams/src/lib/atoms/ValidationMessage.tsx +63 -63
- package/packages/diagrams/src/lib/components/AiButton.tsx +52 -52
- package/packages/diagrams/src/lib/components/ControlEdgeList.tsx +303 -303
- package/packages/diagrams/src/lib/components/CreateFunctionModal.tsx +264 -264
- package/packages/diagrams/src/lib/components/CustomCodeModal.tsx +287 -287
- package/packages/diagrams/src/lib/components/DiagramPanel.tsx +331 -331
- package/packages/diagrams/src/lib/components/FunctionModalTooltip.tsx +30 -30
- package/packages/diagrams/src/lib/components/GraphQLCustomCodeModal.tsx +210 -210
- package/packages/diagrams/src/lib/components/Header.tsx +143 -143
- package/packages/diagrams/src/lib/components/MiniMapCommon.tsx +24 -24
- package/packages/diagrams/src/lib/components/ResizeIcon.tsx +81 -81
- package/packages/diagrams/src/lib/components/SideBar.tsx +40 -40
- package/packages/diagrams/src/lib/components/automation/AISuggestionsModal.tsx +269 -269
- package/packages/diagrams/src/lib/components/automation/AISuggestionsPanel.tsx +28 -175
- package/packages/diagrams/src/lib/components/automation/AutomationApiNode.tsx +1 -1
- package/packages/diagrams/src/lib/components/automation/AutomationDecisionNode.tsx +94 -0
- package/packages/diagrams/src/lib/components/automation/AutomationEndNode.tsx +1 -1
- package/packages/diagrams/src/lib/components/automation/AutomationExecutionPanel.tsx +439 -439
- package/packages/diagrams/src/lib/components/automation/AutomationFormattingNode.tsx +1 -1
- package/packages/diagrams/src/lib/components/automation/AutomationInteractionNode.tsx +693 -693
- package/packages/diagrams/src/lib/components/automation/AutomationMonitoringNode.tsx +399 -399
- package/packages/diagrams/src/lib/components/automation/AutomationNavigationNode.tsx +1 -1
- package/packages/diagrams/src/lib/components/automation/AutomationNodeCard.tsx +414 -0
- package/packages/diagrams/src/lib/components/automation/AutomationSlackNode.tsx +694 -694
- package/packages/diagrams/src/lib/components/automation/AutomationSmsNode.tsx +62 -0
- package/packages/diagrams/src/lib/components/automation/AutomationStartNode.tsx +1 -1
- package/packages/diagrams/src/lib/components/automation/AutomationTelegramNode.tsx +664 -664
- package/packages/diagrams/src/lib/components/automation/AutomationVoiceCallNode.tsx +65 -0
- package/packages/diagrams/src/lib/components/automation/AutomationWorkflowNode.tsx +85 -0
- package/packages/diagrams/src/lib/components/automation/NodeAIAssistantPopup.tsx +504 -504
- package/packages/diagrams/src/lib/components/automation/index.ts +29 -19
- package/packages/diagrams/src/lib/components/automation/statusColors.ts +124 -124
- package/packages/diagrams/src/lib/contexts/CardDataProvider.tsx +111 -111
- package/packages/diagrams/src/lib/contexts/DiagramProvider.tsx +392 -391
- package/packages/diagrams/src/lib/contexts/diagramStoreTypes.tsx +134 -134
- package/packages/diagrams/src/lib/contexts/onConnect.ts +39 -39
- package/packages/diagrams/src/lib/contexts/onDragStart.ts +45 -45
- package/packages/diagrams/src/lib/contexts/onNodeDragEnd.ts +179 -179
- package/packages/diagrams/src/lib/contexts/onNodesChange.ts +406 -406
- package/packages/diagrams/src/lib/contexts/onReconnect.ts +59 -59
- package/packages/diagrams/src/lib/contexts/onWorkflowNodeDelete.ts +65 -65
- package/packages/diagrams/src/lib/contexts/setContentHeight.ts +14 -14
- package/packages/diagrams/src/lib/contexts/setDiagramType.ts +10 -10
- package/packages/diagrams/src/lib/contexts/setEdgeShapeType.ts +7 -7
- package/packages/diagrams/src/lib/contexts/setEdges.ts +9 -9
- package/packages/diagrams/src/lib/contexts/setLayoutDirection.ts +9 -9
- package/packages/diagrams/src/lib/contexts/setNodeSetting.ts +17 -17
- package/packages/diagrams/src/lib/contexts/setNodes.ts +10 -10
- package/packages/diagrams/src/lib/contexts/setPannable.ts +7 -7
- package/packages/diagrams/src/lib/contexts/setSelectedEdge.ts +7 -7
- package/packages/diagrams/src/lib/contexts/setSelectedNode.ts +7 -7
- package/packages/diagrams/src/lib/contexts/undo.ts +163 -163
- package/packages/diagrams/src/lib/contexts/updateNodeSetting.ts +17 -17
- package/packages/diagrams/src/lib/examples/TwilioWhatsAppConfigExample.ts +128 -128
- package/packages/diagrams/src/lib/externals.ts +4 -4
- package/packages/diagrams/src/lib/hooks/customUseReactFlow.tsx +90 -90
- package/packages/diagrams/src/lib/hooks/updateNodes.ts +45 -45
- package/packages/diagrams/src/lib/hooks/useAddChildButton.tsx +61 -61
- package/packages/diagrams/src/lib/hooks/useAddSwitchCase.ts +75 -75
- package/packages/diagrams/src/lib/hooks/useAutoRegisterFunctions.ts +135 -135
- package/packages/diagrams/src/lib/hooks/useAutoRegisterVariables.ts +286 -286
- package/packages/diagrams/src/lib/hooks/useDeleteNodeByEvent.ts +64 -64
- package/packages/diagrams/src/lib/hooks/useDragCallbacks.tsx +122 -122
- package/packages/diagrams/src/lib/hooks/useFormValidation.ts +349 -349
- package/packages/diagrams/src/lib/hooks/useFunctionFormCallbacks.ts +136 -136
- package/packages/diagrams/src/lib/hooks/useIsSelectedNode.ts +11 -11
- package/packages/diagrams/src/lib/hooks/useModalControls.ts +13 -13
- package/packages/diagrams/src/lib/hooks/useNodeDragHandlers.ts +43 -43
- package/packages/diagrams/src/lib/hooks/useNodeSelection.ts +55 -55
- package/packages/diagrams/src/lib/hooks/useRenderDividers.tsx +19 -19
- package/packages/diagrams/src/lib/hooks/useRenderPins.tsx +74 -74
- package/packages/diagrams/src/lib/hooks/useResizeObserver.ts +21 -21
- package/packages/diagrams/src/lib/hooks/useTreeChildNode.ts +536 -536
- package/packages/diagrams/src/lib/i18n.ts +42 -42
- package/packages/diagrams/src/lib/icons/icons.tsx +324 -0
- package/packages/diagrams/src/lib/icons/index.ts +29 -0
- package/packages/diagrams/src/lib/icons/types.ts +7 -0
- package/packages/diagrams/src/lib/molecules/AddingBlock.tsx +147 -147
- package/packages/diagrams/src/lib/molecules/AvailableVariablesDisplay.tsx +57 -57
- package/packages/diagrams/src/lib/molecules/Block.tsx +143 -143
- package/packages/diagrams/src/lib/molecules/BlockProvider.tsx +28 -28
- package/packages/diagrams/src/lib/molecules/BlockWrapper.tsx +14 -14
- package/packages/diagrams/src/lib/molecules/ConditionRule.tsx +131 -131
- package/packages/diagrams/src/lib/molecules/DraggablePane.tsx +198 -198
- package/packages/diagrams/src/lib/molecules/EntityNodeBlocks.tsx +66 -66
- package/packages/diagrams/src/lib/molecules/SideHandles.tsx +215 -215
- package/packages/diagrams/src/lib/molecules/StencilItem.tsx +85 -85
- package/packages/diagrams/src/lib/molecules/WorkflowNodeActionButtons.tsx +62 -62
- package/packages/diagrams/src/lib/molecules/animated-add-button.tsx +83 -83
- package/packages/diagrams/src/lib/molecules/json-viewer.tsx +107 -107
- package/packages/diagrams/src/lib/organisms/AddNodeView.tsx +102 -102
- package/packages/diagrams/src/lib/organisms/Card/EntityNode.tsx +259 -259
- package/packages/diagrams/src/lib/organisms/Card/card.params.ts +29 -29
- package/packages/diagrams/src/lib/organisms/Card/card.types.ts +5 -5
- package/packages/diagrams/src/lib/organisms/CodeModal.tsx +105 -105
- package/packages/diagrams/src/lib/organisms/ConditionRuleGroup.tsx +138 -138
- package/packages/diagrams/src/lib/organisms/CustomEdge/EdgeMarkers.tsx +51 -51
- package/packages/diagrams/src/lib/organisms/CustomEdge/custom-edge-generator.tsx +135 -135
- package/packages/diagrams/src/lib/organisms/CustomEdge/custom-edge.params.ts +6 -6
- package/packages/diagrams/src/lib/organisms/CustomEdge/custom-edge.type.ts +15 -15
- package/packages/diagrams/src/lib/organisms/CustomEdge/useCreateBendPoint.tsx +121 -121
- package/packages/diagrams/src/lib/organisms/CustomEdge/useEdgeModal.ts +37 -37
- package/packages/diagrams/src/lib/organisms/CustomEdge/useEdgePath.tsx +99 -99
- package/packages/diagrams/src/lib/organisms/DownloadPanel.tsx +345 -345
- package/packages/diagrams/src/lib/organisms/EdgeModal.tsx +243 -243
- package/packages/diagrams/src/lib/organisms/HistoryPane.tsx +118 -118
- package/packages/diagrams/src/lib/organisms/NodeContextMenu.tsx +259 -259
- package/packages/diagrams/src/lib/organisms/PropertiesPane.tsx +276 -276
- package/packages/diagrams/src/lib/organisms/SmartDynamicForm.tsx +226 -226
- package/packages/diagrams/src/lib/organisms/Stencil.tsx +60 -60
- package/packages/diagrams/src/lib/organisms/UseDiagramStore.tsx +4 -4
- package/packages/diagrams/src/lib/organisms/WorkFlowNode/NodeActionButtons.tsx +45 -45
- package/packages/diagrams/src/lib/organisms/WorkFlowNode/NodeTypeDisplay.tsx +114 -114
- package/packages/diagrams/src/lib/organisms/WorkFlowNode/WorkflowNodeIcons.tsx +21 -23
- package/packages/diagrams/src/lib/organisms/WorkflowNode.tsx +484 -484
- package/packages/diagrams/src/lib/services/GoogleSheetsService.ts +961 -961
- package/packages/diagrams/src/lib/services/SlackService.ts +134 -134
- package/packages/diagrams/src/lib/services/TwilioWhatsAppService.ts +273 -273
- package/packages/diagrams/src/lib/styles.css +55 -55
- package/packages/diagrams/src/lib/templates/PageLinks.tsx +13 -13
- package/packages/diagrams/src/lib/templates/arch/ArchDiagram.tsx +793 -793
- package/packages/diagrams/src/lib/templates/arch/components/EdgeDialog.tsx +82 -82
- package/packages/diagrams/src/lib/templates/arch/components/EdgeSettings.tsx +81 -81
- package/packages/diagrams/src/lib/templates/arch/components/GroupControls.tsx +59 -59
- package/packages/diagrams/src/lib/templates/arch/components/GroupSizeDialog.tsx +81 -81
- package/packages/diagrams/src/lib/templates/arch/components/NodeDialog.tsx +214 -214
- package/packages/diagrams/src/lib/templates/arch/components/nodeTypes.ts +91 -91
- package/packages/diagrams/src/lib/templates/arch/controls/ArchDiagramControls.tsx +349 -349
- package/packages/diagrams/src/lib/templates/arch/data/templatee-data.ts +212 -212
- package/packages/diagrams/src/lib/templates/cloud-arch/components/CloudArchitectureDiagram.tsx +3912 -3912
- package/packages/diagrams/src/lib/templates/cloud-arch/components/FormatConverter.tsx +809 -809
- package/packages/diagrams/src/lib/templates/cloud-arch/components/FragmentImporter.tsx +276 -276
- package/packages/diagrams/src/lib/templates/cloud-arch/components/PropertiesPanel.tsx +1063 -1063
- package/packages/diagrams/src/lib/templates/cloud-arch/components/ServiceIconPicker.tsx +138 -138
- package/packages/diagrams/src/lib/templates/cloud-arch/components/SettingsSidebar.tsx +656 -656
- package/packages/diagrams/src/lib/templates/cloud-arch/components/SubnetSelector.tsx +468 -468
- package/packages/diagrams/src/lib/templates/cloud-arch/components/nodes/ServiceNode.tsx +310 -310
- package/packages/diagrams/src/lib/templates/cloud-arch/components/nodes/SubnetNode.tsx +475 -475
- package/packages/diagrams/src/lib/templates/cloud-arch/components/nodes/UsersNode.tsx +277 -277
- package/packages/diagrams/src/lib/templates/cloud-arch/data/diagramManager.ts +364 -364
- package/packages/diagrams/src/lib/templates/cloud-arch/data/types.ts +183 -183
- package/packages/diagrams/src/lib/templates/cloud-arch/integration/diagramValidator.ts +379 -379
- package/packages/diagrams/src/lib/templates/cloud-arch/messages/errorMessages.json +95 -95
- package/packages/diagrams/src/lib/templates/cloud-arch/types/localization.ts +368 -368
- package/packages/diagrams/src/lib/templates/cloud-arch/types/validation.ts +72 -72
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/aws-icons.ts +557 -557
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/awsValidation.ts +446 -446
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/azure-icons.ts +802 -802
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/azureValidation.ts +495 -495
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/cloudValidation.ts +929 -929
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/errorMessages.ts +283 -283
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/gcp-icons.ts +186 -186
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/gcpValidation.ts +312 -312
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/genericValidation.ts +689 -689
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/iconMapping.ts +383 -383
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/idGenerator.ts +220 -220
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/localizationManager.ts +300 -300
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/restrictionEngine.ts +550 -550
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/restrictionValidator.ts +400 -400
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/serviceIcons.tsx +129 -129
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/serviceMapping.ts +330 -330
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/translations.ts +54 -54
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/validationExtractor.ts +342 -342
- package/packages/diagrams/src/lib/templates/collaborationDiagram/CollaborationDiagram.tsx +15 -15
- package/packages/diagrams/src/lib/templates/collaborationDiagram/components/AddCollabEdgeDialog.tsx +181 -181
- package/packages/diagrams/src/lib/templates/collaborationDiagram/components/CollabLayout.ts +182 -182
- package/packages/diagrams/src/lib/templates/collaborationDiagram/components/CollabObjectNodeSettings.tsx +86 -86
- package/packages/diagrams/src/lib/templates/collaborationDiagram/components/CollaborationDiagramFlow.tsx +731 -731
- package/packages/diagrams/src/lib/templates/collaborationDiagram/components/DraggableEdgeLabel.tsx +123 -123
- package/packages/diagrams/src/lib/templates/collaborationDiagram/controls/CollaborationControls.tsx +131 -131
- package/packages/diagrams/src/lib/templates/collaborationDiagram/nodes/CollabEdge.tsx +170 -170
- package/packages/diagrams/src/lib/templates/collaborationDiagram/nodes/CollabObjectNode.tsx +178 -178
- package/packages/diagrams/src/lib/templates/home.style.css +16 -16
- package/packages/diagrams/src/lib/templates/node-forms/ApiForm.tsx +416 -416
- package/packages/diagrams/src/lib/templates/node-forms/CallForm.tsx +370 -370
- package/packages/diagrams/src/lib/templates/node-forms/ForLoopNode.tsx +313 -313
- package/packages/diagrams/src/lib/templates/node-forms/FunctionForm.tsx +211 -211
- package/packages/diagrams/src/lib/templates/node-forms/GraphQLForm.tsx +679 -679
- package/packages/diagrams/src/lib/templates/node-forms/IfNodeForm.tsx +97 -97
- package/packages/diagrams/src/lib/templates/node-forms/LetNodeForm.tsx +533 -533
- package/packages/diagrams/src/lib/templates/node-forms/LoopNode.tsx +149 -149
- package/packages/diagrams/src/lib/templates/node-forms/NodeForm.tsx +383 -383
- package/packages/diagrams/src/lib/templates/node-forms/ReturnNodeForm.tsx +96 -96
- package/packages/diagrams/src/lib/templates/node-forms/SetNodeForm.tsx +141 -141
- package/packages/diagrams/src/lib/templates/node-forms/SwitchNodeForm.tsx +249 -249
- package/packages/diagrams/src/lib/templates/node-forms/TryCatchForm.tsx +167 -167
- package/packages/diagrams/src/lib/templates/nodeFormSchema.json +84 -84
- package/packages/diagrams/src/lib/templates/sequence/SequenceDiagram.tsx +22 -22
- package/packages/diagrams/src/lib/templates/sequence/components/ActivationBarNode.tsx +33 -33
- package/packages/diagrams/src/lib/templates/sequence/components/AddMessageDialog.tsx +302 -302
- package/packages/diagrams/src/lib/templates/sequence/components/CombinedFragmentNode.tsx +65 -65
- package/packages/diagrams/src/lib/templates/sequence/components/EntitySettings.tsx +559 -559
- package/packages/diagrams/src/lib/templates/sequence/components/FragmentSettings.tsx +116 -116
- package/packages/diagrams/src/lib/templates/sequence/components/SequenceComponents.tsx +14 -14
- package/packages/diagrams/src/lib/templates/sequence/components/SequenceDiagramFlow.tsx +1361 -1361
- package/packages/diagrams/src/lib/templates/sequence/components/SequenceEntityNode.tsx +394 -394
- package/packages/diagrams/src/lib/templates/sequence/components/SequenceMessageEdge.tsx +272 -272
- package/packages/diagrams/src/lib/templates/sequence/components/SimpleEntitySettings.tsx +89 -89
- package/packages/diagrams/src/lib/templates/sequence/controls/DiagramControls.tsx +707 -707
- package/packages/diagrams/src/lib/templates/sequence/data/template-data.ts +635 -635
- package/packages/diagrams/src/lib/templates/stateMachine/StateMachineDiagram.tsx +66 -66
- package/packages/diagrams/src/lib/templates/stateMachine/components/CompositeStateNodeSettings.tsx +638 -638
- package/packages/diagrams/src/lib/templates/stateMachine/components/CustomEdge.tsx +220 -220
- package/packages/diagrams/src/lib/templates/stateMachine/components/EdgeSettings.tsx +193 -193
- package/packages/diagrams/src/lib/templates/stateMachine/components/SelfConnectingEdge.tsx +41 -41
- package/packages/diagrams/src/lib/templates/stateMachine/components/StateMachineComponents.tsx +49 -49
- package/packages/diagrams/src/lib/templates/stateMachine/components/StateMachineDiagramFlow.tsx +1238 -1238
- package/packages/diagrams/src/lib/templates/stateMachine/components/StateMachineLayout.ts +350 -350
- package/packages/diagrams/src/lib/templates/stateMachine/components/StateNodeSettings.tsx +188 -188
- package/packages/diagrams/src/lib/templates/stateMachine/components/useSelfTransition.ts +114 -114
- package/packages/diagrams/src/lib/templates/stateMachine/controls/StateDiagramControls.tsx +488 -488
- package/packages/diagrams/src/lib/templates/stateMachine/data/template-data.ts +4 -4
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/ChoicePointNode.tsx +54 -54
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/CompositeStateNode.tsx +225 -225
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/EntryPointNode.tsx +31 -31
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/ExitPointNode.tsx +44 -44
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/FinalStateNode.tsx +41 -41
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/ForkJoinNode.tsx +53 -53
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/HistoryStateNode.tsx +36 -36
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/InitialStateNode.tsx +29 -29
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/JunctionPointNode.tsx +33 -33
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/PinPointNode.tsx +111 -111
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/StateNode.tsx +124 -124
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/bendPoint.tsx +71 -71
- package/packages/diagrams/src/lib/templates/systemFlow/SystemFlowDiagram.tsx +67 -67
- package/packages/diagrams/src/lib/templates/systemFlow/components/EdgeSettings.tsx +330 -330
- package/packages/diagrams/src/lib/templates/systemFlow/components/FloatingEdge.tsx +219 -219
- package/packages/diagrams/src/lib/templates/systemFlow/components/SystemFlowComponents.tsx +28 -28
- package/packages/diagrams/src/lib/templates/systemFlow/components/SystemFlowDiagramFlow.tsx +1179 -1179
- package/packages/diagrams/src/lib/templates/systemFlow/components/SystemFlowNodeSettings.tsx +151 -151
- package/packages/diagrams/src/lib/templates/systemFlow/controls/SystemFlowControls.tsx +435 -435
- package/packages/diagrams/src/lib/templates/systemFlow/data/template-data.ts +308 -308
- package/packages/diagrams/src/lib/templates/systemFlow/demo.tsx +91 -91
- package/packages/diagrams/src/lib/templates/systemFlow/index.ts +5 -5
- package/packages/diagrams/src/lib/templates/systemFlow/nodes/BendpointNode.tsx +80 -80
- package/packages/diagrams/src/lib/templates/systemFlow/nodes/SystemNode.tsx +92 -92
- package/packages/diagrams/src/lib/templates/systemFlow/nodes/TreeSystemNode.tsx +755 -755
- package/packages/diagrams/src/lib/templates/useCaseDiagram/UseCaseDiagram.tsx +16 -16
- package/packages/diagrams/src/lib/templates/useCaseDiagram/components/ActorNodeSettings.tsx +103 -103
- package/packages/diagrams/src/lib/templates/useCaseDiagram/components/AddRelationshipDialog.tsx +186 -186
- package/packages/diagrams/src/lib/templates/useCaseDiagram/components/PackageNodeSettings.tsx +205 -205
- package/packages/diagrams/src/lib/templates/useCaseDiagram/components/UseCaseDiagramFlow.tsx +637 -637
- package/packages/diagrams/src/lib/templates/useCaseDiagram/components/UseCaseNodeSettings.tsx +120 -120
- package/packages/diagrams/src/lib/templates/useCaseDiagram/controls/UseCaseControls.tsx +289 -289
- package/packages/diagrams/src/lib/templates/useCaseDiagram/nodes/PackageNode.tsx +83 -83
- package/packages/diagrams/src/lib/templates/useCaseDiagram/nodes/UseCaseEdge.tsx +115 -115
- package/packages/diagrams/src/lib/templates/useCaseDiagram/nodes/UseCaseNode.tsx +230 -230
- package/packages/diagrams/src/lib/templates/validationSchema.json +277 -277
- package/packages/diagrams/src/lib/theme.ts +439 -439
- package/packages/diagrams/src/lib/types/FunctionSignature.ts +11 -11
- package/packages/diagrams/src/lib/types/SmartDynamicFormField.ts +37 -37
- package/packages/diagrams/src/lib/types/automation-node-data-types.ts +45 -131
- package/packages/diagrams/src/lib/types/available-variables.ts +18 -18
- package/packages/diagrams/src/lib/types/card-node.ts +68 -68
- package/packages/diagrams/src/lib/types/collaboration-types.ts +114 -114
- package/packages/diagrams/src/lib/types/colors.ts +25 -25
- package/packages/diagrams/src/lib/types/condition-builder.ts +18 -18
- package/packages/diagrams/src/lib/types/diagram-types.ts +14 -14
- package/packages/diagrams/src/lib/types/edge-types.ts +39 -39
- package/packages/diagrams/src/lib/types/function-execution.ts +35 -35
- package/packages/diagrams/src/lib/types/hooks.types.ts +6 -6
- package/packages/diagrams/src/lib/types/ndoe-form-types.ts +139 -139
- package/packages/diagrams/src/lib/types/node-types.ts +13 -23
- package/packages/diagrams/src/lib/types/sequence-types.ts +178 -178
- package/packages/diagrams/src/lib/types/shared-node-types.ts +21 -21
- package/packages/diagrams/src/lib/types/state-machine-types.ts +225 -225
- package/packages/diagrams/src/lib/types/stencil-item.ts +7 -7
- package/packages/diagrams/src/lib/types/structures.ts +80 -80
- package/packages/diagrams/src/lib/types/system-flow-types.ts +129 -129
- package/packages/diagrams/src/lib/types/usecase-types.ts +84 -84
- package/packages/diagrams/src/lib/types/validation-types.ts +134 -134
- package/packages/diagrams/src/lib/types/workflow-content-dynamic-form-type.ts +23 -23
- package/packages/diagrams/src/lib/types/workflow-node-data-types.ts +172 -172
- package/packages/diagrams/src/lib/utils/AutomationExecutionEngine.ts +658 -1179
- package/packages/diagrams/src/lib/utils/add-new-block.ts +34 -34
- package/packages/diagrams/src/lib/utils/add-new-node.ts +52 -52
- package/packages/diagrams/src/lib/utils/addToHistory.ts +15 -15
- package/packages/diagrams/src/lib/utils/automation-flow-processor.ts +556 -619
- package/packages/diagrams/src/lib/utils/closestPoint.ts +45 -45
- package/packages/diagrams/src/lib/utils/color-options.tsx +26 -26
- package/packages/diagrams/src/lib/utils/compress-img.ts +59 -59
- package/packages/diagrams/src/lib/utils/configLoader.ts +329 -329
- package/packages/diagrams/src/lib/utils/constant-lengths.ts +8 -8
- package/packages/diagrams/src/lib/utils/create-updated.tsx +40 -40
- package/packages/diagrams/src/lib/utils/createHistoryChange.ts +3 -3
- package/packages/diagrams/src/lib/utils/dividerUtils.tsx +59 -59
- package/packages/diagrams/src/lib/utils/edge-hooks.ts +53 -53
- package/packages/diagrams/src/lib/utils/elkLayout.ts +297 -297
- package/packages/diagrams/src/lib/utils/event-hooks.ts +69 -69
- package/packages/diagrams/src/lib/utils/event-store.ts +58 -58
- package/packages/diagrams/src/lib/utils/flow-node-hooks.ts +28 -28
- package/packages/diagrams/src/lib/utils/flow-to-js.ts +1465 -1465
- package/packages/diagrams/src/lib/utils/functionGenerator.ts +38 -38
- package/packages/diagrams/src/lib/utils/generateEdgesFromNodeOrder.ts +113 -113
- package/packages/diagrams/src/lib/utils/helpers.types.ts +10 -10
- package/packages/diagrams/src/lib/utils/highlightText.tsx +93 -93
- package/packages/diagrams/src/lib/utils/iconMapper.tsx +76 -76
- package/packages/diagrams/src/lib/utils/logger.ts +5 -5
- package/packages/diagrams/src/lib/utils/model-hooks.ts +129 -129
- package/packages/diagrams/src/lib/utils/node-hooks.ts +78 -78
- package/packages/diagrams/src/lib/utils/nodeAIAssistantConfig.ts +54 -54
- package/packages/diagrams/src/lib/utils/nodeOrderByEdges.ts +437 -437
- package/packages/diagrams/src/lib/utils/nodeutils.ts +242 -242
- package/packages/diagrams/src/lib/utils/object.ts +13 -13
- package/packages/diagrams/src/lib/utils/useDebounce.ts +19 -19
- package/packages/diagrams/src/lib/utils/utilities.ts +105 -105
- package/packages/diagrams/src/lib/utils/validationEngine.ts +610 -610
- package/packages/diagrams/src/lib/utils/vhToPixels.ts +9 -9
- package/packages/diagrams/tsconfig.json +21 -21
- package/packages/diagrams/tsconfig.lib.json +26 -25
- package/packages/diagrams/webpack.config.js +17 -17
- package/packages/interfaces/.babelrc +12 -12
- package/packages/interfaces/.eslintrc.json +18 -18
- package/packages/interfaces/README.md +7 -7
- package/packages/interfaces/project.json +8 -8
- package/packages/interfaces/src/index.ts +21 -21
- package/packages/interfaces/src/lib/Button.tsx +1 -1
- package/packages/interfaces/src/lib/DataGrid.ts +14 -14
- package/packages/interfaces/src/lib/StyledBox.tsx +1 -1
- package/packages/interfaces/src/lib/ToolbarItem.ts +7 -7
- package/packages/interfaces/src/lib/UserCard.ts +8 -8
- package/packages/interfaces/src/lib/yup.ts +3 -3
- package/packages/interfaces/tsconfig.json +17 -17
- package/packages/interfaces/tsconfig.lib.json +24 -24
- package/packages/molecules/.babelrc +12 -12
- package/packages/molecules/.eslintrc.json +18 -18
- package/packages/molecules/README.md +7 -7
- package/packages/molecules/project.json +8 -8
- package/packages/molecules/src/index.ts +47 -41
- package/packages/molecules/src/lib/ActionTextField/ActionTextField.module.css +7 -7
- package/packages/molecules/src/lib/ActionTextField/ActionTextField.spec.tsx +10 -10
- package/packages/molecules/src/lib/ActionTextField/ActionTextField.tsx +33 -33
- package/packages/molecules/src/lib/ClosableButton/CloseableButton.module.css +7 -7
- package/packages/molecules/src/lib/ClosableButton/CloseableButton.spec.tsx +11 -11
- package/packages/molecules/src/lib/ClosableButton/CloseableButton.tsx +69 -69
- package/packages/molecules/src/lib/EditorTab/EditorTab.module.css +7 -7
- package/packages/molecules/src/lib/EditorTab/EditorTab.spec.tsx +10 -10
- package/packages/molecules/src/lib/EditorTab/EditorTab.tsx +42 -42
- package/packages/molecules/src/lib/EditorTab/TabPanel.tsx +25 -25
- package/packages/molecules/src/lib/ParamsActionField/ParamsActionField.module.css +7 -7
- package/packages/molecules/src/lib/ParamsActionField/ParamsActionField.spec.tsx +10 -10
- package/packages/molecules/src/lib/ParamsActionField/ParamsActionField.tsx +24 -24
- package/packages/molecules/src/lib/SvgIcons/icons.tsx +323 -291
- package/packages/molecules/src/lib/SvgIcons/index.ts +31 -25
- package/packages/molecules/src/lib/SvgIcons/types.ts +7 -7
- package/packages/molecules/src/lib/TableWithInlineView/TableWithInlineView.module.css +7 -7
- package/packages/molecules/src/lib/TableWithInlineView/TableWithInlineView.spec.tsx +10 -10
- package/packages/molecules/src/lib/TableWithInlineView/TableWithInlineView.tsx +47 -47
- package/packages/molecules/src/lib/UserCard/UserCard.module.css +7 -7
- package/packages/molecules/src/lib/UserCard/UserCard.spec.tsx +11 -11
- package/packages/molecules/src/lib/UserCard/UserCard.tsx +22 -22
- package/packages/molecules/src/lib/VerbSelection/HTTPVerbSelection.module.css +7 -7
- package/packages/molecules/src/lib/VerbSelection/HTTPVerbSelection.spec.tsx +10 -10
- package/packages/molecules/src/lib/VerbSelection/HTTPVerbSelection.tsx +72 -72
- package/packages/molecules/tsconfig.json +17 -17
- package/packages/molecules/tsconfig.lib.json +30 -30
- package/packages/organisms/.babelrc +12 -12
- package/packages/organisms/.eslintrc.json +18 -18
- package/packages/organisms/README.md +7 -7
- package/packages/organisms/project.json +8 -8
- package/packages/organisms/src/index.ts +4 -4
- package/packages/organisms/src/lib/EditorToolbar/EditorToolbar.module.css +7 -7
- package/packages/organisms/src/lib/EditorToolbar/EditorToolbar.spec.tsx +10 -10
- package/packages/organisms/src/lib/EditorToolbar/EditorToolbar.tsx +117 -117
- package/packages/organisms/src/lib/EditorToolbar/SortableItem.tsx +51 -51
- package/packages/organisms/src/lib/UserList/UserList.module.css +7 -7
- package/packages/organisms/src/lib/UserList/UserList.spec.tsx +11 -11
- package/packages/organisms/src/lib/UserList/UserList.tsx +48 -48
- package/packages/organisms/src/lib/UserList/store.ts +49 -49
- package/packages/organisms/tsconfig.json +17 -17
- package/packages/organisms/tsconfig.lib.json +24 -24
- package/packages/zustand/.babelrc +12 -12
- package/packages/zustand/.eslintrc.json +18 -18
- package/packages/zustand/README.md +7 -7
- package/packages/zustand/project.json +8 -8
- package/packages/zustand/src/index.ts +4 -4
- package/packages/zustand/tsconfig.json +17 -17
- package/packages/zustand/tsconfig.lib.json +24 -24
- package/tsconfig.base.json +29 -29
- package/packages/diagrams/src/lib/components/automation/AutomationAISuggestionNode.tsx +0 -304
- package/packages/diagrams/src/lib/components/automation/AutomationEmailNode.tsx +0 -773
- package/packages/diagrams/src/lib/components/automation/AutomationGoogleServicesNode.tsx +0 -779
- package/packages/diagrams/src/lib/components/automation/AutomationNoteNode.tsx +0 -422
- package/packages/diagrams/src/lib/components/automation/AutomationSheetsNode.tsx +0 -1135
- package/packages/diagrams/src/lib/examples/GoogleSheetsConfigurationExamples.ts +0 -306
|
@@ -1,930 +1,930 @@
|
|
|
1
|
-
import { Node } from 'reactflow';
|
|
2
|
-
import { validateResourcePlacement, getValidationSummary } from './genericValidation';
|
|
3
|
-
import { CloudProvider } from '../types/validation';
|
|
4
|
-
|
|
5
|
-
interface ValidationResult {
|
|
6
|
-
isValid: boolean;
|
|
7
|
-
message?: string;
|
|
8
|
-
suggestions?: string[];
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
interface ValidationWarning {
|
|
12
|
-
message: string;
|
|
13
|
-
severity: 'warning' | 'info' | 'error';
|
|
14
|
-
suggestions?: string[];
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const validateCloudProviderPlacement = (
|
|
18
|
-
tempNode: Node,
|
|
19
|
-
parentNode: Node | null,
|
|
20
|
-
nodes: Node[],
|
|
21
|
-
cloudProvider?: CloudProvider
|
|
22
|
-
): ValidationResult => {
|
|
23
|
-
// Check for cross-provider contamination
|
|
24
|
-
const crossProviderValidation = validateCrossProviderPlacement(tempNode, nodes, cloudProvider);
|
|
25
|
-
if (!crossProviderValidation.isValid) {
|
|
26
|
-
return crossProviderValidation;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Direct validation for AWS (working implementation)
|
|
30
|
-
if (cloudProvider === 'aws') {
|
|
31
|
-
const childService = tempNode.data?.service;
|
|
32
|
-
const parentService = parentNode?.data?.service;
|
|
33
|
-
|
|
34
|
-
// Root level validation
|
|
35
|
-
if (!parentNode) {
|
|
36
|
-
if (childService === 'account') {
|
|
37
|
-
return { isValid: true, message: 'AWS Account can be placed at root level' };
|
|
38
|
-
} else {
|
|
39
|
-
return {
|
|
40
|
-
isValid: false,
|
|
41
|
-
message: `${childService} cannot be at root level. Only AWS Account can be at root.`,
|
|
42
|
-
suggestions: ['Create an AWS Account first', 'Place this inside an AWS Account']
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// AWS Account containment rules
|
|
48
|
-
if (parentService === 'account') {
|
|
49
|
-
const allowedInAccount = ['vpc', 'availability-zone', 'local-zone'];
|
|
50
|
-
if (allowedInAccount.includes(childService)) {
|
|
51
|
-
return { isValid: true, message: `AWS Account can contain ${childService}` };
|
|
52
|
-
} else {
|
|
53
|
-
return {
|
|
54
|
-
isValid: false,
|
|
55
|
-
message: `${childService} cannot be placed directly in AWS Account. Use VPC → Subnet hierarchy.`,
|
|
56
|
-
suggestions: ['Create VPC first', 'Place services in Subnet within VPC']
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// VPC containment rules
|
|
62
|
-
if (parentService === 'vpc') {
|
|
63
|
-
const allowedInVpc = ['subnet', 'availability-zone', 'security-group'];
|
|
64
|
-
if (allowedInVpc.includes(childService)) {
|
|
65
|
-
return { isValid: true, message: `VPC can contain ${childService}` };
|
|
66
|
-
} else {
|
|
67
|
-
return {
|
|
68
|
-
isValid: false,
|
|
69
|
-
message: `${childService} cannot be placed directly in VPC. Place in Subnet within VPC.`,
|
|
70
|
-
suggestions: ['Create Subnet first', 'Place services in Subnet']
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Subnet containment rules
|
|
76
|
-
if (parentService === 'subnet') {
|
|
77
|
-
const forbiddenInSubnet = ['account', 'vpc', 'subnet'];
|
|
78
|
-
if (forbiddenInSubnet.includes(childService)) {
|
|
79
|
-
return {
|
|
80
|
-
isValid: false,
|
|
81
|
-
message: `${childService} cannot be placed inside Subnet. Check AWS hierarchy.`,
|
|
82
|
-
suggestions: ['Place containers at appropriate level']
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
return { isValid: true, message: `Subnet can contain ${childService} service` };
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Other AWS containers
|
|
89
|
-
if (parentService === 'availability-zone') {
|
|
90
|
-
return { isValid: true, message: `Availability Zone can contain ${childService}` };
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (parentService === 'security-group') {
|
|
94
|
-
return { isValid: true, message: `Security Group can contain ${childService}` };
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Default fallback - allow but warn
|
|
98
|
-
console.warn(`AWS validation: Unknown parent-child relationship: ${parentService} → ${childService}`);
|
|
99
|
-
return {
|
|
100
|
-
isValid: true,
|
|
101
|
-
message: `${parentService || 'container'} can contain ${childService}`
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Use generic validation system for other providers
|
|
106
|
-
if (cloudProvider) {
|
|
107
|
-
const restrictionResults = validateResourcePlacement(tempNode, parentNode, nodes, cloudProvider);
|
|
108
|
-
const summary = getValidationSummary(restrictionResults);
|
|
109
|
-
|
|
110
|
-
return {
|
|
111
|
-
isValid: summary.isValid,
|
|
112
|
-
message: summary.message,
|
|
113
|
-
suggestions: summary.suggestions
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
return { isValid: true };
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Validates cross-provider placement to prevent mixing incompatible services
|
|
122
|
-
*/
|
|
123
|
-
const validateCrossProviderPlacement = (
|
|
124
|
-
tempNode: Node,
|
|
125
|
-
nodes: Node[],
|
|
126
|
-
cloudProvider?: CloudProvider
|
|
127
|
-
): ValidationResult => {
|
|
128
|
-
if (!cloudProvider) return { isValid: true };
|
|
129
|
-
|
|
130
|
-
const existingProviders = new Set(
|
|
131
|
-
nodes
|
|
132
|
-
.filter(node => node.data?.cloudProvider)
|
|
133
|
-
.map(node => node.data.cloudProvider)
|
|
134
|
-
);
|
|
135
|
-
|
|
136
|
-
if (existingProviders.size > 0 && !existingProviders.has(cloudProvider)) {
|
|
137
|
-
const existingProvidersList = Array.from(existingProviders).join(', ');
|
|
138
|
-
return {
|
|
139
|
-
isValid: false,
|
|
140
|
-
message: `Cannot mix cloud providers. This diagram already contains ${existingProvidersList} services. Please use a separate diagram for ${cloudProvider} services.`,
|
|
141
|
-
suggestions: [
|
|
142
|
-
'Create a separate diagram for each cloud provider',
|
|
143
|
-
'Use hybrid/multi-cloud architecture patterns if needed',
|
|
144
|
-
'Consider using a multi-cloud management service'
|
|
145
|
-
]
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
return { isValid: true };
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Automatically finds the best parent node based on position and schema rules
|
|
154
|
-
* @param nodePosition - Position where the node will be placed
|
|
155
|
-
* @param service - Service type of the node
|
|
156
|
-
* @param cloudProvider - Cloud provider (aws, azure, gcp)
|
|
157
|
-
* @param nodes - All existing nodes
|
|
158
|
-
* @returns The best parent node or null if no valid parent found
|
|
159
|
-
*/
|
|
160
|
-
export const findAutoParent = (
|
|
161
|
-
nodePosition: { x: number; y: number },
|
|
162
|
-
service: string,
|
|
163
|
-
cloudProvider: 'aws' | 'azure' | 'gcp',
|
|
164
|
-
nodes: Node[]
|
|
165
|
-
): Node | null => {
|
|
166
|
-
// Get all potential parent nodes (container nodes)
|
|
167
|
-
const potentialParents = nodes.filter(node =>
|
|
168
|
-
node.type === 'subnetNode' &&
|
|
169
|
-
node.data?.cloudProvider === cloudProvider
|
|
170
|
-
);
|
|
171
|
-
|
|
172
|
-
// First, find all containers that actually contain the drop position
|
|
173
|
-
const containingParents = potentialParents.filter(parent =>
|
|
174
|
-
isPositionWithinNode(nodePosition, parent, nodes)
|
|
175
|
-
);
|
|
176
|
-
|
|
177
|
-
// Debug logging for development
|
|
178
|
-
if (process.env.NODE_ENV === 'development') {
|
|
179
|
-
console.log(`Finding auto parent for ${service} at position:`, {
|
|
180
|
-
position: nodePosition,
|
|
181
|
-
potentialParents: potentialParents.map(p => ({ id: p.id, label: p.data?.label, service: p.data?.service })),
|
|
182
|
-
containingParents: containingParents.map(p => ({ id: p.id, label: p.data?.label, service: p.data?.service }))
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// If we have containers that contain the position, prioritize those
|
|
187
|
-
if (containingParents.length > 0) {
|
|
188
|
-
// Sort containing containers by specificity (smallest area first for most specific container)
|
|
189
|
-
const sortedContainingParents = containingParents.sort((a, b) => {
|
|
190
|
-
// First sort by z-index (highest first - more specific layers)
|
|
191
|
-
const aZIndex = a.style?.zIndex || 0;
|
|
192
|
-
const bZIndex = b.style?.zIndex || 0;
|
|
193
|
-
|
|
194
|
-
if (aZIndex !== bZIndex) {
|
|
195
|
-
return (bZIndex as number) - (aZIndex as number);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// Then sort by area (smallest first - most specific container)
|
|
199
|
-
const aArea = (Number(a.style?.width) || 0) * (Number(a.style?.height) || 0);
|
|
200
|
-
const bArea = (Number(b.style?.width) || 0) * (Number(b.style?.height) || 0);
|
|
201
|
-
return aArea - bArea;
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
// Find the best containing parent based on validation rules
|
|
205
|
-
for (const potentialParent of sortedContainingParents) {
|
|
206
|
-
// Create a temporary node to test validation
|
|
207
|
-
const tempNode: Node = {
|
|
208
|
-
id: `temp-${Date.now()}`,
|
|
209
|
-
type: 'serviceNode',
|
|
210
|
-
position: nodePosition,
|
|
211
|
-
data: {
|
|
212
|
-
service,
|
|
213
|
-
cloudProvider,
|
|
214
|
-
},
|
|
215
|
-
parentNode: potentialParent.id,
|
|
216
|
-
};
|
|
217
|
-
|
|
218
|
-
// Validate if this placement is allowed
|
|
219
|
-
const validation = validateCloudProviderPlacement(
|
|
220
|
-
tempNode,
|
|
221
|
-
potentialParent,
|
|
222
|
-
nodes,
|
|
223
|
-
cloudProvider
|
|
224
|
-
);
|
|
225
|
-
|
|
226
|
-
if (validation.isValid) {
|
|
227
|
-
return potentialParent;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// If no containing containers found or none are valid, fall back to default behavior
|
|
233
|
-
// Sort all potential parents by z-index and area as fallback
|
|
234
|
-
const sortedParents = potentialParents.sort((a, b) => {
|
|
235
|
-
const aZIndex = a.style?.zIndex || 0;
|
|
236
|
-
const bZIndex = b.style?.zIndex || 0;
|
|
237
|
-
|
|
238
|
-
if (aZIndex !== bZIndex) {
|
|
239
|
-
return (bZIndex as number) - (aZIndex as number);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// If same z-index, prefer smaller containers
|
|
243
|
-
const aArea = (Number(a.style?.width) || 0) * (Number(a.style?.height) || 0);
|
|
244
|
-
const bArea = (Number(b.style?.width) || 0) * (Number(b.style?.height) || 0);
|
|
245
|
-
return aArea - bArea;
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
// Try each potential parent with validation
|
|
249
|
-
for (const potentialParent of sortedParents) {
|
|
250
|
-
// Create a temporary node to test validation
|
|
251
|
-
const tempNode: Node = {
|
|
252
|
-
id: `temp-${Date.now()}`,
|
|
253
|
-
type: 'serviceNode',
|
|
254
|
-
position: nodePosition,
|
|
255
|
-
data: {
|
|
256
|
-
service,
|
|
257
|
-
cloudProvider,
|
|
258
|
-
},
|
|
259
|
-
parentNode: potentialParent.id,
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
// Validate if this placement is allowed
|
|
263
|
-
const validation = validateCloudProviderPlacement(
|
|
264
|
-
tempNode,
|
|
265
|
-
potentialParent,
|
|
266
|
-
nodes,
|
|
267
|
-
cloudProvider
|
|
268
|
-
);
|
|
269
|
-
|
|
270
|
-
if (validation.isValid) {
|
|
271
|
-
return potentialParent;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// If no valid parent found in containers, check if it can be placed at root
|
|
276
|
-
const tempNode: Node = {
|
|
277
|
-
id: `temp-${Date.now()}`,
|
|
278
|
-
type: 'serviceNode',
|
|
279
|
-
position: nodePosition,
|
|
280
|
-
data: {
|
|
281
|
-
service,
|
|
282
|
-
cloudProvider,
|
|
283
|
-
},
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
const rootValidation = validateCloudProviderPlacement(
|
|
287
|
-
tempNode,
|
|
288
|
-
null,
|
|
289
|
-
nodes,
|
|
290
|
-
cloudProvider
|
|
291
|
-
);
|
|
292
|
-
|
|
293
|
-
return rootValidation.isValid ? null : getDefaultParent(service, cloudProvider, nodes);
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
/**
|
|
297
|
-
* Checks if a position is within the bounds of a node
|
|
298
|
-
* Handles nested node positioning correctly by calculating absolute coordinates
|
|
299
|
-
*/
|
|
300
|
-
const isPositionWithinNode = (
|
|
301
|
-
position: { x: number; y: number },
|
|
302
|
-
node: Node,
|
|
303
|
-
allNodes?: Node[]
|
|
304
|
-
): boolean => {
|
|
305
|
-
// Calculate absolute position of the node (considering parent positioning)
|
|
306
|
-
let nodeX = node.position.x;
|
|
307
|
-
let nodeY = node.position.y;
|
|
308
|
-
|
|
309
|
-
// If the node has a parent, we need to calculate the absolute position
|
|
310
|
-
// by traversing up the parent chain
|
|
311
|
-
if (node.parentNode && allNodes) {
|
|
312
|
-
const parentNode = allNodes.find(n => n.id === node.parentNode);
|
|
313
|
-
if (parentNode) {
|
|
314
|
-
// Recursively calculate parent's absolute position
|
|
315
|
-
const parentAbsolutePos = getAbsolutePosition(parentNode, allNodes);
|
|
316
|
-
nodeX = parentAbsolutePos.x + node.position.x;
|
|
317
|
-
nodeY = parentAbsolutePos.y + node.position.y;
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
const nodeWidth = (node.style?.width as number) || (node.data?.width as number) || 200;
|
|
322
|
-
const nodeHeight = (node.style?.height as number) || (node.data?.height as number) || 150;
|
|
323
|
-
|
|
324
|
-
// Add some padding to make it easier to drop items near edges
|
|
325
|
-
const padding = 10;
|
|
326
|
-
|
|
327
|
-
const isWithin = (
|
|
328
|
-
position.x >= nodeX - padding &&
|
|
329
|
-
position.x <= nodeX + nodeWidth + padding &&
|
|
330
|
-
position.y >= nodeY - padding &&
|
|
331
|
-
position.y <= nodeY + nodeHeight + padding
|
|
332
|
-
);
|
|
333
|
-
|
|
334
|
-
// Debug logging for development
|
|
335
|
-
if (process.env.NODE_ENV === 'development') {
|
|
336
|
-
console.log(`Position check for ${node.data?.service || 'unknown'} (${node.data?.label || 'no label'}):`, {
|
|
337
|
-
dropPosition: position,
|
|
338
|
-
originalPosition: node.position,
|
|
339
|
-
calculatedPosition: { x: nodeX, y: nodeY },
|
|
340
|
-
nodeSize: { width: nodeWidth, height: nodeHeight },
|
|
341
|
-
bounds: {
|
|
342
|
-
left: nodeX - padding,
|
|
343
|
-
right: nodeX + nodeWidth + padding,
|
|
344
|
-
top: nodeY - padding,
|
|
345
|
-
bottom: nodeY + nodeHeight + padding
|
|
346
|
-
},
|
|
347
|
-
isWithin,
|
|
348
|
-
hasParent: !!node.parentNode,
|
|
349
|
-
parentNode: node.parentNode
|
|
350
|
-
});
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
return isWithin;
|
|
354
|
-
};
|
|
355
|
-
|
|
356
|
-
/**
|
|
357
|
-
* Recursively calculates the absolute position of a node by traversing up the parent chain
|
|
358
|
-
*/
|
|
359
|
-
const getAbsolutePosition = (node: Node, allNodes: Node[]): { x: number; y: number } => {
|
|
360
|
-
let absoluteX = node.position.x;
|
|
361
|
-
let absoluteY = node.position.y;
|
|
362
|
-
|
|
363
|
-
if (node.parentNode) {
|
|
364
|
-
const parentNode = allNodes.find(n => n.id === node.parentNode);
|
|
365
|
-
if (parentNode) {
|
|
366
|
-
const parentAbsolutePos = getAbsolutePosition(parentNode, allNodes);
|
|
367
|
-
absoluteX = parentAbsolutePos.x + node.position.x;
|
|
368
|
-
absoluteY = parentAbsolutePos.y + node.position.y;
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
return { x: absoluteX, y: absoluteY };
|
|
373
|
-
};
|
|
374
|
-
|
|
375
|
-
/**
|
|
376
|
-
* Gets the default parent based on service type and cloud provider
|
|
377
|
-
*/
|
|
378
|
-
const getDefaultParent = (
|
|
379
|
-
service: string,
|
|
380
|
-
cloudProvider: 'aws' | 'azure' | 'gcp',
|
|
381
|
-
nodes: Node[]
|
|
382
|
-
): Node | null => {
|
|
383
|
-
// Define comprehensive default parent hierarchy for each cloud provider
|
|
384
|
-
const defaultParents = {
|
|
385
|
-
aws: {
|
|
386
|
-
// Compute services
|
|
387
|
-
compute: ['subnet', 'availability-zone', 'vpc', 'account'],
|
|
388
|
-
ec2: ['subnet', 'availability-zone', 'vpc', 'account'],
|
|
389
|
-
lambda: ['account'],
|
|
390
|
-
'elastic-beanstalk': ['account'],
|
|
391
|
-
fargate: ['subnet', 'vpc', 'account'],
|
|
392
|
-
batch: ['subnet', 'vpc', 'account'],
|
|
393
|
-
'app-runner': ['account'],
|
|
394
|
-
'serverless-application-repository': ['account'],
|
|
395
|
-
|
|
396
|
-
// Database services
|
|
397
|
-
database: ['subnet', 'vpc', 'account'],
|
|
398
|
-
rds: ['subnet', 'vpc', 'account'],
|
|
399
|
-
aurora: ['subnet', 'vpc', 'account'],
|
|
400
|
-
dynamodb: ['account'],
|
|
401
|
-
elasticache: ['subnet', 'vpc', 'account'],
|
|
402
|
-
neptune: ['subnet', 'vpc', 'account'],
|
|
403
|
-
documentdb: ['subnet', 'vpc', 'account'],
|
|
404
|
-
keyspaces: ['account'],
|
|
405
|
-
timestream: ['account'],
|
|
406
|
-
|
|
407
|
-
// Storage services
|
|
408
|
-
storage: ['account'],
|
|
409
|
-
s3: ['account'],
|
|
410
|
-
ebs: ['account'],
|
|
411
|
-
efs: ['account'],
|
|
412
|
-
fsx: ['account'],
|
|
413
|
-
backup: ['account'],
|
|
414
|
-
'storage-gateway': ['account'],
|
|
415
|
-
|
|
416
|
-
// Networking services
|
|
417
|
-
networking: ['vpc', 'account'],
|
|
418
|
-
'elastic-load-balancing': ['subnet', 'vpc', 'account'],
|
|
419
|
-
'route-53': ['account'],
|
|
420
|
-
'direct-connect': ['account'],
|
|
421
|
-
'transit-gateway': ['account'],
|
|
422
|
-
'global-accelerator': ['account'],
|
|
423
|
-
'site-to-site-vpn': ['vpc', 'account'],
|
|
424
|
-
'client-vpn': ['vpc', 'account'],
|
|
425
|
-
|
|
426
|
-
// Security services
|
|
427
|
-
security: ['account'],
|
|
428
|
-
iam: ['account'],
|
|
429
|
-
cognito: ['account'],
|
|
430
|
-
kms: ['account'],
|
|
431
|
-
'secrets-manager': ['account'],
|
|
432
|
-
'certificate-manager': ['account'],
|
|
433
|
-
waf: ['account'],
|
|
434
|
-
shield: ['account'],
|
|
435
|
-
guardduty: ['account'],
|
|
436
|
-
'security-hub': ['account'],
|
|
437
|
-
'network-firewall': ['subnet', 'vpc', 'account'],
|
|
438
|
-
|
|
439
|
-
// Container services
|
|
440
|
-
containers: ['subnet', 'vpc', 'account'],
|
|
441
|
-
ecs: ['subnet', 'vpc', 'account'],
|
|
442
|
-
'elastic-container-service': ['subnet', 'vpc', 'account'],
|
|
443
|
-
eks: ['subnet', 'vpc', 'account'],
|
|
444
|
-
'elastic-kubernetes-service': ['subnet', 'vpc', 'account'],
|
|
445
|
-
'elastic-container-registry': ['account'],
|
|
446
|
-
|
|
447
|
-
// Serverless services
|
|
448
|
-
serverless: ['account'],
|
|
449
|
-
},
|
|
450
|
-
azure: {
|
|
451
|
-
// Compute services
|
|
452
|
-
virtualMachine: ['subnet', 'virtual-network', 'resource-group', 'subscription'],
|
|
453
|
-
'virtual-machines': ['subnet', 'virtual-network', 'resource-group', 'subscription'],
|
|
454
|
-
'app-services': ['resource-group', 'subscription'],
|
|
455
|
-
'app-service': ['resource-group', 'subscription'],
|
|
456
|
-
'function-apps': ['resource-group', 'subscription'],
|
|
457
|
-
'batch-accounts': ['resource-group', 'subscription'],
|
|
458
|
-
'kubernetes-services': ['resource-group', 'subscription'],
|
|
459
|
-
'container-instances': ['resource-group', 'subscription'],
|
|
460
|
-
'virtual-machine-scale-sets': ['resource-group', 'subscription'],
|
|
461
|
-
|
|
462
|
-
// Database services
|
|
463
|
-
database: ['resource-group', 'subscription'],
|
|
464
|
-
'sql-database': ['resource-group', 'subscription'],
|
|
465
|
-
'cosmos-db': ['resource-group', 'subscription'],
|
|
466
|
-
'mysql-server': ['resource-group', 'subscription'],
|
|
467
|
-
'postgresql-server': ['resource-group', 'subscription'],
|
|
468
|
-
'redis-cache': ['resource-group', 'subscription'],
|
|
469
|
-
|
|
470
|
-
// Storage services
|
|
471
|
-
storageAccount: ['resource-group', 'subscription'],
|
|
472
|
-
'storage-accounts': ['resource-group', 'subscription'],
|
|
473
|
-
'managed-disks': ['resource-group', 'subscription'],
|
|
474
|
-
'blob-storage': ['resource-group', 'subscription'],
|
|
475
|
-
'file-storage': ['resource-group', 'subscription'],
|
|
476
|
-
|
|
477
|
-
// Networking services
|
|
478
|
-
networkInterface: ['subnet', 'virtual-network', 'resource-group', 'subscription'],
|
|
479
|
-
'network-interfaces': ['subnet', 'virtual-network', 'resource-group', 'subscription'],
|
|
480
|
-
loadBalancer: ['resource-group', 'subscription'],
|
|
481
|
-
'load-balancers': ['resource-group', 'subscription'],
|
|
482
|
-
'application-gateway': ['subnet', 'virtual-network', 'resource-group', 'subscription'],
|
|
483
|
-
'vpn-gateway': ['virtual-network', 'resource-group', 'subscription'],
|
|
484
|
-
'express-route': ['resource-group', 'subscription'],
|
|
485
|
-
'cdn-profiles': ['resource-group', 'subscription'],
|
|
486
|
-
|
|
487
|
-
// Security services
|
|
488
|
-
'key-vaults': ['resource-group', 'subscription'],
|
|
489
|
-
'security-center': ['subscription'],
|
|
490
|
-
'azure-firewall': ['subnet', 'virtual-network', 'resource-group', 'subscription'],
|
|
491
|
-
'network-security-groups': ['resource-group', 'subscription'],
|
|
492
|
-
'azure-active-directory': ['subscription'],
|
|
493
|
-
},
|
|
494
|
-
gcp: {
|
|
495
|
-
// Compute services
|
|
496
|
-
compute: ['subnet', 'vpc', 'project'],
|
|
497
|
-
'compute-engine': ['subnet', 'vpc', 'project'],
|
|
498
|
-
'app-engine': ['project'],
|
|
499
|
-
'cloud-functions': ['project'],
|
|
500
|
-
'kubernetes-engine': ['project'],
|
|
501
|
-
'cloud-run': ['project'],
|
|
502
|
-
'cloud-build': ['project'],
|
|
503
|
-
|
|
504
|
-
// Database services
|
|
505
|
-
database: ['project'],
|
|
506
|
-
'cloud-sql': ['project'],
|
|
507
|
-
'cloud-spanner': ['project'],
|
|
508
|
-
'cloud-bigtable': ['project'],
|
|
509
|
-
'cloud-firestore': ['project'],
|
|
510
|
-
'cloud-memorystore': ['project'],
|
|
511
|
-
|
|
512
|
-
// Storage services
|
|
513
|
-
storage: ['project'],
|
|
514
|
-
'cloud-storage': ['project'],
|
|
515
|
-
'persistent-disk': ['project'],
|
|
516
|
-
'filestore': ['project'],
|
|
517
|
-
|
|
518
|
-
// Networking services
|
|
519
|
-
networking: ['vpc', 'project'],
|
|
520
|
-
'cloud-load-balancing': ['project'],
|
|
521
|
-
'cloud-cdn': ['project'],
|
|
522
|
-
'cloud-dns': ['project'],
|
|
523
|
-
'cloud-interconnect': ['project'],
|
|
524
|
-
'cloud-vpn': ['vpc', 'project'],
|
|
525
|
-
'cloud-nat': ['vpc', 'project'],
|
|
526
|
-
'cloud-router': ['vpc', 'project'],
|
|
527
|
-
|
|
528
|
-
// Security services
|
|
529
|
-
'cloud-iam': ['project'],
|
|
530
|
-
'cloud-kms': ['project'],
|
|
531
|
-
'cloud-security-command-center': ['project'],
|
|
532
|
-
'cloud-armor': ['project'],
|
|
533
|
-
'binary-authorization': ['project'],
|
|
534
|
-
'cloud-asset-inventory': ['project'],
|
|
535
|
-
|
|
536
|
-
// Serverless services
|
|
537
|
-
cloudFunction: ['project'],
|
|
538
|
-
cloudRun: ['project'],
|
|
539
|
-
},
|
|
540
|
-
};
|
|
541
|
-
|
|
542
|
-
// Get the service category/type
|
|
543
|
-
const serviceType = getServiceType(service, cloudProvider);
|
|
544
|
-
const parentHierarchy = defaultParents[cloudProvider]?.[serviceType as keyof typeof defaultParents[typeof cloudProvider]];
|
|
545
|
-
|
|
546
|
-
if (!parentHierarchy) {
|
|
547
|
-
// If no specific hierarchy found, use the service name directly
|
|
548
|
-
const directHierarchy = defaultParents[cloudProvider]?.[service as keyof typeof defaultParents[typeof cloudProvider]];
|
|
549
|
-
if (directHierarchy) {
|
|
550
|
-
return findParentFromHierarchy(directHierarchy, nodes, cloudProvider);
|
|
551
|
-
}
|
|
552
|
-
return null;
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
return findParentFromHierarchy(parentHierarchy, nodes, cloudProvider);
|
|
556
|
-
};
|
|
557
|
-
|
|
558
|
-
/**
|
|
559
|
-
* Finds the first available parent from a hierarchy
|
|
560
|
-
*/
|
|
561
|
-
const findParentFromHierarchy = (
|
|
562
|
-
hierarchy: string[],
|
|
563
|
-
nodes: Node[],
|
|
564
|
-
cloudProvider: 'aws' | 'azure' | 'gcp'
|
|
565
|
-
): Node | null => {
|
|
566
|
-
for (const parentType of hierarchy) {
|
|
567
|
-
const parent = nodes.find(node =>
|
|
568
|
-
node.type === 'subnetNode' &&
|
|
569
|
-
node.data?.service === parentType &&
|
|
570
|
-
node.data?.cloudProvider === cloudProvider
|
|
571
|
-
);
|
|
572
|
-
|
|
573
|
-
if (parent) {
|
|
574
|
-
return parent;
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
return null;
|
|
578
|
-
};
|
|
579
|
-
|
|
580
|
-
/**
|
|
581
|
-
* Maps service to service type/category with comprehensive mapping
|
|
582
|
-
*/
|
|
583
|
-
const getServiceType = (service: string, cloudProvider: 'aws' | 'azure' | 'gcp'): string => {
|
|
584
|
-
const serviceTypeMap = {
|
|
585
|
-
aws: {
|
|
586
|
-
// Compute services
|
|
587
|
-
ec2: 'compute',
|
|
588
|
-
lambda: 'serverless',
|
|
589
|
-
'elastic-beanstalk': 'compute',
|
|
590
|
-
fargate: 'containers',
|
|
591
|
-
batch: 'compute',
|
|
592
|
-
'app-runner': 'compute',
|
|
593
|
-
'application-auto-scaling': 'compute',
|
|
594
|
-
'ec2-auto-scaling': 'compute',
|
|
595
|
-
'serverless-application-repository': 'serverless',
|
|
596
|
-
|
|
597
|
-
// Database services
|
|
598
|
-
rds: 'database',
|
|
599
|
-
aurora: 'database',
|
|
600
|
-
dynamodb: 'database',
|
|
601
|
-
elasticache: 'database',
|
|
602
|
-
neptune: 'database',
|
|
603
|
-
documentdb: 'database',
|
|
604
|
-
keyspaces: 'database',
|
|
605
|
-
timestream: 'database',
|
|
606
|
-
'database-migration-service': 'database',
|
|
607
|
-
|
|
608
|
-
// Storage services
|
|
609
|
-
s3: 'storage',
|
|
610
|
-
ebs: 'storage',
|
|
611
|
-
efs: 'storage',
|
|
612
|
-
fsx: 'storage',
|
|
613
|
-
backup: 'storage',
|
|
614
|
-
'storage-gateway': 'storage',
|
|
615
|
-
snowball: 'storage',
|
|
616
|
-
'snowball-edge': 'storage',
|
|
617
|
-
snowcone: 'storage',
|
|
618
|
-
snowmobile: 'storage',
|
|
619
|
-
|
|
620
|
-
// Networking services
|
|
621
|
-
vpc: 'networking',
|
|
622
|
-
'elastic-load-balancing': 'networking',
|
|
623
|
-
'route-53': 'networking',
|
|
624
|
-
'direct-connect': 'networking',
|
|
625
|
-
'transit-gateway': 'networking',
|
|
626
|
-
'global-accelerator': 'networking',
|
|
627
|
-
'site-to-site-vpn': 'networking',
|
|
628
|
-
'client-vpn': 'networking',
|
|
629
|
-
'app-mesh': 'networking',
|
|
630
|
-
'cloud-map': 'networking',
|
|
631
|
-
'cloud-wan': 'networking',
|
|
632
|
-
privatelink: 'networking',
|
|
633
|
-
'vpc-lattice': 'networking',
|
|
634
|
-
|
|
635
|
-
// Security services
|
|
636
|
-
'security-group': 'security',
|
|
637
|
-
iam: 'security',
|
|
638
|
-
cognito: 'security',
|
|
639
|
-
kms: 'security',
|
|
640
|
-
'secrets-manager': 'security',
|
|
641
|
-
'certificate-manager': 'security',
|
|
642
|
-
waf: 'security',
|
|
643
|
-
shield: 'security',
|
|
644
|
-
guardduty: 'security',
|
|
645
|
-
'security-hub': 'security',
|
|
646
|
-
'network-firewall': 'security',
|
|
647
|
-
inspector: 'security',
|
|
648
|
-
macie: 'security',
|
|
649
|
-
detective: 'security',
|
|
650
|
-
|
|
651
|
-
// Container services
|
|
652
|
-
ecs: 'containers',
|
|
653
|
-
'elastic-container-service': 'containers',
|
|
654
|
-
eks: 'containers',
|
|
655
|
-
'elastic-kubernetes-service': 'containers',
|
|
656
|
-
'elastic-container-registry': 'containers',
|
|
657
|
-
'ecs-anywhere': 'containers',
|
|
658
|
-
'eks-anywhere': 'containers',
|
|
659
|
-
'eks-cloud': 'containers',
|
|
660
|
-
'eks-distro': 'containers',
|
|
661
|
-
},
|
|
662
|
-
azure: {
|
|
663
|
-
// Compute services
|
|
664
|
-
'virtual-machine': 'virtualMachine',
|
|
665
|
-
'virtual-machines': 'virtualMachine',
|
|
666
|
-
'app-services': 'appService',
|
|
667
|
-
'app-service': 'appService',
|
|
668
|
-
'function-apps': 'appService',
|
|
669
|
-
'batch-accounts': 'compute',
|
|
670
|
-
'kubernetes-services': 'containers',
|
|
671
|
-
'container-instances': 'containers',
|
|
672
|
-
'virtual-machine-scale-sets': 'virtualMachine',
|
|
673
|
-
|
|
674
|
-
// Database services
|
|
675
|
-
'sql-database': 'database',
|
|
676
|
-
'cosmos-db': 'database',
|
|
677
|
-
'mysql-server': 'database',
|
|
678
|
-
'postgresql-server': 'database',
|
|
679
|
-
'redis-cache': 'database',
|
|
680
|
-
'mariadb-server': 'database',
|
|
681
|
-
'managed-database': 'database',
|
|
682
|
-
|
|
683
|
-
// Storage services
|
|
684
|
-
'storage-account': 'storageAccount',
|
|
685
|
-
'storage-accounts': 'storageAccount',
|
|
686
|
-
'managed-disks': 'storageAccount',
|
|
687
|
-
'blob-storage': 'storageAccount',
|
|
688
|
-
'file-storage': 'storageAccount',
|
|
689
|
-
|
|
690
|
-
// Networking services
|
|
691
|
-
'network-interface': 'networkInterface',
|
|
692
|
-
'network-interfaces': 'networkInterface',
|
|
693
|
-
'load-balancer': 'loadBalancer',
|
|
694
|
-
'load-balancers': 'loadBalancer',
|
|
695
|
-
'application-gateway': 'loadBalancer',
|
|
696
|
-
'vpn-gateway': 'networking',
|
|
697
|
-
'express-route': 'networking',
|
|
698
|
-
'cdn-profiles': 'networking',
|
|
699
|
-
|
|
700
|
-
// Security services
|
|
701
|
-
'key-vaults': 'security',
|
|
702
|
-
'security-center': 'security',
|
|
703
|
-
'azure-firewall': 'security',
|
|
704
|
-
'network-security-groups': 'security',
|
|
705
|
-
'azure-active-directory': 'security',
|
|
706
|
-
},
|
|
707
|
-
gcp: {
|
|
708
|
-
// Compute services
|
|
709
|
-
'compute-engine': 'compute',
|
|
710
|
-
'app-engine': 'compute',
|
|
711
|
-
'cloud-functions': 'cloudFunction',
|
|
712
|
-
'kubernetes-engine': 'containers',
|
|
713
|
-
'cloud-run': 'cloudRun',
|
|
714
|
-
'cloud-build': 'compute',
|
|
715
|
-
|
|
716
|
-
// Database services
|
|
717
|
-
'cloud-sql': 'database',
|
|
718
|
-
'cloud-spanner': 'database',
|
|
719
|
-
'cloud-bigtable': 'database',
|
|
720
|
-
'cloud-firestore': 'database',
|
|
721
|
-
'cloud-memorystore': 'database',
|
|
722
|
-
|
|
723
|
-
// Storage services
|
|
724
|
-
'cloud-storage': 'storage',
|
|
725
|
-
'persistent-disk': 'storage',
|
|
726
|
-
'filestore': 'storage',
|
|
727
|
-
|
|
728
|
-
// Networking services
|
|
729
|
-
'cloud-load-balancing': 'networking',
|
|
730
|
-
'cloud-cdn': 'networking',
|
|
731
|
-
'cloud-dns': 'networking',
|
|
732
|
-
'cloud-interconnect': 'networking',
|
|
733
|
-
'cloud-vpn': 'networking',
|
|
734
|
-
'cloud-nat': 'networking',
|
|
735
|
-
'cloud-router': 'networking',
|
|
736
|
-
'cloud-firewall-rules': 'networking',
|
|
737
|
-
'virtual-private-cloud': 'networking',
|
|
738
|
-
|
|
739
|
-
// Security services
|
|
740
|
-
'cloud-iam': 'security',
|
|
741
|
-
'cloud-kms': 'security',
|
|
742
|
-
'cloud-security-command-center': 'security',
|
|
743
|
-
'cloud-armor': 'security',
|
|
744
|
-
'binary-authorization': 'security',
|
|
745
|
-
'cloud-asset-inventory': 'security',
|
|
746
|
-
iam: 'security',
|
|
747
|
-
'data-loss-prevention-api': 'security',
|
|
748
|
-
beyondcorp: 'security',
|
|
749
|
-
},
|
|
750
|
-
};
|
|
751
|
-
|
|
752
|
-
return serviceTypeMap[cloudProvider]?.[service as keyof typeof serviceTypeMap[typeof cloudProvider]] || service;
|
|
753
|
-
};
|
|
754
|
-
|
|
755
|
-
/**
|
|
756
|
-
* Provides smart placement suggestions based on best practices
|
|
757
|
-
*/
|
|
758
|
-
export const getPlacementSuggestions = (
|
|
759
|
-
service: string,
|
|
760
|
-
cloudProvider: 'aws' | 'azure' | 'gcp',
|
|
761
|
-
nodes: Node[]
|
|
762
|
-
): string[] => {
|
|
763
|
-
const suggestions: string[] = [];
|
|
764
|
-
|
|
765
|
-
// Check if recommended containers exist
|
|
766
|
-
const serviceType = getServiceType(service, cloudProvider);
|
|
767
|
-
const recommendedContainers = getRecommendedContainers(service, cloudProvider);
|
|
768
|
-
|
|
769
|
-
for (const container of recommendedContainers) {
|
|
770
|
-
const exists = nodes.some(node =>
|
|
771
|
-
node.type === 'subnetNode' &&
|
|
772
|
-
node.data?.service === container &&
|
|
773
|
-
node.data?.cloudProvider === cloudProvider
|
|
774
|
-
);
|
|
775
|
-
|
|
776
|
-
if (!exists) {
|
|
777
|
-
suggestions.push(`Consider creating a ${container} container first for better organization`);
|
|
778
|
-
}
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
// Add cloud-specific best practice suggestions
|
|
782
|
-
if (cloudProvider === 'aws') {
|
|
783
|
-
if (serviceType === 'compute' && !nodes.some(n => n.data?.service === 'subnet')) {
|
|
784
|
-
suggestions.push('AWS compute resources should be placed in subnets for proper network isolation');
|
|
785
|
-
}
|
|
786
|
-
if (serviceType === 'database' && !nodes.some(n => n.data?.service === 'subnet')) {
|
|
787
|
-
suggestions.push('AWS database resources should be placed in private subnets for security');
|
|
788
|
-
}
|
|
789
|
-
} else if (cloudProvider === 'azure') {
|
|
790
|
-
if (serviceType === 'virtualMachine' && !nodes.some(n => n.data?.service === 'subnet')) {
|
|
791
|
-
suggestions.push('Azure VMs should be placed in subnets within a Virtual Network');
|
|
792
|
-
}
|
|
793
|
-
if (!nodes.some(n => n.data?.service === 'resource-group')) {
|
|
794
|
-
suggestions.push('Azure resources should be organized in Resource Groups');
|
|
795
|
-
}
|
|
796
|
-
} else if (cloudProvider === 'gcp') {
|
|
797
|
-
if (!nodes.some(n => n.data?.service === 'project')) {
|
|
798
|
-
suggestions.push('GCP resources must be organized within a Project');
|
|
799
|
-
}
|
|
800
|
-
if (serviceType === 'compute' && !nodes.some(n => n.data?.service === 'subnet')) {
|
|
801
|
-
suggestions.push('GCP compute resources should be placed in subnets for network organization');
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
return suggestions;
|
|
806
|
-
};
|
|
807
|
-
|
|
808
|
-
/**
|
|
809
|
-
* Gets recommended containers for a service
|
|
810
|
-
*/
|
|
811
|
-
const getRecommendedContainers = (service: string, cloudProvider: 'aws' | 'azure' | 'gcp'): string[] => {
|
|
812
|
-
const containerRecommendations = {
|
|
813
|
-
aws: {
|
|
814
|
-
compute: ['account', 'vpc', 'subnet'],
|
|
815
|
-
database: ['account', 'vpc', 'subnet'],
|
|
816
|
-
storage: ['account'],
|
|
817
|
-
networking: ['account', 'vpc'],
|
|
818
|
-
security: ['account'],
|
|
819
|
-
containers: ['account', 'vpc', 'subnet'],
|
|
820
|
-
serverless: ['account'],
|
|
821
|
-
},
|
|
822
|
-
azure: {
|
|
823
|
-
virtualMachine: ['subscription', 'resource-group', 'virtual-network', 'subnet'],
|
|
824
|
-
database: ['subscription', 'resource-group'],
|
|
825
|
-
storageAccount: ['subscription', 'resource-group'],
|
|
826
|
-
appService: ['subscription', 'resource-group'],
|
|
827
|
-
networking: ['subscription', 'resource-group'],
|
|
828
|
-
security: ['subscription', 'resource-group'],
|
|
829
|
-
},
|
|
830
|
-
gcp: {
|
|
831
|
-
compute: ['project', 'vpc', 'subnet'],
|
|
832
|
-
database: ['project'],
|
|
833
|
-
storage: ['project'],
|
|
834
|
-
networking: ['project', 'vpc'],
|
|
835
|
-
security: ['project'],
|
|
836
|
-
containers: ['project'],
|
|
837
|
-
},
|
|
838
|
-
};
|
|
839
|
-
|
|
840
|
-
const serviceType = getServiceType(service, cloudProvider);
|
|
841
|
-
return containerRecommendations[cloudProvider]?.[serviceType as keyof typeof containerRecommendations[typeof cloudProvider]] || [];
|
|
842
|
-
};
|
|
843
|
-
|
|
844
|
-
/**
|
|
845
|
-
* Validates placement and provides warnings for sub-optimal configurations
|
|
846
|
-
*/
|
|
847
|
-
export const validatePlacementWithWarnings = (
|
|
848
|
-
node: Node,
|
|
849
|
-
parentNode: Node | null,
|
|
850
|
-
nodes: Node[],
|
|
851
|
-
cloudProvider: 'aws' | 'azure' | 'gcp'
|
|
852
|
-
): { isValid: boolean; warnings: ValidationWarning[] } => {
|
|
853
|
-
const warnings: ValidationWarning[] = [];
|
|
854
|
-
|
|
855
|
-
// Check for sub-optimal placements
|
|
856
|
-
const serviceType = getServiceType(node.data?.service, cloudProvider);
|
|
857
|
-
|
|
858
|
-
if (cloudProvider === 'aws') {
|
|
859
|
-
// Check for compute resources not in subnets
|
|
860
|
-
if (serviceType === 'compute' && (!parentNode || parentNode.data?.service !== 'subnet')) {
|
|
861
|
-
warnings.push({
|
|
862
|
-
message: 'Compute resources should be placed in subnets for proper network isolation',
|
|
863
|
-
severity: 'warning',
|
|
864
|
-
suggestions: ['Create a subnet and place the compute resource within it']
|
|
865
|
-
});
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
// Check for database resources not in private subnets
|
|
869
|
-
if (serviceType === 'database' && (!parentNode || parentNode.data?.service !== 'subnet')) {
|
|
870
|
-
warnings.push({
|
|
871
|
-
message: 'Database resources should be placed in private subnets for security',
|
|
872
|
-
severity: 'warning',
|
|
873
|
-
suggestions: ['Create a private subnet and place the database within it']
|
|
874
|
-
});
|
|
875
|
-
}
|
|
876
|
-
} else if (cloudProvider === 'azure') {
|
|
877
|
-
// Check for VMs not in subnets
|
|
878
|
-
if (serviceType === 'virtualMachine' && (!parentNode || parentNode.data?.service !== 'subnet')) {
|
|
879
|
-
warnings.push({
|
|
880
|
-
message: 'Virtual machines should be placed in subnets for network organization',
|
|
881
|
-
severity: 'warning',
|
|
882
|
-
suggestions: ['Create a subnet within a virtual network and place the VM there']
|
|
883
|
-
});
|
|
884
|
-
}
|
|
885
|
-
} else if (cloudProvider === 'gcp') {
|
|
886
|
-
// Check for compute resources not in subnets
|
|
887
|
-
if (serviceType === 'compute' && (!parentNode || parentNode.data?.service !== 'subnet')) {
|
|
888
|
-
warnings.push({
|
|
889
|
-
message: 'Compute resources should be placed in subnets for network organization',
|
|
890
|
-
severity: 'warning',
|
|
891
|
-
suggestions: ['Create a subnet within a VPC and place the compute resource there']
|
|
892
|
-
});
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
return { isValid: true, warnings };
|
|
897
|
-
};
|
|
898
|
-
|
|
899
|
-
/**
|
|
900
|
-
* Automatically assigns parent during drag and drop based on drop position
|
|
901
|
-
* @param draggedNode - The node being dragged
|
|
902
|
-
* @param dropPosition - Position where the node is dropped
|
|
903
|
-
* @param nodes - All existing nodes
|
|
904
|
-
* @returns Updated node with automatic parent assignment
|
|
905
|
-
*/
|
|
906
|
-
export const autoAssignParentOnDrop = (
|
|
907
|
-
draggedNode: Node,
|
|
908
|
-
dropPosition: { x: number; y: number },
|
|
909
|
-
nodes: Node[]
|
|
910
|
-
): Node => {
|
|
911
|
-
const cloudProvider = draggedNode.data?.cloudProvider;
|
|
912
|
-
const service = draggedNode.data?.service;
|
|
913
|
-
|
|
914
|
-
if (!cloudProvider || !service) {
|
|
915
|
-
return draggedNode;
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
// Find the best parent based on drop position
|
|
919
|
-
const bestParent = findAutoParent(dropPosition, service, cloudProvider, nodes);
|
|
920
|
-
|
|
921
|
-
// Update the node with the new parent
|
|
922
|
-
const updatedNode: Node = {
|
|
923
|
-
...draggedNode,
|
|
924
|
-
position: dropPosition,
|
|
925
|
-
parentNode: bestParent?.id,
|
|
926
|
-
extent: bestParent ? 'parent' : undefined,
|
|
927
|
-
};
|
|
928
|
-
|
|
929
|
-
return updatedNode;
|
|
1
|
+
import { Node } from 'reactflow';
|
|
2
|
+
import { validateResourcePlacement, getValidationSummary } from './genericValidation';
|
|
3
|
+
import { CloudProvider } from '../types/validation';
|
|
4
|
+
|
|
5
|
+
interface ValidationResult {
|
|
6
|
+
isValid: boolean;
|
|
7
|
+
message?: string;
|
|
8
|
+
suggestions?: string[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface ValidationWarning {
|
|
12
|
+
message: string;
|
|
13
|
+
severity: 'warning' | 'info' | 'error';
|
|
14
|
+
suggestions?: string[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const validateCloudProviderPlacement = (
|
|
18
|
+
tempNode: Node,
|
|
19
|
+
parentNode: Node | null,
|
|
20
|
+
nodes: Node[],
|
|
21
|
+
cloudProvider?: CloudProvider
|
|
22
|
+
): ValidationResult => {
|
|
23
|
+
// Check for cross-provider contamination
|
|
24
|
+
const crossProviderValidation = validateCrossProviderPlacement(tempNode, nodes, cloudProvider);
|
|
25
|
+
if (!crossProviderValidation.isValid) {
|
|
26
|
+
return crossProviderValidation;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Direct validation for AWS (working implementation)
|
|
30
|
+
if (cloudProvider === 'aws') {
|
|
31
|
+
const childService = tempNode.data?.service;
|
|
32
|
+
const parentService = parentNode?.data?.service;
|
|
33
|
+
|
|
34
|
+
// Root level validation
|
|
35
|
+
if (!parentNode) {
|
|
36
|
+
if (childService === 'account') {
|
|
37
|
+
return { isValid: true, message: 'AWS Account can be placed at root level' };
|
|
38
|
+
} else {
|
|
39
|
+
return {
|
|
40
|
+
isValid: false,
|
|
41
|
+
message: `${childService} cannot be at root level. Only AWS Account can be at root.`,
|
|
42
|
+
suggestions: ['Create an AWS Account first', 'Place this inside an AWS Account']
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// AWS Account containment rules
|
|
48
|
+
if (parentService === 'account') {
|
|
49
|
+
const allowedInAccount = ['vpc', 'availability-zone', 'local-zone'];
|
|
50
|
+
if (allowedInAccount.includes(childService)) {
|
|
51
|
+
return { isValid: true, message: `AWS Account can contain ${childService}` };
|
|
52
|
+
} else {
|
|
53
|
+
return {
|
|
54
|
+
isValid: false,
|
|
55
|
+
message: `${childService} cannot be placed directly in AWS Account. Use VPC → Subnet hierarchy.`,
|
|
56
|
+
suggestions: ['Create VPC first', 'Place services in Subnet within VPC']
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// VPC containment rules
|
|
62
|
+
if (parentService === 'vpc') {
|
|
63
|
+
const allowedInVpc = ['subnet', 'availability-zone', 'security-group'];
|
|
64
|
+
if (allowedInVpc.includes(childService)) {
|
|
65
|
+
return { isValid: true, message: `VPC can contain ${childService}` };
|
|
66
|
+
} else {
|
|
67
|
+
return {
|
|
68
|
+
isValid: false,
|
|
69
|
+
message: `${childService} cannot be placed directly in VPC. Place in Subnet within VPC.`,
|
|
70
|
+
suggestions: ['Create Subnet first', 'Place services in Subnet']
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Subnet containment rules
|
|
76
|
+
if (parentService === 'subnet') {
|
|
77
|
+
const forbiddenInSubnet = ['account', 'vpc', 'subnet'];
|
|
78
|
+
if (forbiddenInSubnet.includes(childService)) {
|
|
79
|
+
return {
|
|
80
|
+
isValid: false,
|
|
81
|
+
message: `${childService} cannot be placed inside Subnet. Check AWS hierarchy.`,
|
|
82
|
+
suggestions: ['Place containers at appropriate level']
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
return { isValid: true, message: `Subnet can contain ${childService} service` };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Other AWS containers
|
|
89
|
+
if (parentService === 'availability-zone') {
|
|
90
|
+
return { isValid: true, message: `Availability Zone can contain ${childService}` };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (parentService === 'security-group') {
|
|
94
|
+
return { isValid: true, message: `Security Group can contain ${childService}` };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Default fallback - allow but warn
|
|
98
|
+
console.warn(`AWS validation: Unknown parent-child relationship: ${parentService} → ${childService}`);
|
|
99
|
+
return {
|
|
100
|
+
isValid: true,
|
|
101
|
+
message: `${parentService || 'container'} can contain ${childService}`
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Use generic validation system for other providers
|
|
106
|
+
if (cloudProvider) {
|
|
107
|
+
const restrictionResults = validateResourcePlacement(tempNode, parentNode, nodes, cloudProvider);
|
|
108
|
+
const summary = getValidationSummary(restrictionResults);
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
isValid: summary.isValid,
|
|
112
|
+
message: summary.message,
|
|
113
|
+
suggestions: summary.suggestions
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return { isValid: true };
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Validates cross-provider placement to prevent mixing incompatible services
|
|
122
|
+
*/
|
|
123
|
+
const validateCrossProviderPlacement = (
|
|
124
|
+
tempNode: Node,
|
|
125
|
+
nodes: Node[],
|
|
126
|
+
cloudProvider?: CloudProvider
|
|
127
|
+
): ValidationResult => {
|
|
128
|
+
if (!cloudProvider) return { isValid: true };
|
|
129
|
+
|
|
130
|
+
const existingProviders = new Set(
|
|
131
|
+
nodes
|
|
132
|
+
.filter(node => node.data?.cloudProvider)
|
|
133
|
+
.map(node => node.data.cloudProvider)
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
if (existingProviders.size > 0 && !existingProviders.has(cloudProvider)) {
|
|
137
|
+
const existingProvidersList = Array.from(existingProviders).join(', ');
|
|
138
|
+
return {
|
|
139
|
+
isValid: false,
|
|
140
|
+
message: `Cannot mix cloud providers. This diagram already contains ${existingProvidersList} services. Please use a separate diagram for ${cloudProvider} services.`,
|
|
141
|
+
suggestions: [
|
|
142
|
+
'Create a separate diagram for each cloud provider',
|
|
143
|
+
'Use hybrid/multi-cloud architecture patterns if needed',
|
|
144
|
+
'Consider using a multi-cloud management service'
|
|
145
|
+
]
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return { isValid: true };
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Automatically finds the best parent node based on position and schema rules
|
|
154
|
+
* @param nodePosition - Position where the node will be placed
|
|
155
|
+
* @param service - Service type of the node
|
|
156
|
+
* @param cloudProvider - Cloud provider (aws, azure, gcp)
|
|
157
|
+
* @param nodes - All existing nodes
|
|
158
|
+
* @returns The best parent node or null if no valid parent found
|
|
159
|
+
*/
|
|
160
|
+
export const findAutoParent = (
|
|
161
|
+
nodePosition: { x: number; y: number },
|
|
162
|
+
service: string,
|
|
163
|
+
cloudProvider: 'aws' | 'azure' | 'gcp',
|
|
164
|
+
nodes: Node[]
|
|
165
|
+
): Node | null => {
|
|
166
|
+
// Get all potential parent nodes (container nodes)
|
|
167
|
+
const potentialParents = nodes.filter(node =>
|
|
168
|
+
node.type === 'subnetNode' &&
|
|
169
|
+
node.data?.cloudProvider === cloudProvider
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
// First, find all containers that actually contain the drop position
|
|
173
|
+
const containingParents = potentialParents.filter(parent =>
|
|
174
|
+
isPositionWithinNode(nodePosition, parent, nodes)
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
// Debug logging for development
|
|
178
|
+
if (process.env.NODE_ENV === 'development') {
|
|
179
|
+
console.log(`Finding auto parent for ${service} at position:`, {
|
|
180
|
+
position: nodePosition,
|
|
181
|
+
potentialParents: potentialParents.map(p => ({ id: p.id, label: p.data?.label, service: p.data?.service })),
|
|
182
|
+
containingParents: containingParents.map(p => ({ id: p.id, label: p.data?.label, service: p.data?.service }))
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// If we have containers that contain the position, prioritize those
|
|
187
|
+
if (containingParents.length > 0) {
|
|
188
|
+
// Sort containing containers by specificity (smallest area first for most specific container)
|
|
189
|
+
const sortedContainingParents = containingParents.sort((a, b) => {
|
|
190
|
+
// First sort by z-index (highest first - more specific layers)
|
|
191
|
+
const aZIndex = a.style?.zIndex || 0;
|
|
192
|
+
const bZIndex = b.style?.zIndex || 0;
|
|
193
|
+
|
|
194
|
+
if (aZIndex !== bZIndex) {
|
|
195
|
+
return (bZIndex as number) - (aZIndex as number);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Then sort by area (smallest first - most specific container)
|
|
199
|
+
const aArea = (Number(a.style?.width) || 0) * (Number(a.style?.height) || 0);
|
|
200
|
+
const bArea = (Number(b.style?.width) || 0) * (Number(b.style?.height) || 0);
|
|
201
|
+
return aArea - bArea;
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// Find the best containing parent based on validation rules
|
|
205
|
+
for (const potentialParent of sortedContainingParents) {
|
|
206
|
+
// Create a temporary node to test validation
|
|
207
|
+
const tempNode: Node = {
|
|
208
|
+
id: `temp-${Date.now()}`,
|
|
209
|
+
type: 'serviceNode',
|
|
210
|
+
position: nodePosition,
|
|
211
|
+
data: {
|
|
212
|
+
service,
|
|
213
|
+
cloudProvider,
|
|
214
|
+
},
|
|
215
|
+
parentNode: potentialParent.id,
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
// Validate if this placement is allowed
|
|
219
|
+
const validation = validateCloudProviderPlacement(
|
|
220
|
+
tempNode,
|
|
221
|
+
potentialParent,
|
|
222
|
+
nodes,
|
|
223
|
+
cloudProvider
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
if (validation.isValid) {
|
|
227
|
+
return potentialParent;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// If no containing containers found or none are valid, fall back to default behavior
|
|
233
|
+
// Sort all potential parents by z-index and area as fallback
|
|
234
|
+
const sortedParents = potentialParents.sort((a, b) => {
|
|
235
|
+
const aZIndex = a.style?.zIndex || 0;
|
|
236
|
+
const bZIndex = b.style?.zIndex || 0;
|
|
237
|
+
|
|
238
|
+
if (aZIndex !== bZIndex) {
|
|
239
|
+
return (bZIndex as number) - (aZIndex as number);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// If same z-index, prefer smaller containers
|
|
243
|
+
const aArea = (Number(a.style?.width) || 0) * (Number(a.style?.height) || 0);
|
|
244
|
+
const bArea = (Number(b.style?.width) || 0) * (Number(b.style?.height) || 0);
|
|
245
|
+
return aArea - bArea;
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
// Try each potential parent with validation
|
|
249
|
+
for (const potentialParent of sortedParents) {
|
|
250
|
+
// Create a temporary node to test validation
|
|
251
|
+
const tempNode: Node = {
|
|
252
|
+
id: `temp-${Date.now()}`,
|
|
253
|
+
type: 'serviceNode',
|
|
254
|
+
position: nodePosition,
|
|
255
|
+
data: {
|
|
256
|
+
service,
|
|
257
|
+
cloudProvider,
|
|
258
|
+
},
|
|
259
|
+
parentNode: potentialParent.id,
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
// Validate if this placement is allowed
|
|
263
|
+
const validation = validateCloudProviderPlacement(
|
|
264
|
+
tempNode,
|
|
265
|
+
potentialParent,
|
|
266
|
+
nodes,
|
|
267
|
+
cloudProvider
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
if (validation.isValid) {
|
|
271
|
+
return potentialParent;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// If no valid parent found in containers, check if it can be placed at root
|
|
276
|
+
const tempNode: Node = {
|
|
277
|
+
id: `temp-${Date.now()}`,
|
|
278
|
+
type: 'serviceNode',
|
|
279
|
+
position: nodePosition,
|
|
280
|
+
data: {
|
|
281
|
+
service,
|
|
282
|
+
cloudProvider,
|
|
283
|
+
},
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
const rootValidation = validateCloudProviderPlacement(
|
|
287
|
+
tempNode,
|
|
288
|
+
null,
|
|
289
|
+
nodes,
|
|
290
|
+
cloudProvider
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
return rootValidation.isValid ? null : getDefaultParent(service, cloudProvider, nodes);
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Checks if a position is within the bounds of a node
|
|
298
|
+
* Handles nested node positioning correctly by calculating absolute coordinates
|
|
299
|
+
*/
|
|
300
|
+
const isPositionWithinNode = (
|
|
301
|
+
position: { x: number; y: number },
|
|
302
|
+
node: Node,
|
|
303
|
+
allNodes?: Node[]
|
|
304
|
+
): boolean => {
|
|
305
|
+
// Calculate absolute position of the node (considering parent positioning)
|
|
306
|
+
let nodeX = node.position.x;
|
|
307
|
+
let nodeY = node.position.y;
|
|
308
|
+
|
|
309
|
+
// If the node has a parent, we need to calculate the absolute position
|
|
310
|
+
// by traversing up the parent chain
|
|
311
|
+
if (node.parentNode && allNodes) {
|
|
312
|
+
const parentNode = allNodes.find(n => n.id === node.parentNode);
|
|
313
|
+
if (parentNode) {
|
|
314
|
+
// Recursively calculate parent's absolute position
|
|
315
|
+
const parentAbsolutePos = getAbsolutePosition(parentNode, allNodes);
|
|
316
|
+
nodeX = parentAbsolutePos.x + node.position.x;
|
|
317
|
+
nodeY = parentAbsolutePos.y + node.position.y;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const nodeWidth = (node.style?.width as number) || (node.data?.width as number) || 200;
|
|
322
|
+
const nodeHeight = (node.style?.height as number) || (node.data?.height as number) || 150;
|
|
323
|
+
|
|
324
|
+
// Add some padding to make it easier to drop items near edges
|
|
325
|
+
const padding = 10;
|
|
326
|
+
|
|
327
|
+
const isWithin = (
|
|
328
|
+
position.x >= nodeX - padding &&
|
|
329
|
+
position.x <= nodeX + nodeWidth + padding &&
|
|
330
|
+
position.y >= nodeY - padding &&
|
|
331
|
+
position.y <= nodeY + nodeHeight + padding
|
|
332
|
+
);
|
|
333
|
+
|
|
334
|
+
// Debug logging for development
|
|
335
|
+
if (process.env.NODE_ENV === 'development') {
|
|
336
|
+
console.log(`Position check for ${node.data?.service || 'unknown'} (${node.data?.label || 'no label'}):`, {
|
|
337
|
+
dropPosition: position,
|
|
338
|
+
originalPosition: node.position,
|
|
339
|
+
calculatedPosition: { x: nodeX, y: nodeY },
|
|
340
|
+
nodeSize: { width: nodeWidth, height: nodeHeight },
|
|
341
|
+
bounds: {
|
|
342
|
+
left: nodeX - padding,
|
|
343
|
+
right: nodeX + nodeWidth + padding,
|
|
344
|
+
top: nodeY - padding,
|
|
345
|
+
bottom: nodeY + nodeHeight + padding
|
|
346
|
+
},
|
|
347
|
+
isWithin,
|
|
348
|
+
hasParent: !!node.parentNode,
|
|
349
|
+
parentNode: node.parentNode
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return isWithin;
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Recursively calculates the absolute position of a node by traversing up the parent chain
|
|
358
|
+
*/
|
|
359
|
+
const getAbsolutePosition = (node: Node, allNodes: Node[]): { x: number; y: number } => {
|
|
360
|
+
let absoluteX = node.position.x;
|
|
361
|
+
let absoluteY = node.position.y;
|
|
362
|
+
|
|
363
|
+
if (node.parentNode) {
|
|
364
|
+
const parentNode = allNodes.find(n => n.id === node.parentNode);
|
|
365
|
+
if (parentNode) {
|
|
366
|
+
const parentAbsolutePos = getAbsolutePosition(parentNode, allNodes);
|
|
367
|
+
absoluteX = parentAbsolutePos.x + node.position.x;
|
|
368
|
+
absoluteY = parentAbsolutePos.y + node.position.y;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
return { x: absoluteX, y: absoluteY };
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Gets the default parent based on service type and cloud provider
|
|
377
|
+
*/
|
|
378
|
+
const getDefaultParent = (
|
|
379
|
+
service: string,
|
|
380
|
+
cloudProvider: 'aws' | 'azure' | 'gcp',
|
|
381
|
+
nodes: Node[]
|
|
382
|
+
): Node | null => {
|
|
383
|
+
// Define comprehensive default parent hierarchy for each cloud provider
|
|
384
|
+
const defaultParents = {
|
|
385
|
+
aws: {
|
|
386
|
+
// Compute services
|
|
387
|
+
compute: ['subnet', 'availability-zone', 'vpc', 'account'],
|
|
388
|
+
ec2: ['subnet', 'availability-zone', 'vpc', 'account'],
|
|
389
|
+
lambda: ['account'],
|
|
390
|
+
'elastic-beanstalk': ['account'],
|
|
391
|
+
fargate: ['subnet', 'vpc', 'account'],
|
|
392
|
+
batch: ['subnet', 'vpc', 'account'],
|
|
393
|
+
'app-runner': ['account'],
|
|
394
|
+
'serverless-application-repository': ['account'],
|
|
395
|
+
|
|
396
|
+
// Database services
|
|
397
|
+
database: ['subnet', 'vpc', 'account'],
|
|
398
|
+
rds: ['subnet', 'vpc', 'account'],
|
|
399
|
+
aurora: ['subnet', 'vpc', 'account'],
|
|
400
|
+
dynamodb: ['account'],
|
|
401
|
+
elasticache: ['subnet', 'vpc', 'account'],
|
|
402
|
+
neptune: ['subnet', 'vpc', 'account'],
|
|
403
|
+
documentdb: ['subnet', 'vpc', 'account'],
|
|
404
|
+
keyspaces: ['account'],
|
|
405
|
+
timestream: ['account'],
|
|
406
|
+
|
|
407
|
+
// Storage services
|
|
408
|
+
storage: ['account'],
|
|
409
|
+
s3: ['account'],
|
|
410
|
+
ebs: ['account'],
|
|
411
|
+
efs: ['account'],
|
|
412
|
+
fsx: ['account'],
|
|
413
|
+
backup: ['account'],
|
|
414
|
+
'storage-gateway': ['account'],
|
|
415
|
+
|
|
416
|
+
// Networking services
|
|
417
|
+
networking: ['vpc', 'account'],
|
|
418
|
+
'elastic-load-balancing': ['subnet', 'vpc', 'account'],
|
|
419
|
+
'route-53': ['account'],
|
|
420
|
+
'direct-connect': ['account'],
|
|
421
|
+
'transit-gateway': ['account'],
|
|
422
|
+
'global-accelerator': ['account'],
|
|
423
|
+
'site-to-site-vpn': ['vpc', 'account'],
|
|
424
|
+
'client-vpn': ['vpc', 'account'],
|
|
425
|
+
|
|
426
|
+
// Security services
|
|
427
|
+
security: ['account'],
|
|
428
|
+
iam: ['account'],
|
|
429
|
+
cognito: ['account'],
|
|
430
|
+
kms: ['account'],
|
|
431
|
+
'secrets-manager': ['account'],
|
|
432
|
+
'certificate-manager': ['account'],
|
|
433
|
+
waf: ['account'],
|
|
434
|
+
shield: ['account'],
|
|
435
|
+
guardduty: ['account'],
|
|
436
|
+
'security-hub': ['account'],
|
|
437
|
+
'network-firewall': ['subnet', 'vpc', 'account'],
|
|
438
|
+
|
|
439
|
+
// Container services
|
|
440
|
+
containers: ['subnet', 'vpc', 'account'],
|
|
441
|
+
ecs: ['subnet', 'vpc', 'account'],
|
|
442
|
+
'elastic-container-service': ['subnet', 'vpc', 'account'],
|
|
443
|
+
eks: ['subnet', 'vpc', 'account'],
|
|
444
|
+
'elastic-kubernetes-service': ['subnet', 'vpc', 'account'],
|
|
445
|
+
'elastic-container-registry': ['account'],
|
|
446
|
+
|
|
447
|
+
// Serverless services
|
|
448
|
+
serverless: ['account'],
|
|
449
|
+
},
|
|
450
|
+
azure: {
|
|
451
|
+
// Compute services
|
|
452
|
+
virtualMachine: ['subnet', 'virtual-network', 'resource-group', 'subscription'],
|
|
453
|
+
'virtual-machines': ['subnet', 'virtual-network', 'resource-group', 'subscription'],
|
|
454
|
+
'app-services': ['resource-group', 'subscription'],
|
|
455
|
+
'app-service': ['resource-group', 'subscription'],
|
|
456
|
+
'function-apps': ['resource-group', 'subscription'],
|
|
457
|
+
'batch-accounts': ['resource-group', 'subscription'],
|
|
458
|
+
'kubernetes-services': ['resource-group', 'subscription'],
|
|
459
|
+
'container-instances': ['resource-group', 'subscription'],
|
|
460
|
+
'virtual-machine-scale-sets': ['resource-group', 'subscription'],
|
|
461
|
+
|
|
462
|
+
// Database services
|
|
463
|
+
database: ['resource-group', 'subscription'],
|
|
464
|
+
'sql-database': ['resource-group', 'subscription'],
|
|
465
|
+
'cosmos-db': ['resource-group', 'subscription'],
|
|
466
|
+
'mysql-server': ['resource-group', 'subscription'],
|
|
467
|
+
'postgresql-server': ['resource-group', 'subscription'],
|
|
468
|
+
'redis-cache': ['resource-group', 'subscription'],
|
|
469
|
+
|
|
470
|
+
// Storage services
|
|
471
|
+
storageAccount: ['resource-group', 'subscription'],
|
|
472
|
+
'storage-accounts': ['resource-group', 'subscription'],
|
|
473
|
+
'managed-disks': ['resource-group', 'subscription'],
|
|
474
|
+
'blob-storage': ['resource-group', 'subscription'],
|
|
475
|
+
'file-storage': ['resource-group', 'subscription'],
|
|
476
|
+
|
|
477
|
+
// Networking services
|
|
478
|
+
networkInterface: ['subnet', 'virtual-network', 'resource-group', 'subscription'],
|
|
479
|
+
'network-interfaces': ['subnet', 'virtual-network', 'resource-group', 'subscription'],
|
|
480
|
+
loadBalancer: ['resource-group', 'subscription'],
|
|
481
|
+
'load-balancers': ['resource-group', 'subscription'],
|
|
482
|
+
'application-gateway': ['subnet', 'virtual-network', 'resource-group', 'subscription'],
|
|
483
|
+
'vpn-gateway': ['virtual-network', 'resource-group', 'subscription'],
|
|
484
|
+
'express-route': ['resource-group', 'subscription'],
|
|
485
|
+
'cdn-profiles': ['resource-group', 'subscription'],
|
|
486
|
+
|
|
487
|
+
// Security services
|
|
488
|
+
'key-vaults': ['resource-group', 'subscription'],
|
|
489
|
+
'security-center': ['subscription'],
|
|
490
|
+
'azure-firewall': ['subnet', 'virtual-network', 'resource-group', 'subscription'],
|
|
491
|
+
'network-security-groups': ['resource-group', 'subscription'],
|
|
492
|
+
'azure-active-directory': ['subscription'],
|
|
493
|
+
},
|
|
494
|
+
gcp: {
|
|
495
|
+
// Compute services
|
|
496
|
+
compute: ['subnet', 'vpc', 'project'],
|
|
497
|
+
'compute-engine': ['subnet', 'vpc', 'project'],
|
|
498
|
+
'app-engine': ['project'],
|
|
499
|
+
'cloud-functions': ['project'],
|
|
500
|
+
'kubernetes-engine': ['project'],
|
|
501
|
+
'cloud-run': ['project'],
|
|
502
|
+
'cloud-build': ['project'],
|
|
503
|
+
|
|
504
|
+
// Database services
|
|
505
|
+
database: ['project'],
|
|
506
|
+
'cloud-sql': ['project'],
|
|
507
|
+
'cloud-spanner': ['project'],
|
|
508
|
+
'cloud-bigtable': ['project'],
|
|
509
|
+
'cloud-firestore': ['project'],
|
|
510
|
+
'cloud-memorystore': ['project'],
|
|
511
|
+
|
|
512
|
+
// Storage services
|
|
513
|
+
storage: ['project'],
|
|
514
|
+
'cloud-storage': ['project'],
|
|
515
|
+
'persistent-disk': ['project'],
|
|
516
|
+
'filestore': ['project'],
|
|
517
|
+
|
|
518
|
+
// Networking services
|
|
519
|
+
networking: ['vpc', 'project'],
|
|
520
|
+
'cloud-load-balancing': ['project'],
|
|
521
|
+
'cloud-cdn': ['project'],
|
|
522
|
+
'cloud-dns': ['project'],
|
|
523
|
+
'cloud-interconnect': ['project'],
|
|
524
|
+
'cloud-vpn': ['vpc', 'project'],
|
|
525
|
+
'cloud-nat': ['vpc', 'project'],
|
|
526
|
+
'cloud-router': ['vpc', 'project'],
|
|
527
|
+
|
|
528
|
+
// Security services
|
|
529
|
+
'cloud-iam': ['project'],
|
|
530
|
+
'cloud-kms': ['project'],
|
|
531
|
+
'cloud-security-command-center': ['project'],
|
|
532
|
+
'cloud-armor': ['project'],
|
|
533
|
+
'binary-authorization': ['project'],
|
|
534
|
+
'cloud-asset-inventory': ['project'],
|
|
535
|
+
|
|
536
|
+
// Serverless services
|
|
537
|
+
cloudFunction: ['project'],
|
|
538
|
+
cloudRun: ['project'],
|
|
539
|
+
},
|
|
540
|
+
};
|
|
541
|
+
|
|
542
|
+
// Get the service category/type
|
|
543
|
+
const serviceType = getServiceType(service, cloudProvider);
|
|
544
|
+
const parentHierarchy = defaultParents[cloudProvider]?.[serviceType as keyof typeof defaultParents[typeof cloudProvider]];
|
|
545
|
+
|
|
546
|
+
if (!parentHierarchy) {
|
|
547
|
+
// If no specific hierarchy found, use the service name directly
|
|
548
|
+
const directHierarchy = defaultParents[cloudProvider]?.[service as keyof typeof defaultParents[typeof cloudProvider]];
|
|
549
|
+
if (directHierarchy) {
|
|
550
|
+
return findParentFromHierarchy(directHierarchy, nodes, cloudProvider);
|
|
551
|
+
}
|
|
552
|
+
return null;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
return findParentFromHierarchy(parentHierarchy, nodes, cloudProvider);
|
|
556
|
+
};
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Finds the first available parent from a hierarchy
|
|
560
|
+
*/
|
|
561
|
+
const findParentFromHierarchy = (
|
|
562
|
+
hierarchy: string[],
|
|
563
|
+
nodes: Node[],
|
|
564
|
+
cloudProvider: 'aws' | 'azure' | 'gcp'
|
|
565
|
+
): Node | null => {
|
|
566
|
+
for (const parentType of hierarchy) {
|
|
567
|
+
const parent = nodes.find(node =>
|
|
568
|
+
node.type === 'subnetNode' &&
|
|
569
|
+
node.data?.service === parentType &&
|
|
570
|
+
node.data?.cloudProvider === cloudProvider
|
|
571
|
+
);
|
|
572
|
+
|
|
573
|
+
if (parent) {
|
|
574
|
+
return parent;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
return null;
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Maps service to service type/category with comprehensive mapping
|
|
582
|
+
*/
|
|
583
|
+
const getServiceType = (service: string, cloudProvider: 'aws' | 'azure' | 'gcp'): string => {
|
|
584
|
+
const serviceTypeMap = {
|
|
585
|
+
aws: {
|
|
586
|
+
// Compute services
|
|
587
|
+
ec2: 'compute',
|
|
588
|
+
lambda: 'serverless',
|
|
589
|
+
'elastic-beanstalk': 'compute',
|
|
590
|
+
fargate: 'containers',
|
|
591
|
+
batch: 'compute',
|
|
592
|
+
'app-runner': 'compute',
|
|
593
|
+
'application-auto-scaling': 'compute',
|
|
594
|
+
'ec2-auto-scaling': 'compute',
|
|
595
|
+
'serverless-application-repository': 'serverless',
|
|
596
|
+
|
|
597
|
+
// Database services
|
|
598
|
+
rds: 'database',
|
|
599
|
+
aurora: 'database',
|
|
600
|
+
dynamodb: 'database',
|
|
601
|
+
elasticache: 'database',
|
|
602
|
+
neptune: 'database',
|
|
603
|
+
documentdb: 'database',
|
|
604
|
+
keyspaces: 'database',
|
|
605
|
+
timestream: 'database',
|
|
606
|
+
'database-migration-service': 'database',
|
|
607
|
+
|
|
608
|
+
// Storage services
|
|
609
|
+
s3: 'storage',
|
|
610
|
+
ebs: 'storage',
|
|
611
|
+
efs: 'storage',
|
|
612
|
+
fsx: 'storage',
|
|
613
|
+
backup: 'storage',
|
|
614
|
+
'storage-gateway': 'storage',
|
|
615
|
+
snowball: 'storage',
|
|
616
|
+
'snowball-edge': 'storage',
|
|
617
|
+
snowcone: 'storage',
|
|
618
|
+
snowmobile: 'storage',
|
|
619
|
+
|
|
620
|
+
// Networking services
|
|
621
|
+
vpc: 'networking',
|
|
622
|
+
'elastic-load-balancing': 'networking',
|
|
623
|
+
'route-53': 'networking',
|
|
624
|
+
'direct-connect': 'networking',
|
|
625
|
+
'transit-gateway': 'networking',
|
|
626
|
+
'global-accelerator': 'networking',
|
|
627
|
+
'site-to-site-vpn': 'networking',
|
|
628
|
+
'client-vpn': 'networking',
|
|
629
|
+
'app-mesh': 'networking',
|
|
630
|
+
'cloud-map': 'networking',
|
|
631
|
+
'cloud-wan': 'networking',
|
|
632
|
+
privatelink: 'networking',
|
|
633
|
+
'vpc-lattice': 'networking',
|
|
634
|
+
|
|
635
|
+
// Security services
|
|
636
|
+
'security-group': 'security',
|
|
637
|
+
iam: 'security',
|
|
638
|
+
cognito: 'security',
|
|
639
|
+
kms: 'security',
|
|
640
|
+
'secrets-manager': 'security',
|
|
641
|
+
'certificate-manager': 'security',
|
|
642
|
+
waf: 'security',
|
|
643
|
+
shield: 'security',
|
|
644
|
+
guardduty: 'security',
|
|
645
|
+
'security-hub': 'security',
|
|
646
|
+
'network-firewall': 'security',
|
|
647
|
+
inspector: 'security',
|
|
648
|
+
macie: 'security',
|
|
649
|
+
detective: 'security',
|
|
650
|
+
|
|
651
|
+
// Container services
|
|
652
|
+
ecs: 'containers',
|
|
653
|
+
'elastic-container-service': 'containers',
|
|
654
|
+
eks: 'containers',
|
|
655
|
+
'elastic-kubernetes-service': 'containers',
|
|
656
|
+
'elastic-container-registry': 'containers',
|
|
657
|
+
'ecs-anywhere': 'containers',
|
|
658
|
+
'eks-anywhere': 'containers',
|
|
659
|
+
'eks-cloud': 'containers',
|
|
660
|
+
'eks-distro': 'containers',
|
|
661
|
+
},
|
|
662
|
+
azure: {
|
|
663
|
+
// Compute services
|
|
664
|
+
'virtual-machine': 'virtualMachine',
|
|
665
|
+
'virtual-machines': 'virtualMachine',
|
|
666
|
+
'app-services': 'appService',
|
|
667
|
+
'app-service': 'appService',
|
|
668
|
+
'function-apps': 'appService',
|
|
669
|
+
'batch-accounts': 'compute',
|
|
670
|
+
'kubernetes-services': 'containers',
|
|
671
|
+
'container-instances': 'containers',
|
|
672
|
+
'virtual-machine-scale-sets': 'virtualMachine',
|
|
673
|
+
|
|
674
|
+
// Database services
|
|
675
|
+
'sql-database': 'database',
|
|
676
|
+
'cosmos-db': 'database',
|
|
677
|
+
'mysql-server': 'database',
|
|
678
|
+
'postgresql-server': 'database',
|
|
679
|
+
'redis-cache': 'database',
|
|
680
|
+
'mariadb-server': 'database',
|
|
681
|
+
'managed-database': 'database',
|
|
682
|
+
|
|
683
|
+
// Storage services
|
|
684
|
+
'storage-account': 'storageAccount',
|
|
685
|
+
'storage-accounts': 'storageAccount',
|
|
686
|
+
'managed-disks': 'storageAccount',
|
|
687
|
+
'blob-storage': 'storageAccount',
|
|
688
|
+
'file-storage': 'storageAccount',
|
|
689
|
+
|
|
690
|
+
// Networking services
|
|
691
|
+
'network-interface': 'networkInterface',
|
|
692
|
+
'network-interfaces': 'networkInterface',
|
|
693
|
+
'load-balancer': 'loadBalancer',
|
|
694
|
+
'load-balancers': 'loadBalancer',
|
|
695
|
+
'application-gateway': 'loadBalancer',
|
|
696
|
+
'vpn-gateway': 'networking',
|
|
697
|
+
'express-route': 'networking',
|
|
698
|
+
'cdn-profiles': 'networking',
|
|
699
|
+
|
|
700
|
+
// Security services
|
|
701
|
+
'key-vaults': 'security',
|
|
702
|
+
'security-center': 'security',
|
|
703
|
+
'azure-firewall': 'security',
|
|
704
|
+
'network-security-groups': 'security',
|
|
705
|
+
'azure-active-directory': 'security',
|
|
706
|
+
},
|
|
707
|
+
gcp: {
|
|
708
|
+
// Compute services
|
|
709
|
+
'compute-engine': 'compute',
|
|
710
|
+
'app-engine': 'compute',
|
|
711
|
+
'cloud-functions': 'cloudFunction',
|
|
712
|
+
'kubernetes-engine': 'containers',
|
|
713
|
+
'cloud-run': 'cloudRun',
|
|
714
|
+
'cloud-build': 'compute',
|
|
715
|
+
|
|
716
|
+
// Database services
|
|
717
|
+
'cloud-sql': 'database',
|
|
718
|
+
'cloud-spanner': 'database',
|
|
719
|
+
'cloud-bigtable': 'database',
|
|
720
|
+
'cloud-firestore': 'database',
|
|
721
|
+
'cloud-memorystore': 'database',
|
|
722
|
+
|
|
723
|
+
// Storage services
|
|
724
|
+
'cloud-storage': 'storage',
|
|
725
|
+
'persistent-disk': 'storage',
|
|
726
|
+
'filestore': 'storage',
|
|
727
|
+
|
|
728
|
+
// Networking services
|
|
729
|
+
'cloud-load-balancing': 'networking',
|
|
730
|
+
'cloud-cdn': 'networking',
|
|
731
|
+
'cloud-dns': 'networking',
|
|
732
|
+
'cloud-interconnect': 'networking',
|
|
733
|
+
'cloud-vpn': 'networking',
|
|
734
|
+
'cloud-nat': 'networking',
|
|
735
|
+
'cloud-router': 'networking',
|
|
736
|
+
'cloud-firewall-rules': 'networking',
|
|
737
|
+
'virtual-private-cloud': 'networking',
|
|
738
|
+
|
|
739
|
+
// Security services
|
|
740
|
+
'cloud-iam': 'security',
|
|
741
|
+
'cloud-kms': 'security',
|
|
742
|
+
'cloud-security-command-center': 'security',
|
|
743
|
+
'cloud-armor': 'security',
|
|
744
|
+
'binary-authorization': 'security',
|
|
745
|
+
'cloud-asset-inventory': 'security',
|
|
746
|
+
iam: 'security',
|
|
747
|
+
'data-loss-prevention-api': 'security',
|
|
748
|
+
beyondcorp: 'security',
|
|
749
|
+
},
|
|
750
|
+
};
|
|
751
|
+
|
|
752
|
+
return serviceTypeMap[cloudProvider]?.[service as keyof typeof serviceTypeMap[typeof cloudProvider]] || service;
|
|
753
|
+
};
|
|
754
|
+
|
|
755
|
+
/**
|
|
756
|
+
* Provides smart placement suggestions based on best practices
|
|
757
|
+
*/
|
|
758
|
+
export const getPlacementSuggestions = (
|
|
759
|
+
service: string,
|
|
760
|
+
cloudProvider: 'aws' | 'azure' | 'gcp',
|
|
761
|
+
nodes: Node[]
|
|
762
|
+
): string[] => {
|
|
763
|
+
const suggestions: string[] = [];
|
|
764
|
+
|
|
765
|
+
// Check if recommended containers exist
|
|
766
|
+
const serviceType = getServiceType(service, cloudProvider);
|
|
767
|
+
const recommendedContainers = getRecommendedContainers(service, cloudProvider);
|
|
768
|
+
|
|
769
|
+
for (const container of recommendedContainers) {
|
|
770
|
+
const exists = nodes.some(node =>
|
|
771
|
+
node.type === 'subnetNode' &&
|
|
772
|
+
node.data?.service === container &&
|
|
773
|
+
node.data?.cloudProvider === cloudProvider
|
|
774
|
+
);
|
|
775
|
+
|
|
776
|
+
if (!exists) {
|
|
777
|
+
suggestions.push(`Consider creating a ${container} container first for better organization`);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// Add cloud-specific best practice suggestions
|
|
782
|
+
if (cloudProvider === 'aws') {
|
|
783
|
+
if (serviceType === 'compute' && !nodes.some(n => n.data?.service === 'subnet')) {
|
|
784
|
+
suggestions.push('AWS compute resources should be placed in subnets for proper network isolation');
|
|
785
|
+
}
|
|
786
|
+
if (serviceType === 'database' && !nodes.some(n => n.data?.service === 'subnet')) {
|
|
787
|
+
suggestions.push('AWS database resources should be placed in private subnets for security');
|
|
788
|
+
}
|
|
789
|
+
} else if (cloudProvider === 'azure') {
|
|
790
|
+
if (serviceType === 'virtualMachine' && !nodes.some(n => n.data?.service === 'subnet')) {
|
|
791
|
+
suggestions.push('Azure VMs should be placed in subnets within a Virtual Network');
|
|
792
|
+
}
|
|
793
|
+
if (!nodes.some(n => n.data?.service === 'resource-group')) {
|
|
794
|
+
suggestions.push('Azure resources should be organized in Resource Groups');
|
|
795
|
+
}
|
|
796
|
+
} else if (cloudProvider === 'gcp') {
|
|
797
|
+
if (!nodes.some(n => n.data?.service === 'project')) {
|
|
798
|
+
suggestions.push('GCP resources must be organized within a Project');
|
|
799
|
+
}
|
|
800
|
+
if (serviceType === 'compute' && !nodes.some(n => n.data?.service === 'subnet')) {
|
|
801
|
+
suggestions.push('GCP compute resources should be placed in subnets for network organization');
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
return suggestions;
|
|
806
|
+
};
|
|
807
|
+
|
|
808
|
+
/**
|
|
809
|
+
* Gets recommended containers for a service
|
|
810
|
+
*/
|
|
811
|
+
const getRecommendedContainers = (service: string, cloudProvider: 'aws' | 'azure' | 'gcp'): string[] => {
|
|
812
|
+
const containerRecommendations = {
|
|
813
|
+
aws: {
|
|
814
|
+
compute: ['account', 'vpc', 'subnet'],
|
|
815
|
+
database: ['account', 'vpc', 'subnet'],
|
|
816
|
+
storage: ['account'],
|
|
817
|
+
networking: ['account', 'vpc'],
|
|
818
|
+
security: ['account'],
|
|
819
|
+
containers: ['account', 'vpc', 'subnet'],
|
|
820
|
+
serverless: ['account'],
|
|
821
|
+
},
|
|
822
|
+
azure: {
|
|
823
|
+
virtualMachine: ['subscription', 'resource-group', 'virtual-network', 'subnet'],
|
|
824
|
+
database: ['subscription', 'resource-group'],
|
|
825
|
+
storageAccount: ['subscription', 'resource-group'],
|
|
826
|
+
appService: ['subscription', 'resource-group'],
|
|
827
|
+
networking: ['subscription', 'resource-group'],
|
|
828
|
+
security: ['subscription', 'resource-group'],
|
|
829
|
+
},
|
|
830
|
+
gcp: {
|
|
831
|
+
compute: ['project', 'vpc', 'subnet'],
|
|
832
|
+
database: ['project'],
|
|
833
|
+
storage: ['project'],
|
|
834
|
+
networking: ['project', 'vpc'],
|
|
835
|
+
security: ['project'],
|
|
836
|
+
containers: ['project'],
|
|
837
|
+
},
|
|
838
|
+
};
|
|
839
|
+
|
|
840
|
+
const serviceType = getServiceType(service, cloudProvider);
|
|
841
|
+
return containerRecommendations[cloudProvider]?.[serviceType as keyof typeof containerRecommendations[typeof cloudProvider]] || [];
|
|
842
|
+
};
|
|
843
|
+
|
|
844
|
+
/**
|
|
845
|
+
* Validates placement and provides warnings for sub-optimal configurations
|
|
846
|
+
*/
|
|
847
|
+
export const validatePlacementWithWarnings = (
|
|
848
|
+
node: Node,
|
|
849
|
+
parentNode: Node | null,
|
|
850
|
+
nodes: Node[],
|
|
851
|
+
cloudProvider: 'aws' | 'azure' | 'gcp'
|
|
852
|
+
): { isValid: boolean; warnings: ValidationWarning[] } => {
|
|
853
|
+
const warnings: ValidationWarning[] = [];
|
|
854
|
+
|
|
855
|
+
// Check for sub-optimal placements
|
|
856
|
+
const serviceType = getServiceType(node.data?.service, cloudProvider);
|
|
857
|
+
|
|
858
|
+
if (cloudProvider === 'aws') {
|
|
859
|
+
// Check for compute resources not in subnets
|
|
860
|
+
if (serviceType === 'compute' && (!parentNode || parentNode.data?.service !== 'subnet')) {
|
|
861
|
+
warnings.push({
|
|
862
|
+
message: 'Compute resources should be placed in subnets for proper network isolation',
|
|
863
|
+
severity: 'warning',
|
|
864
|
+
suggestions: ['Create a subnet and place the compute resource within it']
|
|
865
|
+
});
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
// Check for database resources not in private subnets
|
|
869
|
+
if (serviceType === 'database' && (!parentNode || parentNode.data?.service !== 'subnet')) {
|
|
870
|
+
warnings.push({
|
|
871
|
+
message: 'Database resources should be placed in private subnets for security',
|
|
872
|
+
severity: 'warning',
|
|
873
|
+
suggestions: ['Create a private subnet and place the database within it']
|
|
874
|
+
});
|
|
875
|
+
}
|
|
876
|
+
} else if (cloudProvider === 'azure') {
|
|
877
|
+
// Check for VMs not in subnets
|
|
878
|
+
if (serviceType === 'virtualMachine' && (!parentNode || parentNode.data?.service !== 'subnet')) {
|
|
879
|
+
warnings.push({
|
|
880
|
+
message: 'Virtual machines should be placed in subnets for network organization',
|
|
881
|
+
severity: 'warning',
|
|
882
|
+
suggestions: ['Create a subnet within a virtual network and place the VM there']
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
} else if (cloudProvider === 'gcp') {
|
|
886
|
+
// Check for compute resources not in subnets
|
|
887
|
+
if (serviceType === 'compute' && (!parentNode || parentNode.data?.service !== 'subnet')) {
|
|
888
|
+
warnings.push({
|
|
889
|
+
message: 'Compute resources should be placed in subnets for network organization',
|
|
890
|
+
severity: 'warning',
|
|
891
|
+
suggestions: ['Create a subnet within a VPC and place the compute resource there']
|
|
892
|
+
});
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
return { isValid: true, warnings };
|
|
897
|
+
};
|
|
898
|
+
|
|
899
|
+
/**
|
|
900
|
+
* Automatically assigns parent during drag and drop based on drop position
|
|
901
|
+
* @param draggedNode - The node being dragged
|
|
902
|
+
* @param dropPosition - Position where the node is dropped
|
|
903
|
+
* @param nodes - All existing nodes
|
|
904
|
+
* @returns Updated node with automatic parent assignment
|
|
905
|
+
*/
|
|
906
|
+
export const autoAssignParentOnDrop = (
|
|
907
|
+
draggedNode: Node,
|
|
908
|
+
dropPosition: { x: number; y: number },
|
|
909
|
+
nodes: Node[]
|
|
910
|
+
): Node => {
|
|
911
|
+
const cloudProvider = draggedNode.data?.cloudProvider;
|
|
912
|
+
const service = draggedNode.data?.service;
|
|
913
|
+
|
|
914
|
+
if (!cloudProvider || !service) {
|
|
915
|
+
return draggedNode;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
// Find the best parent based on drop position
|
|
919
|
+
const bestParent = findAutoParent(dropPosition, service, cloudProvider, nodes);
|
|
920
|
+
|
|
921
|
+
// Update the node with the new parent
|
|
922
|
+
const updatedNode: Node = {
|
|
923
|
+
...draggedNode,
|
|
924
|
+
position: dropPosition,
|
|
925
|
+
parentNode: bestParent?.id,
|
|
926
|
+
extent: bestParent ? 'parent' : undefined,
|
|
927
|
+
};
|
|
928
|
+
|
|
929
|
+
return updatedNode;
|
|
930
930
|
};
|