Created
February 16, 2022 11:47
-
-
Save gtrabanco/84cde5075458541517b5edb8d1c9f298 to your computer and use it in GitHub Desktop.
Parse urls like express router or react router to accept params in url and replace params in url
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function getURLParams(urlWithParams) { | |
const paramsURLParts = urlWithParams.split('/'); | |
let params = {}; | |
for (const index in paramsURLParts) { | |
let parsedParam; | |
let part = paramsURLParts.at(index); | |
if (part.match(/:([\w_]{1}[\w0-9-_]+)/i)) { | |
part = part.replace(':', ''); | |
} | |
// Optional | |
parsedParam = part.match(/^\[([.]{2,3})?([\w_]{1}[\w0-9-_]+)\]$/i); | |
if (parsedParam) { | |
const lastGetOtherPars = | |
parseInt(index) === paramsURLParts.length - 1 && | |
parsedParam[1] !== 'undefined'; | |
params[parsedParam[2].toLowerCase()] = { | |
mandatory: false, | |
index: parseInt(index), | |
lastGetOtherPars, | |
}; | |
continue; | |
} | |
// Mandatory Param | |
parsedParam = part.match(/^([.]{2,3})?([\w_]{1}[\w0-9-_]+)$/i); | |
if (parsedParam) { | |
const lastGetOtherPars = | |
parseInt(index) === paramsURLParts.length - 1 && | |
parsedParam[1] !== 'undefined'; | |
params[parsedParam[2].toLowerCase()] = { | |
mandatory: true, | |
index: parseInt(index), | |
lastGetOtherPars, | |
}; | |
continue; | |
} | |
} | |
return params; | |
} | |
function getURLParamsValues(url, params) { | |
let result = {}; | |
const urlParts = url.split('/'); | |
for (const [param, paramInfo] of Object.entries(params)) { | |
if (paramInfo.mandatory && urlParts.at(paramInfo.index)?.length === 0) | |
throw new Error( | |
`Mandatory param name "${param}" is not defined in url: ${url}` | |
); | |
if (paramInfo.lastGetOtherPars) { | |
result[param] = | |
urlParts | |
.slice(paramInfo.index) | |
.map((item) => decodeURIComponent(item)) ?? null; | |
} else { | |
result[param] = decodeURIComponent(urlParts.at(paramInfo.index)) ?? null; | |
} | |
} | |
return result ?? {}; | |
} | |
// Transform url like http://:host/custom/path/:id to be completed with object | |
// { host: "localhost", id: 7 } | |
// Result should be: http://localhost/custom/path/7 | |
export function transformURLWithParamsValues(urlWithParams, paramsValues) { | |
let url = urlWithParams.split('/'); | |
const params = getURLParams(urlWithParams); | |
for (const [param, paramInfo] of Object.entries(params)) { | |
if (paramInfo.mandatory && url.at(paramInfo.index)?.length === 0) | |
throw new Error( | |
`Mandatory param name "${param}" is not defined in url: ${url}` | |
); | |
if (paramsValues[param]) url[paramInfo.index] = paramsValues[param]; | |
} | |
url = url | |
.map((item, key) => (key in [0, 1, 2] ? item : encodeURIComponent(item))) | |
.join('/'); | |
if (`${url}/`.match(/\/:([.]{2,3})?([\w_]{1}[\w0-9-_]+)\//i)) { | |
throw new Error( | |
`There is undefined param when susbstituting ${urlWithParams}` | |
); | |
} | |
return url; | |
} | |
// const getUrlProps = parseURLWithParams('http://:host/:app/[:other] | |
// console.log(getUrlProps('http://localhost/blog/some/more/path') | |
// Should print something similar to: { host: "localhost", app: "blog", other: ["some", "more", "path"]} | |
export default function parseURLWithParams(paramsURL = '') { | |
const params = getURLParams(paramsURL); | |
return (url) => { | |
return getURLParamsValues(url, params); | |
}; | |
} |
Author
gtrabanco
commented
Feb 16, 2022
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment