UNPKG

teamsfx-extension

Version:

Create, debug, and deploy Teams apps with Teams Toolkit

930 lines 44.6 kB
// Copyright (c) Microsoft Corporation. // Licensed under the MIT license. "use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.selectSubscription = exports.signInM365 = exports.signInAzure = exports.signOutM365 = exports.signOutAzure = exports.cmpAccountsHandler = exports.showError = exports.cmdHdlDisposeTreeView = exports.cmdHdlLoadTreeView = exports.openAzureAccountHandler = exports.openM365AccountHandler = exports.openManifestHandler = exports.openReportIssues = exports.openBotManagement = exports.openAppManagement = exports.openSamplesHandler = exports.openWelcomeHandler = exports.openDocumentHandler = exports.preDebugCheckHandler = exports.backendExtensionsInstallHandler = exports.validateSpfxDependenciesHandler = exports.validateDependenciesHandler = exports.addCapabilityHandler = exports.updateAADHandler = exports.detectVsCodeEnv = exports.runCommand = exports.publishHandler = exports.deployHandler = exports.provisionHandler = exports.buildPackageHandler = exports.validateManifestHandler = exports.updateProjectHandler = exports.createNewProjectHandler = exports.activate = exports.core = void 0; const vscode_1 = require("vscode"); const teamsfx_api_1 = require("@microsoft/teamsfx-api"); const teamsfx_core_1 = require("@microsoft/teamsfx-core"); const userInterface_1 = require("./userInterface"); const graphLogin_1 = require("./commonlib/graphLogin"); const azureLogin_1 = require("./commonlib/azureLogin"); const appStudioLogin_1 = require("./commonlib/appStudioLogin"); const appStudioCodeSpaceLogin_1 = require("./commonlib/appStudioCodeSpaceLogin"); const log_1 = require("./commonlib/log"); const telemetry_1 = require("./commonlib/telemetry"); const commandsTreeViewProvider_1 = require("./commandsTreeViewProvider"); const extensionPackage = require("./../package.json"); const extensionVariables_1 = require("./extensionVariables"); const extTelemetry_1 = require("./telemetry/extTelemetry"); const extTelemetryEvents_1 = require("./telemetry/extTelemetryEvents"); const commonUtils = require("./debug/commonUtils"); const error_1 = require("./error"); const webviewPanel_1 = require("./controls/webviewPanel"); const constants = require("./debug/constants"); const commonUtils_1 = require("./utils/commonUtils"); const fs = require("fs-extra"); const vscode = require("vscode"); const checker_1 = require("./debug/depsChecker/checker"); const backendExtensionsInstall_1 = require("./debug/depsChecker/backendExtensionsInstall"); const dotnetChecker_1 = require("./debug/depsChecker/dotnetChecker"); const util = require("util"); const StringResources = require("./resources/Strings.json"); const vscodeAdapter_1 = require("./debug/depsChecker/vscodeAdapter"); const vscodeLogger_1 = require("./debug/depsChecker/vscodeLogger"); const vscodeTelemetry_1 = require("./debug/depsChecker/vscodeTelemetry"); const PanelType_1 = require("./controls/PanelType"); const constant_1 = require("./commonlib/common/constant"); const azureNodeChecker_1 = require("./debug/depsChecker/azureNodeChecker"); const spfxNodeChecker_1 = require("./debug/depsChecker/spfxNodeChecker"); const teamsfxTaskHandler_1 = require("./debug/teamsfxTaskHandler"); const vsc_ui_1 = require("./qm/vsc_ui"); const runningTasks = new Set(); // to control state of task execution function activate() { var _a; return __awaiter(this, void 0, void 0, function* () { const result = teamsfx_api_1.ok(null); try { exports.core = teamsfx_core_1.CoreProxy.getInstance(); { const result = yield exports.core.withDialog(userInterface_1.default); if (result.isErr()) { showError(result.error); return teamsfx_api_1.err(result.error); } } { const result = yield exports.core.withGraphToken(graphLogin_1.default); if (result.isErr()) { showError(result.error); return teamsfx_api_1.err(result.error); } } { azureLogin_1.default.setStatusChangeMap("successfully-sign-in-azure", (status, token, accountInfo) => { if (status === constant_1.signedIn) { vscode_1.window.showInformationMessage(StringResources.vsc.handlers.azureSignIn); } else if (status === constant_1.signedOut) { vscode_1.window.showInformationMessage(StringResources.vsc.handlers.azureSignOut); } return Promise.resolve(); }, false); const result = yield exports.core.withAzureAccount(azureLogin_1.default); if (result.isErr()) { showError(result.error); return teamsfx_api_1.err(result.error); } } { let appstudioLogin = appStudioLogin_1.default; const vscodeEnv = detectVsCodeEnv(); if (vscodeEnv === teamsfx_api_1.VsCodeEnv.codespaceBrowser || vscodeEnv === teamsfx_api_1.VsCodeEnv.codespaceVsCode) { appstudioLogin = appStudioCodeSpaceLogin_1.default; } appstudioLogin.setStatusChangeMap("successfully-sign-in-m365", (status, token, accountInfo) => { if (status === constant_1.signedIn) { vscode_1.window.showInformationMessage(StringResources.vsc.handlers.m365SignIn); } else if (status === constant_1.signedOut) { vscode_1.window.showInformationMessage(StringResources.vsc.handlers.m365SignOut); } return Promise.resolve(); }, false); const result = yield exports.core.withAppStudioToken(appstudioLogin); if (result.isErr()) { showError(result.error); return teamsfx_api_1.err(result.error); } } { const telemetry = new telemetry_1.VSCodeTelemetryReporter(extensionPackage.aiKey, extensionPackage.version, extensionPackage.name); const result = yield exports.core.withTelemetry(telemetry); if (result.isErr()) { showError(result.error); return teamsfx_api_1.err(result.error); } } { const result = yield exports.core.withLogger(log_1.default); if (result.isErr()) { showError(result.error); return teamsfx_api_1.err(result.error); } } { const result = yield exports.core.withTreeProvider(commandsTreeViewProvider_1.default.getTreeView("teamsfx-accounts")); if (result.isErr()) { showError(result.error); return teamsfx_api_1.err(result.error); } } { const globalConfig = new teamsfx_api_1.ConfigMap(); globalConfig.set("function-dotnet-checker-enabled", vscodeAdapter_1.vscodeAdapter.dotnetCheckerEnabled()); const result = yield exports.core.init(globalConfig); if (result.isErr()) { showError(result.error); return teamsfx_api_1.err(result.error); } } { const workspacePath = ((_a = vscode_1.workspace.workspaceFolders) === null || _a === void 0 ? void 0 : _a.length) ? vscode_1.workspace.workspaceFolders[0].uri.fsPath : undefined; const result = yield exports.core.open(workspacePath); if (result.isErr()) { showError(result.error); return teamsfx_api_1.err(result.error); } } { yield openMarkdownHandler(); } } catch (e) { const FxError = { name: e.name, source: error_1.ExtensionSource, message: e.message, stack: e.stack, timestamp: new Date(), }; showError(FxError); return teamsfx_api_1.err(FxError); } return result; }); } exports.activate = activate; function createNewProjectHandler(args) { return __awaiter(this, void 0, void 0, function* () { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.CreateProjectStart, getTriggerFromProperty(args)); return yield runCommand(teamsfx_api_1.Stage.create); }); } exports.createNewProjectHandler = createNewProjectHandler; function updateProjectHandler(args) { return __awaiter(this, void 0, void 0, function* () { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.UpdateProjectStart, getTriggerFromProperty(args)); return yield runCommand(teamsfx_api_1.Stage.update); }); } exports.updateProjectHandler = updateProjectHandler; function validateManifestHandler(args) { return __awaiter(this, void 0, void 0, function* () { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.ValidateManifestStart, getTriggerFromProperty(args)); const func = { namespace: "fx-solution-azure", method: "validateManifest", }; const result = yield exports.core.executeUserTask(func); if (result.isErr()) { extTelemetry_1.ExtTelemetry.sendTelemetryErrorEvent(extTelemetryEvents_1.TelemetryEvent.ValidateManifest, result.error); } else { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.ValidateManifest, { [extTelemetryEvents_1.TelemetryProperty.Success]: extTelemetryEvents_1.TelemetrySuccess.Yes, }); } return result; }); } exports.validateManifestHandler = validateManifestHandler; function buildPackageHandler(args) { return __awaiter(this, void 0, void 0, function* () { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.BuildStart, getTriggerFromProperty(args)); const func = { namespace: "fx-solution-azure", method: "buildPackage", }; const result = yield exports.core.executeUserTask(func); if (result.isErr()) { extTelemetry_1.ExtTelemetry.sendTelemetryErrorEvent(extTelemetryEvents_1.TelemetryEvent.Build, result.error); } else { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.Build, { [extTelemetryEvents_1.TelemetryProperty.Success]: extTelemetryEvents_1.TelemetrySuccess.Yes, }); } return result; }); } exports.buildPackageHandler = buildPackageHandler; function provisionHandler(args) { return __awaiter(this, void 0, void 0, function* () { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.ProvisionStart, getTriggerFromProperty(args)); return yield runCommand(teamsfx_api_1.Stage.provision); }); } exports.provisionHandler = provisionHandler; function deployHandler(args) { return __awaiter(this, void 0, void 0, function* () { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.DeployStart, getTriggerFromProperty(args)); return yield runCommand(teamsfx_api_1.Stage.deploy); }); } exports.deployHandler = deployHandler; function publishHandler(args) { return __awaiter(this, void 0, void 0, function* () { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.PublishStart, getTriggerFromProperty(args)); return yield runCommand(teamsfx_api_1.Stage.publish); }); } exports.publishHandler = publishHandler; const coreExeceutor = function (func, answers) { return __awaiter(this, void 0, void 0, function* () { return yield exports.core.callFunc(func, answers); }); }; function runCommand(stage) { return __awaiter(this, void 0, void 0, function* () { const eventName = extTelemetry_1.ExtTelemetry.stageToEvent(stage); let result = teamsfx_api_1.ok(null); try { // 1. check concurrent lock if (runningTasks.size > 0 && stage !== teamsfx_api_1.Stage.create) { result = teamsfx_api_1.err(new teamsfx_api_1.UserError(error_1.ExtensionErrors.ConcurrentTriggerTask, util.format(StringResources.vsc.handlers.concurrentTriggerTask, Array.from(runningTasks).join(",")), error_1.ExtensionSource)); yield processResult(eventName, result); return result; } // 2. lock runningTasks.add(stage); // 3. check core not empty const checkCoreRes = checkCoreNotEmpty(); if (checkCoreRes.isErr()) { throw checkCoreRes.error; } const answers = new teamsfx_api_1.ConfigMap(); answers.set("stage", stage); answers.set("platform", teamsfx_api_1.Platform.VSCode); // 4. getQuestions const qres = yield exports.core.getQuestions(stage, teamsfx_api_1.Platform.VSCode); if (qres.isErr()) { throw qres.error; } const vscenv = detectVsCodeEnv(); answers.set("vscenv", vscenv); log_1.default.info(util.format(StringResources.vsc.handlers.vsCodeEnvironment, vscenv)); // 5. run question model const node = qres.value; if (node) { const res = yield teamsfx_api_1.traverse(node, answers, vsc_ui_1.VS_CODE_UI, coreExeceutor); if (res.type === teamsfx_api_1.InputResultType.error) { throw res.error; } else if (res.type === teamsfx_api_1.InputResultType.cancel) { throw new teamsfx_api_1.UserError(error_1.ExtensionErrors.UserCancel, StringResources.vsc.common.userCancel, error_1.ExtensionSource); } } // 6. run task if (stage === teamsfx_api_1.Stage.create) result = yield exports.core.create(answers); else if (stage === teamsfx_api_1.Stage.update) result = yield exports.core.update(answers); else if (stage === teamsfx_api_1.Stage.provision) result = yield exports.core.provision(answers); else if (stage === teamsfx_api_1.Stage.deploy) result = yield exports.core.deploy(answers); else if (stage === teamsfx_api_1.Stage.debug) result = yield exports.core.localDebug(answers); else if (stage === teamsfx_api_1.Stage.publish) result = yield exports.core.publish(answers); else { throw new teamsfx_api_1.SystemError(error_1.ExtensionErrors.UnsupportedOperation, util.format(StringResources.vsc.handlers.operationNotSupport, stage), error_1.ExtensionSource); } } catch (e) { if ("name" in e && e.name === "DoProvisionFirst") { runningTasks.delete(stage); if (eventName) { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(eventName, { [extTelemetryEvents_1.TelemetryProperty.Success]: extTelemetryEvents_1.TelemetrySuccess.No, }); } return yield provisionHandler(); } result = wrapError(e); } // 7. unlock runningTasks.delete(stage); // 8. send telemetry and show error yield processResult(eventName, result); return result; }); } exports.runCommand = runCommand; function detectVsCodeEnv() { // extensionKind returns ExtensionKind.UI when running locally, so use this to detect remote const extension = vscode.extensions.getExtension("Microsoft.teamsfx-extension"); if ((extension === null || extension === void 0 ? void 0 : extension.extensionKind) === vscode.ExtensionKind.Workspace) { // running remotely // Codespaces browser-based editor will return UIKind.Web for uiKind if (vscode.env.uiKind === vscode.UIKind.Web) { return teamsfx_api_1.VsCodeEnv.codespaceBrowser; } else if (vscode.env.remoteName === "codespaces") { return teamsfx_api_1.VsCodeEnv.codespaceVsCode; } else { return teamsfx_api_1.VsCodeEnv.remote; } } else { // running locally return teamsfx_api_1.VsCodeEnv.local; } } exports.detectVsCodeEnv = detectVsCodeEnv; function runUserTask(func, eventName) { return __awaiter(this, void 0, void 0, function* () { let result = teamsfx_api_1.ok(null); try { // 1. check concurrent lock if (runningTasks.size > 0) { result = teamsfx_api_1.err(new teamsfx_api_1.UserError(error_1.ExtensionErrors.ConcurrentTriggerTask, util.format(StringResources.vsc.handlers.concurrentTriggerTask, Array.from(runningTasks).join(",")), error_1.ExtensionSource)); yield processResult(eventName, result); return result; } // 2. lock runningTasks.add(eventName); // 3. check core not empty const checkCoreRes = checkCoreNotEmpty(); if (checkCoreRes.isErr()) { throw checkCoreRes.error; } const answers = new teamsfx_api_1.ConfigMap(); answers.set("task", eventName); answers.set("platform", teamsfx_api_1.Platform.VSCode); // 4. getQuestions const qres = yield exports.core.getQuestionsForUserTask(func, teamsfx_api_1.Platform.VSCode); if (qres.isErr()) { throw qres.error; } // 5. run question model const node = qres.value; if (node) { const res = yield teamsfx_api_1.traverse(node, answers, vsc_ui_1.VS_CODE_UI, coreExeceutor); if (res.type === teamsfx_api_1.InputResultType.error && res.error) { throw res.error; } else if (res.type === teamsfx_api_1.InputResultType.cancel) { throw new teamsfx_api_1.UserError(error_1.ExtensionErrors.UserCancel, StringResources.vsc.common.userCancel, error_1.ExtensionSource); } } // 6. run task result = yield exports.core.executeUserTask(func, answers); } catch (e) { result = wrapError(e); } // 7. unlock runningTasks.delete(eventName); // 8. send telemetry and show error yield processResult(eventName, result); return result; }); } //TODO workaround function isLoginFaiureError(error) { return !!error.message && error.message.includes("Cannot get user login information"); } function processResult(eventName, result) { return __awaiter(this, void 0, void 0, function* () { if (result.isErr()) { if (eventName) { extTelemetry_1.ExtTelemetry.sendTelemetryErrorEvent(eventName, result.error); } const error = result.error; if (teamsfx_core_1.isUserCancelError(error)) { return; } if (isLoginFaiureError(error)) { vscode_1.window.showErrorMessage(StringResources.vsc.handlers.loginFailed); return; } showError(error); } else { if (eventName) { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(eventName, { [extTelemetryEvents_1.TelemetryProperty.Success]: extTelemetryEvents_1.TelemetrySuccess.Yes, }); } } }); } function wrapError(e) { if (e instanceof teamsfx_api_1.UserError || e instanceof teamsfx_api_1.SystemError || (e.constructor && e.constructor.name && (e.constructor.name === "SystemError" || e.constructor.name === "UserError"))) { return teamsfx_api_1.err(e); } return teamsfx_api_1.err(teamsfx_api_1.returnSystemError(e, error_1.ExtensionSource, error_1.ExtensionErrors.UnknwonError)); } function checkCoreNotEmpty() { if (!exports.core) { return teamsfx_api_1.err(teamsfx_api_1.returnSystemError(new Error(StringResources.vsc.handlers.coreNotReady), error_1.ExtensionSource, error_1.ExtensionErrors.UnsupportedOperation)); } return teamsfx_api_1.ok(null); } /** * manually added customized command */ function updateAADHandler(args) { return __awaiter(this, void 0, void 0, function* () { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.UpdateAadStart, getTriggerFromProperty(args)); const func = { namespace: "fx-solution-azure/fx-resource-aad-app-for-teams", method: "aadUpdatePermission", }; return yield runUserTask(func, extTelemetryEvents_1.TelemetryEvent.UpdateAad); }); } exports.updateAADHandler = updateAADHandler; function addCapabilityHandler(args) { return __awaiter(this, void 0, void 0, function* () { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.AddCapStart, getTriggerFromProperty(args)); const func = { namespace: "fx-solution-azure", method: "addCapability", }; return yield runUserTask(func, extTelemetryEvents_1.TelemetryEvent.AddCap); }); } exports.addCapabilityHandler = addCapabilityHandler; /** * check & install required dependencies during local debug when selected hosting type is Azure. */ function validateDependenciesHandler() { return __awaiter(this, void 0, void 0, function* () { const nodeChecker = new azureNodeChecker_1.AzureNodeChecker(vscodeAdapter_1.vscodeAdapter, vscodeLogger_1.vscodeLogger, vscodeTelemetry_1.vscodeTelemetry); const dotnetChecker = new dotnetChecker_1.DotnetChecker(vscodeAdapter_1.vscodeAdapter, vscodeLogger_1.vscodeLogger, vscodeTelemetry_1.vscodeTelemetry); const depsChecker = new checker_1.DepsChecker(vscodeLogger_1.vscodeLogger, vscodeAdapter_1.vscodeAdapter, [nodeChecker, dotnetChecker]); yield validateDependenciesCore(depsChecker); }); } exports.validateDependenciesHandler = validateDependenciesHandler; /** * check & install required dependencies during local debug when selected hosting type is SPFx. */ function validateSpfxDependenciesHandler() { return __awaiter(this, void 0, void 0, function* () { const nodeChecker = new spfxNodeChecker_1.SPFxNodeChecker(vscodeAdapter_1.vscodeAdapter, vscodeLogger_1.vscodeLogger, vscodeTelemetry_1.vscodeTelemetry); const depsChecker = new checker_1.DepsChecker(vscodeLogger_1.vscodeLogger, vscodeAdapter_1.vscodeAdapter, [nodeChecker]); yield validateDependenciesCore(depsChecker); }); } exports.validateSpfxDependenciesHandler = validateSpfxDependenciesHandler; function validateDependenciesCore(depsChecker) { return __awaiter(this, void 0, void 0, function* () { const shouldContinue = yield depsChecker.resolve(); if (!shouldContinue) { yield vscode_1.debug.stopDebugging(); // TODO: better mechanism to stop the tasks and debug session. throw new Error("debug stopped."); } }); } /** * install functions binding before launch local debug */ function backendExtensionsInstallHandler() { return __awaiter(this, void 0, void 0, function* () { if (vscode_1.workspace.workspaceFolders && vscode_1.workspace.workspaceFolders.length > 0) { const workspaceFolder = vscode_1.workspace.workspaceFolders[0]; const backendRoot = yield commonUtils.getProjectRoot(workspaceFolder.uri.fsPath, constants.backendFolderName); if (backendRoot) { const dotnetChecker = new dotnetChecker_1.DotnetChecker(vscodeAdapter_1.vscodeAdapter, vscodeLogger_1.vscodeLogger, vscodeTelemetry_1.vscodeTelemetry); const backendExtensionsInstaller = new backendExtensionsInstall_1.BackendExtensionsInstaller(dotnetChecker, vscodeLogger_1.vscodeLogger); try { yield backendExtensionsInstaller.install(backendRoot); } catch (error) { yield checker_1.DepsChecker.handleErrorWithDisplay(error, vscodeAdapter_1.vscodeAdapter); throw error; } } } }); } exports.backendExtensionsInstallHandler = backendExtensionsInstallHandler; /** * call localDebug on core */ function preDebugCheckHandler() { return __awaiter(this, void 0, void 0, function* () { try { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.DebugPreCheck); } catch (_a) { // ignore telemetry error } let result = teamsfx_api_1.ok(null); result = yield runCommand(teamsfx_api_1.Stage.debug); if (result.isErr()) { try { extTelemetry_1.ExtTelemetry.sendTelemetryErrorEvent(extTelemetryEvents_1.TelemetryEvent.DebugPreCheck, result.error); } finally { // ignore telemetry error teamsfxTaskHandler_1.terminateAllRunningTeamsfxTasks(); throw result.error; } } const portsInUse = yield commonUtils.getPortsInUse(); if (portsInUse.length > 0) { let message; if (portsInUse.length > 1) { message = util.format(StringResources.vsc.localDebug.portsAlreadyInUse, portsInUse.join(", ")); } else { message = util.format(StringResources.vsc.localDebug.portAlreadyInUse, portsInUse[0]); } const error = new teamsfx_api_1.UserError(error_1.ExtensionErrors.PortAlreadyInUse, message, error_1.ExtensionSource); try { extTelemetry_1.ExtTelemetry.sendTelemetryErrorEvent(extTelemetryEvents_1.TelemetryEvent.DebugPreCheck, error); } finally { // ignore telemetry error vscode_1.window.showErrorMessage(message); teamsfxTaskHandler_1.terminateAllRunningTeamsfxTasks(); throw error; } } }); } exports.preDebugCheckHandler = preDebugCheckHandler; function openDocumentHandler(args) { return __awaiter(this, void 0, void 0, function* () { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.Documentation, getTriggerFromProperty(args)); return vscode_1.env.openExternal(vscode_1.Uri.parse("https://aka.ms/build-first-app")); }); } exports.openDocumentHandler = openDocumentHandler; function openWelcomeHandler(args) { return __awaiter(this, void 0, void 0, function* () { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.QuickStart, getTriggerFromProperty(args)); webviewPanel_1.WebviewPanel.createOrShow(extensionVariables_1.ext.context.extensionPath, PanelType_1.PanelType.QuickStart); }); } exports.openWelcomeHandler = openWelcomeHandler; function getTriggerFromProperty(args) { const isFromTreeView = args && args.toString() === "TreeView"; return { [extTelemetryEvents_1.TelemetryProperty.TriggerFrom]: isFromTreeView ? extTelemetryEvents_1.TelemetryTiggerFrom.TreeView : extTelemetryEvents_1.TelemetryTiggerFrom.CommandPalette, }; } function openMarkdownHandler() { return __awaiter(this, void 0, void 0, function* () { const afterScaffold = extensionVariables_1.ext.context.globalState.get("openReadme", false); if (afterScaffold && vscode_1.workspace.workspaceFolders && vscode_1.workspace.workspaceFolders.length > 0) { extensionVariables_1.ext.context.globalState.update("openReadme", false); const workspaceFolder = vscode_1.workspace.workspaceFolders[0]; const workspacePath = workspaceFolder.uri.fsPath; let targetFolder; if (yield commonUtils_1.isSPFxProject(workspacePath)) { targetFolder = `${workspacePath}/SPFx`; } else { const tabFolder = yield commonUtils.getProjectRoot(workspacePath, constants.frontendFolderName); const botFolder = yield commonUtils.getProjectRoot(workspacePath, constants.botFolderName); if (tabFolder && botFolder) { targetFolder = workspacePath; } else if (tabFolder) { targetFolder = tabFolder; } else { targetFolder = botFolder; } } const uri = vscode_1.Uri.file(`${targetFolder}/README.md`); vscode_1.workspace .openTextDocument(uri) .then((document) => { vscode_1.window.showTextDocument(document); }) .then(() => { const PreviewMarkdownCommand = "markdown.showPreviewToSide"; vscode_1.commands.executeCommand(PreviewMarkdownCommand, uri); }); } }); } function openSamplesHandler(args) { return __awaiter(this, void 0, void 0, function* () { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.Samples, getTriggerFromProperty(args)); webviewPanel_1.WebviewPanel.createOrShow(extensionVariables_1.ext.context.extensionPath, PanelType_1.PanelType.SampleGallery); }); } exports.openSamplesHandler = openSamplesHandler; function openAppManagement(args) { return __awaiter(this, void 0, void 0, function* () { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.ManageTeamsApp, getTriggerFromProperty(args)); return vscode_1.env.openExternal(vscode_1.Uri.parse("https://dev.teams.microsoft.com/home")); }); } exports.openAppManagement = openAppManagement; function openBotManagement(args) { return __awaiter(this, void 0, void 0, function* () { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.ManageTeamsBot, getTriggerFromProperty(args)); return vscode_1.env.openExternal(vscode_1.Uri.parse("https://dev.teams.microsoft.com/bots")); }); } exports.openBotManagement = openBotManagement; function openReportIssues(args) { return __awaiter(this, void 0, void 0, function* () { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.ReportIssues, getTriggerFromProperty(args)); return vscode_1.env.openExternal(vscode_1.Uri.parse("https://github.com/OfficeDev/TeamsFx/issues")); }); } exports.openReportIssues = openReportIssues; function openManifestHandler(args) { return __awaiter(this, void 0, void 0, function* () { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.OpenManifestEditorStart, getTriggerFromProperty(args)); if (vscode_1.workspace.workspaceFolders && vscode_1.workspace.workspaceFolders.length > 0) { const workspaceFolder = vscode_1.workspace.workspaceFolders[0]; const configRoot = yield commonUtils.getProjectRoot(workspaceFolder.uri.fsPath, `.${teamsfx_api_1.ConfigFolderName}`); const manifestFile = `${configRoot}/${constants.manifestFileName}`; if (fs.existsSync(manifestFile)) { vscode_1.workspace.openTextDocument(manifestFile).then((document) => { vscode_1.window.showTextDocument(document); }); extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.OpenManifestEditor, { [extTelemetryEvents_1.TelemetryProperty.Success]: extTelemetryEvents_1.TelemetrySuccess.Yes, }); return teamsfx_api_1.ok(null); } else { const FxError = { name: "FileNotFound", source: error_1.ExtensionSource, message: util.format(StringResources.vsc.handlers.fileNotFound, manifestFile), timestamp: new Date(), }; showError(FxError); extTelemetry_1.ExtTelemetry.sendTelemetryErrorEvent(extTelemetryEvents_1.TelemetryEvent.OpenManifestEditor, FxError); return teamsfx_api_1.err(FxError); } } else { const FxError = { name: "NoWorkspace", source: error_1.ExtensionSource, message: StringResources.vsc.handlers.noOpenWorkspace, timestamp: new Date(), }; showError(FxError); extTelemetry_1.ExtTelemetry.sendTelemetryErrorEvent(extTelemetryEvents_1.TelemetryEvent.OpenManifestEditor, FxError); return teamsfx_api_1.err(FxError); } }); } exports.openManifestHandler = openManifestHandler; function openM365AccountHandler() { return __awaiter(this, void 0, void 0, function* () { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.OpenM365Portal); return vscode_1.env.openExternal(vscode_1.Uri.parse("https://admin.microsoft.com/Adminportal/")); }); } exports.openM365AccountHandler = openM365AccountHandler; function openAzureAccountHandler() { return __awaiter(this, void 0, void 0, function* () { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.OpenAzurePortal); return vscode_1.env.openExternal(vscode_1.Uri.parse("https://portal.azure.com/")); }); } exports.openAzureAccountHandler = openAzureAccountHandler; function cmdHdlLoadTreeView(context) { return __awaiter(this, void 0, void 0, function* () { const disposables = commandsTreeViewProvider_1.default.registerTreeViews(); context.subscriptions.push(...disposables); // Register SignOut tree view command vscode_1.commands.registerCommand("fx-extension.signOut", (node) => __awaiter(this, void 0, void 0, function* () { try { switch (node.contextValue) { case "signedinM365": { signOutM365(true); break; } case "signedinAzure": { signOutAzure(true); break; } } } catch (e) { showError(e); } })); vscode_1.commands.registerCommand("fx-extension.signInGuideline", (node) => __awaiter(this, void 0, void 0, function* () { // TODO: update the link when documentation is ready switch (node.contextValue) { case "signinM365": { yield vscode_1.env.openExternal(vscode_1.Uri.parse("https://www.office.com/")); break; } case "signinAzure": { yield vscode_1.env.openExternal(vscode_1.Uri.parse("https://portal.azure.com/")); break; } } })); }); } exports.cmdHdlLoadTreeView = cmdHdlLoadTreeView; function cmdHdlDisposeTreeView() { commandsTreeViewProvider_1.default.dispose(); } exports.cmdHdlDisposeTreeView = cmdHdlDisposeTreeView; function showError(e) { return __awaiter(this, void 0, void 0, function* () { log_1.default.error(`code:${e.source}.${e.name}, message: ${e.message}, stack: ${e.stack}`); const errorCode = `${e.source}.${e.name}`; if (teamsfx_core_1.isUserCancelError(e)) { return; } else if ("helpLink" in e && e.helpLink && typeof e.helpLink != "undefined") { const help = { title: StringResources.vsc.handlers.getHelp, run: () => __awaiter(this, void 0, void 0, function* () { vscode_1.commands.executeCommand("vscode.open", vscode_1.Uri.parse(`${e.helpLink}#${e.source}${e.name}`)); }), }; const button = yield vscode_1.window.showErrorMessage(`[${errorCode}]: ${e.message}`, help); if (button) yield button.run(); } else if ("issueLink" in e && e.issueLink && typeof e.issueLink != "undefined") { const path = e.issueLink.replace(/\/$/, "") + "?"; const param = `title=new+bug+report: ${errorCode}&body=${e.message}\n\n${e.stack}`; const issue = { title: StringResources.vsc.handlers.reportIssue, run: () => __awaiter(this, void 0, void 0, function* () { vscode_1.commands.executeCommand("vscode.open", vscode_1.Uri.parse(`${path}${param}`)); }), }; const button = yield vscode_1.window.showErrorMessage(`[${errorCode}]: ${e.message}`, issue); if (button) yield button.run(); } else { yield vscode_1.window.showErrorMessage(`[${errorCode}]: ${e.message}`); } }); } exports.showError = showError; function cmpAccountsHandler() { return __awaiter(this, void 0, void 0, function* () { const signInAzureOption = { id: "signInAzure", label: "Sign in to Azure", function: () => signInAzure(), }; const signOutAzureOption = { id: "signOutAzure", label: "Sign out of Azure: ", function: () => signOutAzure(false), }; const signInM365Option = { id: "signinM365", label: "Sign in to M365", function: () => signInM365(), }; const signOutM365Option = { id: "signOutM365", label: "Sign out of M365: ", function: () => signOutM365(false), }; //TODO: hide subscription list until core or api expose the get subscription list API // let selectSubscriptionOption: VscQuickPickItem = { // id: "selectSubscription", // label: "Specify an Azure Subscription", // function: () => selectSubscription(), // detail: "4 subscriptions discovered" // }; const quickPick = vscode_1.window.createQuickPick(); const quickItemOptionArray = []; const m365Account = yield appStudioLogin_1.default.getStatus(); if (m365Account.status === "SignedIn") { const accountInfo = m365Account.accountInfo; const email = accountInfo.upn ? accountInfo.upn : undefined; if (email !== undefined) { signOutM365Option.label = signOutM365Option.label.concat(email); } quickItemOptionArray.push(signOutM365Option); } else { quickItemOptionArray.push(signInM365Option); } const azureAccount = yield azureLogin_1.default.getStatus(); if (azureAccount.status === "SignedIn") { const accountInfo = azureAccount.accountInfo; const email = accountInfo.upn ? accountInfo.upn : undefined; if (email !== undefined) { signOutAzureOption.label = signOutAzureOption.label.concat(email); } quickItemOptionArray.push(signOutAzureOption); //quickItemOptionArray.push(selectSubscriptionOption); } else { quickItemOptionArray.push(signInAzureOption); } quickPick.items = quickItemOptionArray; quickPick.onDidChangeSelection((selection) => { if (selection[0]) { selection[0].function().catch(console.error); } }); quickPick.onDidHide(() => quickPick.dispose()); quickPick.show(); }); } exports.cmpAccountsHandler = cmpAccountsHandler; function signOutAzure(isFromTreeView) { return __awaiter(this, void 0, void 0, function* () { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.SignOutStart, { [extTelemetryEvents_1.TelemetryProperty.TriggerFrom]: isFromTreeView ? extTelemetryEvents_1.TelemetryTiggerFrom.TreeView : extTelemetryEvents_1.TelemetryTiggerFrom.CommandPalette, [extTelemetryEvents_1.TelemetryProperty.AccountType]: extTelemetryEvents_1.AccountType.Azure, }); const result = yield azureLogin_1.default.signout(); if (result) { yield commandsTreeViewProvider_1.default.getTreeView("teamsfx-accounts").refresh([ { commandId: "fx-extension.signinAzure", label: StringResources.vsc.handlers.signInAzure, contextValue: "signinAzure", }, ]); yield commandsTreeViewProvider_1.default.getTreeView("teamsfx-accounts").remove([ { commandId: "fx-extension.selectSubscription", label: "", parent: "fx-extension.signinAzure", }, ]); } }); } exports.signOutAzure = signOutAzure; function signOutM365(isFromTreeView) { return __awaiter(this, void 0, void 0, function* () { extTelemetry_1.ExtTelemetry.sendTelemetryEvent(extTelemetryEvents_1.TelemetryEvent.SignOutStart, { [extTelemetryEvents_1.TelemetryProperty.TriggerFrom]: isFromTreeView ? extTelemetryEvents_1.TelemetryTiggerFrom.TreeView : extTelemetryEvents_1.TelemetryTiggerFrom.CommandPalette, [extTelemetryEvents_1.TelemetryProperty.AccountType]: extTelemetryEvents_1.AccountType.M365, }); let appstudioLogin = appStudioLogin_1.default; const vscodeEnv = detectVsCodeEnv(); if (vscodeEnv === teamsfx_api_1.VsCodeEnv.codespaceBrowser || vscodeEnv === teamsfx_api_1.VsCodeEnv.codespaceVsCode) { appstudioLogin = appStudioCodeSpaceLogin_1.default; } const result = yield appstudioLogin.signout(); if (result) { yield commandsTreeViewProvider_1.default.getTreeView("teamsfx-accounts").refresh([ { commandId: "fx-extension.signinM365", label: StringResources.vsc.handlers.signIn365, contextValue: "signinM365", }, ]); } }); } exports.signOutM365 = signOutM365; function signInAzure() { return __awaiter(this, void 0, void 0, function* () { vscode.commands.executeCommand("fx-extension.signinAzure"); }); } exports.signInAzure = signInAzure; function signInM365() { return __awaiter(this, void 0, void 0, function* () { vscode.commands.executeCommand("fx-extension.signinM365"); }); } exports.signInM365 = signInM365; function selectSubscription() { return __awaiter(this, void 0, void 0, function* () { vscode.commands.executeCommand("fx-extension.specifySubscription"); }); } exports.selectSubscription = selectSubscription; //# sourceMappingURL=handlers.js.map