@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.
233 lines (227 loc) • 8.43 kB
JavaScript
/*!
* ====================================================
* Rzl Utils-JS.
* ----------------------------------------------------
* Version: 3.11.0.
* Author: Rizalvin Dwiky.
* Repository: https://github.com/rzl-zone/utils-js.
* ====================================================
*/
import { isURL } from './chunk-ONZFBJVW.js';
import { normalizeString } from './chunk-BPYW5YL7.js';
import { toStringArrayUnRecursive } from './chunk-22V4WP3H.js';
import { isEmptyValue } from './chunk-UIAWUZ4H.js';
import { isInteger } from './chunk-WVSPXFTY.js';
import { normalizePathname } from './chunk-SZUNAEMR.js';
import { isEmptyString } from './chunk-ULQPCIA2.js';
import { assertIsArray } from './chunk-RZOGBYIS.js';
import { safeStableStringify } from './chunk-AXDYWO67.js';
import { isString, getPreciseType, isUndefined, isNonEmptyString, isFunction, isNumber, isError, isArray, isNil, isNull, isPlainObject, isBoolean, isNonEmptyArray } from './chunk-MSUW5VHZ.js';
var constructURL = (baseUrl, queryParams, removeParams) => {
if (isString(baseUrl)) {
if (isEmptyString(baseUrl)) {
throw new TypeError(`First parameter (\`baseUrl\`) cannot be an empty-string.`);
}
baseUrl = normalizeString(baseUrl);
} else if (!isURL(baseUrl)) {
throw new TypeError(
`First parameter (\`baseUrl\`) must be of type an URL instance or a \`string\` and a non empty-string, but received: \`${getPreciseType(
baseUrl
)}\`, with current value: \`${safeStableStringify(baseUrl, {
keepUndefined: true
})}\`.`
);
}
if (!isUndefined(removeParams)) {
assertIsArray(removeParams, {
message: ({ currentType, validType }) => `Third parameter (\`removeParams\`) must be of type \`${validType} of strings\`, but received: \`${currentType}\`.`
});
if (!removeParams.every((param) => isNonEmptyString(param))) {
throw new TypeError(
`Third parameter (\`removeParams\`) must be of type \`array\` and contains \`string\` only and non empty-string.`
);
}
}
try {
if (!isUndefined(queryParams) && !isFunction(queryParams[Symbol.iterator])) {
throw new TypeError(
`Second parameter (\`queryParams\`) must be iterable (like URLSearchParams.entries() or an array of [[string, string | number]...]), but received: \`${getPreciseType(
queryParams
)}\`, with value: \`${safeStableStringify(queryParams, {
keepUndefined: true
})}\`.`
);
}
const urlInstance = new URL(baseUrl);
if (!isUndefined(queryParams)) {
const paramObject = Object.fromEntries(queryParams);
if (!isEmptyValue(paramObject)) {
const mergedParams = new URLSearchParams(urlInstance.search);
for (const [key, value] of Object.entries(paramObject)) {
if (!isNonEmptyString(value) && !isNumber(value, { includeNaN: true })) {
throw new TypeError(
`Second parameter (\`queryParams\`) must be iterable (like URLSearchParams.entries() or an array of [[string, string | number]...]), but received: \`${getPreciseType(
queryParams
)}\`, with value: \`${safeStableStringify(queryParams, {
keepUndefined: true
})}\`.`
);
}
mergedParams.set(key, String(value));
}
if (removeParams?.length) {
toStringArrayUnRecursive(removeParams).map((paramKey) => {
mergedParams.delete(paramKey);
});
}
urlInstance.search = mergedParams.toString();
}
}
removeParams?.forEach((param) => urlInstance.searchParams.delete(param));
return urlInstance;
} catch (error) {
if (isError(error)) throw error;
throw new Error(
"Failed to construct a valid URL in `constructURL()`, Error:" + error
);
}
};
var extractURLs = (url) => {
if (!isNonEmptyString(url)) return null;
let decoded;
try {
decoded = decodeURIComponent(url);
} catch {
return null;
}
const urlPattern = /https?:\/\/.*?(?=https?:\/\/|\s|$)/g;
const matches = decoded.match(urlPattern);
if (!matches) return null;
const cleaned = matches.map((url2) => url2.replace(/[.,;:!?)]*$/, "")).filter((url2) => {
try {
const u = new URL(url2);
return u.protocol === "http:" || u.protocol === "https:";
} catch {
return false;
}
});
return cleaned.length ? cleaned : null;
};
var getFirstPrefixPathname = (result, defaultValue = "/") => {
if (!isNonEmptyString(defaultValue)) {
throw new TypeError(
`Second parameter (\`defaultValue\`) must be of type \`string\` and not an \`empty-string\`, but received: \`${getPreciseType(
defaultValue
)}\`, with value: \`${safeStableStringify(defaultValue, {
keepUndefined: true
})}\`.`
);
}
if (isArray(result)) {
if (!result.every((item) => isString(item))) {
throw new TypeError(
`First parameter (\`result\`) must be of type \`string\` or \`array of string\`, but received: \`${getPreciseType(
result
)}\`, with value: \`${safeStableStringify(result, {
keepUndefined: true
})}\`.`
);
}
for (const item of result) {
const normalized = normalizePathname(item);
if (normalized !== "/") {
return normalized;
}
}
return normalizePathname(defaultValue);
}
if (isString(result)) {
const normalized = normalizePathname(result);
return normalized !== "/" ? normalized : normalizePathname(defaultValue);
}
if (!isNil(result)) {
throw new TypeError(
`First parameter (\`result\`) must be of type \`string\`, \`array-string\`, \`null\` or \`undefined\`, but received: \`${getPreciseType(
result
)}\`.`
);
}
return normalizePathname(defaultValue);
};
var getPrefixPathname = (url, base = null, options = {}) => {
const errors = [];
if (!isString(url) && !isArray(url)) {
errors.push(
`First parameter (\`url\`) must be of type \`string\` or \`array-string\`, but received: \`${getPreciseType(
url
)}\`.`
);
}
if (!isString(base) && !isArray(base) && !isNull(base)) {
errors.push(
`Second parameter (\`base\`) must be of type \`string\`, \`array-string\` or \`null\`, but received: \`${getPreciseType(
base
)}\`.`
);
}
if (!isPlainObject(options)) {
errors.push(
`Second parameter (\`options\`) must be of type \`plain-object\`, but received: \`${getPreciseType(
options
)}\`.`
);
}
const { levels = 1, removeDuplicates = true } = options;
if (!isInteger(levels) || isInteger(levels) && levels < 0) {
errors.push(
`Parameter \`levels\` property of the \`options\` (second parameter) must be of type \`integer-number\` and minimum is \`0\`, but received: \`${getPreciseType(
levels
)}\`, with value: \`${safeStableStringify(levels, {
keepUndefined: true
})}\`.`
);
}
if (!isBoolean(removeDuplicates)) {
errors.push(
`Parameter \`removeDuplicates\` property of the \`options\` (second parameter) must be of type \`boolean\`, but received: \`${getPreciseType(
removeDuplicates
)}\`.`
);
}
if (isNonEmptyArray(errors)) {
throw new TypeError(
`Invalid parameter(s) in \`getPrefixPathname\` function:
- ${errors.join("\n- ")}`
);
}
function getLevel(singleUrl) {
const parts = normalizePathname(singleUrl).split("/").filter(Boolean);
return `/${parts.slice(0, levels).join("/")}`;
}
function processUrl(singleUrl) {
if (base) {
singleUrl = normalizePathname(singleUrl);
if (isArray(base)) {
for (const b of base) {
if (singleUrl.startsWith(normalizePathname(b))) {
return getLevel(singleUrl);
}
}
} else if (isNonEmptyString(base) && singleUrl.startsWith(normalizePathname(base))) {
return getLevel(singleUrl);
}
return null;
}
return getLevel(singleUrl);
}
if (isArray(url)) {
const result = url.map(processUrl).filter((r) => !isNull(r));
const uniqueResult = removeDuplicates ? [...new Set(result)] : result;
if (uniqueResult.length === 1) {
return uniqueResult[0];
}
return uniqueResult;
}
return processUrl(url);
};
export { constructURL, extractURLs, getFirstPrefixPathname, getPrefixPathname };