/
weylin
/
WtDev
Обзор
Документация
Войти
/
weylin
/
WtDev
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
dev
src/extension.ts
624 строки
18 KB
Weylin
Доработана проверка существования конфига при старте плагина
01 ноя 2025, 03:03
01 ноя 2025, 03:03
5dcc130
Код
Авторство
О чём код?
import * as vscode from "vscode"; import { downloadXmlElems, getAvailableServers, getRootFolder, getBackendFolder, uploadSourceCode, uploadAllXmlElems, downloadPackage, isWtDevFolder, findOutdatedXmlElems, NoWtConfigError, NoRootFolderError, WtConfigError, updateLocalXmlElemsFromServer, getSrcFolder, getTasks, runTask, downloadBackupPackage, getMainConfig, backupLocalData, downloadXmlElemsFromPackageScheme, WrongBackendVersionError, getRequiredBackendUrl, getLocalXmlElem, saveRemoteXmlElemToTempFile, getLocalPackageSchemes, uploadAllToServer, getAvailablePipelines, getAvailableVisibleServers, mainConfigExists, } from "./upload"; import path from "path"; import { AxiosError } from "axios"; import { globalEventManager, XmlElem } from "./common"; import { WtTest } from "./testing"; import { runPipeline } from "./pipeline"; export async function activate(context: vscode.ExtensionContext) { try { if (!(await mainConfigExists())) { throw new NoWtConfigError(); } const wtTest = new WtTest(); context.subscriptions.push(wtTest.controller); context.subscriptions.push(await wtTest.createFileWatcher()); context.subscriptions.push( vscode.commands.registerCommand( "wtdev.diffFiles", async (xmlFilePath: string) => { const localXmlElem = await getLocalXmlElem(xmlFilePath); if (!localXmlElem) { vscode.window.showWarningMessage("Local XML file not found"); return false; } const remoteFilePath = await saveRemoteXmlElemToTempFile( localXmlElem?.id ); if (!remoteFilePath) { vscode.window.showWarningMessage("Remote XML file not found"); return false; } const localXmlFileUri = vscode.Uri.file(localXmlElem.filepath); const remoteXmlFileUri = vscode.Uri.file(remoteFilePath); await vscode.commands.executeCommand( "vscode.diff", localXmlFileUri, remoteXmlFileUri, `Diff ${localXmlElem.name}: Local - Remote` ); return true; } ) ); if (!(await isWtDevFolder())) { return false; } const mainStatusBarWidget = new MainStatusBarWidget( "wtdev.updateLocalXmlElemsFromServer" ); context.subscriptions.push(mainStatusBarWidget.statusBarItem); //const outdatedXmlElems = await findOutdatedXmlElems(); //mainStatusBarWidget.outdatedXmlsCount = outdatedXmlElems.length; context.subscriptions.push( vscode.commands.registerCommand("wtdev.uploadAllToTarget", async () => { const servers = await getAvailableVisibleServers(); const serverNames = servers.map((s) => s.url); const selectedServerUrl = await showSingleSelect( "Выберите сервер", serverNames ); if (!selectedServerUrl) { vscode.window.showErrorMessage(`Не выбран url сервера`); return false; } const selectedServer = servers.find((s) => s.url === selectedServerUrl); if (!selectedServer) { vscode.window.showErrorMessage( `Не найден сервер с url ${selectedServerUrl}` ); return false; } await downloadBackupPackage(selectedServer); const { fileUploadResult, xmlUploadResult } = await uploadAllToServer( selectedServer ); if (fileUploadResult.ok) { vscode.window.showInformationMessage( `Загружено на стенд файлов: ${fileUploadResult.updatedFilesCnt}; XML: ${xmlUploadResult.uploadXmlsCount}` ); } else { vscode.window.showErrorMessage( `Загрузка файлов на стенд не удалась. ${fileUploadResult.message}` ); } await vscode.commands.executeCommand( "wtdev.checkForOutdatedLocalXmlElems" ); return true; }) ); context.subscriptions.push( vscode.commands.registerCommand("wtdev.addItemById", async () => { const elemId = String(await showTextInput("Введите ID элемента")); const xmlFileDownloadResult = await downloadXmlElems([elemId]); if (xmlFileDownloadResult.ok) { vscode.window.showInformationMessage( `Xml-файл с id ${elemId} успешно скачан.` ); } else { vscode.window.showErrorMessage( `Не удалось скачать xml-файл с id ${elemId}` ); } }) ); context.subscriptions.push( vscode.commands.registerCommand( "wtdev.addItemsFromPackageScheme", async () => { const packageSchemeName = String( await showTextInput("Введите имя пакета на сервере") ); const xmlFileDownloadResult = await downloadXmlElemsFromPackageScheme( packageSchemeName ); if (xmlFileDownloadResult.ok) { vscode.window.showInformationMessage( `Xml-файлы (${xmlFileDownloadResult.elems.length}) из пакета успешно скачаны.` ); } else { vscode.window.showErrorMessage( `Не удалось скачать xml-файлы из пакета` ); } } ) ); context.subscriptions.push( vscode.commands.registerCommand( "wtdev.checkForOutdatedLocalXmlElems", async () => { mainStatusBarWidget.outdatedXmlElems = await findOutdatedXmlElems(); } ) ); context.subscriptions.push( vscode.commands.registerCommand( "wtdev.updateLocalXmlElemsFromServer", async () => { const confirmResult = await vscode.window.showInformationMessage( `Локальные XML-файлы (${mainStatusBarWidget.outdatedXmlsCount}) будут обновлены со стенда. Вы уверены, что хотите продолжить?`, { modal: true, }, "Update" ); if (confirmResult === "Update") { await backupLocalData(); const updateResult = await updateLocalXmlElemsFromServer(); if (updateResult.ok) { vscode.window.showInformationMessage( "Локальные XML-файлы обновлены." ); } else { vscode.window.showInformationMessage( `Не удалось обновить локальные XML-файлы: ${updateResult.message}` ); } await vscode.commands.executeCommand( "wtdev.checkForOutdatedLocalXmlElems" ); } } ) ); context.subscriptions.push( vscode.commands.registerCommand("wtdev.createFullPackage", async () => { const createdPackage = await downloadPackage(); if (createdPackage.ok) { vscode.window.showInformationMessage(`Пакет успешно создан.`); } else { vscode.window.showErrorMessage( `Не удалось создать пакет. ${createdPackage.message}` ); } }) ); context.subscriptions.push( vscode.commands.registerCommand("wtdev.createPackage", async () => { const schemes = await getLocalPackageSchemes(); const schemeNames = schemes.map((s) => s.name); const selectedSchemeName = await showSingleSelect( "Выберите схему пакета", schemeNames ); const selectedScheme = schemes.find( (s) => s.name === selectedSchemeName ); if (!selectedScheme) { vscode.window.showErrorMessage( `Не найдена схема пакета "${selectedSchemeName}"` ); return; } const createdPackage = await downloadPackage({ scheme: selectedScheme, }); if (createdPackage.ok) { vscode.window.showInformationMessage( `Пакет "${selectedScheme.name}" успешно создан.` ); } else { vscode.window.showErrorMessage( `Не удалось создать пакет. ${createdPackage.message}` ); } }) ); context.subscriptions.push( vscode.commands.registerCommand("wtdev.runPipeline", async () => { const pipelines = await getAvailablePipelines(); if (!pipelines) { vscode.window.showErrorMessage( `В конфиге не указан ни один пайплайн` ); return false; } const pipelineNames = pipelines.map((j) => j.name); const selectedPipelineName = await showSingleSelect( "Выберите пайплайн", pipelineNames ); if (!selectedPipelineName) { vscode.window.showErrorMessage(`Не выбран пайплайн`); return false; } const selectedPipeline = pipelines.find( (p) => p.name === selectedPipelineName ); if (!selectedPipeline) { vscode.window.showErrorMessage( `Не найден пайплайн с названием "${selectedPipelineName}"` ); return false; } mainStatusBarWidget.inProgress = true; const ok = await runPipeline( selectedPipeline, (stageDesc: string, curStep: number, totalStepsCnt: number) => { mainStatusBarWidget.progressMessage = `${curStep}/${totalStepsCnt} ${stageDesc}...`; } ); mainStatusBarWidget.inProgress = false; if (ok) { vscode.window.showInformationMessage( `Пайплайн "${selectedPipeline.name}" успешно завершен` ); } else { vscode.window.showErrorMessage( `Ошибка при выполнении пайплайна "${selectedPipeline.name}"` ); } return true; }) ); context.subscriptions.push( vscode.commands.registerCommand("wtdev.runTask", async () => { const configTasks = await getTasks(); if (!configTasks) { return false; } const configTaskTitles = configTasks.map((ct) => ct.title); const selectedСonfigTaskTitle = await showSingleSelect( "Выберите задачу", configTaskTitles ); if (!selectedСonfigTaskTitle) { vscode.window.showErrorMessage(`Не выбрана задача`); return false; } const selectedConfigTask = configTasks.find( (ct) => ct.title === selectedСonfigTaskTitle ); if (!selectedConfigTask) { vscode.window.showErrorMessage( `Не найдена задача с названием "${selectedСonfigTaskTitle}"` ); return false; } const taskCompleted = await runTask(selectedConfigTask); if (taskCompleted) { vscode.window.showInformationMessage( `Задача "${selectedConfigTask.title}" выполнена"` ); } else { vscode.window.showErrorMessage( `Не удалось выполнить задачу "${selectedConfigTask.title}"` ); } return true; }) ); context.subscriptions.push( vscode.workspace.onDidSaveTextDocument(async (event) => { //console.log("event :>> ", event); //const filename = vscode.window.activeTextEditor?.document.fileName; const srcFolder = await getSrcFolder(); if (!srcFolder || !event.fileName.startsWith(srcFolder)) { return false; } /*if (!isFileUploadable(event.fileName)) { return false; }*/ const uploadResult = await uploadSourceCode(event.fileName); if (!uploadResult) { return false; } if (uploadResult.ok && uploadResult.updatedFilesCnt > 0) { vscode.window.showInformationMessage( `Файл ${path.basename(event.fileName)} загружен на стенд.` ); } else if (!uploadResult.ok && uploadResult.updatedFilesCnt > 0) { vscode.window.showErrorMessage( `Загрузка не удалась. ${uploadResult.message}` ); } return true; }) ); await vscode.commands.executeCommand("wtdev.checkForOutdatedLocalXmlElems"); return true; } catch (e) { console.log("typeof e :>> ", typeof e); if (e instanceof NoWtConfigError || e instanceof NoRootFolderError) { return false; } else if (e instanceof WtConfigError) { vscode.window.showErrorMessage( `Ошибка в конфигурационном файле. ${e.message}` ); return false; } else if (e instanceof WrongBackendVersionError) { const answer = await vscode.window.showErrorMessage( `Версия бэкенда отличается от рекомендуемой.`, "Скачать рекомендуемый бэкенд" ); if (answer === "Скачать рекомендуемый бэкенд") { await vscode.commands.executeCommand( "vscode.open", vscode.Uri.parse(getRequiredBackendUrl()) ); } return false; } else if (e instanceof AxiosError) { vscode.window.showErrorMessage(`Не удалось соединиться с сервером.`); return false; } else if (e instanceof AggregateError) { vscode.window.showErrorMessage(`Какая-то ошибка. ${e}`); console.log("error: ", e.errors); e.errors.forEach((err) => console.log(err.message)); //throw e; return false; } else { throw e; } } } export function deactivate() {} class MainStatusBarWidget { public statusBarItem: vscode.StatusBarItem; private _downloadXmlsCommand: string; private _outdatedXmlElems: XmlElem[] = []; private _inProgress: boolean = false; private _progressMessage: string = ""; constructor(downloadXmlsCommand: string) { this._downloadXmlsCommand = downloadXmlsCommand; this.statusBarItem = vscode.window.createStatusBarItem( vscode.StatusBarAlignment.Left, 100 ); } public get outdatedXmlsCount() { return this._outdatedXmlElems.length; } public set outdatedXmlElems(newXmlElems: XmlElem[]) { this._outdatedXmlElems = newXmlElems.map((xe) => ({ name: xe.name, id: xe.id, form: xe.form, hash: xe.hash, xml: "", filepath: xe.filepath, })); this.updateView(); } public get inProgress() { return this._inProgress; } public set inProgress(value) { this._inProgress = value; this.updateView(); } public set progressMessage(value: string) { this._progressMessage = value; this.updateView(); } updateView() { this.statusBarItem.backgroundColor = new vscode.ThemeColor( "statusBarItem.background" ); this.statusBarItem.command = undefined; const textParts: string[] = []; let mainIcon = "$(code)"; textParts.push(" WtDev"); if (this._inProgress) { mainIcon = "$(loading~spin)"; textParts.push(` - ${this._progressMessage}`); } else if (this.outdatedXmlsCount > 0) { textParts.push(` - Outdated XMLs: ${this.outdatedXmlsCount}`); this.statusBarItem.backgroundColor = new vscode.ThemeColor( "statusBarItem.warningBackground" ); this.statusBarItem.command = this._downloadXmlsCommand; } this.updateTooltip(); this.statusBarItem.name = "WtDev"; this.statusBarItem.text = mainIcon + textParts.join(""); this.statusBarItem.show(); } updateTooltip() { const tooltip = new vscode.MarkdownString(); if (this.outdatedXmlsCount > 0) { const tooltipParts: string[] = []; for (const outdatedXmlElem of this._outdatedXmlElems) { const cmdShowDiffArgs = [outdatedXmlElem.filepath]; const cmdShowDiffUri = vscode.Uri.parse( `command:wtdev.diffFiles?${encodeURIComponent( JSON.stringify(cmdShowDiffArgs) )}` ); tooltipParts.push( `- ${outdatedXmlElem.name} *(${outdatedXmlElem.form})* [show diff](${cmdShowDiffUri})` ); } tooltip.value = "**Outdated XML files**\n" + tooltipParts.join("\n"); tooltip.isTrusted = true; } this.statusBarItem.tooltip = tooltip; } } async function showSingleSelect( title: string, options: string[] ): Promise<string> { const quickPick = vscode.window.createQuickPick(); quickPick.placeholder = title; quickPick.items = options.map((o) => ({ label: o, })); //quickPick.buttons = [{ tooltip: "cancel", iconPath: "" }, { tooltip: "ok" }]; quickPick.onDidHide(() => quickPick.dispose()); quickPick.show(); return new Promise((resolve) => { quickPick.onDidChangeSelection((selection) => { console.log("selection :>> ", selection); quickPick.hide(); resolve(selection?.[0].label); }); }); } async function showTextInput(title: string) { const quickPick = vscode.window.createQuickPick(); quickPick.placeholder = title; quickPick.onDidHide(() => quickPick.dispose()); quickPick.show(); return new Promise((resolve) => { quickPick.onDidAccept(() => { quickPick.hide(); resolve(quickPick.value); }); }); } /* Upload File (on Save, with XML?) Upload All (Files & XMLs) Download All XMLs Download All (XMLs and files) ??? Add XML (by ID) Add XMLs (from package, by package name) check imports on file upload */