esa-cli
Version:
A CLI for operating Alibaba Cloud ESA Functions and Pages.
183 lines (182 loc) • 6.81 kB
JavaScript
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());
});
};
import { exec } from 'child_process';
import * as fs from 'fs/promises';
import os from 'os';
import * as path from 'path';
import { promisify } from 'util';
import AdmZip from 'adm-zip';
import chalk from 'chalk';
import fetch from 'node-fetch';
import t from '../i18n/index.js';
import logger from '../libs/logger.js';
const execAsync = promisify(exec);
function getBinDir() {
const home = os.homedir();
return path.join(home || '', '.deno', 'bin');
}
/**
* 下载文件
* @param url 远程文件URL
* @param dest 本地保存路径
*/
export function downloadFile(url, dest) {
return __awaiter(this, void 0, void 0, function* () {
const response = yield fetch(url);
if (!response.ok) {
throw new Error(`Error downloading file: ${response.status} ${response.statusText}`);
}
const fileStream = yield fs.open(dest, 'w');
return new Promise((resolve, reject) => {
var _a, _b;
(_a = response.body) === null || _a === void 0 ? void 0 : _a.pipe(fileStream.createWriteStream());
(_b = response.body) === null || _b === void 0 ? void 0 : _b.on('error', (err) => {
fileStream.close();
reject(err);
});
fileStream.createWriteStream().on('finish', () => {
fileStream.close();
resolve();
});
});
});
}
/**
* 解压Zip文件 adm 是同步的
* @param zipPath Zip文件路径
* @param extractPath 解压目标目录
*/
export function unzipFile(zipPath, extractPath) {
const zip = new AdmZip(zipPath);
zip.extractAllTo(extractPath, true);
logger.info(`UnzipFile success: from ${zipPath} to ${extractPath}`);
}
/**
* 获取用户的 PATH 环境变量(win下专用)
* @returns 用户 PATH
*/
function getUserPath() {
return __awaiter(this, void 0, void 0, function* () {
const { stdout } = yield execAsync('reg query "HKCU\\Environment" /v Path');
const match = stdout.match(/Path\s+REG_EXPAND_SZ\s+(.*)/i);
if (match && match[1]) {
return match[1].trim();
}
return '';
});
}
/**
* 检查 BinDir 是否在用户的 PATH 中(win下专用)
* @param binDir BinDir 路径
* @returns 是否包含
*/
function isBinDirInPath(binDir) {
return __awaiter(this, void 0, void 0, function* () {
const userPath = yield getUserPath();
return userPath
.split(';')
.map((p) => p.toLowerCase())
.includes(binDir.toLowerCase());
});
}
/**
* 将 BinDir 添加到用户的 PATH 环境变量(win下专用)
* @param binDir BinDir 路径
*/
function addBinDirToPath(binDir) {
return __awaiter(this, void 0, void 0, function* () {
// Use setx to add to PATH
// setx has a 2047 character limit for PATH
const command = `setx Path "%Path%;${binDir}"`;
try {
yield execAsync(command);
logger.info(`Path add success: ${binDir}`);
}
catch (error) {
throw new Error(`Add BinDir to Path failed: ${error}`);
}
});
}
export function downloadRuntimeAndUnzipForWindows() {
return __awaiter(this, void 0, void 0, function* () {
try {
const BinDir = getBinDir();
const DenoZip = path.join(BinDir, 'deno.zip');
const Target = 'x86_64-pc-windows-msvc';
const DownloadUrl = `http://esa-runtime.myalicdn.com/runtime/deno-${Target}.zip`;
logger.ora.start('Downloading...');
try {
yield fs.mkdir(BinDir, { recursive: true });
}
catch (error) {
const err = error;
logger.ora.fail();
logger.error(`mkdir error ${BinDir}: ${err.message}`);
process.exit(1);
}
try {
yield downloadFile(DownloadUrl, DenoZip);
}
catch (error) {
const err = error;
logger.ora.fail();
logger.error(`${t('deno_download_failed').d('Download failed')}: ${err.message}`);
process.exit(1);
}
logger.info(`Unzip file to: ${BinDir}`);
try {
logger.ora.text = 'Unzip...';
unzipFile(DenoZip, BinDir);
}
catch (error) {
const err = error;
logger.ora.fail();
logger.error(`${t('deno_unzip_failed').d('Unzip failed')}: ${err.message}`);
process.exit(1);
}
try {
logger.ora.text = 'Deleting temp file...';
yield fs.unlink(DenoZip);
logger.ora.succeed('Download success');
logger.info(`Delete temp file: ${DenoZip}`);
}
catch (error) {
logger.warn(`Delete temp file ${DenoZip} failed: ${error}`);
}
try {
logger.ora.text = 'Adding Bin dir to PATH...';
const inPath = yield isBinDirInPath(BinDir);
if (!inPath) {
logger.info(`${BinDir} not in PATH`);
yield addBinDirToPath(BinDir);
}
else {
logger.info(`${BinDir} in PATH already`);
}
}
catch (error) {
const err = error;
logger.ora.fail();
logger.error(`${t('deno_add_path_failed').d('Add BinDir to Path failed')}: ${err.message}`);
process.exit(1);
}
logger.success(t('deno_install_success').d('Runtime install success!'));
logger.block();
const dev = chalk.green('esa-cli dev');
logger.log(t('deno_install_success_tips', { dev }).d(`Please run ${dev} again`));
}
catch (error) {
const err = error;
logger.ora.fail();
logger.error(`Download Error: ${err.message}`);
process.exit(1);
}
});
}