Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { Result } from '../../shared/telemetry/telemetry'
import { StateMachineNode } from '../explorer/stepFunctionsNodes'
import { telemetry } from '../../shared/telemetry/telemetry'
import { fs } from '../../shared/fs/fs'
import { openWorkflowStudioWithDefinition } from '../utils'
import { openWorkflowStudioWithDefinition } from '../stepFunctionsWorkflowStudioUtils'

export async function downloadStateMachineDefinition(params: {
outputChannel: vscode.OutputChannel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ import {
ExecutionDetailsContext,
ApiCallRequestMessage,
InitResponseMessage,
StartExecutionMessage,
} from '../messageHandlers/types'
import {
loadStageMessageHandler,
handleUnsupportedMessage,
apiCallMessageHandler,
} from '../messageHandlers/handleMessageHelpers'
import { parseExecutionArnForStateMachine, openWorkflowStudio, showExecuteStateMachineWebview } from '../utils'
import { parseExecutionArnForStateMachine } from '../utils'
import { getLogger } from '../../shared/logger/logger'
import { openWorkflowStudio } from '../stepFunctionsWorkflowStudioUtils'

/**
* Handles messages received from the ExecutionDetails webview. Depending on the message type and command,
Expand All @@ -39,7 +41,7 @@ export async function handleMessage(message: Message, context: ExecutionDetailsC
break
}
case Command.START_EXECUTION:
void startExecutionMessageHandler(context)
void startExecutionMessageHandler(message as StartExecutionMessage, context)
break
case Command.EDIT_STATE_MACHINE:
void editStateMachineMessageHandler(context)
Expand Down Expand Up @@ -85,7 +87,7 @@ async function initMessageHandler(context: ExecutionDetailsContext) {
}
}

async function startExecutionMessageHandler(context: ExecutionDetailsContext) {
async function startExecutionMessageHandler(message: StartExecutionMessage, context: ExecutionDetailsContext) {
const logger = getLogger('stepfunctions')
try {
// Parsing execution ARN to get state machine info
Expand All @@ -96,10 +98,13 @@ async function startExecutionMessageHandler(context: ExecutionDetailsContext) {

const { region, stateMachineName, stateMachineArn } = parsedArn

const executeStateMachineUtils = await import('../vue/executeStateMachine/executeStateMachine.js')
const { showExecuteStateMachineWebview } = executeStateMachineUtils
await showExecuteStateMachineWebview({
arn: stateMachineArn,
name: stateMachineName,
region: region,
executionInput: message.executionInput,
})
} catch (error) {
logger.error('Start execution failed: %O', error)
Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/stepFunctions/messageHandlers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ export interface SyncFileRequestMessage extends SaveFileRequestMessage {
fileContents: string
}

export interface StartExecutionMessage extends Message {
executionInput?: string
}

export enum ApiAction {
IAMListRoles = 'iam:ListRoles',
SFNTestState = 'sfn:TestState',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*!
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

import * as StepFunctions from '@aws-sdk/client-sfn'
import * as vscode from 'vscode'
import { StepFunctionsClient } from '../shared/clients/stepFunctions'
import { WorkflowStudioEditorProvider } from './workflowStudio/workflowStudioEditorProvider'

/**
* Opens a state machine definition in Workflow Studio
* @param stateMachineArn The ARN of the state machine
* @param region The AWS region
*/
export const openWorkflowStudio = async (stateMachineArn: string, region: string) => {
const client: StepFunctionsClient = new StepFunctionsClient(region)
const stateMachineDetails: StepFunctions.DescribeStateMachineCommandOutput = await client.getStateMachineDetails({
stateMachineArn,
})

await openWorkflowStudioWithDefinition(stateMachineDetails.definition)
}

/**
* Opens a state machine definition in Workflow Studio using pre-fetched definition content
* @param definition The state machine definition content
* @param options Optional webview configuration options
*/
export const openWorkflowStudioWithDefinition = async (
definition: string | undefined,
options?: {
preserveFocus?: boolean
viewColumn?: vscode.ViewColumn
}
) => {
const doc = await vscode.workspace.openTextDocument({
language: 'asl',
content: definition,
})

const textEditor = await vscode.window.showTextDocument(doc)
await WorkflowStudioEditorProvider.openWithWorkflowStudio(textEditor.document.uri, {
preserveFocus: options?.preserveFocus ?? false,
viewColumn: options?.viewColumn ?? vscode.ViewColumn.One,
})
}
69 changes: 0 additions & 69 deletions packages/core/src/stepFunctions/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ import {
} from 'amazon-states-language-service'
import { fromExtensionManifest } from '../shared/settings'
import { IamRole } from '../shared/clients/iam'
import { WorkflowStudioEditorProvider } from './workflowStudio/workflowStudioEditorProvider'
import { VueWebview } from '../webviews/main'
import { ExecuteStateMachineWebview } from './vue/executeStateMachine/executeStateMachine'
import globals from '../shared/extensionGlobals'

const documentSettings: DocumentLanguageSettings = { comments: 'error', trailingCommas: 'error' }
const languageService = getLanguageService({})
Expand Down Expand Up @@ -135,71 +131,6 @@ export const parseExecutionArnForStateMachine = (executionArn: string) => {
}
}

/**
* Opens a state machine definition in Workflow Studio
* @param stateMachineArn The ARN of the state machine
* @param region The AWS region
*/
export const openWorkflowStudio = async (stateMachineArn: string, region: string) => {
const client: StepFunctionsClient = new StepFunctionsClient(region)
const stateMachineDetails: StepFunctions.DescribeStateMachineCommandOutput = await client.getStateMachineDetails({
stateMachineArn,
})

await openWorkflowStudioWithDefinition(stateMachineDetails.definition)
}

/**
* Opens a state machine definition in Workflow Studio using pre-fetched definition content
* @param definition The state machine definition content
* @param options Optional webview configuration options
*/
export const openWorkflowStudioWithDefinition = async (
definition: string | undefined,
options?: {
preserveFocus?: boolean
viewColumn?: vscode.ViewColumn
}
) => {
const doc = await vscode.workspace.openTextDocument({
language: 'asl',
content: definition,
})

const textEditor = await vscode.window.showTextDocument(doc)
await WorkflowStudioEditorProvider.openWithWorkflowStudio(textEditor.document.uri, {
preserveFocus: options?.preserveFocus ?? false,
viewColumn: options?.viewColumn ?? vscode.ViewColumn.One,
})
}

/**
* Shows the Execute State Machine webview with the provided state machine data
* @param extensionContext The extension context
* @param outputChannel The output channel for logging
* @param stateMachineData Object containing arn, name, and region of the state machine
* @returns The webview instance
*/
export const showExecuteStateMachineWebview = async (stateMachineData: {
arn: string
name: string
region: string
}) => {
const Panel = VueWebview.compilePanel(ExecuteStateMachineWebview)
const wv = new Panel(globals.context, globals.outputChannel, {
arn: stateMachineData.arn,
name: stateMachineData.name,
region: stateMachineData.region,
})

await wv.show({
title: localize('AWS.executeStateMachine.title', 'Start Execution'),
cssFiles: ['executeStateMachine.css'],
})

return wv
}

const isInvalidJson = (content: string): boolean => {
try {
JSON.parse(content)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ import { VueWebview } from '../../../webviews/main'
import * as vscode from 'vscode'
import { telemetry } from '../../../shared/telemetry/telemetry'
import { ExecutionDetailProvider } from '../../executionDetails/executionDetailProvider'
import { showExecuteStateMachineWebview } from '../../utils'
import globals from '../../../shared/extensionGlobals'

interface StateMachine {
arn: string
name: string
region: string
executionInput?: string
}

export class ExecuteStateMachineWebview extends VueWebview {
Expand Down Expand Up @@ -89,11 +90,45 @@ export class ExecuteStateMachineWebview extends VueWebview {
}
}

export async function executeStateMachine(context: ExtContext, node: StateMachineNode): Promise<void> {
/**
* Shows the Execute State Machine webview with the provided state machine data
* @param extensionContext The extension context
* @param outputChannel The output channel for logging
* @param stateMachineData Object containing arn, name, region, and optional executionInput of the state machine
* @returns The webview instance
*/
export const showExecuteStateMachineWebview = async (stateMachineData: {
arn: string
name: string
region: string
executionInput?: string
}) => {
const Panel = VueWebview.compilePanel(ExecuteStateMachineWebview)
const wv = new Panel(globals.context, globals.outputChannel, {
arn: stateMachineData.arn,
name: stateMachineData.name,
region: stateMachineData.region,
executionInput: stateMachineData.executionInput,
})

await wv.show({
title: localize('AWS.executeStateMachine.title', 'Start Execution'),
cssFiles: ['executeStateMachine.css'],
})

return wv
}

export async function executeStateMachine(
context: ExtContext,
node: StateMachineNode,
executionInput?: string
): Promise<void> {
await showExecuteStateMachineWebview({
arn: node.details.stateMachineArn || '',
name: node.details.name || '',
region: node.regionCode,
executionInput,
})
telemetry.stepfunctions_executeStateMachineView.emit()
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,15 @@ const defaultInitialData = {
name: '',
region: '',
arn: '',
executionInput: '',
}

export default defineComponent({
async created() {
this.initialData = (await client.init()) ?? this.initialData
if (this.initialData.executionInput) {
this.executionInput = this.formatJson(this.initialData.executionInput)
}
},
data: () => ({
initialData: defaultInitialData,
Expand Down Expand Up @@ -89,7 +93,9 @@ export default defineComponent({
break
case 'textarea':
this.placeholderJson = defaultJsonPlaceholder
this.executionInput = ''
if (!this.initialData.executionInput) {
this.executionInput = ''
}
this.fileInputVisible = false
break
}
Expand All @@ -104,7 +110,7 @@ export default defineComponent({
reader.onload = (event) => {
if (event.target) {
const result = event.target.result
this.executionInput = result as string
this.executionInput = this.formatJson(result as string)
}
} // desired file content
reader.onerror = (error) => {
Expand All @@ -115,6 +121,15 @@ export default defineComponent({
this.textAreaVisible = true
}
},
formatJson: function (jsonString: string): string {
try {
const parsed = JSON.parse(jsonString)
return JSON.stringify(parsed, null, 2)
} catch (error) {
console.warn('Failed to format JSON:', error)
return jsonString
}
},
sendInput: function () {
client.executeStateMachine(this.executionInput || '{}')
},
Expand Down
Loading