webview-ui/src/Draft/DraftDockerfile/state.ts (104 lines of code) (raw):

import { WebviewStateUpdater } from "../../utilities/state"; import { getWebviewMessageContext } from "../../utilities/vscode"; import { LanguageInfo, LanguageVersionInfo } from "../../../../src/webview-contract/webviewDefinitions/draft/types"; import { Validatable, ValidatableValue, invalid, isValid, unset, valid } from "../../utilities/validation"; import { WorkspaceFolderConfig } from "../../../../src/webview-contract/webviewDefinitions/shared/workspaceTypes"; import { ExistingFiles } from "../../../../src/webview-contract/webviewDefinitions/draft/draftDockerfile"; const defaultPortNumber = 80; export type EventDef = { setSelectedLanguage: Validatable<LanguageInfo>; setSelectedLanguageVersion: Validatable<string>; setSelectedPort: Validatable<number>; setCreating: void; }; export type DraftDockerfileState = { workspaceConfig: WorkspaceFolderConfig; supportedLanguages: LanguageInfo[]; existingFiles: ExistingFiles; status: Status; selectedLocation: ValidatableValue<string>; selectedLanguage: Validatable<LanguageInfo>; isBuilderImageRequired: boolean; selectedLanguageVersion: Validatable<string>; builderImageTag: Validatable<string>; runtimeImageTag: Validatable<string>; selectedPort: Validatable<number>; }; export type Status = "Editing" | "Creating" | "Created"; export const stateUpdater: WebviewStateUpdater<"draftDockerfile", EventDef, DraftDockerfileState> = { createState: (initialState) => ({ workspaceConfig: initialState.workspaceConfig, supportedLanguages: initialState.supportedLanguages, existingFiles: initialState.existingFiles, status: "Editing", selectedLocation: getValidatedLocation(initialState.location, initialState.existingFiles), selectedLanguage: unset(), isBuilderImageRequired: false, selectedLanguageVersion: unset(), builderImageTag: unset(), runtimeImageTag: unset(), selectedPort: valid(defaultPortNumber), }), vscodeMessageHandler: { pickLocationResponse: (state, response) => ({ ...state, existingFiles: response.existingFiles, selectedLocation: getValidatedLocation(response.location, response.existingFiles), }), getLanguageVersionInfoResponse: (state, response) => ({ ...state, ...getLanguageVersionState(state, response.language, response.versionInfo), }), createDockerfileResponse: (state, existingFiles) => ({ ...state, existingFiles, status: "Created", }), }, eventHandler: { setSelectedLanguage: (state, selectedLanguage) => ({ ...state, selectedLanguage, isBuilderImageRequired: isValid(selectedLanguage) ? selectedLanguage.value.isBuilderImageRequired : false, selectedLanguageVersion: unset(), selectedPort: isValid(selectedLanguage) ? valid(selectedLanguage.value.defaultPort ?? defaultPortNumber) : valid(defaultPortNumber), }), setSelectedLanguageVersion: (state, selectedLanguageVersion) => ({ ...state, selectedLanguageVersion, }), setSelectedPort: (state, selectedPort) => ({ ...state, selectedPort }), setCreating: (state) => ({ ...state, status: "Creating" }), }, }; export const vscode = getWebviewMessageContext<"draftDockerfile">({ pickLocationRequest: null, getLanguageVersionInfoRequest: null, createDockerfileRequest: null, openFileRequest: null, launchDraftDeployment: null, launchDraftWorkflow: null, }); type LanguageVersionState = Pick<DraftDockerfileState, "builderImageTag" | "runtimeImageTag">; function getLanguageVersionState( state: DraftDockerfileState, language: string, versionInfo: LanguageVersionInfo, ): LanguageVersionState { if (!isValid(state.selectedLanguage) || language !== state.selectedLanguage.value.name) { // Keep the state unchanged. return { builderImageTag: state.builderImageTag, runtimeImageTag: state.runtimeImageTag, }; } return { builderImageTag: versionInfo.builderImageTag ? valid(versionInfo.builderImageTag) : unset(), runtimeImageTag: valid(versionInfo.runtimeImageTag), }; } function getValidatedLocation(location: string, existingFiles: ExistingFiles): ValidatableValue<string> { if (existingFiles.length === 0) return valid(location); return invalid(location, "Dockerfile or dockerignore already exist in the selected directory."); }