UNPKG

@mk-singh/utils

Version:

A collection of TypeScript utilities for Deno including route factory with navigation support

164 lines (163 loc) 5.69 kB
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); };