Skip to content

Commit 09bfdf2

Browse files
author
Vlad Nikolaenko
committed
feat(stepfunctions): Miltiple Workflow Studio integration improvements and fixes
1 parent dbfb0b2 commit 09bfdf2

File tree

4 files changed

+81
-25
lines changed

4 files changed

+81
-25
lines changed

packages/core/package.nls.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626
"AWS.stepFunctions.asl.maxItemsComputed.desc": "The maximum number of outline symbols and folding regions computed (limited for performance reasons).",
2727
"AWS.stepFunctions.workflowStudio.actions.progressMessage": "Opening asl file in Workflow Studio",
2828
"AWS.stepFunctions.workflowStudio.actions.saveSuccessMessage": "{0} has been saved",
29-
"AWS.stepFunctions.workflowStudio.actions.invalidJson": "The Workflow Studio editor was not opened because the JSON in the file is invalid. To access Workflow Studio, please fix the JSON and manually reopen the integration.",
29+
"AWS.stepFunctions.workflowStudio.actions.InvalidJSONContent": "The Workflow Studio editor was not opened because the JSON in the file is invalid. To access Workflow Studio, please fix the JSON and manually reopen the integration.",
30+
"AWS.stepFunctions.workflowStudio.actions.InvalidYAMLContent": "The Workflow Studio editor was not opened because the YAML in the file is invalid. To access Workflow Studio, please fix the YAML and manually reopen the integration.",
31+
"AWS.stepFunctions.workflowStudio.actions.webviewFetchFailed": "Failed to load Workflow Studio editor. Please check your network connection and try again.",
3032
"AWS.configuration.description.awssam.debug.api": "API Gateway configuration",
3133
"AWS.configuration.description.awssam.debug.api.clientCertId": "The API Gateway client certificate ID",
3234
"AWS.configuration.description.awssam.debug.api.headers": "Additional HTTP headers",

packages/core/src/stepFunctions/utils.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import * as nls from 'vscode-nls'
66
const localize = nls.loadMessageBundle()
77

88
import { IAM, StepFunctions } from 'aws-sdk'
9+
import * as yaml from 'js-yaml'
910
import * as vscode from 'vscode'
1011
import { StepFunctionsClient } from '../shared/clients/stepFunctionsClient'
1112
import { fileExists } from '../shared/filesystemUtilities'
@@ -232,7 +233,7 @@ export async function isDocumentValid(text: string, textDocument?: vscode.TextDo
232233
}
233234

234235
/**
235-
* Checks if the JSON content in a text document is invalid.
236+
* Checks if the JSON content in an ASL text document is invalid.
236237
* Returns `true` for invalid JSON; `false` for valid JSON, empty content, or non-JSON files.
237238
*
238239
* @param textDocument - The text document to check.
@@ -241,9 +242,25 @@ export async function isDocumentValid(text: string, textDocument?: vscode.TextDo
241242
export const isInvalidJsonFile = (textDocument: vscode.TextDocument): boolean => {
242243
const documentContent = textDocument.getText().trim()
243244
// An empty file or whitespace-only text is considered valid JSON for our use case
244-
return textDocument.fileName.toLowerCase().endsWith('.json') && documentContent
245-
? isInvalidJson(documentContent)
246-
: false
245+
return textDocument.languageId === 'asl' && documentContent ? isInvalidJson(documentContent) : false
246+
}
247+
248+
/**
249+
* Checks if the YAML content in an ASL text document is invalid.
250+
* Returns `true` for invalid YAML; `false` for valid YAML, empty content, or non-YAML files.
251+
*
252+
* @param textDocument - The text document to check.
253+
* @returns `true` if invalid; `false` otherwise.
254+
*/
255+
export const isInvalidYamlFile = (textDocument: vscode.TextDocument): boolean => {
256+
try {
257+
if (textDocument.languageId === 'asl-yaml') {
258+
yaml.load(textDocument.getText())
259+
}
260+
return false
261+
} catch {
262+
return true
263+
}
247264
}
248265

