generateElement(schema) {
    const {
      String: StringElement,
      Number: NumberElement,
      Boolean: BooleanElement,
      Null: NullElement,
      Enum: EnumElement,
      // Ref: RefElement,
    } = this.minim.elements;

    const typeGeneratorMap = {
      boolean: BooleanElement,
      string: StringElement,
      number: NumberElement,
      integer: NumberElement,
      null: NullElement,
      file: StringElement,
    };

    if (schema.allOf && schema.allOf.length === 1 && schema.definitions
        && Object.keys(schema).length === 2) {
      // Since we can't have $ref at root with definitions.
      // `allOf` with a single item is used as a work around for this type of schema
      // We can safely ignore the allOf and unwrap it as normal schema in this case
      return this.generateElement(schema.allOf[0]);
    }

    const type = this.typeForSchema(schema);

    let element;

    if (schema.$ref) {
      // element = new RefElement(idForDataStructure(schema.$ref));
      element = new this.minim.elements.Element();

      try {
        element.element = idForDataStructure(schema.$ref);
      } catch (error) {
        // Cannot find ID for reference, let's attempt to dereference the value
        // and provide element dereferenced.
        // This may be because we cannot express a reference in API Elements,
        // for example a reference to `#/definitions/User/properties/name`
        const ref = lookupReference(schema.$ref, this.root);
        return this.generateElement(ref.referenced);
      }

      return element;
    } if (schema.enum) {
      element = this.generateEnum(schema);
    } else if (type === 'array') {
      element = this.generateArray(schema);
    } else if (type === 'object') {
      element = this.generateObject(schema);
    } else if (type && typeGeneratorMap[type]) {
      element = new typeGeneratorMap[type]();
    } else if (type) {
      throw new Error(`Unhandled schema type '${type}'`);
    } else {
      element = new this.minim.elements.Enum();
      element.enumerations = [
        new this.minim.elements.String(),
        new this.minim.elements.Number(),
        new this.minim.elements.Boolean(),
        this.generateArray(schema),
        this.generateObject(schema),
      ];
    }

    if (element) {
      if (schema.title) {
        element.title = new StringElement(schema.title);
      }

      if (schema.description) {
        element.description = new StringElement(schema.description);
      }

      if (schema['x-nullable']) {
        element.attributes.set('typeAttributes', ['nullable']);
      }

      let def = schema.default;

      if (def !== undefined && !_.isArray(def) && !_.isObject(def)) {
        // TODO Support defaults for arrays and objects
        if (schema.enum) {
          def = new EnumElement(def);

          def.content.attributes.set('typeAttributes', ['fixed']);
        }

        element.attributes.set('default', def);
      }

      let samples = [];

      if (schema.example) {
        samples = [dereference(schema.example, this.root)];
      }

      if (samples.length > 0) {
        if (schema.enum) {
          samples = samples.map((item) => {
            const enumeration = new EnumElement(item);
            enumeration.content.attributes.set('typeAttributes', ['fixed']);
            return enumeration;
          });
        }

        const hasSample = samples.length === 1 && samples[0];
        const emptyContent = !element.content || element.content.length === 0;

        if (hasSample && emptyContent) {
          // Convert the sample value to an element as a cheap and easy way to
          // check the type matches our element. It will also refract
          // object/array items that are the sample value as members/elements
          // for us so we can grab its content

          const example = this.minim.toElement(samples[0]);

          if (element.element === example.element) {
            element.content = example.content;
          } else {
            element.attributes.set('samples', samples);
          }
        } else {
          element.attributes.set('samples', samples);
        }
      }

      const validationDescriptions = this.generateValidationDescriptions(schema);

      if (validationDescriptions.length > 0) {
        const description = validationDescriptions.map(value => `- ${value}`);

        if (element.description && element.description.toValue()) {
          description.splice(0, 0, `${element.description.toValue()}\n`);
        }

        element.description = new StringElement(description.join('\n'));
      }
    }

    return element;
  }
// Generates an element representing the given schema
Generates an element representing the given schema
Generates an element representing the given schema
generateElement(schema) {
    const {
      String: StringElement,
      Number: NumberElement,
      Boolean: BooleanElement,
      Null: NullElement,
      Enum: EnumElement,
    } = this.minim.elements;
    const typeGeneratorMap = {
      boolean: BooleanElement,
      string: StringElement,
      number: NumberElement,
      integer: NumberElement,
      null: NullElement,
      file: StringElement,
    };
    if (schema.allOf && schema.allOf.length === 1 && schema.definitions
        && Object.keys(schema).length === 2) {
      return this.generateElement(schema.allOf[0]);
    }
    const type = this.typeForSchema(schema);
    let element;
    if (schema.$ref) {
      element = new this.minim.elements.Element();
      try {
        element.element = idForDataStructure(schema.$ref);
      } catch (error) {
        const ref = lookupReference(schema.$ref, this.root);
        return this.generateElement(ref.referenced);
      }
      return element;
    } if (schema.enum) {
      element = this.generateEnum(schema);
    } else if (type === 'array') {
      element = this.generateArray(schema);
    } else if (type === 'object') {
      element = this.generateObject(schema);
    } else if (type && typeGeneratorMap[type]) {
      element = new typeGeneratorMap[type]();
    } else if (type) {
      throw new Error(`Unhandled schema type '${type}'`);
    } else {
      element = new this.minim.elements.Enum();
      element.enumerations = [
        new this.minim.elements.String(),
        new this.minim.elements.Number(),
        new this.minim.elements.Boolean(),
        this.generateArray(schema),
        this.generateObject(schema),
      ];
    }
    if (element) {
      if (schema.title) {
        element.title = new StringElement(schema.title);
      }
      if (schema.description) {
        element.description = new StringElement(schema.description);
      }
      if (schema['x-nullable']) {
        element.attributes.set('typeAttributes', ['nullable']);
      }
      let def = schema.default;
      if (def !== undefined && !_.isArray(def) && !_.isObject(def)) {
        if (schema.enum) {
          def = new EnumElement(def);
          def.content.attributes.set('typeAttributes', ['fixed']);
        }
        element.attributes.set('default', def);
      }
      let samples = [];
      if (schema.example) {
        samples = [dereference(schema.example, this.root)];
      }
      if (samples.length > 0) {
        if (schema.enum) {
          samples = samples.map((item) => {
            const enumeration = new EnumElement(item);
            enumeration.content.attributes.set('typeAttributes', ['fixed']);
            return enumeration;
          });
        }
        const hasSample = samples.length === 1 && samples[0];
        const emptyContent = !element.content || element.content.length === 0;
        if (hasSample && emptyContent) {
          const example = this.minim.toElement(samples[0]);
          if (element.element === example.element) {
            element.content = example.content;
          } else {
            element.attributes.set('samples', samples);
          }
        } else {
          element.attributes.set('samples', samples);
        }
      }
      const validationDescriptions = this.generateValidationDescriptions(schema);
      if (validationDescriptions.length > 0) {
        const description = validationDescriptions.map(value => `- ${value}`);
        if (element.description && element.description.toValue()) {
          description.splice(0, 0, `${element.description.toValue()}\n`);
        }
        element.description = new StringElement(description.join('\n'));
      }
    }
    return element;
  }
