Files
cli/src/command/login.ts
abearxiong 5774391bbe feat: refactor deploy command to enhance file upload process and user handling
- 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.
2026-02-02 17:57:50 +08:00

182 lines
5.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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);