UNPKG

@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
/*! * ==================================================== * 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 };