@rzl-zone/utils-js
Version:
A modern, lightweight set of JavaScript utility functions with TypeScript support for everyday development, crafted to enhance code readability and maintainability.
270 lines (261 loc) • 11.6 kB
JavaScript
/*!
* ====================================================
* Rzl Utils-JS.
* ----------------------------------------------------
* Version: 3.11.0.
* Author: Rizalvin Dwiky.
* Repository: https://github.com/rzl-zone/utils-js.
* ====================================================
*/
;
var chunk7FGNVDEV_cjs = require('./chunk-7FGNVDEV.cjs');
var chunkBAV5T2E3_cjs = require('./chunk-BAV5T2E3.cjs');
var chunkDAPAK2W3_cjs = require('./chunk-DAPAK2W3.cjs');
var chunkSYHPSOUU_cjs = require('./chunk-SYHPSOUU.cjs');
var parseCustomDate = (dateString, format) => {
if (!chunkSYHPSOUU_cjs.isNonEmptyString(dateString) || !chunkSYHPSOUU_cjs.isNonEmptyString(format)) {
throw new TypeError(
`Parameter \`dateString\` and \`format\` must be of type \`string\` and not empty-string, but received: "['dateString': \`${chunkSYHPSOUU_cjs.getPreciseType(
dateString
)}\` - (current value: \`${chunkDAPAK2W3_cjs.safeStableStringify(dateString, {
keepUndefined: true
})}\`), 'format': \`${chunkSYHPSOUU_cjs.getPreciseType(
format
)}\` - (current value: \`${chunkDAPAK2W3_cjs.safeStableStringify(format, {
keepUndefined: true
})}\`)]".`
);
}
const dateParts = dateString.split(/[-/]/).map(Number);
if (dateParts.length !== 3 || dateParts.some(isNaN)) return null;
let day, month, year;
if (format === "DD/MM/YYYY") {
[day, month, year] = dateParts;
} else if (format === "MM/DD/YYYY") {
[month, day, year] = dateParts;
} else {
return null;
}
month -= 1;
const date = new Date(year, month, day);
if (date.getFullYear() !== year || date.getMonth() !== month || date.getDate() !== day) {
return null;
}
return date;
};
var validateJsonParsingOptions = (optionsValue = {}) => {
chunkSYHPSOUU_cjs.assertIsPlainObject(optionsValue, {
message: ({ currentType, validType }) => `Second parameter (\`options\`) must be of type \`${validType}\`, but received: \`${currentType}\`.`
});
const convertBooleans = chunkSYHPSOUU_cjs.hasOwnProp(optionsValue, "convertBooleans") ? optionsValue.convertBooleans : false;
const convertDates = chunkSYHPSOUU_cjs.hasOwnProp(optionsValue, "convertDates") ? optionsValue.convertDates : false;
const convertNumbers = chunkSYHPSOUU_cjs.hasOwnProp(optionsValue, "convertNumbers") ? optionsValue.convertNumbers : false;
const loggingOnFail = chunkSYHPSOUU_cjs.hasOwnProp(optionsValue, "loggingOnFail") ? optionsValue.loggingOnFail : false;
const removeEmptyArrays = chunkSYHPSOUU_cjs.hasOwnProp(optionsValue, "removeEmptyArrays") ? optionsValue.removeEmptyArrays : false;
const removeEmptyObjects = chunkSYHPSOUU_cjs.hasOwnProp(optionsValue, "removeEmptyObjects") ? optionsValue.removeEmptyObjects : false;
const removeNulls = chunkSYHPSOUU_cjs.hasOwnProp(optionsValue, "removeNulls") ? optionsValue.removeNulls : false;
const removeUndefined = chunkSYHPSOUU_cjs.hasOwnProp(optionsValue, "removeUndefined") ? optionsValue.removeUndefined : false;
const strictMode = chunkSYHPSOUU_cjs.hasOwnProp(optionsValue, "strictMode") ? optionsValue.strictMode : false;
const checkSymbols = chunkSYHPSOUU_cjs.hasOwnProp(optionsValue, "checkSymbols") ? optionsValue.checkSymbols : false;
const convertNaN = chunkSYHPSOUU_cjs.hasOwnProp(optionsValue, "convertNaN") ? optionsValue.convertNaN : false;
const customDateFormats = chunkSYHPSOUU_cjs.hasOwnProp(optionsValue, "customDateFormats") ? optionsValue.customDateFormats : [];
const onError = chunkSYHPSOUU_cjs.hasOwnProp(optionsValue, "onError") ? optionsValue.onError : chunkBAV5T2E3_cjs.noop;
if (!(chunkSYHPSOUU_cjs.isBoolean(convertBooleans) && chunkSYHPSOUU_cjs.isBoolean(convertDates) && chunkSYHPSOUU_cjs.isBoolean(convertNumbers) && chunkSYHPSOUU_cjs.isBoolean(convertNaN) && chunkSYHPSOUU_cjs.isBoolean(checkSymbols) && chunkSYHPSOUU_cjs.isBoolean(loggingOnFail) && chunkSYHPSOUU_cjs.isBoolean(removeEmptyArrays) && chunkSYHPSOUU_cjs.isBoolean(removeEmptyObjects) && chunkSYHPSOUU_cjs.isBoolean(removeNulls) && chunkSYHPSOUU_cjs.isBoolean(removeUndefined) && chunkSYHPSOUU_cjs.isBoolean(strictMode) && chunkSYHPSOUU_cjs.isArray(customDateFormats) && chunkSYHPSOUU_cjs.isFunction(onError))) {
throw new TypeError(
`Invalid \`options\` parameter (second argument): \`convertBooleans\`, \`convertDates\`, \`convertNumbers\`, \`loggingOnFail\`, \`removeEmptyArrays\`, \`removeEmptyObjects\`, \`removeNulls\`, \`removeUndefined\`, \`strictMode\` expected to be a \`boolean\` type, \`customDateFormats\` expected to be a \`array\` type and \`onError\` expected to be a \`void function\` type. But received: ['convertBooleans': \`${chunkSYHPSOUU_cjs.getPreciseType(
convertBooleans
)}\`, 'convertDates': \`${chunkSYHPSOUU_cjs.getPreciseType(
convertDates
)}\`, 'convertNumbers': \`${chunkSYHPSOUU_cjs.getPreciseType(
convertNumbers
)}\`, 'loggingOnFail': \`${chunkSYHPSOUU_cjs.getPreciseType(
loggingOnFail
)}\`, 'removeEmptyArrays': \`${chunkSYHPSOUU_cjs.getPreciseType(
removeEmptyArrays
)}\`, 'removeEmptyObjects': \`${chunkSYHPSOUU_cjs.getPreciseType(
removeEmptyObjects
)}\`, 'removeNulls': \`${chunkSYHPSOUU_cjs.getPreciseType(
removeNulls
)}\`, 'removeUndefined': \`${chunkSYHPSOUU_cjs.getPreciseType(
removeUndefined
)}\`, 'strictMode': \`${chunkSYHPSOUU_cjs.getPreciseType(
strictMode
)}\`, 'customDateFormats': \`${chunkSYHPSOUU_cjs.getPreciseType(
customDateFormats
)}\`, 'onError': \`${chunkSYHPSOUU_cjs.getPreciseType(onError)}\`].`
);
}
return {
convertBooleans,
convertDates,
convertNumbers,
convertNaN,
loggingOnFail,
removeEmptyArrays,
removeEmptyObjects,
removeNulls,
removeUndefined,
strictMode,
customDateFormats,
onError,
checkSymbols
};
};
var cleanParsedData = (data, options = {}) => {
const validOptions = validateJsonParsingOptions(options);
if (chunkSYHPSOUU_cjs.isNull(data)) return validOptions.removeNulls ? void 0 : null;
if (chunkSYHPSOUU_cjs.isUndefined(data)) return validOptions.removeUndefined ? void 0 : void 0;
if (chunkSYHPSOUU_cjs.isString(data)) {
const trimmed = data.trim();
if (validOptions.convertNaN && trimmed === "NaN") return NaN;
if (validOptions.convertNumbers && !isNaN(Number(trimmed))) {
return Number(trimmed);
}
if (validOptions.convertBooleans) {
if (trimmed === "true") return true;
if (trimmed === "false") return false;
}
if (validOptions.convertDates) {
if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(trimmed)) {
return new Date(trimmed);
}
if (validOptions.customDateFormats?.length) {
for (const format of validOptions.customDateFormats) {
const date = parseCustomDate(trimmed, format);
if (date) return date;
}
}
}
return validOptions.strictMode ? void 0 : trimmed;
}
if (chunkSYHPSOUU_cjs.isArray(data)) {
const cleanedArray = data.map((item) => cleanParsedData(item, validOptions)).filter((item) => !chunkSYHPSOUU_cjs.isUndefined(item));
return validOptions.removeEmptyArrays && chunk7FGNVDEV_cjs.isEmptyArray(cleanedArray) ? void 0 : cleanedArray;
}
if (chunkSYHPSOUU_cjs.isObject(data)) {
const cleanedObject = {};
for (const key in data) {
if (Object.prototype.hasOwnProperty.call(data, key)) {
const cleanedValue = cleanParsedData(data[key], validOptions);
if (!chunkSYHPSOUU_cjs.isUndefined(cleanedValue)) {
cleanedObject[key] = cleanedValue;
}
}
}
return validOptions.removeEmptyObjects && chunk7FGNVDEV_cjs.isEmptyObject(cleanedObject, { checkSymbols: validOptions.checkSymbols }) ? void 0 : cleanedObject;
}
return validOptions.strictMode ? void 0 : data;
};
var extractDigits = (value) => {
if (!chunkSYHPSOUU_cjs.isString(value) && !chunkSYHPSOUU_cjs.isNumber(value)) return 0;
const cleaned = String(value).trim().replace(/[^0-9]/g, "");
return Number(cleaned) || 0;
};
function fixSingleQuotesEscapeBackslash(input) {
const validEscapes = /* @__PURE__ */ new Set(["\\", '"', "/", "b", "f", "n", "r", "t", "u"]);
let output = "";
let inSingleQuote = false;
let inDoubleQuote = false;
let escapeNext = false;
for (let i = 0; i < input.length; i++) {
const c = input[i];
if (escapeNext) {
if (inSingleQuote) {
if (c === "'") {
output += "'";
} else if (validEscapes.has(c)) {
if (c === "\\") {
output += "\\\\";
} else if (c === '"') {
output += '\\"';
} else {
output += "\\" + c;
}
} else {
output += "\\\\" + c;
}
} else if (inDoubleQuote) {
if (c === '"') {
output += '\\"';
} else if (validEscapes.has(c)) {
output += "\\" + c;
} else {
output += "\\\\" + c;
}
} else {
output += "\\" + c;
}
escapeNext = false;
continue;
}
if (c === "\\") {
escapeNext = true;
continue;
}
if (!inSingleQuote && !inDoubleQuote) {
if (c === "'") {
output += '"';
inSingleQuote = true;
continue;
}
if (c === '"') {
output += '"';
inDoubleQuote = true;
continue;
}
} else if (inSingleQuote) {
if (c === "'") {
output += '"';
inSingleQuote = false;
continue;
}
} else if (inDoubleQuote) {
if (c === '"') {
output += '"';
inDoubleQuote = false;
continue;
}
}
output += c;
}
return output;
}
function safeJsonParse(value, options = {}) {
if (chunkSYHPSOUU_cjs.isNull(value)) return null;
const validOptions = validateJsonParsingOptions(options);
if (validOptions.convertNaN && (chunkSYHPSOUU_cjs.isNaN(value) || chunkSYHPSOUU_cjs.isNonEmptyString(value) && value === "NaN")) {
return NaN;
}
if (validOptions.convertNumbers && !chunkSYHPSOUU_cjs.isNaN(Number(value)) && chunkSYHPSOUU_cjs.isNumber(extractDigits(value))) {
return Number(value);
}
if (!chunkSYHPSOUU_cjs.isString(value)) return void 0;
try {
let normalized = fixSingleQuotesEscapeBackslash(value);
if (validOptions.removeUndefined) {
normalized = normalized.replace(/,\s*"[^"]*"\s*:\s*undefined(?=\s*[},])/g, "").replace(/"[^"]*"\s*:\s*undefined\s*(,)?/g, "");
} else {
normalized = normalized.replace(/:\s*undefined(?=\s*[,}])/g, ":null");
}
if (validOptions.convertNaN) {
normalized = normalized.replace(/:\s*NaN(?=\s*[,}])/g, ':"NaN"');
} else {
normalized = normalized.replace(/:\s*NaN(?=\s*[,}])/g, ':"NaN"').replace(/,\s*"[^"]*"\s*:\s*NaN(?=\s*[},])/g, "").replace(/"[^"]*"\s*:\s*NaN\s*(,)?/g, "");
}
normalized = normalized.replace(/,(\s*[}\]])/g, "$1");
const parsed = JSON.parse(normalized);
return cleanParsedData(parsed, validOptions);
} catch (error) {
if (validOptions.loggingOnFail) {
console.error("Failed to parsing at `safeJsonParse`:", error);
}
validOptions.onError(
chunkSYHPSOUU_cjs.isError(error) ? new Error(error.message.replace(/^JSON\.parse:/, "Failed to parsing")) : new Error(String(error))
);
return void 0;
}
}
exports.cleanParsedData = cleanParsedData;
exports.extractDigits = extractDigits;
exports.parseCustomDate = parseCustomDate;
exports.safeJsonParse = safeJsonParse;