require_relative 'openapi/info_object.rb'
require_relative 'openapi/server_object.rb'
require_relative 'openapi/paths_object.rb'
require_relative 'openapi/tag_object.rb'
module Praxis
module Docs
class OpenApiGenerator < Generator
API_DOCS_DIRNAME = 'docs/openapi'
# substitutes ":params_like_so" for {params_like_so}
def self.templatize_url( string )
Mustermann.new(string).to_templates.first
end
def save!
initialize_directories
# Restrict the versions listed in the index file to the ones for which we have at least 1 resource
write_index_file( for_versions: resources_by_version.keys )
resources_by_version.keys.each do |version|
write_version_file(version)
end
end
def initialize(root)
require 'yaml'
@root = root
@resources_by_version = Hash.new do |h,k|
h[k] = Set.new
end
@infos = ApiDefinition.instance.infos
collect_resources
collect_types
end
private
def write_index_file( for_versions: )
# TODO. create a simple html file that can link to the individual versions available
end
def write_version_file( version )
# version_info = infos_by_version[version]
# # Hack, let's "inherit/copy" all traits of a version from the global definition
# # Eventually traits should be defined for a version (and inheritable from global) so we'll emulate that here
# version_info[:traits] = infos_by_version[:traits]
dumped_resources = dump_resources( resources_by_version[version] )
processed_types = scan_types_for_version(version, dumped_resources)
# Here we have:
# processed types: which includes mediatypes and normal types...real classes
# processed resources for this version: resources_by_version[version]
info_object = OpenApi::InfoObject.new(version: version, api_definition_info: @infos[version])
# We only support a server in Praxis ... so we'll use the base path
server_object = OpenApi::ServerObject.new( url: @infos[version].base_path )
paths_object = OpenApi::PathsObject.new( resources: resources_by_version[version])
full_data = {
openapi: "3.0.2",
info: info_object.dump,
servers: [server_object.dump],
paths: paths_object.dump,
# responses: {}, #TODO!! what do we get here? the templates?...need to transform to "Responses Definitions Object"
# securityDefinitions: {}, # NOTE: No security definitions in Praxis
# security: [], # NOTE: No security definitions in Praxis
}
# Create the top level tags by:
# 1- First adding all the resource display names (and descriptions)
tags_for_resources = resources_by_version[version].collect do |resource|
OpenApi::TagObject.new(name: resource.display_name, description: resource.description ).dump
end
full_data[:tags] = tags_for_resources
# 2- Then adding all of the top level traits but marking them special with the x-traitTag (of Redoc)
tags_for_traits = (ApiDefinition.instance.traits).collect do |name, info|
OpenApi::TagObject.new(name: name, description: info.description).dump.merge(:'x-traitTag' => true)
end
unless tags_for_traits.empty?
full_data[:tags] = full_data[:tags] + tags_for_traits
end
# Include only MTs (i.e., not custom types or simple types...)
component_schemas = reusable_schema_objects(processed_types.select{|t| t < Praxis::MediaType})
# 3- Then adding all of the top level Mediatypes...so we can present them at the bottom, otherwise they don't show
tags_for_mts = component_schemas.map do |(name, info)|
special_redoc_anchor = "