generateElement ( schema ) { const { String : StringElement , Number : NumberElement , Boolean : BooleanElement , Null : NullElement , Enum : EnumElement , } = this . minim . elements ; const typeGeneratorMap = { boolean : BooleanElement , string : StringElement , number : NumberElement , integer : NumberElement , null : NullElement , file : StringElement , } ; if ( schema . allOf && schema . allOf . length === 1 && schema . definitions && Object . keys ( schema ) . length === 2 ) { return this . generateElement ( schema . allOf [ 0 ] ) ; } const type = this . typeForSchema ( schema ) ; let element ; if ( schema . $ref ) { element = new this . minim . elements . Element ( ) ; try { element . element = idForDataStructure ( schema . $ref ) ; } catch ( error ) { const ref = lookupReference ( schema . $ref , this . root ) ; return this . generateElement ( ref . referenced ) ; } return element ; } if ( schema . enum ) { element = this . generateEnum ( schema ) ; } else if ( type === 'array' ) { element = this . generateArray ( schema ) ; } else if ( type === 'object' ) { element = this . generateObject ( schema ) ; } else if ( type && typeGeneratorMap [ type ] ) { element = new typeGeneratorMap [ type ] ( ) ; } else if ( type ) { throw new Error ( ` ${ type } ` ) ; } else { element = new this . minim . elements . Enum ( ) ; element . enumerations = [ new this . minim . elements . String ( ) , new this . minim . elements . Number ( ) , new this . minim . elements . Boolean ( ) , this . generateArray ( schema ) , this . generateObject ( schema ) , ] ; } if ( element ) { if ( schema . title ) { element . title = new StringElement ( schema . title ) ; } if ( schema . description ) { element . description = new StringElement ( schema . description ) ; } if ( schema [ 'x-nullable' ] ) { element . attributes . set ( 'typeAttributes' , [ 'nullable' ] ) ; } let def = schema . default ; if ( def !== undefined && ! _ . isArray ( def ) && ! _ . isObject ( def ) ) { if ( schema . enum ) { def = new EnumElement ( def ) ; def . content . attributes . set ( 'typeAttributes' , [ 'fixed' ] ) ; } element . attributes . set ( 'default' , def ) ; } let samples = [ ] ; if ( schema . example ) { samples = [ dereference ( schema . example , this . root ) ] ; } if ( samples . length > 0 ) { if ( schema . enum ) { samples = samples . map ( ( item ) => { const enumeration = new EnumElement ( item ) ; enumeration . content . attributes . set ( 'typeAttributes' , [ 'fixed' ] ) ; return enumeration ; } ) ; } const hasSample = samples . length === 1 && samples [ 0 ] ; const emptyContent = ! element . content || element . content . length === 0 ; if ( hasSample && emptyContent ) { const example = this . minim . toElement ( samples [ 0 ] ) ; if ( element . element === example . element ) { element . content = example . content ; } else { element . attributes . set ( 'samples' , samples ) ; } } else { element . attributes . set ( 'samples' , samples ) ; } } const validationDescriptions = this . generateValidationDescriptions ( schema ) ; if ( validationDescriptions . length > 0 ) { const description = validationDescriptions . map ( value => ` ${ value } ` ) ; if ( element . description && element . description . toValue ( ) ) { description . splice ( 0 , 0 , ` ${ element . description . toValue ( ) } \n ` ) ; } element . description = new StringElement ( description . join ( '\n' ) ) ; } } return element ; }
Generates an element representing the given schema
Generates an element representing the given schema
// Ref: RefElement, // Since we can't have $ref at root with definitions. // `allOf` with a single item is used as a work around for this type of schema // We can safely ignore the allOf and unwrap it as normal schema in this case // element = new RefElement(idForDataStructure(schema.$ref)); // Cannot find ID for reference, let's attempt to dereference the value // and provide element dereferenced. // This may be because we cannot express a reference in API Elements, // for example a reference to `#/definitions/User/properties/name` // TODO Support defaults for arrays and objects // Convert the sample value to an element as a cheap and easy way to // check the type matches our element. It will also refract // object/array items that are the sample value as members/elements // for us so we can grab its content