move utils to zutils

This commit is contained in:
CounterFire2023 2024-01-17 18:54:50 +08:00
parent a153eded7b
commit 959740af19
16 changed files with 80 additions and 760 deletions

View File

@ -7,7 +7,7 @@ import { reportPayResult } from 'service/game.svr'
import { PriceSvr } from 'service/price.svr'
import { OrderCacheSvr } from 'service/ordercache.svr'
import { BaseController, role, ROLE_ANON, router, ZError } from 'zutils'
import { fromWei, toBigWei } from 'utils/number.util'
import { fromWei, toBigWei } from 'zutils/utils/bn.util'
let errorRes = function (msg: string) {
logger.info(`error res: ${msg}`)

View File

@ -2,7 +2,7 @@ import { getModelForClass, index, modelOptions, mongoose, prop, ReturnModelType,
import { dbconn } from 'decorators/dbconn'
import { Base, TimeStamps } from '@typegoose/typegoose/lib/defaultClasses'
import { BaseModule } from './Base'
import { genRandomString, sha512 } from 'utils/security.util'
import { genRandomString, sha512 } from 'zutils/utils/security.util'
export enum PlatEnum {
GOOGLE = 0,

View File

@ -6,7 +6,7 @@ import { plugin, prop, ReturnModelType } from '@typegoose/typegoose'
import findOrCreate from 'mongoose-findorcreate'
import { Connection } from 'mongoose'
import { ObjectId } from 'bson'
import { isTrue } from '../utils/string.util'
import { isTrue } from 'zutils/utils/string.util'
import { AnyParamConstructor } from '@typegoose/typegoose/lib/types'
const jsonExcludeKeys = ['updatedAt', '__v']

View File

@ -1,37 +1,26 @@
import {
FastifyInstance,
FastifyPluginAsync,
FastifyReply,
FastifyRequest,
} from "fastify";
import fastifyPlugin from "fastify-plugin";
import { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest } from 'fastify'
import fastifyPlugin from 'fastify-plugin'
/**
* post get req.params
*/
declare module "fastify" {
declare module 'fastify' {
interface FastifyInstance {
zReqParser: (request: FastifyRequest, reply: FastifyReply) => {};
zReqParser: (request: FastifyRequest, reply: FastifyReply) => {}
}
}
const zReqParserPlugin: FastifyPluginAsync = async function (
fastify: FastifyInstance,
options?: any
) {
fastify.addHook(
"preValidation",
async (request: FastifyRequest, reply: FastifyReply) => {
let params = request.params || {};
const zReqParserPlugin: FastifyPluginAsync = async function (fastify: FastifyInstance, options?: any) {
fastify.addHook('preValidation', async (request: FastifyRequest, reply: FastifyReply) => {
let params = request.params || {}
if (request.query) {
Object.assign(params, request.query);
Object.assign(params, request.query)
}
if (request.body) {
Object.assign(params, request.body);
Object.assign(params, request.body)
}
request.params = params;
request.params = params
})
return
}
);
return;
};
export default fastifyPlugin(zReqParserPlugin, "4.x");
export default fastifyPlugin(zReqParserPlugin, '4.x')

View File

@ -1,73 +1,62 @@
import {
FastifyInstance,
FastifyPluginAsync,
FastifyReply,
FastifyRequest,
} from "fastify";
import fastifyPlugin from "fastify-plugin";
import { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest } from 'fastify'
import fastifyPlugin from 'fastify-plugin'
const getTokenFromHeader = function (request) {
let token: string | undefined;
let token: string | undefined
if (request.headers && request.headers.authorization) {
const parts = request.headers.authorization.split(" ");
const parts = request.headers.authorization.split(' ')
if (parts.length === 2) {
const scheme = parts[0];
const scheme = parts[0]
if (/^Bearer$/i.test(scheme)) {
token = parts[1];
token = parts[1]
}
}
}
return token;
};
return token
}
const getTokenFromCookie = function (request) {
let token: string | undefined;
let token: string | undefined
if (request.cookies) {
if (request.cookies["token"]) {
token = request.cookies["token"];
if (request.cookies['token']) {
token = request.cookies['token']
}
}
return token;
};
return token
}
const getTokenFromParams = function (request) {
let token: string | undefined;
token = request.params && request.params.token;
return token;
};
let token: string | undefined
token = request.params && request.params.token
return token
}
const getTokenFromQuery = function (request) {
let token: string | undefined;
token = request.query && request.query.token;
return token;
};
let token: string | undefined
token = request.query && request.query.token
return token
}
const getTokenFromBody = function (request) {
let token: string | undefined;
token = request.body && request.body.token;
return token;
};
let token: string | undefined
token = request.body && request.body.token
return token
}
const zTokenParserPlugin: FastifyPluginAsync = async function (
fastify: FastifyInstance,
options?: any
) {
fastify.addHook(
"preValidation",
async (request: FastifyRequest, reply: FastifyReply) => {
request["token"] =
const zTokenParserPlugin: FastifyPluginAsync = async function (fastify: FastifyInstance, options?: any) {
fastify.addHook('preValidation', async (request: FastifyRequest, reply: FastifyReply) => {
request['token'] =
getTokenFromHeader(request) ||
getTokenFromCookie(request) ||
getTokenFromParams(request) ||
getTokenFromQuery(request) ||
getTokenFromBody(request);
getTokenFromBody(request)
})
return
}
);
return;
};
/**
* request的header, cookie, params, query和body中获取token, request.token中
* header中的字段key为authorization, Bearer xxxx
* key都为 token
*/
export default fastifyPlugin(zTokenParserPlugin, "4.x");
export default fastifyPlugin(zTokenParserPlugin, '4.x')

View File

@ -1,19 +1,19 @@
import {NetClient} from "net/NetClient";
import { NetClient } from 'net/NetClient'
const FACEBOOK_API_HOST = 'https://graph.facebook.com'
export const FACEBOOK_APP_ID = '1204701000119770';
const FACEBOOK_APP_SECRET = '5a1deba64b30c7326f497fc52691207f';
export const FACEBOOK_APP_ID = '1204701000119770'
const FACEBOOK_APP_SECRET = '5a1deba64b30c7326f497fc52691207f'
export async function getAppAccessToken() {
const url = `${FACEBOOK_API_HOST}/oauth/access_token?client_id=${FACEBOOK_APP_ID}&clent_secret=${FACEBOOK_APP_SECRET}&grant_type=client_credentials`;
return new NetClient().httpGet(url);
const url = `${FACEBOOK_API_HOST}/oauth/access_token?client_id=${FACEBOOK_APP_ID}&clent_secret=${FACEBOOK_APP_SECRET}&grant_type=client_credentials`
return new NetClient().httpGet(url)
}
export async function verifyFbUserAccessToken(accessToken: string) {
const url = `${FACEBOOK_API_HOST}/debug_token?input_token=${accessToken}&access_token=GG|${FACEBOOK_APP_ID}|${FACEBOOK_APP_SECRET}`;
return new NetClient().httpGet(url);
const url = `${FACEBOOK_API_HOST}/debug_token?input_token=${accessToken}&access_token=GG|${FACEBOOK_APP_ID}|${FACEBOOK_APP_SECRET}`
return new NetClient().httpGet(url)
}
export async function fetchUserInfo(accessToken: string) {
const url = `${FACEBOOK_API_HOST}/me?fields=["email","id", "name"]&access_token=${accessToken}`;
return new NetClient().httpGet(url);
const url = `${FACEBOOK_API_HOST}/me?fields=["email","id", "name"]&access_token=${accessToken}`
return new NetClient().httpGet(url)
}

View File

@ -1,10 +1,10 @@
import axios from 'axios'
import { hmacsha256, md5, sha1 } from 'utils/security.util'
import { hmacSha256, md5, sha1 } from 'zutils/utils/security.util'
import crypto from 'crypto'
import { generateKVStr } from 'utils/net.util'
import { generateKVStr } from 'zutils/utils/net.util'
import logger from 'logger/logger'
import { GasSvr } from './gas.svr'
import { toBigInt, toBigWei } from 'utils/number.util'
import { toBigInt, toBigWei } from 'zutils/utils/bn.util'
import { PriceSvr } from './price.svr'
export function createSimpleSign(data: any) {
@ -17,7 +17,7 @@ export function createSimpleSign(data: any) {
.sort()
.map(key => `${key}=${signData[key]}`)
.join('&')
let sign = hmacsha256(signStr, secret)
let sign = hmacSha256(signStr, secret).toLowerCase()
return {
appid,
timestamp,
@ -85,7 +85,7 @@ export function checkSimpleSign(headers: any, data: any) {
.sort()
.map(key => `${key}=${signData[key]}`)
.join('&')
const expectedSign = hmacsha256(signStr, process.env.ALCHEMY_APP_SECRET)
const expectedSign = hmacSha256(signStr, process.env.ALCHEMY_APP_SECRET).toLowerCase()
logger.info('compare sign: ', sign, expectedSign)
// const expectedSign = sha1(appIdToCheck + process.env.ALCHEMY_APP_SECRET + timestamp)
return sign === expectedSign

View File

@ -1,4 +1,4 @@
import { shortUuid, uuid } from 'utils/security.util'
import { shortUuid } from 'zutils/utils/security.util'
import { ZError, singleton } from 'zutils'
export interface IQrData {

View File

@ -1,7 +1,7 @@
import axios from 'axios'
import { PayRecordClass } from 'modules/PayRecord'
import { DocumentType } from '@typegoose/typegoose'
import { hmacsha256 } from 'utils/security.util'
import { hmacSha256 } from 'zutils/utils/security.util'
import { NetClient } from 'net/NetClient'
import logger from 'logger/logger'
import { ReportQueue } from 'modules/ReportQueue'
@ -47,7 +47,7 @@ export function assembleGameData(data: DocumentType<PayRecordClass>, mini = true
export function checkGameSign({ id, timestamp, sign }: { id: string; timestamp: string; sign: string }) {
const signStr = `id=${id}&timestamp=${timestamp}`
const hash = hmacsha256(signStr, process.env.HASH_SALT)
const hash = hmacSha256(signStr, process.env.HASH_SALT).toLowerCase()
return sign === hash
}
@ -57,7 +57,7 @@ export async function reportPayResult(data: DocumentType<PayRecordClass>) {
.sort()
.map(key => `${key}=${encodeURIComponent(repData[key])}`)
.join('&')
const sign = hmacsha256(signStr, process.env.HASH_SALT)
const sign = hmacSha256(signStr, process.env.HASH_SALT).toLowerCase()
const url = `${process.env.GAME_PAY_CB_URL}?c=Shop&a=buyGoodsDirect&${signStr}&sign=${sign}`
const reqConfig: any = {
method: 'get',
@ -92,7 +92,7 @@ export async function reportPurchaseResult(records: IPayResult[], channel: strin
.join('&'),
)
.join('&')
const sign = hmacsha256(signStr, process.env.HASH_SALT)
const sign = hmacSha256(signStr, process.env.HASH_SALT).toLowerCase()
reportData.sign = sign
const reqData = {
url,

View File

@ -1,7 +1,7 @@
import axios from 'axios'
import { HTTP_GET, HTTP_POST } from 'common/Constants'
import logger from 'logger/logger'
import { generateKVStr } from 'utils/net.util'
import { generateKVStr } from 'zutils/utils/net.util'
import { prepareOkxReqCfg } from 'utils/okx.utils'
const OKX_BASE = 'https://www.okx.com/api/v5/mktplace'

View File

@ -1,6 +1,6 @@
import { GasSvr } from 'service/gas.svr'
import { PriceSvr } from 'service/price.svr'
import { fromWei, toBigInt, toBigWei } from 'utils/number.util'
import { fromWei, toBigInt, toBigWei } from 'zutils/utils/bn.util'
async function main() {
let cryptoPrice = '0.1'

View File

@ -1,182 +0,0 @@
const TIMEOUT_ERROR = new Error('timeout')
const hexRe = /^[0-9A-Fa-f]+$/gu
/**
* Execute fetch and verify that the response was successful.
*
* @param request - Request information.
* @param options - Fetch options.
* @returns The fetch response.
*/
export async function successfulFetch(request: string, options?: RequestInit) {
const response = await fetch(request, options)
if (!response.ok) {
throw new Error(`Fetch failed with status '${response.status}' for request '${request}'`)
}
return response
}
/**
* Execute fetch and return object response.
*
* @param request - The request information.
* @param options - The fetch options.
* @returns The fetch response JSON data.
*/
export async function handleFetch(request: string, options?: RequestInit) {
const response = await successfulFetch(request, options)
const object = await response.json()
return object
}
/**
* Execute fetch and return object response, log if known error thrown, otherwise rethrow error.
*
* @param request - the request options object
* @param request.url - The request url to query.
* @param request.options - The fetch options.
* @param request.timeout - Timeout to fail request
* @param request.errorCodesToCatch - array of error codes for errors we want to catch in a particular context
* @returns The fetch response JSON data or undefined (if error occurs).
*/
export async function fetchWithErrorHandling({
url,
options,
timeout,
errorCodesToCatch,
}: {
url: string
options?: RequestInit
timeout?: number
errorCodesToCatch?: number[]
}) {
let result
try {
if (timeout) {
result = Promise.race([
await handleFetch(url, options),
new Promise<Response>((_, reject) =>
setTimeout(() => {
reject(TIMEOUT_ERROR)
}, timeout),
),
])
} else {
result = await handleFetch(url, options)
}
} catch (e) {
logOrRethrowError(e, errorCodesToCatch)
}
return result
}
/**
* Fetch that fails after timeout.
*
* @param url - Url to fetch.
* @param options - Options to send with the request.
* @param timeout - Timeout to fail request.
* @returns Promise resolving the request.
*/
export async function timeoutFetch(url: string, options?: RequestInit, timeout = 500): Promise<Response> {
return Promise.race([
successfulFetch(url, options),
new Promise<Response>((_, reject) =>
setTimeout(() => {
reject(TIMEOUT_ERROR)
}, timeout),
),
])
}
/**
* Utility method to log if error is a common fetch error and otherwise rethrow it.
*
* @param error - Caught error that we should either rethrow or log to console
* @param codesToCatch - array of error codes for errors we want to catch and log in a particular context
*/
function logOrRethrowError(error: any, codesToCatch: number[] = []) {
if (!error) {
return
}
const includesErrorCodeToCatch = codesToCatch.some(code =>
error.message.includes(`Fetch failed with status '${code}'`),
)
if (
error instanceof Error &&
(includesErrorCodeToCatch || error.message.includes('Failed to fetch') || error === TIMEOUT_ERROR)
) {
console.error(error)
} else {
throw error
}
}
/**
* key1=val1&key2=val2的字符串
* @param {object} data
* @param {boolean} sort key生序重排
* @param {boolean} ignoreNull (null值不参与拼接)
* @param splitChar , &
* @param equalChar =
*/
export function generateKVStr({
data = {},
sort = false,
encode = false,
ignoreNull = true,
splitChar = '&',
equalChar = '=',
uri = '',
}: {
data?: any
sort?: boolean
encode?: boolean
ignoreNull?: boolean
splitChar?: string
equalChar?: string
uri?: string
}) {
const keys = Object.keys(data)
sort && keys.sort()
let result = ''
let i = 0
for (let key of keys) {
if (ignoreNull && !data[key]) {
continue
}
if (i++ > 0) result += splitChar
if (encode) {
result += `${key}${equalChar}${encodeURIComponent(data[key])}`
} else {
result += `${key}${equalChar}${data[key]}`
}
}
if (uri) {
const joinChar = uri.search(/\?/) === -1 ? '?' : '&'
result = uri + joinChar + result
}
return result
}
/**
* key1=val&key2=val的字符串组装成对象
* @param str key1=val&key2=val的字符串
* @param splitChar , &
* @param equalChar =
*/
export function keyValToObject(str: string, splitChar: string = '&', equalChar = '='): {} {
let result: any = {}
if (!str) {
return result
}
let arrs = str.split(splitChar)
for (let sub of arrs) {
let subArr = sub.split(equalChar)
result[subArr[0]] = subArr[1]
}
return result
}

View File

@ -1,218 +0,0 @@
export declare type HexString = string
export declare type Numbers = number | bigint | string | HexString
const isHexStrict = hex => typeof hex === 'string' && /^((-)?0x[0-9a-f]+|(0x))$/i.test(hex)
export declare type ValidInputTypes = Uint8Array | bigint | string | number | boolean
export const isHex = (hex: ValidInputTypes): boolean =>
typeof hex === 'number' ||
typeof hex === 'bigint' ||
(typeof hex === 'string' && /^((-0x|0x|-)?[0-9a-f]+|(0x))$/i.test(hex))
const base = BigInt(10)
const expo10 = (expo: number) => base ** BigInt(expo)
export const ethUnitMap = {
noether: BigInt('0'),
wei: BigInt(1),
kwei: expo10(3),
Kwei: expo10(3),
babbage: expo10(3),
femtoether: expo10(3),
mwei: expo10(6),
Mwei: expo10(6),
lovelace: expo10(6),
picoether: expo10(6),
gwei: expo10(9),
Gwei: expo10(9),
shannon: expo10(9),
nanoether: expo10(9),
nano: expo10(9),
szabo: expo10(12),
microether: expo10(12),
micro: expo10(12),
finney: expo10(15),
milliether: expo10(15),
milli: expo10(15),
ether: expo10(18),
kether: expo10(21),
grand: expo10(21),
mether: expo10(24),
gether: expo10(27),
tether: expo10(30),
}
export type EtherUnits = keyof typeof ethUnitMap
/**
* Converts value to it's number representation
*/
export const hexToNumber = (value: string): bigint | number => {
if (!isHexStrict(value)) {
throw new Error('Invalid hex string')
}
const [negative, hexValue] = value.startsWith('-') ? [true, value.slice(1)] : [false, value]
const num = BigInt(hexValue)
if (num > Number.MAX_SAFE_INTEGER) {
return negative ? -num : num
}
if (num < Number.MIN_SAFE_INTEGER) {
return num
}
return negative ? -1 * Number(num) : Number(num)
}
export const toNumber = (value: Numbers): number | bigint => {
if (typeof value === 'number') {
return value
}
if (typeof value === 'bigint') {
return value >= Number.MIN_SAFE_INTEGER && value <= Number.MAX_SAFE_INTEGER ? Number(value) : value
}
if (typeof value === 'string' && isHexStrict(value)) {
return hexToNumber(value)
}
try {
return toNumber(BigInt(value))
} catch {
throw new Error('ivalid number: ' + value)
}
}
/**
* Auto converts any given value into it's bigint representation
*
* @param value - The value to convert
* @returns - Returns the value in bigint representation
* @example
* ```ts
* console.log(web3.utils.toBigInt(1));
* > 1n
* ```
*/
export const toBigInt = (value: unknown): bigint => {
if (typeof value === 'number') {
return BigInt(value)
}
if (typeof value === 'bigint') {
return value
}
// isHex passes for dec, too
if (typeof value === 'string' && isHex(value)) {
return BigInt(value)
}
if (typeof value === 'string' && value.indexOf(',') >= 0) {
return BigInt(value.replace(/,/g, ''))
}
throw new Error('invalid number' + value)
}
export const toBigWei = (number: Numbers, unit: EtherUnits = 'ether'): bigint => {
return toBigInt(toWei(number, unit))
}
export const toWei = (number: Numbers, unit: EtherUnits = 'ether'): string => {
const denomination = ethUnitMap[unit]
if (!denomination) {
throw new Error('error unit: ' + unit)
}
// if value is decimal e.g. 24.56 extract `integer` and `fraction` part
// to avoid `fraction` to be null use `concat` with empty string
typeof number === 'string' && number.indexOf(',') >= 0 && (number = number.replace(/,/g, ''))
const [integer, fraction] = String(typeof number === 'string' && !isHexStrict(number) ? number : toNumber(number))
.split('.')
.concat('')
// join the value removing `.` from
// 24.56 -> 2456
const value = BigInt(`${integer}${fraction}`)
// multiply value with denomination
// 2456 * 1000000 -> 2456000000
const updatedValue = value * denomination
// count number of zeros in denomination
const numberOfZerosInDenomination = denomination.toString().length - 1
// check which either `fraction` or `denomination` have lower number of zeros
const decimals = Math.min(fraction.length, numberOfZerosInDenomination)
if (decimals === 0) {
return updatedValue.toString()
}
// Add zeros to make length equal to required decimal points
// If string is larger than decimal points required then remove last zeros
return updatedValue.toString().padStart(decimals, '0').slice(0, -decimals)
}
/**
* Takes a number of wei and converts it to any other ether unit.
* @param number - The value in wei
* @param unit - The unit to convert to
* @returns - Returns the converted value in the given unit
*
* @example
* ```ts
* console.log(web3.utils.fromWei("1", "ether"));
* > 0.000000000000000001
*
* console.log(web3.utils.fromWei("1", "shannon"));
* > 0.000000001
* ```
*/
export const fromWei = (number: Numbers, unit: EtherUnits = 'ether'): string => {
const denomination = ethUnitMap[unit]
if (!denomination) {
throw new Error('invalid unit: ' + unit)
}
// value in wei would always be integer
// 13456789, 1234
const value = String(toNumber(number))
// count number of zeros in denomination
// 1000000 -> 6
const numberOfZerosInDenomination = denomination.toString().length - 1
if (numberOfZerosInDenomination <= 0) {
return value.toString()
}
// pad the value with required zeros
// 13456789 -> 13456789, 1234 -> 001234
const zeroPaddedValue = value.padStart(numberOfZerosInDenomination, '0')
// get the integer part of value by counting number of zeros from start
// 13456789 -> '13'
// 001234 -> ''
const integer = zeroPaddedValue.slice(0, -numberOfZerosInDenomination)
// get the fraction part of value by counting number of zeros backward
// 13456789 -> '456789'
// 001234 -> '001234'
const fraction = zeroPaddedValue.slice(-numberOfZerosInDenomination).replace(/\.?0+$/, '')
if (integer === '') {
return `0.${fraction}`
}
if (fraction === '') {
return integer
}
return `${integer}.${fraction}`
}

View File

@ -1,47 +0,0 @@
/**
*
* @param {Function} cb
* @param {number} maxRetries
* @param {any[]} errorWhiteList
* @param {number} retries
* @return {Promise<T>}
*/
export function retry<T = any>(cb: Function, maxRetries: number = 3, errorWhiteList: any[] = [], retries: number = 0) {
return new Promise<T>((resolve, reject) => {
cb()
.then(resolve)
.catch(e => {
if (errorWhiteList.indexOf(e.constructor) !== -1 && retries++ < maxRetries) {
setTimeout(() => {
retry<T>(cb, maxRetries, errorWhiteList, retries)
.then(resolve)
.catch(e2 => reject(e2))
}, Math.floor(Math.random() * Math.pow(2, retries) * 400))
} else {
reject(e)
}
})
})
}
export class Deferred<T = any> {
public promise: Promise<T>
public resolve: Function
public reject: Function
constructor() {
this.promise = new Promise<T>((resolve, reject) => {
this.resolve = resolve
this.reject = reject
})
}
public then(func: (value: T) => any) {
return this.promise.then.apply(this.promise, arguments)
}
public catch(func: (value: any) => any) {
return this.promise.catch(func)
}
}

View File

@ -1,74 +0,0 @@
import crypto from 'crypto'
import { compressUuid } from './string.util'
const ENCODER = 'base64'
const REG_KEY = /^[0-9a-fA-F]{63,64}$/
export function isEncrypt(msg: string) {
return !REG_KEY.test(msg)
}
export function aesEncrypt(text: string, password: string, iv: string) {
var md5 = crypto.createHash('md5')
const key = md5.update(password).digest('hex')
let cipher = crypto.createCipheriv('aes-256-cbc', key, iv)
let encrypted = cipher.update(text, 'utf8', ENCODER)
encrypted += cipher.final(ENCODER)
return encrypted
}
export function aesDecrypt(encryptedText: string, password: string, iv: string) {
var md5 = crypto.createHash('md5')
const key = md5.update(password).digest('hex')
let decipher = crypto.createDecipheriv('aes-256-cbc', key, iv)
let decrypted = decipher.update(encryptedText, ENCODER, 'utf8')
return decrypted + decipher.final('utf8')
}
export function hmacsha256(text: string, secret: string) {
const mac = crypto.createHmac('sha256', secret)
const data = mac.update(text).digest('hex').toLowerCase()
console.log(`HmacSHA256 rawContent is [${text}], key is [${secret}], hash result is [${data}]`)
return data
}
export function sha512(password: string, salt: string) {
let hash = crypto.createHmac('sha512', salt)
hash.update(password)
let value = hash.digest('hex')
return {
salt: salt,
passwordHash: value,
}
}
export function sha3_256(str: string) {
let hash = crypto.createHash('sha3-256')
hash.update(str)
return hash.digest('hex')
}
export function genRandomString(length: number) {
return crypto
.randomBytes(Math.ceil(length / 2))
.toString('hex')
.slice(0, length)
}
export function uuid() {
return crypto.randomUUID()
}
export function shortUuid() {
let uid = uuid()
return compressUuid(uid)
}
export function md5(content: string) {
var md5 = crypto.createHash('md5')
return md5.update(content).digest('hex')
}
export function sha1(content: string) {
var md5 = crypto.createHash('sha1')
return md5.update(content).digest('hex')
}

View File

@ -1,137 +0,0 @@
/**
* key升序生成 key1=val1&key2=val2的字符串
* @param {object} data
* @param {boolean} ignoreNull (null值不参与拼接)
* @param splitChar , &
* @param equalChar =
*/
export function generateKeyValStr(data: Record<string, any>, ignoreNull = true, splitChar = '&', equalChar = '=') {
const keys = Object.keys(data)
keys.sort()
let result = ''
let i = 0
for (let key of keys) {
if (ignoreNull && !data[key]) {
return
}
if (i++ > 0) result += splitChar
result += `${key}${equalChar}${data[key]}`
}
return result
}
/**
* key1=val&key2=val的字符串组装成对象
* @param str key1=val&key2=val的字符串
* @param splitChar , &
* @param equalChar =
*/
export function keyValToObject(str: string, splitChar: string = '&', equalChar = '='): {} {
let result = {}
if (!str) {
return result
}
let arrs = str.split(splitChar)
for (let sub of arrs) {
let subArr = sub.split(equalChar)
result[subArr[0]] = subArr[1]
}
return result
}
/**
* true
* @param {Object} obj 'true','TRUE',1,'1','on','ON','YES','yes',true,false
* @return {boolean}
*/
export function isTrue(obj) {
return (
obj === 'true' ||
obj === 'TRUE' ||
obj === 'True' ||
obj === 'on' ||
obj === 'ON' ||
obj === true ||
obj === 1 ||
obj === '1' ||
obj === 'YES' ||
obj === 'yes'
)
}
/**
* ObjectId格式是否正确
* @param {string} id
* @return {boolean}
*/
export function isObjectId(id: string): boolean {
//mongoose.Types.ObjectId.isValid(id)
return /^[a-fA-F0-9]{24}$/.test(id)
}
/**
* 10 -> 62
* @param {string | number} number
* @return {string}
*/
export function string10to62(number: string | number) {
const chars = '0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ'.split('')
const radix = chars.length
let qutient = +number
const arr = []
do {
const mod = qutient % radix
qutient = (qutient - mod) / radix
arr.unshift(chars[mod])
} while (qutient)
return arr.join('')
}
/**
* 62 -> 10
* @param {string} numberCode
* @return {number}
*/
export function string62to10(numberCode: string) {
const chars = '0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ'
const radix = chars.length
numberCode = numberCode + ''
const len = numberCode.length
let i = 0
let originNumber = 0
while (i < len) {
originNumber += Math.pow(radix, i++) * (chars.indexOf(numberCode.charAt(len - i)) || 0)
}
return originNumber
}
const reNormalUUID = /^[0-9a-fA-F-]{36}$/
const reLongUUID = /^[0-9a-fA-F]{32}$/
const reShortUUID = /^[0-9a-zA-Z+/]{22,23}$/
const n = /-/g
export function compressUuid(e: string, t: boolean = false) {
if (reNormalUUID.test(e)) {
e = e.replace(n, '')
} else if (!reLongUUID.test(e)) {
return e
}
var r = !0 === t ? 2 : 5
return compressHex(e, r)
}
const CHARS_BASE64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
export function compressHex(e: string, r: number) {
var i,
n = e.length
i = void 0 !== r ? r : n % 3
for (var s = e.slice(0, i), o = []; i < n; ) {
var u = parseInt(e[i], 16),
a = parseInt(e[i + 1], 16),
c = parseInt(e[i + 2], 16)
o.push(CHARS_BASE64[(u << 2) | (a >> 2)])
o.push(CHARS_BASE64[((3 & a) << 4) | c])
i += 3
}
return s + o.join('')
}