- Updated the deploy command to include a new username retrieval mechanism, falling back to the organization if not specified. - Introduced uploadFilesV2 function to streamline file upload logic, including hash checking to prevent redundant uploads. - Modified queryAppVersion to accept a create parameter for better version management. - Added a new test file to validate the uploadFilesV2 functionality.
182 lines
5.1 KiB
TypeScript
182 lines
5.1 KiB
TypeScript
import { program, Command } from '@/program.ts';
|
||
import { getConfig, getEnvToken } from '@/module/get-config.ts';
|
||
import { input, password } from '@inquirer/prompts';
|
||
import { loginInCommand } from '@/module/login/login-by-web.ts';
|
||
import { queryLogin, storage } from '@/module/query.ts';
|
||
import chalk from 'chalk';
|
||
import util from 'util';
|
||
|
||
const pick = (obj: any, keys: string[]) => {
|
||
return keys.reduce((acc, key) => {
|
||
acc[key] = obj[key];
|
||
return acc;
|
||
}, {});
|
||
};
|
||
/**
|
||
* 定义login命令,支持 `-u` 和 `-p` 参数来输入用户名和密码
|
||
*/
|
||
const loginCommand = new Command('login')
|
||
.description('Login to the application')
|
||
.option('-u, --username <username>', 'Specify username')
|
||
.option('-p, --password <password>', 'Specify password')
|
||
.option('-f, --force', 'Force login')
|
||
.option('-w, --web', 'Login on the web')
|
||
.option('-e, --env', 'Login from KEVISUAL_TOKEN environment variable')
|
||
|
||
.action(async (options) => {
|
||
let { username, password } = options;
|
||
if (options.web) {
|
||
await loginInCommand();
|
||
return;
|
||
}
|
||
// 从环境变量登录
|
||
if (options.env) {
|
||
const envToken = getEnvToken();
|
||
if (!envToken) {
|
||
console.log('环境变量 KEVISUAL_TOKEN 未设置');
|
||
return;
|
||
}
|
||
const res = await showMe(false);
|
||
if (res.code === 200) {
|
||
console.log('Login success:', res.data?.username || res.data?.email);
|
||
} else {
|
||
console.log('Login failed:', res.message || 'Invalid token');
|
||
}
|
||
return;
|
||
}
|
||
// 如果没有传递参数,则通过交互式输入
|
||
if (!username) {
|
||
username = await input({
|
||
message: 'Enter your username:',
|
||
});
|
||
}
|
||
if (!password) {
|
||
password = await password({
|
||
message: 'Enter your password:',
|
||
});
|
||
}
|
||
const token = storage.getItem('token');
|
||
if (token) {
|
||
const res = await showMe(false);
|
||
if (res.code === 200) {
|
||
const data = res.data;
|
||
if (data.username === username) {
|
||
console.log('Already Login For', data.username);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
const res = await queryLogin.login({
|
||
username,
|
||
password,
|
||
}).catch((err) => {
|
||
return { code: 500, message: err.message || '' };
|
||
});
|
||
if (res.code === 200) {
|
||
console.log('welcome', username);
|
||
} else {
|
||
console.log('登录失败', res.message || '');
|
||
}
|
||
});
|
||
|
||
program.addCommand(loginCommand);
|
||
|
||
export const getUsername = async () => {
|
||
const token = getEnvToken();
|
||
const localToken = storage.getItem('token');
|
||
if (!token && !localToken) {
|
||
console.log('请先登录');
|
||
return null;
|
||
}
|
||
let me = await queryLogin.getMe(localToken || token);
|
||
if (me?.code === 401) {
|
||
me = await queryLogin.getMe();
|
||
}
|
||
if (me?.code === 200) {
|
||
return me.data?.username;
|
||
}
|
||
return null;
|
||
}
|
||
const showMe = async (show = true) => {
|
||
const token = getEnvToken();
|
||
const localToken = storage.getItem('token');
|
||
if (!token && !localToken) {
|
||
console.log('请先登录');
|
||
return { code: 40400, message: '请先登录' };
|
||
}
|
||
let me = await queryLogin.getMe(localToken || token);
|
||
if (me?.code === 401) {
|
||
me = await queryLogin.getMe();
|
||
}
|
||
if (show) {
|
||
console.log('Me', me.data);
|
||
}
|
||
return me;
|
||
};
|
||
|
||
const switchOrgCommand = new Command('switch').argument('<username>', 'Switch to another organization or username').action(async (username) => {
|
||
const res = await queryLogin.switchUser(username);
|
||
if (res.code === 200) {
|
||
console.log('success switch to', username);
|
||
} else {
|
||
console.log('switch to', username, 'failed', res.message || '');
|
||
}
|
||
});
|
||
|
||
program.addCommand(switchOrgCommand);
|
||
|
||
const command = new Command('me')
|
||
.option('-a, --all', 'show all info')
|
||
.description('')
|
||
.action(async (options) => {
|
||
try {
|
||
let res = await showMe(false);
|
||
let isRefresh = false;
|
||
if (res.code === 200 && res.data?.accessToken) {
|
||
res = await showMe(false);
|
||
isRefresh = true;
|
||
}
|
||
if (res.code === 40400) {
|
||
return
|
||
}
|
||
if (res.code === 200) {
|
||
if (isRefresh) {
|
||
console.log(chalk.green('refresh token success'), '\n');
|
||
}
|
||
} else {
|
||
console.log(
|
||
isRefresh ? chalk.red('refresh token failed, please login again.') : chalk.red('you need login first. \n run `envision login` to login'),
|
||
'\n',
|
||
);
|
||
return;
|
||
}
|
||
const baseURL = getConfig().baseURL;
|
||
const pickData = pick(res?.data, ['username', 'type', 'orgs']);
|
||
|
||
console.log(chalk.blue('baseURL', baseURL));
|
||
if (options.all) {
|
||
console.log(chalk.blue(util.inspect(res?.data, { colors: true, depth: 4 })));
|
||
} else {
|
||
// 打印pickData
|
||
console.log(chalk.blue(util.inspect(pickData, { colors: true, depth: 4 })));
|
||
}
|
||
} catch (error) {
|
||
console.log('me error', error);
|
||
}
|
||
});
|
||
|
||
program.addCommand(command);
|
||
|
||
const logoutCommand = new Command('logout').description('退出登陆').action(async () => {
|
||
try {
|
||
await queryLogin.logout();
|
||
storage.removeItem('token');
|
||
console.log('退出成功');
|
||
} catch (error) {
|
||
console.log('退出失败', error);
|
||
}
|
||
});
|
||
|
||
program.addCommand(logoutCommand);
|