feat(housekeeping): deliver content vertical

This commit is contained in:
Simo committed 2026-08-30 01:54:43 +02:00
1 parent bdab924bdf
commit fd68819d9b
67 files changed
+5742 -1916

No files matched your search

@@ -0,0 +1,58 @@
import "server-only";
import { PERMS } from "@/lib/permission-slugs";
import {
anyCapability,
type HousekeepingCapabilityContext,
} from "../../foundation/contracts";
import { contentQuery } from "./queries/content-queries";
import type { ContentSearchCandidate } from "./search";
type ContentSearchKind = "articles" | "events" | "media" | "help";
const SEARCH_ROUTES = {
articles: [
["content.editorial.articles", anyCapability(PERMS.NEWS_VIEW)],
],
events: [
["content.engagement.events", anyCapability(PERMS.EVENTS_VIEW)],
],
media: [
["content.media.photos", anyCapability(PERMS.PAGES_VIEW)],
["content.media.library", anyCapability(PERMS.PAGES_VIEW)],
["content.media.banners", anyCapability(PERMS.BANNERS_VIEW)],
["content.media.ads", anyCapability(PERMS.PAGES_VIEW)],
],
help: [
["content.help.questions", anyCapability(PERMS.PAGES_VIEW)],
["content.help.email-templates", anyCapability(PERMS.PAGES_VIEW)],
],
} as const;
export async function loadContentSearchCandidates(
kind: ContentSearchKind,
context: HousekeepingCapabilityContext,
term: string,
limit: number,
): Promise<readonly ContentSearchCandidate[]> {
const candidates: ContentSearchCandidate[] = [];
for (const [routeId, capability] of SEARCH_ROUTES[kind]) {
const result = await contentQuery.run(context, {
routeId,
list: { search: term, pageSize: limit, offset: 0 },
});
if (!result.ok) continue;
for (const item of result.data.items) {
if (!item.href) continue;
candidates.push({
id: routeId + ":" + item.id,
title: item.title,
description: item.description ?? item.status,
href: item.href,
capability,
});
if (candidates.length >= limit) return candidates;
}
}
return candidates;
}