ufiber
Version:
Next-gen webserver for node-js developer
54 lines (53 loc) • 1.65 kB
JavaScript
//#region src/utils/url.ts
const tryDecode = (str, decoder) => {
try {
return decoder(str);
} catch {
return str.replace(/(?:%[0-9A-Fa-f]{2})+/g, (match) => {
try {
return decoder(match);
} catch {
return match;
}
});
}
};
/**
* Detects and expands optional parameters in a route path.
*
* Example:
* /api/animals/:type?
* → ['/api/animals', '/api/animals/:type']
*
* If there is no optional parameter, returns null.
*/
const checkOptionalParameter = (path) => {
if (path.charCodeAt(path.length - 1) !== 63 || !path.includes(":")) return null;
const segments = path.split("/");
const results = [];
let basePath = "";
for (const segment of segments) if (segment && !segment.includes(":")) basePath += "/" + segment;
else if (segment.includes(":")) if (segment.includes("?")) {
results.push(basePath === "" ? "/" : basePath);
const optionalSegment = segment.replace("?", "");
basePath += "/" + optionalSegment;
results.push(basePath);
} else basePath += "/" + segment;
return [...new Set(results)];
};
/**
* Merge paths.
* @param {string[]} ...paths - The paths to merge.
* @returns {string} The merged path.
* @example
* mergePath('/api', '/users') // '/api/users'
* mergePath('/api/', '/users') // '/api/users'
* mergePath('/api', '/') // '/api'
* mergePath('/api/', '/') // '/api/'
*/
const mergePath = (base, sub, ...rest) => {
if (rest.length) sub = mergePath(sub, ...rest);
return `${base?.[0] === "/" ? "" : "/"}${base}${sub === "/" ? "" : `${base?.at(-1) === "/" ? "" : "/"}${sub?.[0] === "/" ? sub.slice(1) : sub}`}`;
};
//#endregion
export { checkOptionalParameter, mergePath, tryDecode };