diff --git a/package.json b/package.json index d389c54..ab8555d 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ }, "devDependencies": { "@antfu/eslint-config": "^3.9.2", + "@clack/prompts": "^0.11.0", "@iconify/tools": "^4.0.7", "@nuxt/devtools": "^2.6.2", "@nuxt/image": "^1.8.1", diff --git a/scripts/deploy.js b/scripts/deploy.js index de2eea1..760b48c 100644 --- a/scripts/deploy.js +++ b/scripts/deploy.js @@ -1,7 +1,6 @@ import { execSync } from 'node:child_process' -import fs from 'node:fs' import path from 'node:path' -import readline from 'node:readline' +import * as clack from '@clack/prompts' import SftpClient from 'ssh2-sftp-client' const HOST = '92.53.106.114' @@ -12,73 +11,62 @@ const LOCAL_SRC_ARCHIVE = path.resolve('./src.zip') const DATE = new Date().toISOString().replace(/[-:]/g, '').replace(/\..+/, ''); (async () => { + const spinner = clack.spinner() + try { - const password = await ask(`Введите пароль для ${USERNAME}@${HOST}: `) + clack.intro(`Деплой на ${HOST}`) + + const password = await clack.text({ message: `Введите пароль для пользователя ${USERNAME}` }) // 1) yarn build - execSync('yarn build', { stdio: 'inherit' }) + spinner.start('Собираем проект') + execSync('yarn build --logLevel=silent', { stdio: 'inherit' }) + spinner.stop('Сборка выполнена') // 2) git archive + spinner.start('Делаем архив с исходным кодом') execSync(`git archive --format=zip --output=${LOCAL_SRC_ARCHIVE} main`, { stdio: 'inherit' }) + spinner.stop('Архив с исходным кодом сохранен') const sftp = new SftpClient() + + spinner.start('Подключаемся к серверу') await sftp.connect({ host: HOST, port: 22, username: USERNAME, password, }) + spinner.stop('Подключились к серверу') // 3) Переименование public_html try { + spinner.start('Делаем бэкап public_html') await sftp.rename(`${REMOTE_BASE}/public_html`, `${REMOTE_BASE}/public_html_${DATE}`) - console.log('✅ Папка public_html переименована') + spinner.stop('Папка public_html переименована') } catch { - console.log('⚠️ public_html не найдена, пропускаю переименование') + spinner.stop('public_html не найдена, пропускаю переименование') } // 4) Загрузка dist + spinner.start('Загружаем dist в public_html') await sftp.mkdir(`${REMOTE_BASE}/public_html`, true) - await uploadDir(sftp, LOCAL_DIST, `${REMOTE_BASE}/public_html`) + await sftp.uploadDir(LOCAL_DIST, `${REMOTE_BASE}/public_html`, undefined) + spinner.stop('Статические файлы загружены') // 5) Загрузка src.zip + spinner.start('Загружаем архива с исходным кодом') await sftp.mkdir(`${REMOTE_BASE}/src`, true) await sftp.put(LOCAL_SRC_ARCHIVE, `${REMOTE_BASE}/src.zip`) + spinner.stop('Архив с исходным кодом загружен') await sftp.end() - console.log('🎉 Деплой завершён успешно!') + clack.outro('Деплой завершён успешно!') } catch (err) { - console.error('❌ Ошибка деплоя:', err.message) - process.exit(1) + spinner.stop() + clack.cancel(`Ошибка: ${err.message}`) + process.exit(0) } })() - -function ask(query) { - const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout, - }) - return new Promise((resolve) => { - rl.question(query, (value) => { - rl.close() - resolve(value) - }) - }) -} - -async function uploadDir(sftp, localDir, remoteDir) { - const items = fs.readdirSync(localDir) - for (const item of items) { - const localPath = path.join(localDir, item) - const remotePath = `${remoteDir}/${item}` - if (fs.lstatSync(localPath).isDirectory()) { - await sftp.mkdir(remotePath, true) - await uploadDir(sftp, localPath, remotePath) - } - else { - await sftp.put(localPath, remotePath) - } - } -} diff --git a/yarn.lock b/yarn.lock index 35aff1a..cb53f1a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -452,6 +452,27 @@ __metadata: languageName: node linkType: hard +"@clack/core@npm:0.5.0": + version: 0.5.0 + resolution: "@clack/core@npm:0.5.0" + dependencies: + picocolors: "npm:^1.0.0" + sisteransi: "npm:^1.0.5" + checksum: 10c0/ef55dce4b0a4802171b71fe595865a6452c7cf823d162df7fa9afe2ea5a594b9d97e0b8e2880c2a805f2ce1d2f782cb1637d9f8d2ab8b99010af3a20816fae5a + languageName: node + linkType: hard + +"@clack/prompts@npm:^0.11.0": + version: 0.11.0 + resolution: "@clack/prompts@npm:0.11.0" + dependencies: + "@clack/core": "npm:0.5.0" + picocolors: "npm:^1.0.0" + sisteransi: "npm:^1.0.5" + checksum: 10c0/4c573f2adec3b9109fe861e36312be8ae7cc6e80a5128aa784b9aeafeda5001b23f66c08eca50f4491119b435d9587ec9862956be8c5be472ec3373275003ba8 + languageName: node + linkType: hard + "@clack/prompts@npm:^0.9.1": version: 0.9.1 resolution: "@clack/prompts@npm:0.9.1" @@ -10098,6 +10119,7 @@ __metadata: resolution: "nuxt-app@workspace:." dependencies: "@antfu/eslint-config": "npm:^3.9.2" + "@clack/prompts": "npm:^0.11.0" "@floating-ui/vue": "npm:^1.1.5" "@iconify/tools": "npm:^4.0.7" "@nuxt/devtools": "npm:^2.6.2"