class RopenPi::Specs::OpenApiFormatter

Public Class Methods

new(output, config = ::RopenPi::Specs.config) click to toggle source
# File lib/ropen_pi/specs/open_api_formatter.rb, line 10
def initialize(output, config = ::RopenPi::Specs.config)
  @output = output
  @config = config

  @output.puts 'Generating OpenAPI docs ...'
end

Public Instance Methods

example_group_finished(notification) click to toggle source
# File lib/ropen_pi/specs/open_api_formatter.rb, line 17
def example_group_finished(notification)
  metadata = notification.group.metadata

  return unless metadata.key?(:response)

  open_api_doc = @config.get_doc(metadata[:doc])
  open_api_doc.deep_merge!(metadata_to_open_api(metadata))
end
stop(_notification = nil) click to toggle source
# File lib/ropen_pi/specs/open_api_formatter.rb, line 26
def stop(_notification = nil)
  @config.open_api_docs.each do |url_path, doc|
    # remove 2.0 parameters
    doc[:paths]&.each do |_k, v|
      v.each do |_verb, value|
        merge_clean(value)
      end
    end

    write(doc, url_path)
  end
end

Private Instance Methods

merge_clean(value) click to toggle source
# File lib/ropen_pi/specs/open_api_formatter.rb, line 54
def merge_clean(value)
  is_hash = value.is_a?(Hash)
  if is_hash && value.dig(:parameters)
    schema_param = value&.dig(:parameters)&.find { |p| p[:in] == :body && p[:schema] }

    value[:requestBody][:content][RopenPi::APP_JSON].merge!(schema: schema_param[:schema]) \
      if value && schema_param && value&.dig(:requestBody, :content, RopenPi::APP_JSON)

    value[:parameters].reject! { |p| p[:in] == :body || p[:in] == :formData }
    value[:parameters].each { |p| p.delete(:type) }
    value[:headers]&.each { |p| p.delete(:type) }
  end

  value.delete(:consumes) if is_hash && value.dig(:consumes)
  value.delete(:produces) if is_hash && value.dig(:produces)
end
metadata_to_open_api(metadata) click to toggle source
# File lib/ropen_pi/specs/open_api_formatter.rb, line 71
def metadata_to_open_api(metadata)
  response_code = metadata[:response][:code]
  response = metadata[:response].reject { |k, _v| k == :code }

  app_json = RopenPi::APP_JSON

  # need to merge in to response
  if response[:examples]&.dig(app_json)
    example = response[:examples].dig(app_json).dup
    schema = response.dig(:content, app_json, :schema)

    new_hash = { example: example }
    new_hash[:schema] = schema if schema

    response.merge!(content: { app_json => new_hash })
    response.delete(:examples)
  end

  verb = metadata[:operation][:verb]
  operation = metadata[:operation].reject { |k, _v| k == :verb }
                                  .merge(responses: { response_code => response })

  path_template = metadata[:path_item][:template]

  path_item = metadata[:path_item].reject { |k, _v| k == :template }
                                  .merge(verb => operation)

  { paths: { path_template => path_item } }
end
write(doc, url_path) click to toggle source
# File lib/ropen_pi/specs/open_api_formatter.rb, line 41
def write(doc, url_path)
  file_path = File.join(@config.root_dir, url_path)
  dirname = File.dirname(file_path)
  FileUtils.mkdir_p(dirname) unless File.exist?(dirname)

  File.open(file_path, 'w') do |file|
    writer = RopenPi::Specs::Writer.new(@config.open_api_output_format)
    file.write(writer.write(doc))
  end

  @output.puts "OpenAPI doc generated at #{file_path}"
end