UNPKG

flyde-vscode

Version:

Flyde is an open-source, visual programming language. It runs in the IDE, integrates with existing TypeScript code, both browser and Node.js.

230 lines (184 loc) 6.91 kB
// The module 'vscode' contains the VS Code extensibility API // Import the module and reference it with the alias vscode in your code below import * as vscode from "vscode"; import { FlydeEditorEditorProvider } from "./flydeEditor"; import * as execa from "execa"; var fp = require("find-free-port"); import { initFlydeDevServer } from "@flyde/dev-server/dist/lib"; import { join } from "path"; import TelemetryReporter from "@vscode/extension-telemetry"; import { activateReporter, reportEvent } from "./telemetry"; import { Template, getTemplates, scaffoldTemplate } from "./templateUtils"; // the application insights key (also known as instrumentation key) // telemetry reporter let reporter: TelemetryReporter; // this method is called when your extension is activated // your extension is activated the very first time the command is executed let server: any; let process: execa.ExecaChildProcess; const FLYDE_DEFAULT_SERVER_PORT = 8545; export function activate(context: vscode.ExtensionContext) { // eslint-disable-next-line @typescript-eslint/naming-convention const { Uri } = vscode; const { fs } = vscode.workspace; const firstWorkspace = vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders[0]; const fileRoot = firstWorkspace ? firstWorkspace.uri.fsPath : ""; // ensure it gets properly disposed. Upon disposal the events will be flushed context.subscriptions.push(activateReporter()); reportEvent("activate"); const mainOutputChannel = vscode.window.createOutputChannel("Flyde"); const debugOutputChannel = vscode.window.createOutputChannel("Flyde (Debug)"); let currentTheme = vscode.window.activeColorTheme; let useDarkMode = currentTheme.kind !== vscode.ColorThemeKind.Light && currentTheme.kind !== vscode.ColorThemeKind.HighContrastLight; vscode.window.onDidChangeActiveColorTheme((theme) => { useDarkMode = theme.kind !== vscode.ColorThemeKind.Light && theme.kind !== vscode.ColorThemeKind.HighContrastLight; }); fp(FLYDE_DEFAULT_SERVER_PORT).then(([port]: [number]) => { reportEvent("devServerStart"); const editorStaticsRoot = join(__dirname, "../editor-build"); const cleanServer = initFlydeDevServer({ port, root: fileRoot, editorStaticsRoot, }); context.subscriptions.push({ dispose() { cleanServer(); }, }); context.subscriptions.push( FlydeEditorEditorProvider.register(context, { port, mainOutputChannel, debugOutputChannel, darkMode: useDarkMode, }) ); }); const openAsTextHandler = async (uri: vscode.Uri) => { const document = await vscode.workspace.openTextDocument(uri); // Show the document in the text editor await vscode.window.showTextDocument(document); reporter.sendTelemetryEvent("openAsText"); }; context.subscriptions.push( vscode.commands.registerCommand("flyde.openAsText", openAsTextHandler) ); function getWorkspaceRootPath(): vscode.Uri | undefined { // Check if there is an open workspace if ( vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0 ) { // Return the path of the first workspace folder return vscode.workspace.workspaceFolders[0].uri; } } context.subscriptions.push( vscode.commands.registerCommand( "flyde.newVisualFlow", async (dirName: vscode.Uri) => { reportEvent("newVisualFlow:start"); let folderOrFileUri = dirName ?? getWorkspaceRootPath(); // folder will be undefined when triggered by keybinding if (!folderOrFileUri) { vscode.window.showErrorMessage("No folder or file selected"); return; } const folderStat = await fs.stat(folderOrFileUri); const folderUri = folderStat.type === vscode.FileType.Directory ? folderOrFileUri : vscode.Uri.joinPath(folderOrFileUri, ".."); const templates = getTemplates(); const template = await vscode.window.showQuickPick< Template & { label: string } >( templates.map((t) => ({ ...t, label: t.name, description: t.tags.join(", "), detail: t.description, })) ); if (!template) { vscode.window.showWarningMessage("No template selected, aborting"); return; } const fileName = await vscode.window.showInputBox({ title: "Flow file name", value: "NewFlow", }); if (!fileName) { vscode.window.showWarningMessage("No file name passed, aborting"); return; } const targetPath = Uri.joinPath(folderUri, fileName + ".flyde"); if ( (await fs.readFile(targetPath).then( () => true, () => false )) === true ) { vscode.window.showErrorMessage(`File ${targetPath} already exists!`); return; } try { reportEvent("newVisualFlow:before", { template: template.name }); scaffoldTemplate(template, folderUri.fsPath, fileName); vscode.commands.executeCommand( "vscode.openWith", targetPath, "flydeEditor" ); reportEvent("newVisualFlow:success", { template: template.name }); vscode.window.showInformationMessage( `New flow created at ${fileName}.flyde!` ); } catch (error) { vscode.window.showErrorMessage(`Error creating flow: ${error}`); } } ) ); context.subscriptions.push( vscode.commands.registerCommand("flyde.setOpenAiToken", async () => { const token = await vscode.window.showInputBox({ title: "Please enter your OpenAI API key (will be stored in your settings for future use, you can also set it manually or clear it in the settings)", value: "", ignoreFocusOut: true, password: true, }); if (!token) { vscode.window.showWarningMessage("No token passed, aborting"); return; } await vscode.workspace .getConfiguration() .update("flyde.openAiToken", token, vscode.ConfigurationTarget.Global); vscode.window.showInformationMessage("OpenAI API Token set"); }) ); context.subscriptions.push( vscode.commands.registerCommand("flyde.clearOpenAiToken", async () => { await vscode.workspace .getConfiguration() .update("flyde.openAiToken", "", vscode.ConfigurationTarget.Global); vscode.window.showInformationMessage("OpenAI API Token cleared"); }) ); } // this method is called when your extension is deactivated export function deactivate() { if (server) { server.close(); } if (process) { process.kill(); } }