in src/schema/firefox-schemas-import.js [447:505]
export function foldSchemas(schemas) {
// Map the schemas by prefix.
const schemasByPrefix = {};
schemas.forEach((schema) => {
const [prefix, property, more] = schema.namespace.split('.', 3);
if (more) {
throw new Error('namespace may only have one level of nesting');
}
if (!(prefix in schemasByPrefix)) {
schemasByPrefix[prefix] = {};
}
const namespace = property || 'baseNamespace';
if (schemasByPrefix[prefix][namespace]) {
throw new Error('matching namespaces are not allowed');
} else {
schemasByPrefix[prefix][namespace] = schema;
}
});
// If there aren't any matching prefixes then there's no folding to do.
const hasMatchingPrefixes = Object.keys(schemasByPrefix).some((prefix) => {
const prefixedSchemas = schemasByPrefix[prefix];
// Continue if there are multiple properties (baseNamespace and something
// else) or there is one property that isn't baseNamespace.
return (
Object.keys(prefixedSchemas).length > 1 ||
!('baseNamespace' in prefixedSchemas)
);
});
if (!hasMatchingPrefixes) {
return schemas;
}
// There is folding to do, join the matching schemas.
const foldedSchemas = [];
// The order of the schemas will be maintained since they were inserted in
// the order of schemas.
Object.keys(schemasByPrefix).forEach((namespace) => {
const { baseNamespace = {}, ...nestedSchemas } = schemasByPrefix[namespace];
foldedSchemas.push(baseNamespace);
// Ensure the base namespace is set.
baseNamespace.namespace = namespace;
if (Object.keys(nestedSchemas).length > 0 && !baseNamespace.properties) {
baseNamespace.properties = {};
}
Object.keys(nestedSchemas).forEach((property) => {
const schema = nestedSchemas[property];
delete schema.namespace;
if (schema.types) {
baseNamespace.types = baseNamespace.types || [];
baseNamespace.types = baseNamespace.types.concat(schema.types);
delete schema.types;
}
baseNamespace.properties[property] = schema;
});
});
return foldedSchemas;
}