【调整】申请证书配置CA选项增加liteSSL证书

This commit is contained in:
cai
2026-01-13 16:45:05 +08:00
parent 6c15ae35a1
commit 190e250095
2108 changed files with 58 additions and 401539 deletions

View File

@@ -1,321 +0,0 @@
/**
* 文件定义:业务处理
*/
import * as R from 'ramda'
import { isArray } from './type'
/* -------------- 1、常用正则验证 -------------- */
// 常量定义区域
const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
const PHONE_REGEX = /^1[3-9]\d{9}$/
const ID_CARD_REGEX = /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/
const URL_REGEX = /^((https|http|ftp|rtsp|mms)?:\/\/)[^\s]+/
const DOMAIN_REGEX = /^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/
// 增强版域名正则表达式 - 支持国际化域名和更多顶级域名
const ENHANCED_DOMAIN_REGEX =
/^(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)|(?:\*))\.)+(?:[a-zA-Z\u00a1-\uffff]{2,}|xn--[a-zA-Z0-9]+)$/
// 通配符域名正则表达式 - 支持通配符域名格式 (如 *.example.com)
const WILDCARD_DOMAIN_REGEX = /^\*\.(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/
// IPv4正则表达式 - 更精确的数字范围
const IPV4_SEGMENT = '(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])'
const IPV4_REGEX = new RegExp(`^${IPV4_SEGMENT}\\.${IPV4_SEGMENT}\\.${IPV4_SEGMENT}\\.${IPV4_SEGMENT}$`)
// IPv6正则表达式 - 更精确的十六进制表示
const IPV6_HEX_4DIGIT = '[0-9A-Fa-f]{1,4}'
const IPV6_REGEX = new RegExp(
[
// 标准IPv6地址
`^(${IPV6_HEX_4DIGIT}:){7}${IPV6_HEX_4DIGIT}$`,
// 压缩形式
`^(${IPV6_HEX_4DIGIT}:){1,7}:$`,
'^:((:[0-9A-Fa-f]{1,4}){1,7}|:)$',
// 混合形式
`^(${IPV6_HEX_4DIGIT}:){1,6}:${IPV6_HEX_4DIGIT}$`,
`^(${IPV6_HEX_4DIGIT}:){1,5}(:${IPV6_HEX_4DIGIT}){1,2}$`,
`^(${IPV6_HEX_4DIGIT}:){1,4}(:${IPV6_HEX_4DIGIT}){1,3}$`,
`^(${IPV6_HEX_4DIGIT}:){1,3}(:${IPV6_HEX_4DIGIT}){1,4}$`,
`^(${IPV6_HEX_4DIGIT}:){1,2}(:${IPV6_HEX_4DIGIT}){1,5}$`,
`^${IPV6_HEX_4DIGIT}:(:${IPV6_HEX_4DIGIT}){1,6}$`,
// 特殊形式
`^fe80:(:[0-9A-Fa-f]{1,4}){0,4}%[0-9A-Za-z]{1,}$`,
// IPv4映射到IPv6
`^::((ffff(:0{1,4})?:)?${IPV4_SEGMENT}\\.${IPV4_SEGMENT}\\.${IPV4_SEGMENT}\\.${IPV4_SEGMENT})$`,
`^(${IPV6_HEX_4DIGIT}:){1,4}:${IPV4_SEGMENT}\\.${IPV4_SEGMENT}\\.${IPV4_SEGMENT}\\.${IPV4_SEGMENT}$`,
].join('|'),
)
// IP段正则表达式
const IPS_REGEX = new RegExp(
`^${IPV4_SEGMENT}\\.${IPV4_SEGMENT}\\.${IPV4_SEGMENT}\\.${IPV4_SEGMENT}(\\/([1-2][0-9]|3[0-2]|[1-9]))?$`,
)
// MAC地址正则表达式
const MAC_REGEX = /^([0-9A-Fa-f]{2}-){5}[0-9A-Fa-f]{2}$/
// 中文正则表达式
const CHINESE_REGEX = /^[\u4e00-\u9fa5]+$/
// 端口正则表达式 - 更精确的数字范围
const PORT_REGEX = /^([1-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/
/**
* 判断是否为邮箱
* @param {string} email - 要判断的邮箱
* @returns {boolean} 如果邮箱是有效的,则返回 true否则返回 false
*/
export const isEmail = R.test(EMAIL_REGEX)
/**
* 判断是否为手机号
* @param {string} phone - 要判断的手机号
* @returns {boolean} 如果手机号是有效的,则返回 true否则返回 false
*/
export const isPhone = R.test(PHONE_REGEX)
/**
* 判断是否为身份证号
* @param {string} idCard - 要判断的身份证号
* @returns {boolean} 如果身份证号是有效的,则返回 true否则返 false
*/
export const isIdCard = R.test(ID_CARD_REGEX)
/**
* 判断是否为URL
* @param {string} url - 要判断的url
* @returns {boolean} 如果url是有效的则返回 true否则返回 false
*/
export const isUrl = R.test(URL_REGEX)
/**
* 判断是否为IPv4地址
* @param {string} ip - 要判断的IP地址
* @returns {boolean} 如果是有效的IPv4地址则返回 true否则返回 false
*/
export const isIpv4 = R.test(IPV4_REGEX)
/**
* 判断是否为IPv6地址
* @param {string} ip - 要判断的IP地址
* @returns {boolean} 如果是有效的IPv6地址则返回 true否则返回 false
*/
export const isIpv6 = R.test(IPV6_REGEX)
/**
* 判断是否为IP地址IPv4或IPv6
* @param {string} ip - 要判断的IP地址
* @returns {boolean} 如果IP地址是有效的则返回 true否则返回 false
*/
export const isIp = (ip: string): boolean => isIpv4(ip) || isIpv6(ip)
/**
* 判断是否为IP段
* @param {string} ips - 要判断的IP段
* @returns {boolean} 如果IP段是有效的则返回 true否则返回 false
*/
export const isIps = R.test(IPS_REGEX)
/**
* 判断端口
* @param {string} port - 判断端口
* @returns {boolean} 如果端口是有效的,则返回 true否则返回 false
*/
export const isPort = R.test(PORT_REGEX)
/**
* 判断是否为MAC地址
* @param {string} mac - 要判断的MAC地址
* @returns {boolean} 如果MAC地址是有效的则返回 true否则返回 false
*/
export const isMac = R.test(MAC_REGEX)
/**
* 判断是否为中文
* @param {string} str - 要判断的字符串
* @returns {boolean} 如果字符串是中文,则返回 true否则返回 false
*/
export const isChinese = R.test(CHINESE_REGEX)
/**
* 判断是否为域名
* @param {string} domain - 要判断的域名
* @returns {boolean} 如果域名是有效的,则返回 true否则返回 false
*/
export const isDomain = R.test(DOMAIN_REGEX)
/**
* 判断是否为域名(增强版)
* @param {string} domain - 要判断的域名,支持国际化域名和更多顶级域名
* @returns {boolean} 如果域名是有效的,则返回 true否则返回 false
*/
export const isEnhancedDomain = R.test(ENHANCED_DOMAIN_REGEX)
/**
* 判断是否为通配符域名
* @param {string} domain - 要判断的通配符域名
* @returns {boolean} 如果通配符域名是有效的,则返回 true否则返回 false
*/
export const isWildcardDomain = R.test(WILDCARD_DOMAIN_REGEX)
/**
* 判断是否为域名或通配符域名
* @param {string} domain - 要判断的域名
* @returns {boolean} 如果域名或通配符域名是有效的,则返回 true否则返回 false
*/
export const isDomainOrWildcardDomain = (domain: string): boolean => isDomain(domain) || isWildcardDomain(domain)
/**
* 判断域名组,通过特定字符串分割
* @param {string} domain - 要判断的域名
* @param {string} separator - 分割符
* @returns {boolean} 如果域名组是有效的,则返回 true否则返回 false
*/
export const isDomainGroup = (domain: string, separator: string = ',') => {
return R.all(
R.equals(true),
R.map(
(item: string) => isDomain(item) || isWildcardDomain(item) || isEnhancedDomain(item),
R.split(separator, domain),
),
)
}
/* -------------- 2、常用业务操作 -------------- */
/**
* 手机号加密
* @param {string} phone - 要加密的手机号
* @returns {string} 加密后的手机号
*/
export const encryptPhone = (phone: string): string => phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
/**
* 身份证号加密
* @param {string} idCard - 要加密的身份证号18位最后一位可以是X
* @returns {string} 加密后的身份证号
*/
export const encryptIdCard = (idCard: string): string => idCard.replace(/(\d{6})\d{8}([\dXx]{4})/, '$1****$2')
/**
* 版本号比较
* @param {string} version1 - 版本号1
* @param {string} version2 - 版本号2
* @returns {number} 如果版本号1大于版本号2则返回1如果版本号1小于版本号2则返回-1如果版本号1等于版本号2则返回0
*/
export const compareVersion = (version1: string, version2: string): number => {
// 使用Ramda的pipe函数组合操作
const parseVersion = R.pipe(
R.split('.'),
R.map((v: string) => parseInt(v || '0', 10)),
)
const v1 = parseVersion(version1) // 解析版本号1
const v2 = parseVersion(version2) // 解析版本号2
// 确保两个数组长度相同
const len = Math.max(v1.length, v2.length)
// 使用Ramda的repeat和take函数来填充数组
const paddedV1 = R.concat(v1, R.repeat(0, len - v1.length))
const paddedV2 = R.concat(v2, R.repeat(0, len - v2.length))
// 使用Ramda的zipWith比较每个版本号段
const comparisons = R.zipWith((a: number, b: number) => (a === b ? 0 : a > b ? 1 : -1), paddedV1, paddedV2)
// 找到第一个非零的比较结果
const result = R.find(R.complement(R.equals(0)), comparisons)
return result ?? 0
}
/**
* 字节转换
* @param {number} bytes - 要转换的字节数
* @param {number} [fixed=2] - 保留小数位数
* @param {boolean} [isUnit=true] - 是否显示单位
* @param {string} [endUnit=''] - 指定结束单位,如果指定则转换到该单位为止
* @returns {string} 转换后的字节数
*/
export const formatBytes = (bytes: number, fixed: number = 2, isUnit: boolean = true, endUnit: string = ''): string => {
if (bytes === 0) return isUnit ? '0 B' : '0'
const units = ['B', 'KB', 'MB', 'GB', 'TB']
const c = 1024
// 使用Ramda的递归函数进行单位转换
const convert = (value: number, unitIndex: number): string => {
const unit = units[unitIndex]
const formattedValue = unitIndex === 0 || fixed === 0 ? Math.round(value).toString() : value.toFixed(fixed)
// 如果指定了结束单位或者已经是最小单位
if ((endUnit && unit === endUnit) || value < c || unitIndex >= units.length - 1) {
return isUnit ? `${formattedValue} ${unit}` : formattedValue
}
// 继续转换到下一个单位
return convert(value / c, unitIndex + 1)
}
return convert(bytes, 0)
}
/**
* 柯里化版本的formatBytes
* @param {number} bytes - 要转换的字节数
* @param {number} [fixed=2] - 保留小数位数
* @param {boolean} [isUnit=true] - 是否显示单位
* @param {string} [endUnit=''] - 指定结束单位,如果指定则转换到该单位为止
* @returns {string} 转换后的字节数
*/
export const formatBytesCurried: {
(bytes: number, fixed: number, isUnit: boolean, endUnit: string): string
(bytes: number): (fixed?: number, isUnit?: boolean, endUnit?: string) => string
(bytes: number, fixed: number): (isUnit?: boolean, endUnit?: string) => string
(bytes: number, fixed: number, isUnit: boolean): (endUnit?: string) => string
} = R.curry(formatBytes)
/**
* 分页字符串转换
* @param {string} page - 分页字符串
* @returns {string} 转换后的分页字符串
*/
export const formatPage = (page: string): number => {
const newPage = page.match(/class='Pcount'>共([0-9]*)条</)
if (isArray(newPage) && newPage.length >= 2) return Number(newPage[1])
return 0
}
/* -------------- 3、代理函数 -------------- */
export type ProxyConfig = {
requestTime: number
requestToken: string
request_time: number
request_token: string
}
/**
* 代理配置,仅在开发环境生效
* @param {string} proxyKey - 代理密钥
* @param {string} usage 使用场景 "query" | "params"
* @returns {Object} 返回对象包含 request_time 和 request_token
*/
export const getProxyConfig = async (proxyKey: string, usage: 'query' | 'params' = 'params') => {
const md5 = await import('md5')
const request_time = Date.now()
const request_token = md5.default(String(request_time).concat(md5.default(proxyKey)))
if (usage === 'params') {
return { request_time, request_token, requestTime: request_time, requestToken: request_token }
}
return `request_time=${request_time}&request_token=${request_token}`
}
/** -------------- 4、接口缓存配置 -------------- */
/**
* 接口缓存配置
* @param {function} method - 接口请求方法
* @param {string} params - 接口请求参数
* @param {Record<string, any>} options - 接口请求配置
* @returns {string} 返回数据
*/
export const getCacheConfig = (method: Function, params: string, options: Record<string, any> = {}) => {
console.log(method, params, options)
}