arela
Version:
AI-powered CTO with multi-agent orchestration, code summarization, visual testing (web + mobile) for blazing fast development.
88 lines • 3.11 kB
JavaScript
/**
* Compare two schemas and capture breaking field-level changes.
*/
export function compareSchemas(current, previous, parentField = "") {
const changes = [];
if (!previous) {
return changes;
}
const currentSchema = current ?? {};
const previousSchema = previous ?? {};
// Missing required fields are breaking changes
const previousRequired = previousSchema.required ?? [];
const currentRequired = new Set(currentSchema.required ?? []);
for (const field of previousRequired) {
if (!currentRequired.has(field)) {
const fieldName = joinField(parentField, field);
changes.push({
type: "removed-field",
field: fieldName,
oldValue: "required",
newValue: "optional or missing",
severity: "major",
});
}
}
const previousProps = previousSchema.properties ?? {};
const currentProps = currentSchema.properties ?? {};
for (const [prop, previousPropSchema] of Object.entries(previousProps)) {
const fieldName = joinField(parentField, prop);
const currentPropSchema = currentProps[prop];
if (!currentPropSchema) {
changes.push({
type: "removed-field",
field: fieldName,
oldValue: describeSchema(previousPropSchema),
newValue: "removed",
severity: "major",
});
continue;
}
const previousType = resolveType(previousPropSchema);
const currentType = resolveType(currentPropSchema);
if (previousType && currentType && previousType !== currentType) {
changes.push({
type: "changed-type",
field: fieldName,
oldValue: previousType,
newValue: currentType,
severity: "major",
});
}
if (previousType === "object" || previousPropSchema.properties || previousPropSchema.required) {
changes.push(...compareSchemas(currentPropSchema, previousPropSchema, fieldName));
continue;
}
if (previousType === "array" && previousPropSchema.items) {
const nextCurrent = currentPropSchema.items;
const nextPrevious = previousPropSchema.items;
changes.push(...compareSchemas(nextCurrent, nextPrevious, `${fieldName}[]`));
}
}
return changes;
}
export function resolveType(schema) {
if (!schema) {
return undefined;
}
if (typeof schema.type === "string") {
return schema.type;
}
if (Array.isArray(schema.type) && schema.type.length > 0) {
return schema.type.join(" | ");
}
if (schema.$ref) {
return schema.$ref;
}
if (schema.enum) {
return "enum";
}
return undefined;
}
export function describeSchema(schema) {
return resolveType(schema) ?? "unknown";
}
function joinField(parent, child) {
return parent ? `${parent}.${child}` : child;
}
//# sourceMappingURL=schema-comparator.js.map