/home/techb158/cosmic.abdallabala.com/src/domain
Edit: /home/techb158/cosmic.abdallabala.com/src/domain/validation.js (6080B)
const DIMENSIONS = ["Organizational", "Technical", "Human"];
const DOMAINS = ["Strategic and organizational risks", "Technical risks", "Legal and ethical risks"];
const RISK_STATUSES = ["Open", "In mitigation", "Accepted", "Closed"];
const APPROVAL_STATUSES = ["Pending", "Approved", "Rejected", "Accepted"];
const MITIGATION_STATUSES = ["Not started", "In progress", "Done", "Rejected"];
function requireString(payload, field) {
if (!payload[field] || typeof payload[field] !== "string") {
throw new Error(`${field} is required`);
}
}
function numberInRange(payload, field, min, max) {
const value = Number(payload[field]);
if (!Number.isFinite(value) || value < min || value > max) {
throw new Error(`${field} must be between ${min} and ${max}`);
}
return value;
}
function enumValue(payload, field, allowed, fallback) {
const value = payload[field] || fallback;
if (!allowed.includes(value)) {
throw new Error(`${field} must be one of: ${allowed.join(", ")}`);
}
return value;
}
function validateRiskInput(payload) {
if (!payload || typeof payload !== "object") throw new Error("Risk payload is required");
requireString(payload, "title");
const risk = {
title: payload.title.trim(),
description: payload.description || "",
dimension: enumValue(payload, "dimension", DIMENSIONS, "Technical"),
domain: enumValue(payload, "domain", DOMAINS, "Technical risks"),
lifecycle_phase: payload.lifecycle_phase || payload.lifecyclePhase || "Testing and performance evaluation",
probability: numberInRange(payload, "probability", 1, 5),
impact: numberInRange(payload, "impact", 1, 5),
detectability: numberInRange(payload, "detectability", 1, 5),
status: enumValue(payload, "status", RISK_STATUSES, "Open"),
approval_status: enumValue(payload, "approval_status", APPROVAL_STATUSES, payload.approvalStatus || "Pending"),
due_date: payload.due_date || payload.dueDate || null,
owner_display_name: payload.owner_display_name || payload.owner || "Unassigned",
evidence_summary: payload.evidence_summary || payload.evidence || ""
};
return risk;
}
function validateRiskPatch(payload) {
if (!payload || typeof payload !== "object") throw new Error("Risk patch is required");
const patch = {};
if (payload.title !== undefined) {
if (!payload.title || typeof payload.title !== "string") throw new Error("title cannot be empty");
patch.title = payload.title.trim();
}
if (payload.description !== undefined) patch.description = payload.description || "";
if (payload.dimension !== undefined) patch.dimension = enumValue(payload, "dimension", DIMENSIONS);
if (payload.domain !== undefined) patch.domain = enumValue(payload, "domain", DOMAINS);
if (payload.lifecycle_phase !== undefined || payload.lifecyclePhase !== undefined) patch.lifecycle_phase = payload.lifecycle_phase || payload.lifecyclePhase;
if (payload.probability !== undefined) patch.probability = numberInRange(payload, "probability", 1, 5);
if (payload.impact !== undefined) patch.impact = numberInRange(payload, "impact", 1, 5);
if (payload.detectability !== undefined) patch.detectability = numberInRange(payload, "detectability", 1, 5);
if (payload.status !== undefined) patch.status = enumValue(payload, "status", RISK_STATUSES);
if (payload.approval_status !== undefined || payload.approvalStatus !== undefined) {
patch.approval_status = enumValue({ approval_status: payload.approval_status || payload.approvalStatus }, "approval_status", APPROVAL_STATUSES);
}
if (payload.due_date !== undefined || payload.dueDate !== undefined) patch.due_date = payload.due_date || payload.dueDate || null;
if (payload.owner_display_name !== undefined || payload.owner !== undefined) patch.owner_display_name = payload.owner_display_name || payload.owner || "Unassigned";
if (payload.evidence_summary !== undefined || payload.evidence !== undefined) patch.evidence_summary = payload.evidence_summary || payload.evidence || "";
return patch;
}
function validateMitigationInput(payload) {
if (!payload || typeof payload !== "object") throw new Error("Mitigation payload is required");
requireString(payload, "title");
return {
title: payload.title.trim(),
description: payload.description || "",
status: enumValue(payload, "status", MITIGATION_STATUSES, "Not started"),
progress_percent: numberInRange(Object.assign({ progress_percent: 0 }, payload), "progress_percent", 0, 100),
effectiveness_percent: numberInRange(Object.assign({ effectiveness_percent: 0 }, payload), "effectiveness_percent", 0, 100),
due_date: payload.due_date || payload.dueDate || null,
owner_display_name: payload.owner_display_name || payload.owner || "Unassigned"
};
}
function validateMitigationPatch(payload) {
if (!payload || typeof payload !== "object") throw new Error("Mitigation patch is required");
const patch = {};
if (payload.title !== undefined) {
if (!payload.title || typeof payload.title !== "string") throw new Error("title cannot be empty");
patch.title = payload.title.trim();
}
if (payload.description !== undefined) patch.description = payload.description || "";
if (payload.status !== undefined) patch.status = enumValue(payload, "status", MITIGATION_STATUSES);
if (payload.progress_percent !== undefined) patch.progress_percent = numberInRange(payload, "progress_percent", 0, 100);
if (payload.effectiveness_percent !== undefined) patch.effectiveness_percent = numberInRange(payload, "effectiveness_percent", 0, 100);
if (payload.due_date !== undefined || payload.dueDate !== undefined) patch.due_date = payload.due_date || payload.dueDate || null;
if (payload.owner_display_name !== undefined || payload.owner !== undefined) patch.owner_display_name = payload.owner_display_name || payload.owner || "Unassigned";
return patch;
}
module.exports = {
DIMENSIONS,
DOMAINS,
RISK_STATUSES,
APPROVAL_STATUSES,
MITIGATION_STATUSES,
validateRiskInput,
validateRiskPatch,
validateMitigationInput,
validateMitigationPatch
};