export function foldSchemas()

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;
}