🎨 Refactoring CLI

This commit is contained in:
Tw93
2023-06-22 14:36:02 +08:00
parent 87e91ecbf5
commit b2d0d7a2ae
38 changed files with 1466 additions and 5120 deletions

5
bin/utils/dir.ts vendored
View File

@@ -1,8 +1,11 @@
import path from 'path';
import { fileURLToPath } from 'url';
// Convert the current module URL to a file path
const currentModulePath = fileURLToPath(import.meta.url);
// Resolve the parent directory of the current module
export const npmDirectory = path.join(
path.dirname(fileURLToPath(import.meta.url)),
path.dirname(currentModulePath),
'..'
);

21
bin/utils/info.ts vendored Normal file
View File

@@ -0,0 +1,21 @@
import crypto from 'crypto';
import prompts from "prompts";
// Generates an identifier based on the given URL.
export function getIdentifier(url: string) {
const postFixHash = crypto.createHash('md5')
.update(url)
.digest('hex')
.substring(0, 6);
return `pake-${postFixHash}`;
}
export async function promptText(message: string, initial?: string): Promise<string> {
const response = await prompts({
type: 'text',
name: 'content',
message,
initial,
});
return response.content;
}

View File

@@ -1,9 +1,9 @@
import { exec } from 'child_process';
import { promisify } from 'util';
import logger from '@/options/logger.js';
import dns from 'dns';
import http from 'http';
import { promisify } from 'util';
import logger from '@/options/logger';
const resolve = promisify(dns.resolve);
const ping = async (host: string) => {
const lookup = promisify(dns.lookup);
@@ -23,32 +23,25 @@ const ping = async (host: string) => {
});
};
const resolve = promisify(dns.resolve);
async function isChinaDomain(domain: string): Promise<boolean> {
try {
// 解析域名为IP地址
const [ip] = await resolve(domain);
return await isChinaIP(ip, domain);
} catch (error) {
// 域名无法解析返回false
logger.info(`${domain} can't be parse!`);
return false;
}
}
async function isChinaIP(ip: string, domain: string): Promise<boolean> {
try {
const delay = await ping(ip);
logger.info(`${domain} latency is ${delay} ms`);
// 判断延迟是否超过500ms
return delay > 500;
} catch (error) {
// 命令执行出错,返回false
logger.info(`ping ${domain} failed!`);
return false;
}
try {
const delay = await ping(ip);
logger.info(`${domain} latency is ${delay} ms`);
return delay > 500;
} catch (error) {
logger.info(`ping ${domain} failed!`);
return false;
}
}
export { isChinaDomain, isChinaIP };

View File

@@ -1,5 +1,5 @@
export const IS_MAC = process.platform === 'darwin';
const { platform } = process;
export const IS_WIN = process.platform === 'win32';
export const IS_LINUX = process.platform === 'linux';
export const IS_MAC = platform === 'darwin';
export const IS_WIN = platform === 'win32';
export const IS_LINUX = platform === 'linux';

4
bin/utils/shell.ts vendored
View File

@@ -1,9 +1,9 @@
import shelljs from "shelljs";
import { npmDirectory } from "./dir.js";
import { npmDirectory } from "./dir";
export function shellExec(command: string) {
return new Promise<number>((resolve, reject) => {
shelljs.exec(command, { async: true, silent: false, cwd: npmDirectory}, (code) => {
shelljs.exec(command, { async: true, silent: false, cwd: npmDirectory }, (code) => {
if (code === 0) {
resolve(0);
} else {

1489
bin/utils/tlds.ts vendored

File diff suppressed because it is too large Load Diff

55
bin/utils/url.ts vendored
View File

@@ -1,45 +1,40 @@
import url from 'url';
import isurl from 'is-url';
import tlds from './tlds.js';
import psl from 'psl';
import isUrl from 'is-url';
export function getDomain(inputUrl: string) {
const parsed = url.parse(inputUrl).host;
var parts = parsed.split('.');
if (parts[0] === 'www' && parts[1] !== 'com') {
parts.shift();
}
var ln = parts.length,
i = ln,
minLength = parts[parts.length - 1].length,
part;
// Extracts the domain from a given URL.
export function getDomain(inputUrl: string): string | null {
try {
const url = new URL(inputUrl);
// Use PSL to parse domain names.
const parsed = psl.parse(url.hostname);
// iterate backwards
while ((part = parts[--i])) {
// stop when we find a non-TLD part
if (
i === 0 || // 'asia.com' (last remaining must be the SLD)
i < ln - 2 || // TLDs only span 2 levels
part.length < minLength || // 'www.cn.com' (valid TLD as second-level domain)
tlds.indexOf(part) < 0 // officialy not a TLD
) {
return part;
// If domain is available, split it and return the SLD.
if ("domain" in parsed && parsed.domain) {
return parsed.domain.split('.')[0];
} else {
return null;
}
} catch (error) {
return null;
}
}
function appendProtocol(inputUrl: string): string {
const parsed = url.parse(inputUrl);
if (!parsed.protocol) {
const urlWithProtocol = `https://${inputUrl}`;
return urlWithProtocol;
// Appends 'https://' protocol to the URL if not present.
export function appendProtocol(inputUrl: string): string {
try {
new URL(inputUrl);
return inputUrl;
} catch {
return `https://${inputUrl}`;
}
return inputUrl;
}
// Normalizes the URL by ensuring it has a protocol and is valid.
export function normalizeUrl(urlToNormalize: string): string {
const urlWithProtocol = appendProtocol(urlToNormalize);
if (isurl(urlWithProtocol)) {
if (isUrl(urlWithProtocol)) {
return urlWithProtocol;
} else {
throw new Error(`Your url "${urlWithProtocol}" is invalid`);

18
bin/utils/validate.ts vendored
View File

@@ -1,23 +1,25 @@
import * as Commander from 'commander';
import { normalizeUrl } from './url.js';
import fs from 'fs';
import { InvalidArgumentError } from 'commander';
import { normalizeUrl } from './url';
export function validateNumberInput(value: string) {
const parsedValue = Number(value);
if (isNaN(parsedValue)) {
throw new Commander.InvalidArgumentError('Not a number.');
throw new InvalidArgumentError('Not a number.');
}
return parsedValue;
}
export function validateUrlInput(url: string) {
if(!fs.existsSync(url)) {
const isFile = fs.existsSync(url);
if (!isFile) {
try {
return normalizeUrl(url)
return normalizeUrl(url);
} catch (error) {
throw new Commander.InvalidArgumentError(error.message);
throw new InvalidArgumentError(error.message);
}
} else {
return url;
}
return url;
}