@techmely/utils
Version:
Collection of helpful JavaScript / TypeScript utils
641 lines (620 loc) • 18.9 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
/*!
* @techmely/utils
* Copyright(c) 2021-2022 Techmely <techmely.creation@gmail.com>
* MIT Licensed
*/
// src/array/index.ts
function unique(array) {
return [...new Set(array)];
}
function take(array, limit) {
return array.slice(0, limit);
}
function findLastIndex(array, predicate) {
let l = array.length;
while (l--) {
if (predicate(array[l], l, array)) {
return l;
}
}
return -1;
}
function groupBy(list, keyGetter) {
const map = /* @__PURE__ */ new Map();
list.forEach((item) => {
const key = keyGetter(item);
const collection = map.get(key);
if (collection) {
collection.push(item);
} else {
map.set(key, [item]);
}
});
return map;
}
var remove = (arr, el) => {
const i = arr.indexOf(el);
if (i > -1) {
arr.splice(i, 1);
}
};
function sample(arr, count) {
return Array.from({ length: count }, (_) => arr[Math.round(Math.random() * (arr.length - 1))]);
}
function shuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
const factor = Math.floor(Math.random() * (i + 1));
[array[i], array[factor]] = [array[factor], array[i]];
}
return array;
}
// src/base/index.ts
var noop = () => {
};
var assert = (condition, message) => {
if (!condition) {
throw new Error(message);
}
};
// src/bytes/index.ts
var formatBytes = (bytes, options) => {
const sizes = ["bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
const { numberOfDecimals = 0 } = options ?? {};
if (!bytes || bytes <= 0) {
return "0 bytes";
}
if (bytes === 1) {
return "1 byte";
}
const base = 1e3;
const exponent = Math.trunc(Math.log(bytes) / Math.log(base));
const rawValue = bytes / base ** exponent;
let [whole, partial = ""] = rawValue.toString().split(".");
if (numberOfDecimals > 0) {
const count = numberOfDecimals - partial.length;
if (count > 0) {
partial += "0".repeat(count);
}
whole += `.${partial.slice(0, numberOfDecimals)}`;
}
const abbreviationSuffix = sizes[exponent];
return `${whole} ${abbreviationSuffix}`;
};
var formatDecimals = (bytes = 0) => bytes >= 1e9 ? 2 : 0;
// src/calculate/index.ts
function clamp(n, min, max) {
return Math.min(max, Math.max(min, n));
}
function sum(...args) {
return [...args].flat(1).reduce((a, b) => a + b, 0);
}
function lerp(y1, y2, mu) {
return y1 * (1 - mu) + y2 * mu;
}
// src/regex/index.ts
var emailRegex = new RegExp(
/^(([^\s"(),.:;<>@[\\\]]+(\.[^\s"(),.:;<>@[\\\]]+)*)|(".+"))@((\[(?:\d{1,3}\.){3}\d{1,3}])|(([\dA-Za-z-]+\.)+[A-Za-z]{2,}))$/
);
var isValidEmail = (email) => emailRegex.test(email);
var vietnamPhoneRegex = new RegExp(/^0(\d{9})$/);
var isValidVnPhone = (phone) => vietnamPhoneRegex.test(phone);
var urlRegex = /(((^https?:(?:\/\/)?)(?:[\w$&+,:;=-]+@)?[\d.A-Za-z-]+(?::\d+)?|(?:www.|[\w$&+,:;=-]+@)[\d.A-Za-z-]+)((?:\/[\w%+./~-]*)?\??[\w%&+.;=@-]*(?:#\w*)?)?)$/;
var isValidUrl = (path) => urlRegex.test(path);
var hexColor = /^#(([\da-f]{2}){3,4})$/;
var multilineCommentsRegex = /\/\*(.|[\r\n])*?\*\//gm;
var singlelineCommentsRegex = /\/\/.*/g;
var escapedSpaceCharactersRegex = /( |\\t|\\n|\\f|\\r)+/g;
// src/colors/index.ts
function isHex(hex) {
return hexColor.test(hex);
}
function percentToHex(percent) {
if (percent < 0 || percent > 100) {
throw new Error("Value must in range [0, 100]");
}
const intValue = Math.round(percent / 100 * 255);
const hexValue = intValue.toString(16);
return hexValue.padStart(2, "0").toUpperCase();
}
var HEX_LENGTH = 6;
var HEX_OPACITY_LENGTH = 8;
function alphaHex(hex, alpha) {
if (!hex) {
throw new Error("Hex value is required");
}
if (hex.length === HEX_OPACITY_LENGTH) {
return `${hex.slice(0, HEX_LENGTH)}${percentToHex(alpha)}`;
}
return `${hex}${percentToHex(alpha)}`;
}
// src/mines/index.ts
var MimeType = /* @__PURE__ */ ((MimeType2) => {
MimeType2["JPG"] = "image/jpeg";
MimeType2["GIF"] = "image/gif";
MimeType2["PNG"] = "image/png";
MimeType2["MP4"] = "video/mp4";
MimeType2["QuickTime"] = "video/quicktime";
MimeType2["AVI"] = "video/x-msvideo";
MimeType2["WMV"] = "video/x-ms-wmv";
MimeType2["HEIC"] = "image/heic";
return MimeType2;
})(MimeType || {});
var mimeTable = [
{ ext: ["gif"], type: "image/gif" /* GIF */ },
{ ext: ["jpe", "jpeg", "jpg"], type: "image/jpeg" /* JPG */ },
{ ext: ["png"], type: "image/png" /* PNG */ },
{ ext: ["qt", "mov"], type: "video/quicktime" /* QuickTime */ },
{ ext: ["mp4", "mp4v", "mpg4", "m4v"], type: "video/mp4" /* MP4 */ },
{ ext: ["avi"], type: "video/x-msvideo" /* AVI */ },
{ ext: ["wmv"], type: "video/x-ms-wmv" /* WMV */ },
{ ext: ["heic"], type: "image/heic" /* HEIC */ }
];
var getMimeTypeFromExtension = (extension) => {
const result = mimeTable.find(({ ext }) => ext.includes(extension));
if (!result) {
throw new Error(`'${extension}' is not a valid extension`);
}
return result.type;
};
// src/download/index.ts
function downloadByData(data, filename, mime, bom) {
const blobData = typeof bom !== "undefined" ? [bom, data] : [data];
const blob = new Blob(blobData, { type: mime || "application/octet-stream" });
const blobURL = window.URL.createObjectURL(blob);
const tempLink = document.createElement("a");
tempLink.style.display = "none";
tempLink.href = blobURL;
tempLink.setAttribute("download", filename);
tempLink.dataset.testid = "link-download-blob-file";
if (typeof tempLink.download === "undefined") {
tempLink.setAttribute("target", "_blank");
}
document.body.append(tempLink);
tempLink.click();
document.body.removeChild(tempLink);
window.URL.revokeObjectURL(blobURL);
}
// src/is/index.ts
function isNotNull(v) {
return v !== null;
}
function isArray(val) {
return val && Array.isArray(val);
}
function isPrimitive(value) {
if (value === null) {
return true;
}
return !["array", "function", "object"].includes(typeof value);
}
var isDef = (val) => typeof val !== "undefined";
var isUndef = (val) => !isDef(val);
var isBoolean = (val) => typeof val === "boolean";
var isFunction = (val) => typeof val === "function";
var isNumber = (val) => toString.call(val) === "[object Number]";
var isString = (val) => typeof val === "string";
var isObject = (val) => toString.call(val) === "[object Object]";
var isMap = (val) => toString.call(val) === "[object Map]";
var isSet = (val) => toString.call(val) === "[object Set]";
var isDate = (val) => toString.call(val) === "[object Date]";
var isSymbol = (val) => typeof val === "symbol";
var isPromise = (val) => {
return isObject(val) && isFunction(val.then) && isFunction(val.catch);
};
var isFalsy = (val) => isNotNull(val) && isDef(val) && isNotEmpty(val);
var isWindow = (val) => typeof window !== "undefined" && toString.call(val) === "[object Window]";
var isStream = (val) => val !== null && typeof val === "object" && typeof val.pipe === "function";
var isBrowser = typeof window !== "undefined";
var isEmptyArr = (array) => (array == null ? void 0 : array.length) === 0;
function isEmpty(val) {
if (!val) {
return true;
}
if (isArray(val)) {
return isEmptyArr(val);
}
if (isString(val)) {
return val.trim().length === 0;
}
if (val instanceof Map || val instanceof Set) {
return val.size === 0;
}
if (isObject(val)) {
return Object.keys(val).length === 0;
}
return false;
}
function isNotEmpty(val) {
return !isEmpty(val);
}
function isNotEmpties(...args) {
if (args.length > 1) {
return args.reduce((a, b) => a && isNotEmpty(b), true);
}
return false;
}
function isEmpties(...args) {
if (args.length > 1) {
return args.reduce((a, b) => a && isEmpty(b), true);
}
return false;
}
function isPngImage(buffer) {
if (!buffer || buffer.length < 8) {
return false;
}
return buffer[0] === 137 && buffer[1] === 80 && buffer[2] === 78 && buffer[3] === 71 && buffer[4] === 13 && buffer[5] === 10 && buffer[6] === 26 && buffer[7] === 10;
}
// src/object/index.ts
function deepMerge(target, ...sources) {
if (sources.length === 0) {
return target;
}
const source = sources.shift();
if (source === void 0) {
return target;
}
if (isMergeableObject(target) && isMergeableObject(source)) {
Object.keys(source).forEach((key) => {
if (isMergeableObject(source[key])) {
if (!target[key]) {
target[key] = {};
}
deepMerge(target[key], source[key]);
} else {
target[key] = source[key];
}
});
}
return deepMerge(target, ...sources);
}
function isMergeableObject(item) {
return isObject(item) && !isArray(item);
}
function removeEmptyObj(obj) {
return Object.fromEntries(
Object.entries(obj).filter(([_, v]) => isNotNull(v) && isDef(v) && isNotEmpty(v))
);
}
function removeUndefObj(obj) {
Object.keys(obj).forEach(
(key) => isUndef(obj[key]) ? obj[key] = void 0 : {}
);
return obj;
}
function objectMap(obj, fn) {
return Object.fromEntries(
Object.entries(obj).map(([k, v]) => fn(k, v)).filter(isNotNull)
);
}
function isKeyOf(obj, k) {
return k in obj;
}
function objectKeys(obj) {
return Object.keys(obj);
}
function objectEntries(obj) {
return Object.entries(obj);
}
function objectPick(obj, keys, omitUndefined = false) {
return keys.reduce((n, k) => {
if (k in obj) {
if (!omitUndefined || obj[k] !== void 0) {
n[k] = obj[k];
}
}
return n;
}, {});
}
function pick(from, val) {
return val.replace(/\[([^\[\]]*)\]/g, ".$1.").split(".").filter((t) => t !== "").reduce((prev, cur) => prev && prev[cur], from);
}
function objectGet(from, selector) {
return pick(from, selector);
}
function objectGets(from, ...selectors) {
return [...selectors].map((s) => pick(from, s));
}
var hasChanged = (value, oldValue) => !Object.is(value, oldValue);
// src/string/index.ts
var cacheStringFunction = (fn) => {
const cache = /* @__PURE__ */ Object.create(null);
return (str) => {
const hit = cache[str];
return hit || (cache[str] = fn(str));
};
};
var camelizeRE = /-(\w)/g;
var camelize = cacheStringFunction((str) => {
return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : "");
});
var hyphenateRE = /\B([A-Z])/g;
var hyphenate = cacheStringFunction(
(str) => str.replace(hyphenateRE, "-$1").toLowerCase()
);
var snake2camel = cacheStringFunction((src) => {
return src.replace(/_([a-z])/g, (g) => g[1].toUpperCase());
});
var capitalizeFirst = cacheStringFunction((value) => {
return value.replace(/^./, value[0].toUpperCase());
});
function slugify(text) {
if (!text) {
return "";
}
return text.toString().normalize("NFKD").toLowerCase().trim().replace(/\s+/g, "-").replace(/[Đđ]/g, "d").replace(/[^\w-]+/g, "").replace(/--+/g, "-");
}
function getRandomString(length, alphanumeric) {
let str = "";
let i = 0;
const min = alphanumeric === "a" ? 10 : 0;
const max = alphanumeric === "n" ? 10 : 62;
while (i++ < length) {
let r = Math.trunc(Math.random() * (max - min) + min);
str += String.fromCodePoint(r += r > 9 ? r < 36 ? 55 : 61 : 48);
}
return str;
}
// src/convert/index.ts
function intToHex(integer) {
if (integer < 0) {
throw new Error("Invalid integer as argument, must be unsigned!");
}
const hex = integer.toString(16);
return hex.length % 2 ? `0${hex}` : hex;
}
function intToBuffer(integer) {
const hex = intToHex(integer);
return Buffer.from(hex, "hex");
}
// src/vector/index.ts
function neg(A) {
return [-A[0], -A[1]];
}
function add(A, B) {
return [A[0] + B[0], A[1] + B[1]];
}
function sub(A, B) {
return [A[0] - B[0], A[1] - B[1]];
}
function vec(A, B) {
return [B[0] - A[0], B[1] - A[1]];
}
function mul(A, n) {
return [A[0] * n, A[1] * n];
}
function div(A, n) {
return [A[0] / n, A[1] / n];
}
function per(A) {
return [A[1], -A[0]];
}
function dpr(A, B) {
return A[0] * B[0] + A[1] * B[1];
}
function len(A) {
return Math.hypot(A[0], A[1]);
}
function len2(A) {
return A[0] * A[0] + A[1] * A[1];
}
function dist2(A, B) {
return len2(sub(A, B));
}
function uni(A) {
return div(A, len(A));
}
function dist(A, B) {
return Math.hypot(A[1] - B[1], A[0] - B[0]);
}
function med(A, B) {
return mul(add(A, B), 0.5);
}
function rotAround(A, C, r) {
const s = Math.sin(r);
const c = Math.cos(r);
const px = A[0] - C[0];
const py = A[1] - C[1];
const nx = px * c - py * s;
const ny = px * s + py * c;
return [nx + C[0], ny + C[1]];
}
function lrp(A, B, t) {
return add(A, mul(vec(A, B), t));
}
function isLeft(p1, pc, p2) {
return (pc[0] - p1[0]) * (p2[1] - p1[1]) - (p2[0] - p1[0]) * (pc[1] - p1[1]);
}
function clockwise(p1, pc, p2) {
return isLeft(p1, pc, p2) > 0;
}
function isEqual(a, b) {
return a[0] === b[0] && a[1] === b[1];
}
function toPointsArray(points) {
if (isArray(points[0])) {
return points.map(([x, y, pressure = 0.5]) => [x, y, pressure]);
}
return points.map(({ x, y, pressure = 0.5 }) => [x, y, pressure]);
}
function getStrokeRadius(size, thinning, easing, pressure = 0.5) {
if (!thinning) {
return size / 2;
}
const newPressure = clamp(easing(pressure), 0, 1);
return (thinning < 0 ? lerp(size, size + size * clamp(thinning, -0.95, -0.05), newPressure) : lerp(size - size * clamp(thinning, 0.05, 0.95), size, newPressure)) / 2;
}
// src/generate/index.ts
function getRandomIntInclusive(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1) + min);
}
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min) + min);
}
// src/cookie/index.ts
var CookieServices = (nodeEnv, env, cookieDomain) => {
const cookieTokenName = `token_${env}`;
return {
authToken: cookieTokenName,
get(name) {
var _a;
if (typeof window !== "undefined") {
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) {
return (_a = parts.pop()) == null ? void 0 : _a.split(";").shift();
}
return null;
}
return null;
},
remove(cookieName, options) {
const isSecure = options == null ? void 0 : options.secure;
document.cookie = nodeEnv === "production" ? `${cookieName}=; path=/; Domain=${cookieDomain}; ${isSecure ? "Secure" : ""}` : `${cookieName}=; path=/; Secure`;
},
setAppToken(token) {
document.cookie = nodeEnv === "production" ? `${cookieTokenName}=${token}; path=/; Domain=${cookieDomain}; Secure` : `${cookieTokenName}=${token}; path=/; Secure`;
},
getAppToken() {
const appToken = this.get(cookieTokenName);
return appToken;
},
removeAppToken() {
this.remove(cookieTokenName, { secure: true });
},
parseCookie: (cookies) => {
var _a;
return (_a = cookies == null ? void 0 : cookies.split("; ")) == null ? void 0 : _a.reduce((prev, current) => {
const [name, ...value] = current.split("=");
prev[name] = value.join("=");
return prev;
}, {});
},
listenCookieChange(callback, interval = 500) {
let lastCookie = document.cookie;
setInterval(() => {
const { cookie } = document;
if (cookie !== lastCookie) {
try {
callback({
oldCookie: this.parseCookie(lastCookie),
newCookie: this.parseCookie(cookie)
});
} finally {
lastCookie = cookie;
}
}
}, interval);
}
};
};
// src/index.ts
var __DEV__ = process.env.NODE_ENV !== "production";
var EMPTY_OBJ = __DEV__ ? Object.freeze({}) : {};
var EMPTY_ARR = __DEV__ ? Object.freeze([]) : [];
exports.CookieServices = CookieServices;
exports.EMPTY_ARR = EMPTY_ARR;
exports.EMPTY_OBJ = EMPTY_OBJ;
exports.MimeType = MimeType;
exports.add = add;
exports.alphaHex = alphaHex;
exports.assert = assert;
exports.camelize = camelize;
exports.capitalizeFirst = capitalizeFirst;
exports.clamp = clamp;
exports.clockwise = clockwise;
exports.deepMerge = deepMerge;
exports.dist = dist;
exports.dist2 = dist2;
exports.div = div;
exports.downloadByData = downloadByData;
exports.dpr = dpr;
exports.emailRegex = emailRegex;
exports.escapedSpaceCharactersRegex = escapedSpaceCharactersRegex;
exports.findLastIndex = findLastIndex;
exports.formatBytes = formatBytes;
exports.formatDecimals = formatDecimals;
exports.getMimeTypeFromExtension = getMimeTypeFromExtension;
exports.getRandomInt = getRandomInt;
exports.getRandomIntInclusive = getRandomIntInclusive;
exports.getRandomString = getRandomString;
exports.getStrokeRadius = getStrokeRadius;
exports.groupBy = groupBy;
exports.hasChanged = hasChanged;
exports.hexColor = hexColor;
exports.hyphenate = hyphenate;
exports.intToBuffer = intToBuffer;
exports.intToHex = intToHex;
exports.isArray = isArray;
exports.isBoolean = isBoolean;
exports.isBrowser = isBrowser;
exports.isDate = isDate;
exports.isDef = isDef;
exports.isEmpties = isEmpties;
exports.isEmpty = isEmpty;
exports.isEqual = isEqual;
exports.isFalsy = isFalsy;
exports.isFunction = isFunction;
exports.isHex = isHex;
exports.isKeyOf = isKeyOf;
exports.isLeft = isLeft;
exports.isMap = isMap;
exports.isNotEmpties = isNotEmpties;
exports.isNotEmpty = isNotEmpty;
exports.isNotNull = isNotNull;
exports.isNumber = isNumber;
exports.isObject = isObject;
exports.isPngImage = isPngImage;
exports.isPrimitive = isPrimitive;
exports.isPromise = isPromise;
exports.isSet = isSet;
exports.isStream = isStream;
exports.isString = isString;
exports.isSymbol = isSymbol;
exports.isUndef = isUndef;
exports.isValidEmail = isValidEmail;
exports.isValidUrl = isValidUrl;
exports.isValidVnPhone = isValidVnPhone;
exports.isWindow = isWindow;
exports.len = len;
exports.len2 = len2;
exports.lerp = lerp;
exports.lrp = lrp;
exports.med = med;
exports.mimeTable = mimeTable;
exports.mul = mul;
exports.multilineCommentsRegex = multilineCommentsRegex;
exports.neg = neg;
exports.noop = noop;
exports.objectEntries = objectEntries;
exports.objectGet = objectGet;
exports.objectGets = objectGets;
exports.objectKeys = objectKeys;
exports.objectMap = objectMap;
exports.objectPick = objectPick;
exports.per = per;
exports.percentToHex = percentToHex;
exports.remove = remove;
exports.removeEmptyObj = removeEmptyObj;
exports.removeUndefObj = removeUndefObj;
exports.rotAround = rotAround;
exports.sample = sample;
exports.shuffle = shuffle;
exports.singlelineCommentsRegex = singlelineCommentsRegex;
exports.slugify = slugify;
exports.snake2camel = snake2camel;
exports.sub = sub;
exports.sum = sum;
exports.take = take;
exports.toPointsArray = toPointsArray;
exports.uni = uni;
exports.unique = unique;
exports.urlRegex = urlRegex;
exports.vec = vec;
exports.vietnamPhoneRegex = vietnamPhoneRegex;