temp
This commit is contained in:
parent
ce9b43b497
commit
0ee7d9a69a
585
pnpm-lock.yaml
generated
585
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
88
src/command/app/front-app/index.ts
Normal file
88
src/command/app/front-app/index.ts
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/**
|
||||||
|
* 下载 app serve client的包的命令
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { chalk } from '@/module/chalk.ts';
|
||||||
|
import { program, Command } from '../../../program.ts';
|
||||||
|
import { queryApp } from '../../../query/app-manager/query-app.ts';
|
||||||
|
import { installApp, uninstallApp } from '@/module/download/install.ts';
|
||||||
|
export const appCommand = new Command('app').description('app 命令').action(() => {
|
||||||
|
console.log('app');
|
||||||
|
});
|
||||||
|
|
||||||
|
program.addCommand(appCommand);
|
||||||
|
|
||||||
|
const downloadAppCommand = new Command('download')
|
||||||
|
.description('下载 app serve client的包')
|
||||||
|
.option('-i, --id <id>', '下载 app serve client的包, id 或者user/key')
|
||||||
|
.option('-o, --output <output>', '下载 app serve client的包, 输出路径')
|
||||||
|
.action(async (options) => {
|
||||||
|
const id = options.id || '';
|
||||||
|
if (!id) {
|
||||||
|
console.error(chalk.red('id is required'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const [user, key] = id.split('/');
|
||||||
|
const data: any = {};
|
||||||
|
if (user && key) {
|
||||||
|
data.user = user;
|
||||||
|
data.key = key;
|
||||||
|
} else {
|
||||||
|
data.id = id;
|
||||||
|
}
|
||||||
|
const res = await queryApp(data);
|
||||||
|
if (res.code === 200) {
|
||||||
|
const app = res.data;
|
||||||
|
const result = await installApp(app, {
|
||||||
|
appDir: '',
|
||||||
|
// kevisualUrl: 'https://kevisual.cn',
|
||||||
|
kevisualUrl: 'https://kevisual.xiongxiao.me',
|
||||||
|
});
|
||||||
|
if (result.code === 200) {
|
||||||
|
console.log(chalk.green('下载成功', res.data?.user, res.data?.key));
|
||||||
|
} else {
|
||||||
|
console.error(chalk.red(result.message || '下载失败'));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error(chalk.red(res.message || '下载失败'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const uninstallAppCommand = new Command('uninstall')
|
||||||
|
.alias('remove')
|
||||||
|
.description('卸载 app serve client的包')
|
||||||
|
.option('-i, --id <id>', 'user/key')
|
||||||
|
.action(async (options) => {
|
||||||
|
const id = options.id || '';
|
||||||
|
if (!id) {
|
||||||
|
console.error(chalk.red('id is required'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const [user, key] = id.split('/');
|
||||||
|
const data: any = {};
|
||||||
|
if (user && key) {
|
||||||
|
data.user = user;
|
||||||
|
data.key = key;
|
||||||
|
} else {
|
||||||
|
console.error(chalk.red('id is required'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await uninstallApp(
|
||||||
|
{
|
||||||
|
user,
|
||||||
|
key,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
appDir: '',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (result.code === 200) {
|
||||||
|
console.log(chalk.green('卸载成功', user, key));
|
||||||
|
} else {
|
||||||
|
console.error(chalk.red(result.message || '卸载失败'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
appCommand.addCommand(downloadAppCommand);
|
||||||
|
appCommand.addCommand(uninstallAppCommand);
|
@ -1,88 +1,2 @@
|
|||||||
/**
|
import './micro-app/index.ts';
|
||||||
* 下载 app serve client的包的命令
|
import './front-app/index.ts';
|
||||||
*/
|
|
||||||
|
|
||||||
import { chalk } from '@/module/chalk.ts';
|
|
||||||
import { program, Command } from '../../program.ts';
|
|
||||||
import { queryApp } from '../../query/app-manager/query-app.ts';
|
|
||||||
import { installApp, uninstallApp } from '@/module/download/install.ts';
|
|
||||||
export const appCommand = new Command('app').description('app 命令').action(() => {
|
|
||||||
console.log('app');
|
|
||||||
});
|
|
||||||
|
|
||||||
program.addCommand(appCommand);
|
|
||||||
|
|
||||||
const downloadAppCommand = new Command('download')
|
|
||||||
.description('下载 app serve client的包')
|
|
||||||
.option('-i, --id <id>', '下载 app serve client的包, id 或者user/key')
|
|
||||||
.option('-o, --output <output>', '下载 app serve client的包, 输出路径')
|
|
||||||
.action(async (options) => {
|
|
||||||
const id = options.id || '';
|
|
||||||
if (!id) {
|
|
||||||
console.error(chalk.red('id is required'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const [user, key] = id.split('/');
|
|
||||||
const data: any = {};
|
|
||||||
if (user && key) {
|
|
||||||
data.user = user;
|
|
||||||
data.key = key;
|
|
||||||
} else {
|
|
||||||
data.id = id;
|
|
||||||
}
|
|
||||||
const res = await queryApp(data);
|
|
||||||
if (res.code === 200) {
|
|
||||||
const app = res.data;
|
|
||||||
const result = await installApp(app, {
|
|
||||||
appDir: '',
|
|
||||||
// kevisualUrl: 'https://kevisual.cn',
|
|
||||||
kevisualUrl: 'https://kevisual.xiongxiao.me',
|
|
||||||
});
|
|
||||||
if (result.code === 200) {
|
|
||||||
console.log(chalk.green('下载成功', res.data?.user, res.data?.key));
|
|
||||||
} else {
|
|
||||||
console.error(chalk.red(result.message || '下载失败'));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.error(chalk.red(res.message || '下载失败'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const uninstallAppCommand = new Command('uninstall')
|
|
||||||
.alias('remove')
|
|
||||||
.description('卸载 app serve client的包')
|
|
||||||
.option('-i, --id <id>', 'user/key')
|
|
||||||
.action(async (options) => {
|
|
||||||
const id = options.id || '';
|
|
||||||
if (!id) {
|
|
||||||
console.error(chalk.red('id is required'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const [user, key] = id.split('/');
|
|
||||||
const data: any = {};
|
|
||||||
if (user && key) {
|
|
||||||
data.user = user;
|
|
||||||
data.key = key;
|
|
||||||
} else {
|
|
||||||
console.error(chalk.red('id is required'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await uninstallApp(
|
|
||||||
{
|
|
||||||
user,
|
|
||||||
key,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
appDir: '',
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if (result.code === 200) {
|
|
||||||
console.log(chalk.green('卸载成功', user, key));
|
|
||||||
} else {
|
|
||||||
console.error(chalk.red(result.message || '卸载失败'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
appCommand.addCommand(downloadAppCommand);
|
|
||||||
appCommand.addCommand(uninstallAppCommand);
|
|
||||||
|
101
src/command/app/micro-app/index.ts
Normal file
101
src/command/app/micro-app/index.ts
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/**
|
||||||
|
* 下载 app serve client的包的命令
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { chalk } from '@/module/chalk.ts';
|
||||||
|
import { program, Command } from '../../../program.ts';
|
||||||
|
import fs from 'fs';
|
||||||
|
import { Readable } from 'stream';
|
||||||
|
import * as tar from 'tar';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
// Utility function to convert a web ReadableStream to a Node.js Readable stream
|
||||||
|
function nodeReadableStreamFromWeb(webStream: ReadableStream<Uint8Array>) {
|
||||||
|
const reader = webStream.getReader();
|
||||||
|
return new Readable({
|
||||||
|
async read() {
|
||||||
|
const { done, value } = await reader.read();
|
||||||
|
if (done) {
|
||||||
|
this.push(null);
|
||||||
|
} else {
|
||||||
|
this.push(Buffer.from(value));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const appCommand = new Command('micro-app').description('micro-app 命令').action(() => {
|
||||||
|
console.log('micro-app');
|
||||||
|
});
|
||||||
|
|
||||||
|
program.addCommand(appCommand);
|
||||||
|
|
||||||
|
// https://kevisual.xiongxiao.me/api/micro-app/download/file?notNeedToken=y&title=mark-0.0.2.tgz
|
||||||
|
const downloadAppCommand = new Command('download')
|
||||||
|
.description('下载 app serve client的包')
|
||||||
|
.option('-i, --id <id>', '下载 app serve client的包, id 或者title, mark-0.0.2.tgz')
|
||||||
|
.option('-o, --output <output>', '下载 app serve client的包, 输出路径')
|
||||||
|
.option('-x, --extract <extract>', '下载 app serve client的包, 解压, 默认解压到当前目录')
|
||||||
|
.action(async (options) => {
|
||||||
|
const id = options.id || '';
|
||||||
|
if (!id) {
|
||||||
|
console.error(chalk.red('id is required'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let title = '';
|
||||||
|
if (id.includes('.tgz')) {
|
||||||
|
title = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
let curlUrl = `https://kevisual.xiongxiao.me/api/micro-app/download/${id}?notNeedToken=y`;
|
||||||
|
if (title) {
|
||||||
|
curlUrl = `https://kevisual.xiongxiao.me/api/micro-app/download/file?notNeedToken=y&title=${title}`;
|
||||||
|
}
|
||||||
|
console.log('download url', curlUrl);
|
||||||
|
fetch(curlUrl)
|
||||||
|
.then((res) => {
|
||||||
|
const contentDisposition = res.headers.get('content-disposition');
|
||||||
|
let filename = 'downloaded-file.tgz'; // Default filename
|
||||||
|
|
||||||
|
if (contentDisposition) {
|
||||||
|
const match = contentDisposition.match(/filename="?(.+)"?/);
|
||||||
|
if (match && match[1]) {
|
||||||
|
filename = match[1].replace(/^"|"$/g, '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log('filename', filename, contentDisposition);
|
||||||
|
const outputPath = options.output || filename;
|
||||||
|
const fileStream = fs.createWriteStream(outputPath);
|
||||||
|
|
||||||
|
if (res.body) {
|
||||||
|
nodeReadableStreamFromWeb(res.body).pipe(fileStream);
|
||||||
|
|
||||||
|
fileStream.on('finish', async () => {
|
||||||
|
console.log(chalk.green(`下载成功: ${outputPath}`));
|
||||||
|
if (options.extract) {
|
||||||
|
console.log(chalk.green(`解压: ${outputPath}`));
|
||||||
|
const extractPath = path.join(process.cwd(), options.extract || '.');
|
||||||
|
console.log('extractPath', extractPath);
|
||||||
|
// const res = await tar.extract({
|
||||||
|
// file: outputPath,
|
||||||
|
// cwd: extractPath,
|
||||||
|
// });
|
||||||
|
// console.log('res', res);
|
||||||
|
// untar.extract({ file: outputPath, cwd: extractPath });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
fileStream.on('error', (err) => {
|
||||||
|
console.error(chalk.red('文件写入错误:', err));
|
||||||
|
fileStream.close(); // Ensure the stream is closed on error
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error(chalk.red('下载失败: 无法获取文件流'));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(chalk.red('下载请求失败:', err));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
appCommand.addCommand(downloadAppCommand);
|
@ -16,10 +16,11 @@ const command = new Command('deploy')
|
|||||||
.option('-v, --version <version>', 'verbose')
|
.option('-v, --version <version>', 'verbose')
|
||||||
.option('-k, --key <key>', 'key')
|
.option('-k, --key <key>', 'key')
|
||||||
.option('-y, --yes <yes>', 'yes')
|
.option('-y, --yes <yes>', 'yes')
|
||||||
|
.option('-o, --org <org>', 'org')
|
||||||
.option('-u, --update', 'load current app. set current version in product')
|
.option('-u, --update', 'load current app. set current version in product')
|
||||||
.action(async (filePath, options) => {
|
.action(async (filePath, options) => {
|
||||||
try {
|
try {
|
||||||
let { version, key, yes, update } = options;
|
let { version, key, yes, update, org } = options;
|
||||||
if (!version || !key) {
|
if (!version || !key) {
|
||||||
const answers = await inquirer.prompt([
|
const answers = await inquirer.prompt([
|
||||||
{
|
{
|
||||||
@ -69,7 +70,7 @@ const command = new Command('deploy')
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const uploadDirectory = isDirectory ? directory : path.dirname(directory);
|
const uploadDirectory = isDirectory ? directory : path.dirname(directory);
|
||||||
const res = await uploadFiles(_relativeFiles, uploadDirectory, { key, version });
|
const res = await uploadFiles(_relativeFiles, uploadDirectory, { key, version, username: org });
|
||||||
if (res?.code === 200) {
|
if (res?.code === 200) {
|
||||||
console.log('File uploaded successfully!');
|
console.log('File uploaded successfully!');
|
||||||
res.data?.data?.files?.map?.((d) => {
|
res.data?.data?.files?.map?.((d) => {
|
||||||
@ -92,7 +93,11 @@ const command = new Command('deploy')
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const uploadFiles = async (files: string[], directory: string, { key, version }: { key: string; version: string }): Promise<any> => {
|
const uploadFiles = async (
|
||||||
|
files: string[],
|
||||||
|
directory: string,
|
||||||
|
{ key, version, username }: { key: string; version: string; username: string },
|
||||||
|
): Promise<any> => {
|
||||||
const config = await getConfig();
|
const config = await getConfig();
|
||||||
const form = new FormData();
|
const form = new FormData();
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
@ -104,6 +109,9 @@ const uploadFiles = async (files: string[], directory: string, { key, version }:
|
|||||||
}
|
}
|
||||||
form.append('appKey', key);
|
form.append('appKey', key);
|
||||||
form.append('version', version);
|
form.append('version', version);
|
||||||
|
if (username) {
|
||||||
|
form.append('username', username);
|
||||||
|
}
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const _baseURL = getBaseURL();
|
const _baseURL = getBaseURL();
|
||||||
const url = new URL(_baseURL);
|
const url = new URL(_baseURL);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user