46 lines
1.1 KiB
TypeScript
46 lines
1.1 KiB
TypeScript
import type {
|
|
BuiltSection,
|
|
RenderContext,
|
|
RuntimeIssue,
|
|
SectionBuilder,
|
|
} from './runtime-contracts';
|
|
import { SECTION_ORDER } from './runtime-contracts';
|
|
|
|
export interface SectionComposerResult {
|
|
sections: BuiltSection[];
|
|
issues: RuntimeIssue[];
|
|
}
|
|
|
|
export async function composeSections(
|
|
context: RenderContext,
|
|
builders: SectionBuilder[],
|
|
): Promise<SectionComposerResult> {
|
|
const builderByRole = new Map(builders.map((builder) => [builder.role, builder]));
|
|
const sections: BuiltSection[] = [];
|
|
const issues: RuntimeIssue[] = [];
|
|
|
|
for (const role of SECTION_ORDER) {
|
|
const policy = context.policyBySection.get(role);
|
|
if (!policy?.enabled) {
|
|
continue;
|
|
}
|
|
|
|
const builder = builderByRole.get(role);
|
|
if (!builder) {
|
|
issues.push({
|
|
code: 'INVALID_TEMPLATE',
|
|
severity: policy.required ? 'error' : 'warning',
|
|
message: 'No section builder is registered for an enabled section.',
|
|
details: { role },
|
|
});
|
|
continue;
|
|
}
|
|
|
|
const section = await builder.build(context);
|
|
sections.push(section);
|
|
issues.push(...section.issues);
|
|
}
|
|
|
|
return { sections, issues };
|
|
}
|