@beignet/core
Version:
Core framework primitives for Beignet
160 lines • 5.71 kB
JavaScript
export class RuntimeIntegrityError extends Error {
findings;
constructor(findings) {
super(formatRuntimeIntegrityFailure(findings));
this.name = "RuntimeIntegrityError";
this.findings = findings;
}
}
export function defineRuntimeManifest(input) {
return {
listeners: input.listeners ?? [],
schedules: input.schedules ?? [],
tasks: input.tasks ?? [],
outbox: {
events: input.outbox?.events ?? [],
jobs: input.outbox?.jobs ?? [],
},
};
}
export function defineRuntimeRegistries(input) {
return {
listeners: input.listeners ?? [],
schedules: input.schedules ?? [],
tasks: input.tasks ?? [],
outbox: input.outbox,
};
}
export function inspectRuntimeIntegrity(manifest, registries) {
const configs = [
{
artifact: "listener",
label: "listener",
manifestNames: namesFromDefinitions(manifest.listeners),
registryNames: namesFromDefinitions(registries.listeners),
missingCode: "missing_listener_registration",
registryDescription: "runtime registries.listeners",
},
{
artifact: "schedule",
label: "schedule",
manifestNames: namesFromDefinitions(manifest.schedules),
registryNames: namesFromDefinitions(registries.schedules),
missingCode: "missing_schedule_registration",
registryDescription: "runtime registries.schedules",
},
{
artifact: "task",
label: "task",
manifestNames: namesFromDefinitions(manifest.tasks),
registryNames: namesFromDefinitions(registries.tasks),
missingCode: "missing_task_registration",
registryDescription: "runtime registries.tasks",
},
{
artifact: "outboxEvent",
label: "outbox event",
manifestNames: namesFromDefinitions(manifest.outbox.events),
registryNames: namesFromMap(registries.outbox?.events),
missingCode: "missing_outbox_event_registration",
registryDescription: "runtime registries.outbox.events",
},
{
artifact: "outboxJob",
label: "outbox job",
manifestNames: namesFromDefinitions(manifest.outbox.jobs),
registryNames: namesFromMap(registries.outbox?.jobs),
missingCode: "missing_outbox_job_registration",
registryDescription: "runtime registries.outbox.jobs",
},
];
const findings = configs.flatMap((config) => inspectArtifactIntegrity(config));
return {
ok: findings.length === 0,
findings,
};
}
export function createRuntimeIntegrity(options) {
const mode = options.mode ?? "error";
const logger = options.logger ?? console;
return {
kind: "runtime-integrity",
check() {
const result = inspectRuntimeIntegrity(options.manifest, options.registries);
if (result.ok)
return result;
if (mode === "warn") {
logger.warn(`[beignet] ${formatRuntimeIntegrityFailure(result.findings)}`);
return result;
}
throw new RuntimeIntegrityError(result.findings);
},
};
}
export function runRuntimeIntegrityCheck(check) {
return check?.check();
}
function inspectArtifactIntegrity(config) {
const findings = [];
const manifestDuplicates = duplicateNames(config.manifestNames);
const registryDuplicates = duplicateNames(config.registryNames);
for (const name of manifestDuplicates) {
findings.push({
code: "duplicate_runtime_manifest_entry",
artifact: config.artifact,
name,
location: "manifest",
message: `Duplicate ${config.label} "${name}" in runtime manifest.`,
});
}
for (const name of registryDuplicates) {
findings.push({
code: "duplicate_runtime_registry_entry",
artifact: config.artifact,
name,
location: "registry",
message: `Duplicate ${config.label} "${name}" in ${config.registryDescription}.`,
});
}
const registryNameSet = new Set(config.registryNames);
for (const name of uniqueNames(config.manifestNames)) {
if (registryNameSet.has(name))
continue;
findings.push({
code: config.missingCode,
artifact: config.artifact,
name,
message: `Missing ${config.label} registration "${name}": declared in runtime manifest but not present in ${config.registryDescription}.`,
});
}
return findings;
}
function namesFromDefinitions(definitions) {
return (definitions ?? []).map((definition) => definition.name);
}
function namesFromMap(definitions) {
return [...(definitions?.keys() ?? [])];
}
function duplicateNames(names) {
const seen = new Set();
const duplicates = new Set();
for (const name of names) {
if (seen.has(name)) {
duplicates.add(name);
continue;
}
seen.add(name);
}
return [...duplicates].sort();
}
function uniqueNames(names) {
return [...new Set(names)].sort();
}
function formatRuntimeIntegrityFailure(findings) {
const summary = `Runtime integrity check failed with ${findings.length} finding${findings.length === 1 ? "" : "s"}.`;
const details = findings
.map((finding) => `- [${finding.code}] ${finding.message}`)
.join("\n");
return `${summary}\n${details}`;
}
//# sourceMappingURL=runtime-integrity.js.map