UNPKG

@techmely/utils

Version:

Collection of helpful JavaScript / TypeScript utils

641 lines (620 loc) 18.9 kB
'use strict'; 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;