215 lines
6.2 KiB
TypeScript
215 lines
6.2 KiB
TypeScript
|
import { Argument, InvalidArgumentError, program } from "commander";
|
||
|
import * as fs from "fs";
|
||
|
import * as os from "os";
|
||
|
import * as path from "path";
|
||
|
import { initClient, startClient } from "./api";
|
||
|
import { PROFILE_DEFAULT, PROFILE_PATH, SERVER_DEFAULT_URL, TOKEN_FREE } from "./constant";
|
||
|
import { getTokenFree } from './sdk';
|
||
|
import { generateUUID } from "./util";
|
||
|
|
||
|
const packageInfo = require("../package.json");
|
||
|
|
||
|
program
|
||
|
.name("hlt")
|
||
|
.description(
|
||
|
"CUBETIQ HTTP tunnel client with free access for local tunneling"
|
||
|
)
|
||
|
.version(`v${packageInfo.version}`);
|
||
|
|
||
|
// init
|
||
|
program
|
||
|
.command("init")
|
||
|
.description("generate a new client and token with free access")
|
||
|
.option("-s --server <string>", "setting server url", SERVER_DEFAULT_URL)
|
||
|
.option(
|
||
|
"-t --token <string>",
|
||
|
"setting token (default generate FREE access token)",
|
||
|
""
|
||
|
)
|
||
|
.option("-a --access <string>", "setting token access type", TOKEN_FREE)
|
||
|
.option("-c --client <string>", "setting client (auto generate uuid)")
|
||
|
.option(
|
||
|
"-k --key <string>",
|
||
|
"setting client api key for authentication access"
|
||
|
)
|
||
|
.option("-p --profile <string>", "setting profile name", PROFILE_DEFAULT)
|
||
|
.option("-f --force", "force to generate new client and token", false)
|
||
|
.action(async (options) => {
|
||
|
initClient(options);
|
||
|
});
|
||
|
|
||
|
// start
|
||
|
program
|
||
|
.command("start")
|
||
|
.description("start a connection with specific port")
|
||
|
.argument("<port>", "local server port number", (value) => {
|
||
|
const port = parseInt(value, 10);
|
||
|
if (isNaN(port)) {
|
||
|
throw new InvalidArgumentError("Not a number.");
|
||
|
}
|
||
|
return port;
|
||
|
})
|
||
|
.option("-s, --suffix <string>", "suffix for client name")
|
||
|
.option(
|
||
|
"-K, --keep_connection <boolean>",
|
||
|
"keep connection for client and old connection will be closed (override connection)",
|
||
|
true
|
||
|
)
|
||
|
.option(
|
||
|
"-k --key <string>",
|
||
|
"setting client api key for authentication access"
|
||
|
)
|
||
|
.option("-a, --access <string>", "access type (FREE)", TOKEN_FREE)
|
||
|
.option("-p, --profile <string>", "profile name", PROFILE_DEFAULT)
|
||
|
.option("-h, --host <string>", "local host value", "localhost")
|
||
|
.option("-o, --origin <string>", "change request origin")
|
||
|
.action((port, options) => {
|
||
|
startClient({
|
||
|
port,
|
||
|
options,
|
||
|
})
|
||
|
});
|
||
|
|
||
|
// config
|
||
|
program
|
||
|
.command("config")
|
||
|
.description("create and update config file for connection")
|
||
|
.addArgument(
|
||
|
new Argument("<type>", "config type").choices([
|
||
|
"access",
|
||
|
"token",
|
||
|
"server",
|
||
|
"client",
|
||
|
"key",
|
||
|
])
|
||
|
)
|
||
|
.argument("<value>", "config value")
|
||
|
.option("-p --profile <string>", "setting profile name", PROFILE_DEFAULT)
|
||
|
.action(async (type, value, options) => {
|
||
|
if (!type) {
|
||
|
console.error("type config is required!");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const configDir = path.resolve(os.homedir(), PROFILE_PATH);
|
||
|
|
||
|
if (!fs.existsSync(configDir)) {
|
||
|
fs.mkdirSync(configDir);
|
||
|
console.log(`config file ${configDir} was created`);
|
||
|
}
|
||
|
|
||
|
let config: any = {};
|
||
|
const configFilename = `${options.profile}.json`;
|
||
|
const configFilePath = path.resolve(configDir, configFilename);
|
||
|
|
||
|
if (fs.existsSync(configFilePath)) {
|
||
|
config = JSON.parse(fs.readFileSync(configFilePath, "utf8"));
|
||
|
}
|
||
|
|
||
|
if (!config.server) {
|
||
|
config.server = SERVER_DEFAULT_URL;
|
||
|
}
|
||
|
|
||
|
// Error Code status
|
||
|
let errorCode = 0;
|
||
|
|
||
|
if (type === "token" || type === "jwt") {
|
||
|
config.token = value;
|
||
|
} else if (type === "server") {
|
||
|
config.server = value;
|
||
|
} else if (type === "clientId" || type === "client") {
|
||
|
if (!value || value === "" || value === "new") {
|
||
|
config.clientId = generateUUID();
|
||
|
} else {
|
||
|
config.clientId = value;
|
||
|
}
|
||
|
console.log(`client: ${config.clientId} was set to config`);
|
||
|
} else if (type === "apiKey" || type === "key") {
|
||
|
config.apiKey = value;
|
||
|
} else if (type === "access") {
|
||
|
config.access = (value && value.toUpperCase().trim()) || TOKEN_FREE;
|
||
|
|
||
|
// FREE
|
||
|
if (config.access === TOKEN_FREE) {
|
||
|
await getTokenFree(config.server)
|
||
|
.then((resp: any) => {
|
||
|
if (resp.data?.token) {
|
||
|
config.token = resp.data?.token;
|
||
|
} else {
|
||
|
errorCode = 1;
|
||
|
console.error("Generate free token failed, return with null or empty from server!", resp);
|
||
|
return;
|
||
|
}
|
||
|
})
|
||
|
.catch((err: any) => {
|
||
|
errorCode = 1;
|
||
|
console.error("cannot get free token from server", err);
|
||
|
return;
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!config.clientId && config.apiKey) {
|
||
|
config.clientId = config.apiKey;
|
||
|
}
|
||
|
|
||
|
if (errorCode === 0) {
|
||
|
fs.writeFileSync(configFilePath, JSON.stringify(config, null, 2));
|
||
|
console.log(`${type} config saved successfully to: ${configFilePath}`);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// config
|
||
|
program
|
||
|
.command("config-get")
|
||
|
.description("get type from config file")
|
||
|
.addArgument(
|
||
|
new Argument("<type>", "config type").choices([
|
||
|
"access",
|
||
|
"token",
|
||
|
"server",
|
||
|
"client",
|
||
|
"key",
|
||
|
])
|
||
|
)
|
||
|
.option("-p --profile <string>", "setting profile name", PROFILE_DEFAULT)
|
||
|
.action(async (type, options) => {
|
||
|
if (!type) {
|
||
|
console.error("type config is required!");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const configDir = path.resolve(os.homedir(), PROFILE_PATH);
|
||
|
if (!fs.existsSync(configDir)) {
|
||
|
console.log(`config file ${configDir} not found`);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
let config: any = {};
|
||
|
const configFilename = `${options.profile}.json`;
|
||
|
const configFilePath = path.resolve(configDir, configFilename);
|
||
|
|
||
|
if (fs.existsSync(configFilePath)) {
|
||
|
config = JSON.parse(fs.readFileSync(configFilePath, "utf8"));
|
||
|
} else {
|
||
|
console.log(`config file ${configFilePath} not found`);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (type === "token" || type === "jwt") {
|
||
|
console.log(config.token);
|
||
|
} else if (type === "server") {
|
||
|
console.log(config.server);
|
||
|
} else if (type === "clientId" || type === "client") {
|
||
|
console.log(config.clientId);
|
||
|
} else if (type === "apiKey" || type === "key") {
|
||
|
console.log(config.apiKey);
|
||
|
} else if (type === "access") {
|
||
|
console.log(config.access);
|
||
|
} else {
|
||
|
console.log('no config found for type: "' + type + '"');
|
||
|
}
|
||
|
});
|
||
|
|
||
|
program.parse();
|