generated from template/slidev-template
update
This commit is contained in:
132
agent/apps/meilisearch.ts
Normal file
132
agent/apps/meilisearch.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
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/meilisearch/meilisearch/releases/latest";
|
||||
const program = 'program';
|
||||
const proxy = 'https://gh-proxy.org/';
|
||||
const directory = program + '/' + 'meilisearch';
|
||||
|
||||
// 获取平台和架构对应的文件名
|
||||
function getPlatformFileName(): string {
|
||||
const platform = os.platform();
|
||||
const arch = os.arch();
|
||||
|
||||
if (platform === 'darwin') {
|
||||
return arch === 'arm64' ? 'meilisearch-macos-apple-silicon' : 'meilisearch-macos-amd64';
|
||||
} else if (platform === 'linux') {
|
||||
return arch === 'arm64' ? 'meilisearch-linux-aarch64' : 'meilisearch-linux-amd64';
|
||||
} else if (platform === 'win32') {
|
||||
return 'meilisearch-windows-amd64.exe';
|
||||
}
|
||||
|
||||
throw new Error(`Unsupported platform: ${platform}-${arch}`);
|
||||
}
|
||||
|
||||
// 下载文件
|
||||
async function downloadFile(url: string, dest: string): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
https.get(url, {
|
||||
headers: {
|
||||
'User-Agent': 'meilisearch-installer'
|
||||
}
|
||||
}, (response) => {
|
||||
if (response.statusCode === 302 || response.statusCode === 301) {
|
||||
// 处理重定向
|
||||
downloadFile(response.headers.location!, dest).then(resolve).catch(reject);
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.statusCode !== 200) {
|
||||
reject(new Error(`Failed to download: ${response.statusCode}`));
|
||||
return;
|
||||
}
|
||||
|
||||
const fileStream = createWriteStream(dest);
|
||||
response.pipe(fileStream);
|
||||
|
||||
fileStream.on('finish', () => {
|
||||
fileStream.close();
|
||||
resolve();
|
||||
});
|
||||
|
||||
fileStream.on('error', reject);
|
||||
}).on('error', reject);
|
||||
});
|
||||
}
|
||||
|
||||
// 主函数
|
||||
export async function download() {
|
||||
try {
|
||||
console.log('正在获取最新版本信息...');
|
||||
|
||||
// 获取 latest release 信息
|
||||
const releaseData = await new Promise<any>((resolve, reject) => {
|
||||
https.get(proxy + base, {
|
||||
headers: {
|
||||
'User-Agent': 'meilisearch-installer'
|
||||
}
|
||||
}, (response) => {
|
||||
let data = '';
|
||||
response.on('data', chunk => data += chunk);
|
||||
response.on('end', () => resolve(JSON.parse(data)));
|
||||
response.on('error', reject);
|
||||
}).on('error', reject);
|
||||
});
|
||||
|
||||
const version = releaseData.tag_name;
|
||||
console.log(`最新版本: ${version}`);
|
||||
|
||||
const fileName = getPlatformFileName();
|
||||
console.log(`平台文件: ${fileName}`);
|
||||
|
||||
// 查找对应的 asset
|
||||
const asset = releaseData.assets.find((a: any) => a.name === fileName);
|
||||
if (!asset) {
|
||||
throw new Error(`找不到对应的文件: ${fileName}`);
|
||||
}
|
||||
|
||||
// 创建目录
|
||||
if (!fs.existsSync(directory)) {
|
||||
fs.mkdirSync(directory, { recursive: true });
|
||||
}
|
||||
|
||||
const downloadPath = path.join(directory, fileName);
|
||||
|
||||
// 下载文件
|
||||
console.log('正在下载...');
|
||||
await downloadFile(asset.browser_download_url, downloadPath);
|
||||
console.log(`下载完成: ${downloadPath}`);
|
||||
|
||||
// 确定最终文件名
|
||||
const finalFileName = os.platform() === 'win32' ? 'meilisearch.exe' : 'meilisearch';
|
||||
const finalPath = path.join(directory, finalFileName);
|
||||
|
||||
// 重命名为统一的可执行文件名
|
||||
if (downloadPath !== finalPath) {
|
||||
fs.renameSync(downloadPath, finalPath);
|
||||
console.log(`重命名为: ${finalFileName}`);
|
||||
}
|
||||
|
||||
// 给可执行文件添加执行权限(非 Windows)
|
||||
if (os.platform() !== 'win32') {
|
||||
fs.chmodSync(finalPath, 0o755);
|
||||
console.log('已添加执行权限');
|
||||
}
|
||||
|
||||
console.log('安装完成!');
|
||||
} catch (error) {
|
||||
console.error('安装失败:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果直接运行此文件
|
||||
if (require.main === module) {
|
||||
download();
|
||||
}
|
||||
151
agent/apps/nocodb.ts
Normal file
151
agent/apps/nocodb.ts
Normal file
@@ -0,0 +1,151 @@
|
||||
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/nocodb/nocodb/releases/latest";
|
||||
const program = 'program';
|
||||
const proxy = 'https://gh-proxy.org/';
|
||||
const directory = program + '/' + 'nocodb';
|
||||
|
||||
// 获取平台和架构对应的文件名
|
||||
function getPlatformFileName(): string {
|
||||
const platform = os.platform();
|
||||
const arch = os.arch();
|
||||
|
||||
if (platform === 'darwin') {
|
||||
return arch === 'arm64' ? 'Noco-macos-arm64' : 'Noco-macos-x64';
|
||||
} else if (platform === 'linux') {
|
||||
return arch === 'arm64' ? 'Noco-linux-arm64' : 'Noco-linux-x64';
|
||||
} else if (platform === 'win32') {
|
||||
return arch === 'arm64' ? 'Noco-win-arm64.exe' : 'Noco-win-x64.exe';
|
||||
}
|
||||
|
||||
throw new Error(`Unsupported platform: ${platform}-${arch}`);
|
||||
}
|
||||
|
||||
// 下载文件
|
||||
async function downloadFile(url: string, dest: string): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
https.get(url, {
|
||||
headers: {
|
||||
'User-Agent': 'nocodb-installer'
|
||||
}
|
||||
}, (response) => {
|
||||
if (response.statusCode === 302 || response.statusCode === 301) {
|
||||
// 处理重定向
|
||||
downloadFile(response.headers.location!, dest).then(resolve).catch(reject);
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.statusCode !== 200) {
|
||||
reject(new Error(`Failed to download: ${response.statusCode}`));
|
||||
return;
|
||||
}
|
||||
|
||||
const fileStream = createWriteStream(dest);
|
||||
response.pipe(fileStream);
|
||||
|
||||
fileStream.on('finish', () => {
|
||||
fileStream.close();
|
||||
resolve();
|
||||
});
|
||||
|
||||
fileStream.on('error', reject);
|
||||
}).on('error', reject);
|
||||
});
|
||||
}
|
||||
|
||||
// 解压 tar.gz 文件
|
||||
async function extractTarGz(filePath: string, destDir: string): Promise<void> {
|
||||
await pipeline(
|
||||
createReadStream(filePath),
|
||||
createGunzip(),
|
||||
extract({ cwd: destDir })
|
||||
);
|
||||
}
|
||||
|
||||
// 主函数
|
||||
export async function download() {
|
||||
try {
|
||||
console.log('正在获取最新版本信息...');
|
||||
|
||||
// 获取 latest release 信息
|
||||
const releaseData = await new Promise<any>((resolve, reject) => {
|
||||
https.get(proxy+base, {
|
||||
headers: {
|
||||
'User-Agent': 'nocodb-installer'
|
||||
}
|
||||
}, (response) => {
|
||||
let data = '';
|
||||
response.on('data', chunk => data += chunk);
|
||||
response.on('end', () => resolve(JSON.parse(data)));
|
||||
response.on('error', reject);
|
||||
}).on('error', reject);
|
||||
});
|
||||
|
||||
const version = releaseData.tag_name;
|
||||
console.log(`最新版本: ${version}`);
|
||||
|
||||
const fileName = getPlatformFileName();
|
||||
console.log(`平台文件: ${fileName}`);
|
||||
|
||||
// 查找对应的 asset
|
||||
const asset = releaseData.assets.find((a: any) => a.name === fileName);
|
||||
if (!asset) {
|
||||
throw new Error(`找不到对应的文件: ${fileName}`);
|
||||
}
|
||||
|
||||
// 创建目录
|
||||
if (!fs.existsSync(directory)) {
|
||||
fs.mkdirSync(directory, { recursive: true });
|
||||
}
|
||||
|
||||
const downloadPath = path.join(directory, fileName);
|
||||
|
||||
// 下载文件
|
||||
console.log('正在下载...');
|
||||
await downloadFile(asset.browser_download_url, downloadPath);
|
||||
console.log(`下载完成: ${downloadPath}`);
|
||||
|
||||
// 确定最终文件名
|
||||
const finalFileName = os.platform() === 'win32' ? 'nocodb.exe' : 'nocodb';
|
||||
const finalPath = path.join(directory, finalFileName);
|
||||
|
||||
// 如果是 tar.gz 文件,进行解压
|
||||
if (fileName === 'nocodb.tar.gz') {
|
||||
console.log('正在解压...');
|
||||
await extractTarGz(downloadPath, directory);
|
||||
console.log('解压完成');
|
||||
|
||||
// 删除压缩包
|
||||
fs.unlinkSync(downloadPath);
|
||||
} else {
|
||||
// 重命名为统一的可执行文件名
|
||||
if (downloadPath !== finalPath) {
|
||||
fs.renameSync(downloadPath, finalPath);
|
||||
console.log(`重命名为: ${finalFileName}`);
|
||||
}
|
||||
|
||||
// 给可执行文件添加执行权限(非 Windows)
|
||||
if (os.platform() !== 'win32') {
|
||||
fs.chmodSync(finalPath, 0o755);
|
||||
console.log('已添加执行权限');
|
||||
}
|
||||
}
|
||||
|
||||
console.log('安装完成!');
|
||||
} catch (error) {
|
||||
console.error('安装失败:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果直接运行此文件
|
||||
if (require.main === module) {
|
||||
download();
|
||||
}
|
||||
170
agent/apps/pocketbase.ts
Normal file
170
agent/apps/pocketbase.ts
Normal file
@@ -0,0 +1,170 @@
|
||||
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();
|
||||
}
|
||||
|
||||
36
agent/main.ts
Normal file
36
agent/main.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
// import { downloadAndExtractPocketBase } from './apps/pocketbase';
|
||||
|
||||
// // 下载并解压 PocketBase
|
||||
// downloadAndExtractPocketBase()
|
||||
// .then(() => {
|
||||
// console.log('✅ PocketBase 安装成功');
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// console.error('❌ 安装失败:', error);
|
||||
// process.exit(1);
|
||||
// });
|
||||
|
||||
// import { download } from './apps/nocodb';
|
||||
|
||||
// // 下载 NocoDB
|
||||
// download()
|
||||
// .then(() => {
|
||||
// console.log('✅ NocoDB 安装成功');
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// console.error('❌ 安装失败:', error);
|
||||
// process.exit(1);
|
||||
// });
|
||||
|
||||
|
||||
import { download } from "./apps/meilisearch";
|
||||
|
||||
// 下载 MeiliSearch
|
||||
download()
|
||||
.then(() => {
|
||||
console.log('✅ MeiliSearch 安装成功');
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('❌ 安装失败:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user