UNPKG

@cc-heart/utils

Version:

🔧 javascript common tools collection

152 lines (149 loc) • 5.24 kB
import { hasOwn, isObject } from './validate.js'; function parseKey(obj, key, value) { const isArrayKey = key.includes('[') && key.includes(']'); if (isArrayKey) { const keys = key.split(/[[\]]/).filter(Boolean); let currentObj = obj; for (let i = 0; i < keys.length; i++) { let currentKey = keys[i]; if (currentKey.startsWith('.')) currentKey = currentKey.split('.')[1]; if (i === keys.length - 1) { if (Array.isArray(currentObj)) { currentObj.push(value); } else { currentObj[currentKey] = value; } } else { if (!currentObj[currentKey]) { currentObj[currentKey] = keys[i + 1].match(/^\d+$/) ? [] : {}; } currentObj = currentObj[currentKey]; } } } else { let nestedObj = obj; const keyParts = key.split('.'); for (let i = 0; i < keyParts.length - 1; i++) { const currentKey = keyParts[i]; if (!nestedObj[currentKey]) { nestedObj[currentKey] = {}; } nestedObj = nestedObj[currentKey]; } nestedObj[keyParts[keyParts.length - 1]] = value; } } /** * Converts a query string to an object. * * @example `queryStringToObject('foo=1&bar=2&baz=3')` * @example `queryStringToObject('foo=&bar=2&baz=3')` * @example `queryStringToObject('foo[0]=1&foo[1]=2&baz=3')` * @template T - The type of the URL string. * @template U - The type of the object to return. * @param {T} url - The URL string to convert. * @returns {U} The object representation of the query string in `url`. */ function queryStringToObject(url) { const result = {}; if (url) { url.split('&').forEach((item) => { const [rawKey, value] = item.split('='); const key = decodeURIComponent(rawKey); parseKey(result, key, decodeURIComponent(value)); }); } return result; } /** * Converts an object to a query string. * * @param data - The object to convert. * @returns The query string representation of `data`. */ function objectToQueryString(data) { const res = []; for (const key in data) { if (hasOwn(data, key)) { if (Array.isArray(data[key])) { res.push(arrayToQueryString(data[key], key)); } else { res.push(`${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`); } } } return res.join('&'); } /** * convert params routes to regular expressions * * @param path a params paths * @returns null or An array contains the RegExp that matches the params and the path for each params parameter */ function convertParamsRouterToRegExp(path) { const matcher = path.match(/:(.*?)(?:\/|$)/g); if (matcher === null) return null; const reg = new RegExp(path.replace(/:(.*?)(\/|$)/g, '.*?$2')); return [reg, matcher.map((val) => val.replace(/:(.*?)(\/|$)/g, '$1'))]; } /** * Returns the last portion of a path, similar to the Unix basename command. * Trims the query string if it exists. * Optionally, removes a suffix from the result. * * @param path - The path to get the basename from. * @param [suffix] - An optional suffix to remove from the basename. * @returns The basename of the path. */ function basename(path, suffix) { const separator = '/'; const index = path.lastIndexOf(separator); let str = path.slice(index + 1); if (str) { const querySeparator = str.lastIndexOf('?'); if (querySeparator !== -1) { str = str.slice(0, querySeparator); } } if (suffix) { return str.replace(new RegExp(suffix + '$'), ''); } return str; } /** * Convert a multi-dimensional array to a query string. * @param array The multi-dimensional array to convert. * @param field The field name to use in the query string. * @returns The generated query string. */ function arrayToQueryString(array, field) { let queryString = ''; function buildQueryString(arr, prefix) { arr.forEach((element, index) => { if (Array.isArray(element)) { buildQueryString(element, `${prefix}${encodeURIComponent(`[${index}]`)}`); } else if (isObject(element)) { for (const key in element) { if (hasOwn(element, key)) { queryString += `${prefix}${encodeURIComponent(`[${index}]`)}.${encodeURIComponent(key)}=${encodeURIComponent(String(Reflect.get(element, key)))}&`; } } } else { queryString += `${prefix}${encodeURIComponent(`[${index}]`)}=${encodeURIComponent(String(element))}&`; } }); } buildQueryString(array, field); // Remove the trailing '&' if present queryString = queryString.slice(0, -1); return queryString; } export { arrayToQueryString, basename, convertParamsRouterToRegExp, objectToQueryString, parseKey, queryStringToObject };