From 65472cdb9877420441bba65a1b3f73d659353759 Mon Sep 17 00:00:00 2001 From: jb Date: Tue, 14 Apr 2026 18:23:36 -0300 Subject: [PATCH] feat(ide): ide configs for vs code in vitruvio update-ide --- bin/vitruvio.js | 2 + src/commands/update-ide.js | 191 +++++++++++++++++++++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 src/commands/update-ide.js diff --git a/bin/vitruvio.js b/bin/vitruvio.js index 9bbc2bf..b6c8709 100755 --- a/bin/vitruvio.js +++ b/bin/vitruvio.js @@ -8,6 +8,7 @@ var initCmd = require('../src/commands/init'); var updateRepoCmd = require('../src/commands/update-repo'); var updateBaseCmd = require('../src/commands/update-base'); var docsCmd = require('../src/commands/docs'); +var updateIdeCmd = require('../src/commands/update-ide'); var program = new Command(); @@ -20,5 +21,6 @@ initCmd.register(program); updateRepoCmd.register(program); updateBaseCmd.register(program); docsCmd.register(program); +updateIdeCmd.register(program); program.parse(process.argv); diff --git a/src/commands/update-ide.js b/src/commands/update-ide.js new file mode 100644 index 0000000..8719a50 --- /dev/null +++ b/src/commands/update-ide.js @@ -0,0 +1,191 @@ +'use strict'; + +var path = require('path'); +var fs = require('fs'); +var os = require('os'); +var readline = require('readline'); +var fse = require('fs-extra'); +var { execSync } = require('child_process'); +var { cloneWithFallback, cleanupTemp } = require('../utils/git'); + +var SSH_URL = 'ssh://git@git.davinti.com.br:2222/davinTI/ide-config.git'; +var HTTPS_URL = 'https://git.davinti.com.br/davinTI/ide-config.git'; + +var SUPPORTED_IDES = ['vscode']; + +/** + * Returns the VSCode User snippets directory for the current OS. + * Linux/macOS: ~/.config/Code/User/snippets/ + * Windows: %APPDATA%\Code\User\snippets\ + */ +function getSnippetsDir() { + if (process.platform === 'win32') { + var appData = process.env.APPDATA; + if (!appData) { + throw new Error('APPDATA environment variable is not set.'); + } + return path.join(appData, 'Code', 'User', 'snippets'); + } + return path.join(os.homedir(), '.config', 'Code', 'User', 'snippets'); +} + +/** + * Returns the `code` CLI binary name for the current OS. + * Windows ships it as `code.cmd` on PATH. + */ +function getCodeBin() { + return process.platform === 'win32' ? 'code.cmd' : 'code'; +} + +/** + * Checks whether a VSCode extension is currently installed. + * Returns true/false. Fails silently (returns false) if `code` is unavailable. + */ +function isExtensionInstalled(extensionId) { + try { + var codeBin = getCodeBin(); + var output = execSync(codeBin + ' --list-extensions', { stdio: 'pipe' }).toString(); + return output.split('\n').some(function (line) { + return line.trim().toLowerCase() === extensionId.toLowerCase(); + }); + } catch (_) { + return false; + } +} + +/** + * Installs a .vsix file using the `code` CLI. + * Always passes --force so it also updates an already-installed extension. + */ +function installVsix(vsixPath) { + var codeBin = getCodeBin(); + execSync(codeBin + ' --install-extension "' + vsixPath + '" --force', { stdio: 'inherit' }); +} + +/** + * Prompts the user to pick an IDE from a numbered list. + * Resolves with the chosen IDE string. + */ +function promptIde() { + return new Promise(function (resolve) { + var rl = readline.createInterface({ input: process.stdin, output: process.stdout }); + + console.log(''); + console.log('IDEs disponíveis:'); + SUPPORTED_IDES.forEach(function (ide, i) { + console.log(' ' + (i + 1) + '. ' + ide); + }); + console.log(''); + + rl.question('Escolha a IDE [1]: ', function (answer) { + rl.close(); + var trimmed = answer.trim(); + var index; + if (trimmed === '' || trimmed === '1') { + index = 0; + } else { + index = parseInt(trimmed, 10) - 1; + } + if (isNaN(index) || index < 0 || index >= SUPPORTED_IDES.length) { + console.error('Opção inválida: ' + trimmed); + process.exit(1); + } + resolve(SUPPORTED_IDES[index]); + }); + }); +} + +function register(program) { + program + .command('update-ide') + .description('Instala ou atualiza a extensão Vitruvio e os snippets na IDE escolhida') + .action(function () { + promptIde().then(function (ide) { + console.log('IDE selecionada: ' + ide); + console.log('Buscando repositório ide-config...'); + + var tmpDir = null; + try { + tmpDir = cloneWithFallback(SSH_URL, HTTPS_URL); + } catch (e) { + console.error('Erro: não foi possível clonar o repositório ide-config.'); + console.error(e.message); + process.exit(1); + } + + try { + var ideDir = path.join(tmpDir, ide); // e.g. /vscode + + if (!fs.existsSync(ideDir)) { + console.error('Erro: diretório "' + ide + '" não encontrado no repositório ide-config.'); + process.exit(1); + } + + // ── Extension ───────────────────────────────────────────────────── + var vsixFiles = fs.readdirSync(ideDir).filter(function (f) { + return f.endsWith('.vsix'); + }); + + if (vsixFiles.length === 0) { + console.log('Aviso: nenhum arquivo .vsix encontrado em ' + ideDir + '. Pulando extensão.'); + } else { + var vsixFile = vsixFiles[0]; + var vsixPath = path.join(ideDir, vsixFile); + + // Derive extension ID from the vsix filename (publisher.name.vsix → publisher.name) + var extId = vsixFile.replace(/\.vsix$/i, ''); + var alreadyInstalled = isExtensionInstalled(extId); + + if (alreadyInstalled) { + console.log('Extensão já instalada, atualizando ' + extId + '...'); + } else { + console.log('Instalando extensão ' + extId + '...'); + } + + try { + installVsix(vsixPath); + console.log('Extensão instalada com sucesso.'); + } catch (e) { + console.error('Erro ao instalar a extensão: ' + e.message); + console.error('Certifique-se de que o comando "code" está disponível no PATH.'); + process.exit(1); + } + } + + // ── Snippets ─────────────────────────────────────────────────────── + var snippetFiles = fs.readdirSync(ideDir).filter(function (f) { + return f.endsWith('.code-snippets'); + }); + + if (snippetFiles.length === 0) { + console.log('Aviso: nenhum arquivo .code-snippets encontrado em ' + ideDir + '. Pulando snippets.'); + } else { + var snippetsDir; + try { + snippetsDir = getSnippetsDir(); + } catch (e) { + console.error('Erro ao determinar diretório de snippets: ' + e.message); + process.exit(1); + } + + fse.ensureDirSync(snippetsDir); + + snippetFiles.forEach(function (snippetFile) { + var src = path.join(ideDir, snippetFile); + var dest = path.join(snippetsDir, snippetFile); + var action = fs.existsSync(dest) ? 'atualizado' : 'instalado'; + fse.copySync(src, dest); + console.log('Snippet ' + snippetFile + ' ' + action + ' em ' + dest); + }); + } + + console.log(''); + console.log('Configuração da IDE concluída.'); + } finally { + cleanupTemp(tmpDir); + } + }); + }); +} + +module.exports = { register: register };