@mk-singh/utils
Version:
A collection of TypeScript utilities for Deno including route factory with navigation support
164 lines (163 loc) • 5.69 kB
JavaScript
export const createRoutes = (basePath, routes) => {
const result = {};
for (const [key, value] of Object.entries(routes)) {
if (typeof value === "object" && value !== null) {
if ("path" in value) {
const fullPath = `${basePath}/${value.path}`;
const newValue = { ...value, path: fullPath };
const nestedRoutes = Object.entries(value).filter(([k, v]) => !["path", "step", "prev", "next"].includes(k) &&
typeof v === "object" && v !== null);
if (nestedRoutes.length > 0) {
const nestedResult = {};
for (const [nestedKey, nestedValue] of nestedRoutes) {
if (typeof nestedValue === "object" &&
nestedValue !== null) {
nestedResult[nestedKey] = createRoutes(fullPath, {
[nestedKey]: nestedValue,
})[nestedKey];
}
}
result[key] = { ...newValue, ...nestedResult };
}
else {
result[key] = newValue;
}
}
else {
const nestedPath = `${basePath}/${key}`;
result[key] = {
path: nestedPath,
...createRoutes(nestedPath, value),
};
}
}
else {
result[key] = `${basePath}/${value}`;
}
}
resolveNavigationPaths(result, result);
return Object.freeze(result);
};
const resolveNavigationPaths = (obj, rootObj) => {
if (!obj || typeof obj !== "object")
return;
for (const value of Object.values(obj)) {
if (typeof value === "object" && value !== null) {
if ("prev" in value && typeof value.prev === "string") {
const resolvedPath = resolveNavigationPath(value.prev, obj, rootObj);
if (resolvedPath) {
value.prev = resolvedPath;
}
}
if ("next" in value && typeof value.next === "string") {
const resolvedPath = resolveNavigationPath(value.next, obj, rootObj);
if (resolvedPath) {
value.next = resolvedPath;
}
}
resolveNavigationPaths(value, rootObj);
}
}
};
const resolveNavigationPath = (navigationPath, currentContext, rootObj) => {
if (!navigationPath)
return;
const segments = navigationPath.split("/");
let current = currentContext;
for (const segment of segments) {
if (segment === "..") {
current = findParentContext(current, rootObj);
if (!current)
return;
}
else if (segment === ".") {
continue;
}
else if (segment) {
if (current && typeof current === "object" && segment in current) {
current = current[segment];
}
else {
return;
}
}
}
return current && typeof current === "object" && "path" in current
? current.path
: undefined;
};
const findParentContext = (target, root) => {
const findParent = (obj) => {
if (!obj || typeof obj !== "object")
return;
for (const value of Object.values(obj)) {
if (value === target) {
return obj;
}
if (typeof value === "object" && value) {
const found = findParent(value);
if (found)
return found;
}
}
return;
};
return findParent(root);
};
export const findRouteByPath = (pathname, routes) => {
const searchRoutes = (obj) => {
if (obj && typeof obj === "object" && obj.path === pathname) {
return obj;
}
if (obj && typeof obj === "object") {
for (const [key, value] of Object.entries(obj)) {
if (key !== "path" && typeof value === "object" && value) {
const result = searchRoutes(value);
if (result) {
return result;
}
}
}
}
return;
};
return searchRoutes(routes);
};
export const findRouteByNext = (nextPath, routes) => {
const searchRoutes = (obj) => {
if (obj && typeof obj === "object" && obj.next === nextPath) {
return obj;
}
if (obj && typeof obj === "object") {
for (const [key, value] of Object.entries(obj)) {
if (key !== "path" && typeof value === "object" && value) {
const result = searchRoutes(value);
if (result) {
return result;
}
}
}
}
return;
};
return searchRoutes(routes);
};
export const findRouteByPrev = (prevPath, routes) => {
const searchRoutes = (obj) => {
if (obj && typeof obj === "object" && obj.prev === prevPath) {
return obj;
}
if (obj && typeof obj === "object") {
for (const [key, value] of Object.entries(obj)) {
if (key !== "path" && typeof value === "object" && value) {
const result = searchRoutes(value);
if (result) {
return result;
}
}
}
}
return;
};
return searchRoutes(routes);
};