fix(housekeeping): link only reachable preview routes

This commit is contained in:
Simo committed 2026-08-31 18:45:45 +02:00
1 parent 543607a80e
commit d8fb8edff6
6 files changed
+216 -162

No files matched your search

@@ -3,37 +3,63 @@ import { satisfiesCapability } from "./capability-context";
import type {
HousekeepingCapabilityContext,
HousekeepingDomainManifest,
HousekeepingPreviewHref,
} from "./contracts";
import type { HousekeepingRegistry } from "./registry";
import type { HousekeepingRouteRuntime } from "./routing/runtime";
export interface HousekeepingNavigationDomain {
id: HousekeepingDomainId;
href: string;
href: HousekeepingPreviewHref;
iconId: HousekeepingDomainManifest["iconId"];
label: string;
description: string;
items: readonly { id: string; href: string; label: string }[];
items: readonly {
id: string;
href: HousekeepingPreviewHref;
label: string;
}[];
}
export function buildHousekeepingNavigation(
registry: HousekeepingRegistry,
runtime: HousekeepingRouteRuntime,
context: HousekeepingCapabilityContext,
translate: (key: string) => string,
): readonly HousekeepingNavigationDomain[] {
return registry.domains
.filter((domain) => satisfiesCapability(context, domain.capability))
.map((domain) => ({
id: domain.id,
href: domain.previewHref,
iconId: domain.iconId,
label: translate(domain.labelKey),
description: translate(domain.descriptionKey),
items: domain.routes
.filter((route) => satisfiesCapability(context, route.capability))
.map((route) => ({
id: route.id,
href: route.href,
label: translate(route.labelKey),
})),
}));
return runtime.registry.domains.flatMap((domain) => {
if (!satisfiesCapability(context, domain.capability)) return [];
const items = domain.routes
.filter(
(route) =>
runtime.handlers.has(route.id) &&
isConcreteNavigationHref(route.href) &&
satisfiesCapability(context, route.capability),
)
.map((route) => ({
id: route.id,
href: route.href,
label: translate(route.labelKey),
}));
if (items.length === 0) return [];
const landing =
items.find((item) => item.id === domain.landingRouteId) ?? items[0];
if (!landing) return [];
return [
{
id: domain.id,
href: landing.href,
iconId: domain.iconId,
label: translate(domain.labelKey),
description: translate(domain.descriptionKey),
items,
},
];
});
}
function isConcreteNavigationHref(href: HousekeepingPreviewHref): boolean {
return !href.split("/").some((segment) => segment.startsWith(":"));
}