@catbee/utils
Version:
A modular, production-grade utility toolkit for Node.js and TypeScript, designed for robust, scalable applications (including Express-based services). All utilities are tree-shakable and can be imported independently.
260 lines (253 loc) • 9.04 kB
JavaScript
/*
* The MIT License
*
* Copyright (c) 2026 Catbee Technologies. https://catbee.in/license
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
;
var net = require('net');
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
var net__default = /*#__PURE__*/_interopDefault(net);
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var PORT_REGEX = /^[0-9]{1,5}$/;
var UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
var PHONE_ALLOWED_CHARS_REGEX = /^[+]?[0-9\s().-]+$/;
var ALPHANUMERIC_REGEX = /^[A-Za-z0-9]+$/;
var HEX_COLOR_REGEX = /^#([a-f0-9]{6}|[a-f0-9]{3})$/i;
var ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})?)?$/;
var BASE64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
var DOT_ATOM_REGEX = /^[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*$/;
var QUOTED_LOCAL_REGEX = /^"([\s\x21\x23-\x5B\x5D-\x7E]|\\[\x20-\x7E])*"$/;
var TLD_REGEX = /^[A-Za-z]{2,63}$/;
function isPort(value) {
if (typeof value === "number") return Number.isInteger(value) && value > 0 && value <= 65535;
if (!value || typeof value !== "string") return false;
const str = value.trim();
if (!PORT_REGEX.test(str)) return false;
const port = Number(str);
return Number.isInteger(port) && port > 0 && port <= 65535;
}
__name(isPort, "isPort");
function isEmail(str) {
if (!str || typeof str !== "string" || str.length > 254) return false;
const atIndex = str.indexOf("@");
if (atIndex === -1 || atIndex !== str.lastIndexOf("@")) return false;
const local = str.slice(0, atIndex);
const domain = str.slice(atIndex + 1);
if (!local || !domain) return false;
if (!DOT_ATOM_REGEX.test(local) && !QUOTED_LOCAL_REGEX.test(local)) return false;
if (domain.includes("..")) return false;
const labels = domain.split(".");
if (labels.some((l) => !l.length)) return false;
if (labels.length < 2) return false;
const labelRegex = /^[A-Za-z0-9-]{1,63}$/;
for (const label of labels) {
if (!labelRegex.test(label)) return false;
if (label.startsWith("-") || label.endsWith("-")) return false;
}
const tld = labels.at(-1) || "";
if (!TLD_REGEX.test(tld)) return false;
return true;
}
__name(isEmail, "isEmail");
function isUUID(str) {
return UUID_REGEX.test(str);
}
__name(isUUID, "isUUID");
function isURL(str, allowedProtocols = [
"http",
"https",
"ws",
"wss"
]) {
if (!str || typeof str !== "string") return false;
try {
const url = new URL(str);
return allowedProtocols.includes(url.protocol.replace(":", ""));
} catch {
return false;
}
}
__name(isURL, "isURL");
function isPhone(str) {
if (!str || typeof str !== "string") return false;
const digits = str.replace(/\D/g, "");
if (digits.length < 6 || digits.length > 15) return false;
return PHONE_ALLOWED_CHARS_REGEX.test(str);
}
__name(isPhone, "isPhone");
function isAlphanumeric(str) {
if (!str || typeof str !== "string") return false;
return ALPHANUMERIC_REGEX.test(str);
}
__name(isAlphanumeric, "isAlphanumeric");
function isNumeric(value) {
if (typeof value === "number") return Number.isFinite(value);
if (!value || typeof value !== "string") return false;
const str = value.trim();
if (str === "" || str.length > 16) return false;
const num = Number(str);
return Number.isFinite(num);
}
__name(isNumeric, "isNumeric");
function isHexColor(str) {
if (!str || typeof str !== "string") return false;
return HEX_COLOR_REGEX.test(str);
}
__name(isHexColor, "isHexColor");
function isISODate(str) {
if (!str || typeof str !== "string") return false;
if (!ISO_DATE_REGEX.test(str)) return false;
const date = new Date(str);
return !Number.isNaN(date.getTime());
}
__name(isISODate, "isISODate");
function isLengthBetween(str, min, max) {
if (typeof str !== "string") return false;
return str.length >= min && str.length <= max;
}
__name(isLengthBetween, "isLengthBetween");
function isNumberBetween(value, min, max) {
if (typeof value !== "number" || !Number.isFinite(value)) return false;
return value >= min && value <= max;
}
__name(isNumberBetween, "isNumberBetween");
function isAlpha(str) {
if (!str || typeof str !== "string") return false;
return /^[a-zA-Z]+$/.test(str);
}
__name(isAlpha, "isAlpha");
function isStrongPassword(str) {
if (str.length < 8) return false;
const hasUpperCase = /[A-Z]/.test(str);
const hasLowerCase = /[a-z]/.test(str);
const hasNumbers = /[0-9]/.test(str);
const hasSpecialChar = /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>?]/.test(str);
return hasUpperCase && hasLowerCase && hasNumbers && hasSpecialChar;
}
__name(isStrongPassword, "isStrongPassword");
function isIPv4(str) {
if (!str || typeof str !== "string") return false;
const parts = str.split(".");
if (parts.length !== 4) return false;
return parts.every((p) => {
if (p.length > 3 || p.startsWith("0") && p.length > 1) return false;
const n = Number(p);
return Number.isInteger(n) && n >= 0 && n <= 255;
});
}
__name(isIPv4, "isIPv4");
function isIPv6(str) {
if (!str || typeof str !== "string" || str.length > 45) return false;
try {
return net__default.default.isIP(str) === 6;
} catch {
return false;
}
}
__name(isIPv6, "isIPv6");
function isCreditCard(str) {
if (!str || typeof str !== "string") return false;
const s = str.replace(/\D/g, "");
if (s.length < 13 || s.length > 19) return false;
let sum = 0;
for (let i = 0, dbl = false; i < s.length; i++, dbl = !dbl) {
let d = s.charCodeAt(s.length - 1 - i) - 48;
if (dbl) {
d *= 2;
if (d > 9) d -= 9;
}
sum += d;
}
return sum % 10 === 0;
}
__name(isCreditCard, "isCreditCard");
function isValidJSON(str) {
if (!str || typeof str !== "string") return false;
try {
JSON.parse(str);
return true;
} catch {
return false;
}
}
__name(isValidJSON, "isValidJSON");
function isArray(value, itemGuard) {
if (!Array.isArray(value)) return false;
return !itemGuard || value.every((item) => itemGuard(item));
}
__name(isArray, "isArray");
function isBase64(str) {
if (!str || typeof str !== "string") return false;
return BASE64_REGEX.test(str);
}
__name(isBase64, "isBase64");
function hasRequiredProps(obj, requiredProps) {
if (!obj || typeof obj !== "object") return false;
return requiredProps.every((prop) => Object.hasOwn(obj, prop) && obj[prop] != null);
}
__name(hasRequiredProps, "hasRequiredProps");
function isDateInRange(date, minDate, maxDate) {
if (!(date instanceof Date) || !Number.isFinite(date.getTime())) return false;
if (minDate && date < minDate) return false;
if (maxDate && date > maxDate) return false;
return true;
}
__name(isDateInRange, "isDateInRange");
function matchesPattern(str, pattern) {
if (typeof str !== "string") return false;
return pattern.test(str);
}
__name(matchesPattern, "matchesPattern");
function validateAll(value, validators) {
if (!Array.isArray(validators)) return false;
return validators.every((fn) => {
try {
return fn(value);
} catch {
return false;
}
});
}
__name(validateAll, "validateAll");
exports.hasRequiredProps = hasRequiredProps;
exports.isAlpha = isAlpha;
exports.isAlphanumeric = isAlphanumeric;
exports.isArray = isArray;
exports.isBase64 = isBase64;
exports.isCreditCard = isCreditCard;
exports.isDateInRange = isDateInRange;
exports.isEmail = isEmail;
exports.isHexColor = isHexColor;
exports.isIPv4 = isIPv4;
exports.isIPv6 = isIPv6;
exports.isISODate = isISODate;
exports.isLengthBetween = isLengthBetween;
exports.isNumberBetween = isNumberBetween;
exports.isNumeric = isNumeric;
exports.isPhone = isPhone;
exports.isPort = isPort;
exports.isStrongPassword = isStrongPassword;
exports.isURL = isURL;
exports.isUUID = isUUID;
exports.isValidJSON = isValidJSON;
exports.matchesPattern = matchesPattern;
exports.validateAll = validateAll;