@ghini/kit
Version:
js practical tools to assist efficient development
171 lines • 5.13 kB
JavaScript
export {
uuid,
rint,
rside,
gchar,
fhash,
empty,
idhash,
arr_uniq,
arr_diff,
addobjs,
obj2v1,
addTwoDimensionalObjects,
}
import crypto from "crypto";
/**
* 将用户ID转换为高度随机化的唯一推广码
* @param {number} userId - 用户ID (1-10000000000)
* @returns {string} - 唯一推广码 (保证7位及以上)
*/
function idhash(userId) {
const base62 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const m = BigInt(62) ** BigInt(7);
const a = BigInt(12345678901);
let code_num = (a * BigInt(userId)) % m;
let digits = [];
for (let i = 0; i < 7; i++) {
let digit = code_num % BigInt(62);
digits.push(base62[Number(digit)]);
code_num = code_num / BigInt(62);
}
return digits.reverse().join('');
}
/** 数组去重 */
function arr_uniq(arr) {
return [...new Set(arr)];
}
/** 数组差集 从arr1中过滤掉arr2中存在的元素 */
function arr_diff(arr1, arr2) {
const set2 = new Set(arr2);
return arr1.filter(x => !set2.has(x));
}
function uuid(len = 21) {
const byteLength = Math.ceil((len * 3) / 4);
const randomString = crypto.randomBytes(byteLength).toString("base64url");
return randomString.substring(0, len);
}
/** 每个数同等概率,随机例如-3到10 10到-3的整数,可单写5:0-5 */
function rint(a, b = 0) {
if (a > b) {
return Math.floor(Math.random() * (a + 1 - b)) + b;
} else {
return Math.floor(Math.random() * (b + 1 - a)) + a;
}
}
function rside() {
return Math.random() > 0.5 ? 1 : -1;
}
function addTwoDimensionalObjects(...objects) {
const level1Keys = [...new Set(objects.flatMap((obj) => Object.keys(obj)))];
const level2Keys = [
...new Set(
objects.flatMap((obj) =>
Object.values(obj).flatMap((innerObj) => Object.keys(innerObj))
)
),
];
const result = {};
level1Keys.forEach((key1) => {
result[key1] = {};
level2Keys.forEach((key2) => {
result[key1][key2] = objects.reduce((sum, obj) => {
if (!obj[key1]) return sum;
return sum + (obj[key1][key2] || 0);
}, 0);
});
});
return result;
}
function obj2v1(obj2v) {
return Object.fromEntries(
Object.entries(obj2v).map(([key, value]) => {
if (
typeof value === "object" &&
value !== null &&
!Array.isArray(value)
) {
return [
key,
Object.values(value).reduce(
(sum, val) => sum + (typeof val === "number" ? val / 1048576 : 0),
0
),
];
}
return [key, value];
})
);
}
function addobjs(...objects) {
const keys = [...new Set(objects.flatMap((obj) => Object.keys(obj)))];
return keys.reduce((result, key) => {
result[key] = objects.reduce((sum, obj) => sum + (obj[key] || 0), 0);
return result;
}, {});
}
/**
* fhash(fasthash) 生成易于识别图像验证的验证码,服务端应设置最大8位,防止堵塞 n>8?n=8:n;也可以用来随机生码测试性能
* @param {string|Buffer|TypedArray|DataView} cx - 要计算哈希的输入数据,可以是字符串、Buffer 或其他支持的数据类型。
* @param {string} [encode='base64url'] - 指定哈希值的输出编码格式,支持 'hex'、'base64'、'base64url' 等。
* @param {string} [type='sha256'] - 指定哈希算法,默认使用 'sha256',支持 'md5'、'sha1'、'sha512' 等。
* @returns {string} 生成的哈希值,编码格式由 `encode` 参数决定。
*/
function fhash(cx, encode = "base64url", type = "sha256") {
return crypto.createHash(type).update(cx).digest(encode);
}
function gchar(n = 6, characters = 0) {
if (typeof characters === "number") {
switch (characters) {
case 0:
characters = "0123456789";
break;
case 1:
characters = "23457ACDFGHJKLPQRSTUVWXY23457";
break;
case 2:
characters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
break;
case 3:
characters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
break;
case 4:
characters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
break;
}
}
let result = "";
for (let i = 0; i < n; i++) {
const idx = Math.floor(Math.random() * characters.length);
result += characters[idx];
}
return result;
}
/**
* empty 判断一切空,主要是{}和[],为true
* 如果递归recursive=true,当所含内容全是空值,也判断为空返回true:
* @example
* empty({a:[[[[[]]]],{}],b:false,c:null,d:0,e:NaN,f:''},true) //true
* @param {*} x
* @param {*} recursive
* @returns {bool}
*/
function empty(x, recursive = false) {
if (recursive) {
if (!x) return true;
if (Array.isArray(x)) {
return x.length === 0 || x.every((item) => empty(item, true));
}
if (typeof x === "object") {
return (
Object.keys(x).length === 0 ||
Object.values(x).every((value) => empty(value, true))
);
}
return false;
}
return !x || (typeof x === "object" && Object.keys(x).length === 0);
}