🎨 Refactoring CLI
This commit is contained in:
5
bin/utils/dir.ts
vendored
5
bin/utils/dir.ts
vendored
@@ -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
21
bin/utils/info.ts
vendored
Normal 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;
|
||||
}
|
||||
29
bin/utils/ip_addr.ts → bin/utils/ip.ts
vendored
29
bin/utils/ip_addr.ts → bin/utils/ip.ts
vendored
@@ -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 };
|
||||
8
bin/utils/platform.ts
vendored
8
bin/utils/platform.ts
vendored
@@ -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
4
bin/utils/shell.ts
vendored
@@ -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
1489
bin/utils/tlds.ts
vendored
File diff suppressed because it is too large
Load Diff
55
bin/utils/url.ts
vendored
55
bin/utils/url.ts
vendored
@@ -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
18
bin/utils/validate.ts
vendored
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user