UNPKG

build-url-ts

Version:

A small library that builds a URL given its components

118 lines (116 loc) 5.36 kB
function customEncodeURIComponent(str) { return encodeURIComponent(str).replace(/'/g, "%27").replace(/`/g, "%60"); } function buildQueryString(queryParams, lowerCase, disableCSV, useCustomEncoding = true) { const encode = (input) => useCustomEncoding ? customEncodeURIComponent(input) : encodeURIComponent(input); const queryParts = []; for (const [key, value] of Object.entries(queryParams)) { if (value === void 0) continue; const encodedKey = encode(lowerCase ? key.toLowerCase() : key); if (!Array.isArray(value)) { queryParts.push(`${encodedKey}=${encode(formatValue(value, lowerCase))}`); continue; } const items = value.filter((item) => item !== void 0); if (items.length === 0) continue; if (!disableCSV) { const csvValue = items.map((item) => formatValue(item, lowerCase)).join(","); queryParts.push(`${encodedKey}=${encode(csvValue)}`); continue; } let index = disableCSV === "order_desc" ? items.length - 1 : 0; for (const item of items) { const encodedValue = encode(formatValue(item, lowerCase)); switch (disableCSV) { case "array": queryParts.push(`${encodedKey}[]=${encodedValue}`); break; case "order_asc": queryParts.push(`${encodedKey}[${index++}]=${encodedValue}`); break; case "order_desc": queryParts.push(`${encodedKey}[${index--}]=${encodedValue}`); break; default: queryParts.push(`${encodedKey}=${encodedValue}`); break; } } } return queryParts.length > 0 ? `?${queryParts.join("&")}` : ""; } function formatValue(value, lowerCase) { if (value === null || value === void 0) return ""; if (typeof value === "boolean") return value.toString(); if (value === 0) return "0"; if (typeof value === "number" && Number.isNaN(value)) return "NaN"; if (!value) return ""; const stringValue = value instanceof Date ? value.toString() : typeof value === "object" && !Array.isArray(value) ? JSON.stringify(value) : String(value).trim(); return lowerCase ? stringValue.toLowerCase() : stringValue; } function appendPath(path, builtUrl, lowerCase) { const url = builtUrl != null ? builtUrl : ""; const trimmedPath = String(path).trim(); const pathString = lowerCase ? trimmedPath.toLowerCase() : trimmedPath; if (!pathString) return url; if (pathString === "/") { return url.endsWith("/") ? url : `${url}/`; } const hasTrailingSlash = pathString.endsWith("/"); const cleanedPath = pathString.split("/").filter((segment) => segment.length > 0).join("/"); const finalPath = hasTrailingSlash && cleanedPath ? `${cleanedPath}/` : cleanedPath; const baseUrl = url.replace(/\/+$/, ""); return finalPath ? `${baseUrl}/${finalPath}` : baseUrl; } function buildHash(hash, lowerCase) { const trimmedHash = String(hash).trim(); if (!trimmedHash) return ""; const hashString = `#${trimmedHash}`; return lowerCase ? hashString.toLowerCase() : hashString; } function parseUrl(url) { const queryParams = {}; const hashIndex = url.indexOf("#"); const hash = hashIndex === -1 ? "" : url.substring(hashIndex + 1); const withoutHash = hashIndex === -1 ? url : url.substring(0, hashIndex); const queryIndex = withoutHash.indexOf("?"); if (queryIndex === -1) { return { baseUrl: withoutHash, queryParams, hash }; } const baseUrl = withoutHash.substring(0, queryIndex); const queryString = withoutHash.substring(queryIndex + 1); for (const pair of queryString.split("&")) { if (!pair) continue; const eqIndex = pair.indexOf("="); const rawKey = eqIndex === -1 ? pair : pair.substring(0, eqIndex); const rawValue = eqIndex === -1 ? "" : pair.substring(eqIndex + 1); if (rawKey) { queryParams[decodeURIComponent(rawKey)] = rawValue ? decodeURIComponent(rawValue) : ""; } } return { baseUrl, queryParams, hash }; } function buildUrl(url, options) { var _a, _b; const hasStringUrl = typeof url === "string"; const parsed = hasStringUrl ? parseUrl(url) : null; const buildOptions = url !== null && typeof url === "object" ? url : options; let result = (_a = parsed == null ? void 0 : parsed.baseUrl) != null ? _a : ""; const segments = []; if (buildOptions == null ? void 0 : buildOptions.path) segments.push(buildOptions.path); if (buildOptions == null ? void 0 : buildOptions.paths) segments.push(...buildOptions.paths); for (const segment of segments) { result = appendPath(segment, result, buildOptions == null ? void 0 : buildOptions.lowerCase); } const allQueryParams = { ...parsed == null ? void 0 : parsed.queryParams, ...buildOptions == null ? void 0 : buildOptions.queryParams }; if (Object.keys(allQueryParams).length > 0) { result += buildQueryString(allQueryParams, buildOptions == null ? void 0 : buildOptions.lowerCase, buildOptions == null ? void 0 : buildOptions.disableCSV, false); } const finalHash = (buildOptions == null ? void 0 : buildOptions.hash) !== void 0 ? buildOptions.hash : (_b = parsed == null ? void 0 : parsed.hash) != null ? _b : ""; if (finalHash) { result += buildHash(finalHash, buildOptions == null ? void 0 : buildOptions.lowerCase); } return result; } export { appendPath, buildHash, buildQueryString, buildUrl, buildUrl as default }; //# sourceMappingURL=index.mjs.map