Class: Modern::DocGenerator::OpenAPI3

Inherits:
Object
  • Object
show all
Includes:
Paths, Schemas
Defined in:
lib/modern/doc_generator/open_api3.rb,
lib/modern/doc_generator/open_api3/paths.rb,
lib/modern/doc_generator/open_api3/schemas.rb,
lib/modern/doc_generator/open_api3/operations.rb,
lib/modern/doc_generator/open_api3/security_schemes.rb,
lib/modern/doc_generator/open_api3/schema_default_types.rb

Defined Under Namespace

Modules: Operations, Paths, SchemaDefaultTypes, Schemas

Constant Summary collapse

OPENAPI_VERSION =

TODO: this is pretty inflexible. Eventually, consumers may want to

subclass Route, Content, etc., for their own use cases, and that
would make using an external/visiting doc generator impractical.
It's simple enough, though, so let's roll with it for now.
Modern::OPENAPI_VERSION

Instance Method Summary collapse

Methods included from Paths

#_paths

Methods included from Operations

#_operation, #_parameter, #_request_body, #_response, #_security_requirement

Methods included from Schemas

#_build_object_from_schema, #_build_schema_value, #_build_struct, #_flatten_any_of, #_security_schemes, #_struct_ref, #_struct_schemas, #register_literal_type

Methods included from SchemaDefaultTypes

#_register_default_types!

Constructor Details

#initializeOpenAPI3

Returns a new instance of OpenAPI3.



26
27
28
29
# File 'lib/modern/doc_generator/open_api3.rb', line 26

def initialize
  @type_registry = {}
  _register_default_types!
end

Instance Method Details

#_components(descriptor) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/modern/doc_generator/open_api3.rb', line 120

def _components(descriptor)
  # TODO: figure out if we can omit the empty hashes below. We're probably never
  #       going to emit a "minimal" doc; I can't see ever trying to dedupe request
  #       bodies or whatever. (We do security schemes because it's easier and we
  #       do schemas to provide a reason for using dry-struct over a bunch of
  #       hashes.)
  ret = {
    schemas: _struct_schemas(descriptor),
    responses: {},
    parameters: {},
    examples: {},
    requestBodies: {},
    securitySchemes: _security_schemes(descriptor),
    links: {},
    callbacks: {}
  }

  ret
end

#_info(obj) ⇒ Object



116
117
118
# File 'lib/modern/doc_generator/open_api3.rb', line 116

def _info(obj)
  obj.to_h.compact
end

#both(descriptor) ⇒ Object



43
44
45
46
47
48
49
50
# File 'lib/modern/doc_generator/open_api3.rb', line 43

def both(descriptor)
  j = JSON.pretty_generate(hash(descriptor))

  {
    json: j,
    yaml: YAML.dump(JSON.parse(j))
  }
end

#decorate_with_openapi_routes(configuration, descriptor) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/modern/doc_generator/open_api3.rb', line 65

def decorate_with_openapi_routes(configuration, descriptor)
  docs = both(descriptor)

  openapi3_json = docs[:json].freeze
  openapi3_yaml = docs[:yaml].freeze

  serve_json = Modern::Descriptor::Route.new(
    id: "serveOpenApi3Json",
    http_method: :GET,
    path: configuration.open_api_json_path,
    summary: "Serves the OpenAPI3 application spec in JSON form.",
    responses: [
      Modern::Descriptor::Response.new(
        http_code: :default,
        content: [Modern::Descriptor::Content.new(media_type: "application/json")]
      )
    ],
    output_converters: [
      Modern::Descriptor::Converters::Output::JSONBypass
    ],
    action:
      proc do
        response.bypass!
        response.write(openapi3_json)
      end
  )

  serve_yaml = Modern::Descriptor::Route.new(
    id: "serveOpenApi3Yaml",
    http_method: :GET,
    path: configuration.open_api_yaml_path,
    summary: "Serves the OpenAPI3 application spec in YAML form.",
    responses: [
      Modern::Descriptor::Response.new(
        http_code: :default,
        content: [Modern::Descriptor::Content.new(media_type: "application/yaml")]
      )
    ],
    output_converters: [
      Modern::Descriptor::Converters::Output::YAMLBypass
    ],
    action:
      proc do
        response.bypass!
        response.write(openapi3_yaml)
      end
  )

  [serve_json, serve_yaml, descriptor.routes].flatten
end

#hash(descriptor) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/modern/doc_generator/open_api3.rb', line 52

def hash(descriptor)
  ret = {
    openapi: OPENAPI_VERSION,

    info: _info(descriptor.info),
    servers: descriptor.servers.empty? ? nil : descriptor.servers.map(&:to_h),
    paths: _paths(descriptor),
    components: _components(descriptor)
  }.compact

  ret
end

#json(descriptor) ⇒ Object



31
32
33
# File 'lib/modern/doc_generator/open_api3.rb', line 31

def json(descriptor)
  JSON.pretty_generate(hash(descriptor))
end

#yaml(descriptor) ⇒ Object



35
36
37
38
39
40
41
# File 'lib/modern/doc_generator/open_api3.rb', line 35

def yaml(descriptor)
  # TODO: this hack exists just to de-symbolize the output without spending
  #       a bunch of time on it, because we don't have ActiveSupport and
  #       #deep_stringify_keys. It happens once at startup, it's not a big
  #       deal.
  YAML.dump(JSON.parse(json(descriptor)))
end