generated from template/slidev-template
171 lines
4.6 KiB
TypeScript
171 lines
4.6 KiB
TypeScript
import os from "node:os";
|
||
import fs from "node:fs";
|
||
import path from "node:path";
|
||
import https from "node:https";
|
||
import { pipeline } from "node:stream/promises";
|
||
import { createWriteStream, createReadStream } from "node:fs";
|
||
import { createGunzip } from "node:zlib";
|
||
import { extract } from "tar";
|
||
|
||
const base = "https://api.github.com/repos/pocketbase/pocketbase/releases/latest";
|
||
const proxy = 'https://gh-proxy.org/';
|
||
const program = 'program';
|
||
const directory = program + '/' + 'pocketbase';
|
||
|
||
// 获取系统平台和架构
|
||
function getPlatformInfo() {
|
||
const platform = os.platform(); // 'darwin', 'linux', 'win32'
|
||
const arch = os.arch(); // 'x64', 'arm64', etc.
|
||
|
||
let platformName = '';
|
||
let archName = '';
|
||
|
||
// 映射平台名称
|
||
switch (platform) {
|
||
case 'darwin':
|
||
platformName = 'darwin';
|
||
break;
|
||
case 'linux':
|
||
platformName = 'linux';
|
||
break;
|
||
case 'win32':
|
||
platformName = 'windows';
|
||
break;
|
||
default:
|
||
throw new Error(`Unsupported platform: ${platform}`);
|
||
}
|
||
|
||
// 映射架构名称
|
||
switch (arch) {
|
||
case 'x64':
|
||
archName = 'amd64';
|
||
break;
|
||
case 'arm64':
|
||
archName = 'arm64';
|
||
break;
|
||
default:
|
||
throw new Error(`Unsupported architecture: ${arch}`);
|
||
}
|
||
|
||
return { platformName, archName };
|
||
}
|
||
|
||
// 下载文件
|
||
async function downloadFile(url: string, destPath: string): Promise<void> {
|
||
return new Promise((resolve, reject) => {
|
||
https.get(url, (response) => {
|
||
// 处理重定向
|
||
if (response.statusCode === 302 || response.statusCode === 301) {
|
||
const redirectUrl = response.headers.location;
|
||
if (redirectUrl) {
|
||
downloadFile(redirectUrl, destPath).then(resolve).catch(reject);
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (response.statusCode !== 200) {
|
||
reject(new Error(`Failed to download: ${response.statusCode}`));
|
||
return;
|
||
}
|
||
|
||
const fileStream = createWriteStream(destPath);
|
||
response.pipe(fileStream);
|
||
|
||
fileStream.on('finish', () => {
|
||
fileStream.close();
|
||
resolve();
|
||
});
|
||
|
||
fileStream.on('error', reject);
|
||
}).on('error', reject);
|
||
});
|
||
}
|
||
|
||
// 解压 zip 文件 (Windows)
|
||
async function extractZip(zipPath: string, destDir: string): Promise<void> {
|
||
const AdmZip = require('adm-zip');
|
||
const zip = new AdmZip(zipPath);
|
||
zip.extractAllTo(destDir, true);
|
||
}
|
||
|
||
// 提取 tar.gz 文件 (Linux/macOS)
|
||
export async function extractTarGz(tarGzPath: string, destDir: string): Promise<void> {
|
||
await fs.promises.mkdir(destDir, { recursive: true });
|
||
|
||
await pipeline(
|
||
createReadStream(tarGzPath),
|
||
createGunzip(),
|
||
extract({ cwd: destDir })
|
||
);
|
||
}
|
||
|
||
// 主函数:下载并解压 PocketBase
|
||
export async function download(): Promise<void> {
|
||
try {
|
||
const { platformName, archName } = getPlatformInfo();
|
||
|
||
console.log(`检测到系统: ${platformName} ${archName}`);
|
||
|
||
// 获取最新版本信息
|
||
const response = await fetch(base);
|
||
if (!response.ok) {
|
||
throw new Error(`Failed to fetch release info: ${response.status}`);
|
||
}
|
||
|
||
const releaseData = await response.json();
|
||
const tagName = releaseData.tag_name.replace(/^v/, '');
|
||
const assets = releaseData.assets;
|
||
|
||
// 查找匹配的资源文件
|
||
const fileExtension = '.zip';
|
||
const assetPattern = `pocketbase_${tagName}_${platformName}_${archName}${fileExtension}`;
|
||
|
||
const asset = assets.find((a: any) => a.name.includes(assetPattern));
|
||
|
||
if (!asset) {
|
||
throw new Error(`No matching asset found for ${platformName} ${archName}`);
|
||
}
|
||
|
||
console.log(`找到资源: ${asset.name}`);
|
||
console.log(`下载链接: ${asset.browser_download_url}`);
|
||
|
||
// 创建目录
|
||
await fs.promises.mkdir(directory, { recursive: true });
|
||
|
||
const downloadPath = path.join(directory, asset.name);
|
||
|
||
// 下载文件
|
||
console.log('开始下载...');
|
||
await downloadFile(asset.browser_download_url, downloadPath);
|
||
console.log('下载完成');
|
||
|
||
// 解压文件
|
||
console.log('开始解压...');
|
||
await extractZip(downloadPath, directory);
|
||
|
||
console.log('解压完成');
|
||
|
||
// 给可执行文件添加执行权限(非 Windows)
|
||
if (os.platform() !== 'win32') {
|
||
const finalPath = path.join(directory, 'pocketbase');
|
||
fs.chmodSync(finalPath, 0o755);
|
||
console.log('已添加执行权限');
|
||
}
|
||
|
||
// 删除压缩包
|
||
await fs.promises.unlink(downloadPath);
|
||
console.log('清理完成');
|
||
|
||
console.log(`PocketBase 已安装到: ${path.resolve(directory)}`);
|
||
} catch (error) {
|
||
console.error('下载或解压失败:', error);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
// 如果直接运行此文件
|
||
if (require.main === module) {
|
||
download();
|
||
}
|
||
|