95 lines
2.4 KiB
TypeScript
95 lines
2.4 KiB
TypeScript
import { PERMS } from "@/lib/permission-slugs";
|
|
import { authorizeHousekeeping } from "../../foundation/authorization";
|
|
import {
|
|
anyCapability,
|
|
type CapabilityRequirement,
|
|
fail,
|
|
type HousekeepingCapabilityContext,
|
|
type HousekeepingWidgetDefinition,
|
|
ok,
|
|
} from "../../foundation/contracts";
|
|
|
|
export const CONTENT_WIDGET_IDS = [
|
|
"content.editorial-summary",
|
|
"content.media-summary",
|
|
"content.localization-summary",
|
|
] as const;
|
|
|
|
type ContentWidgetLoader = (
|
|
context: HousekeepingCapabilityContext,
|
|
signal: AbortSignal,
|
|
) => Promise<Readonly<Record<string, number>>>;
|
|
|
|
export interface ContentWidgetAdapters {
|
|
readonly editorial: ContentWidgetLoader;
|
|
readonly media: ContentWidgetLoader;
|
|
readonly localization: ContentWidgetLoader;
|
|
}
|
|
|
|
function createWidget(
|
|
id: (typeof CONTENT_WIDGET_IDS)[number],
|
|
kind: "mandatory" | "optional",
|
|
capability: CapabilityRequirement,
|
|
load: ContentWidgetLoader,
|
|
): HousekeepingWidgetDefinition {
|
|
return {
|
|
id,
|
|
owner: "content",
|
|
kind,
|
|
capability,
|
|
async load(context, signal) {
|
|
const authorization = authorizeHousekeeping(context, capability);
|
|
if (!authorization.ok) return authorization;
|
|
try {
|
|
return ok(await load(context, signal), authorization.correlationId);
|
|
} catch {
|
|
return fail(
|
|
"DEPENDENCY_UNAVAILABLE",
|
|
"errors.housekeeping.dependencyUnavailable",
|
|
authorization.correlationId,
|
|
);
|
|
}
|
|
},
|
|
};
|
|
}
|
|
|
|
export function createContentWidgets(
|
|
adapters: ContentWidgetAdapters,
|
|
): readonly HousekeepingWidgetDefinition[] {
|
|
return [
|
|
createWidget(
|
|
"content.editorial-summary",
|
|
"mandatory",
|
|
anyCapability(PERMS.NEWS_VIEW),
|
|
adapters.editorial,
|
|
),
|
|
createWidget(
|
|
"content.media-summary",
|
|
"optional",
|
|
anyCapability(PERMS.PAGES_VIEW, PERMS.BANNERS_VIEW),
|
|
adapters.media,
|
|
),
|
|
createWidget(
|
|
"content.localization-summary",
|
|
"optional",
|
|
anyCapability(PERMS.SETTINGS_VIEW),
|
|
adapters.localization,
|
|
),
|
|
];
|
|
}
|
|
|
|
export const CONTENT_WIDGETS = createContentWidgets({
|
|
async editorial(context, signal) {
|
|
const { loadContentWidget } = await import("./widgets-production");
|
|
return loadContentWidget("editorial", context, signal);
|
|
},
|
|
async media(context, signal) {
|
|
const { loadContentWidget } = await import("./widgets-production");
|
|
return loadContentWidget("media", context, signal);
|
|
},
|
|
async localization(context, signal) {
|
|
const { loadContentWidget } = await import("./widgets-production");
|
|
return loadContentWidget("localization", context, signal);
|
|
},
|
|
});
|