feat: add housekeeping domain registry
This commit is contained in:
1 parent
7edca410fa
commit
2d5f03048a
14 files changed
+694
No files matched your search
@@ -0,0 +1,75 @@
|
||||
import { PERMS } from "@/lib/permission-slugs";
|
||||
import { HOUSEKEEPING_DOMAIN_IDS } from "../migration/types";
|
||||
import type {
|
||||
CapabilityRequirement,
|
||||
HousekeepingDomainManifest,
|
||||
} from "./contracts";
|
||||
|
||||
const approvedDomainIds = new Set<string>(HOUSEKEEPING_DOMAIN_IDS);
|
||||
const knownCapabilitySlugs = new Set<string>(Object.values(PERMS));
|
||||
|
||||
export interface HousekeepingRegistry {
|
||||
domains: readonly HousekeepingDomainManifest[];
|
||||
}
|
||||
|
||||
export function createHousekeepingRegistry(
|
||||
manifests: readonly HousekeepingDomainManifest[],
|
||||
): HousekeepingRegistry {
|
||||
const domainIds = new Set<string>();
|
||||
const routeIds = new Set<string>();
|
||||
const routeHrefs = new Set<string>();
|
||||
|
||||
for (const manifest of manifests) {
|
||||
if (!approvedDomainIds.has(manifest.id)) {
|
||||
throw new Error(`unknown domain id: ${manifest.id}`);
|
||||
}
|
||||
if (domainIds.has(manifest.id)) {
|
||||
throw new Error(`duplicate domain id: ${manifest.id}`);
|
||||
}
|
||||
domainIds.add(manifest.id);
|
||||
|
||||
if (manifest.previewHref !== `/admin-next/${manifest.id}`) {
|
||||
throw new Error(`invalid preview href: ${manifest.previewHref}`);
|
||||
}
|
||||
validateNonEmpty(manifest.labelKey, "label key");
|
||||
validateNonEmpty(manifest.descriptionKey, "description key");
|
||||
validateCapability(manifest.capability);
|
||||
|
||||
for (const route of manifest.routes) {
|
||||
validateNonEmpty(route.id, "route id");
|
||||
if (routeIds.has(route.id)) {
|
||||
throw new Error(`duplicate route id: ${route.id}`);
|
||||
}
|
||||
routeIds.add(route.id);
|
||||
|
||||
validateNonEmpty(route.href, "route href");
|
||||
if (routeHrefs.has(route.href)) {
|
||||
throw new Error(`duplicate route href: ${route.href}`);
|
||||
}
|
||||
routeHrefs.add(route.href);
|
||||
|
||||
validateNonEmpty(route.labelKey, "route label key");
|
||||
validateCapability(route.capability);
|
||||
}
|
||||
}
|
||||
|
||||
return { domains: Object.freeze([...manifests]) };
|
||||
}
|
||||
|
||||
function validateNonEmpty(value: string, name: string): void {
|
||||
if (!value.trim()) {
|
||||
throw new Error(`empty ${name}`);
|
||||
}
|
||||
}
|
||||
|
||||
function validateCapability(requirement: CapabilityRequirement): void {
|
||||
if (requirement.slugs.length === 0) {
|
||||
throw new Error("empty capability requirement");
|
||||
}
|
||||
|
||||
for (const slug of requirement.slugs) {
|
||||
if (!knownCapabilitySlugs.has(slug)) {
|
||||
throw new Error(`unknown capability slug: ${slug}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user