249266
const isInvalidJson = (content: string): boolean => {

packages/core/src/stepFunctions/workflowStudio/workflowStudioEditorProvider.ts

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ import { telemetry } from '../../shared/telemetry/telemetry'
1212
import globals from '../../shared/extensionGlobals'
1313
import { getRandomString, getStringHash } from '../../shared/utilities/textUtilities'
1414
import { ToolkitError } from '../../shared/errors'
15+
import { getTabSizeSetting } from '../../shared/utilities/editorUtilities'
1516
import { WorkflowStudioEditor } from './workflowStudioEditor'
1617
import { i18n } from '../../shared/i18n-helper'
17-
import { isInvalidJsonFile } from '../utils'
18+
import { isInvalidJsonFile, isInvalidYamlFile } from '../utils'
1819

1920
const isLocalDev = false
2021
const localhost = 'http://127.0.0.1:3002'
@@ -72,9 +73,6 @@ export class WorkflowStudioEditorProvider implements vscode.CustomTextEditorProv
7273
* @private
7374
*/
7475
private getWebviewContent = async () => {
75-
if (!this.webviewHtml) {
76-
await this.fetchWebviewHtml()
77-
}
7876
let htmlFileSplit = this.webviewHtml.split('<head>')
7977

8078
// Set asset source to CDN
@@ -86,13 +84,15 @@ export class WorkflowStudioEditorProvider implements vscode.CustomTextEditorProv
8684
const localeTag = `<meta name='locale' content='${locale}'>`
8785
const theme = vscode.window.activeColorTheme.kind
8886
const isDarkMode = theme === vscode.ColorThemeKind.Dark || theme === vscode.ColorThemeKind.HighContrast
87+
const tabSizeTag = `<meta name='tab-size' content='${getTabSizeSetting()}'>`
8988
const darkModeTag = `<meta name='dark-mode' content='${isDarkMode}'>`
90-
let html = `${htmlFileSplit[0]} <head> ${baseTag} ${localeTag} ${darkModeTag} ${htmlFileSplit[1]}`
89+
let html = `${htmlFileSplit[0]} <head> ${baseTag} ${localeTag} ${darkModeTag} ${tabSizeTag} ${htmlFileSplit[1]}`
9190

9291
const nonce = getRandomString()
92+
const localDevURL = isLocalDev ? localhost : ''
9393
htmlFileSplit = html.split("script-src 'self'")
9494

95-
html = `${htmlFileSplit[0]} script-src 'self' 'nonce-${nonce}' ${isLocalDev && localhost} ${htmlFileSplit[1]}`
95+
html = `${htmlFileSplit[0]} script-src 'self' 'nonce-${nonce}' ${localDevURL} ${htmlFileSplit[1]}`
9696
htmlFileSplit = html.split('<body>')
9797

9898
const script = await fs.readFileText(
@@ -115,35 +115,56 @@ export class WorkflowStudioEditorProvider implements vscode.CustomTextEditorProv
115115
_token: vscode.CancellationToken
116116
): Promise<void> {
117117
await telemetry.stepfunctions_openWorkflowStudio.run(async () => {
118-
// For invalid JSON, open default editor and show warning message
119-
if (isInvalidJsonFile(document)) {
118+
const reopenWithDefaultEditor = async () => {
120119
await vscode.commands.executeCommand('vscode.openWith', document.uri, 'default')
121120
webviewPanel.dispose()
122-
void vscode.window.showWarningMessage(i18n('AWS.stepFunctions.workflowStudio.actions.invalidJson'))
121+
}
122+
123+
const isInvalidJson = isInvalidJsonFile(document)
124+
const isInvalidYaml = isInvalidYamlFile(document)
123125

126+
if (isInvalidJson || isInvalidYaml) {
127+
const language = isInvalidJson ? 'JSON' : 'YAML'
128+
const errorKey = isInvalidJson ? 'InvalidJSONContent' : 'InvalidYAMLContent'
129+
130+
await reopenWithDefaultEditor()
131+
void vscode.window.showWarningMessage(i18n(`AWS.stepFunctions.workflowStudio.actions.${errorKey}`))
124132
throw ToolkitError.chain(
125-
'Invalid JSON file',
126-
'The Workflow Studio editor was not opened because the JSON in the file is invalid',
127-
{
128-
code: 'InvalidJSONContent',
129-
}
133+
`Invalid ${language} file`,
134+
`The Workflow Studio editor was not opened because the ${language} in the file is invalid`,
135+
{ code: errorKey }
130136
)
131137
}
132138

133139
if (!this.webviewHtml) {
134-
await this.fetchWebviewHtml()
140+
try {
141+
await this.fetchWebviewHtml()
142+
} catch (e) {
143+
await reopenWithDefaultEditor()
144+
145+
void vscode.window.showWarningMessage(
146+
i18n('AWS.stepFunctions.workflowStudio.actions.webviewFetchFailed')
147+
)
148+
throw ToolkitError.chain(
149+
'Failed to fetch editor content',
150+
'Could not retrieve content for the Workflow Studio editor',
151+
{
152+
code: 'webviewFetchFailed',
153+
}
154+
)
155+
}
135156
}
136157

137158
if (clientId === '') {
138159
clientId = getClientId(globals.globalState)
139160
}
140-
// Attempt to retrieve existing visualization if it exists.
141-
const existingVisualization = this.managedVisualizations.get(document.uri.fsPath)
142161

162+
const existingVisualization = this.managedVisualizations.get(document.uri.fsPath)
143163
if (existingVisualization) {
144-
existingVisualization.showPanel()
164+
// Prevent opening multiple custom editors for a single file
165+
await reopenWithDefaultEditor()
145166
} else {
146-
// Existing visualization does not exist, construct new visualization
167+
// Construct new visualization
147168
try {
148169
const fileId = getStringHash(`${document.uri.fsPath}${clientId}`)
149170
const newVisualization = new WorkflowStudioEditor(

packages/toolkit/package.json

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1412,6 +1412,11 @@
14121412
"command": "aws.openInApplicationComposer",
14131413
"when": "isFileSystemResource && !(resourceFilename =~ /^.*\\.tc\\.json$/) && resourceFilename =~ /^.*\\.(json|yml|yaml|template)$/",
14141414
"group": "z_aws@1"
1415+
},
1416+
{
1417+
"command": "aws.stepfunctions.openWithWorkflowStudio",
1418+
"when": "isFileSystemResource && resourceFilename =~ /^.*\\.asl\\.(json|yml|yaml)$/",
1419+
"group": "z_aws@1"
14151420
}
14161421
],
14171422
"view/item/context": [
@@ -3917,6 +3922,16 @@
39173922
}
39183923
}
39193924
},
3925+
{
3926+
"command": "aws.stepfunctions.openWithWorkflowStudio",
3927+
"title": "%AWS.command.stepFunctions.openWithWorkflowStudio%",
3928+
"category": "%AWS.title%",
3929+
"cloud9": {
3930+
"cn": {
3931+
"category": "%AWS.title.cn%"
3932+
}
3933+
}
3934+
},
39203935
{
39213936
"command": "aws.createNewThreatComposer",
39223937
"title": "%AWS.command.threatComposer.createNew%",
@@ -4654,7 +4669,8 @@
46544669
],
46554670
"configurationDefaults": {
46564671
"workbench.editorAssociations": {
4657-
"{git,gitlens,conflictResolution,vscode-local-history}:/**/*.tc.json": "default"
4672+
"{git,gitlens,conflictResolution,vscode-local-history}:/**/*.tc.json": "default",
4673+
"{git,gitlens,conflictResolution,vscode-local-history}:/**/*.{asl.json,asl.yaml,asl.yml}": "default"
46584674
}
46594675
}
46604676
},

0 commit comments

Comments
 (0)