OpenProject is the leading open source project management software.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openproject/lib/api/open_api.rb

64 lines
2.1 KiB

module API
module OpenAPI
extend self
def spec(version: :stable)
spec_path = Rails.application.root.join("docs/api/apiv3/openapi-spec.yml")
if spec_path.exist?
assemble_spec spec_path
else
API::OpenAPI::BlueprintImport.convert version: version, single_file: true
end
end
def assemble_spec(file_path)
spec = YAML.load File.read(file_path.to_s)
substitute_refs(spec, path: file_path.parent, root_path: file_path.parent)
end
def substitute_refs(spec, path:, root_path:, root_spec: spec)
if spec.is_a?(Hash)
if spec.size == 1 && spec.keys.first == "$ref"
ref_path = path.join spec.values.first
ref_value = YAML.load File.read(ref_path.to_s)
resolve_refs ref_value, path: ref_path.parent, root_path: root_path, root_spec: root_spec
else
spec.map { |k, v| [k, substitute_refs(v, path: path, root_path: root_path, root_spec: root_spec)] }.to_h
end
elsif spec.is_a?(Array)
spec.map { |s| substitute_refs s, path: path, root_path: root_path, root_spec: root_spec }
else
spec
end
end
def resolve_refs(spec, path:, root_path:, root_spec:)
if spec.is_a?(Hash)
if spec.size == 1 && spec.keys.first == "$ref"
ref_path = spec.values.first
if ref_path.start_with?(".")
schema_file = path.join(ref_path).to_s.sub(root_path.to_s, ".")
schema_path = path.join(ref_path).parent.to_s.sub(root_path.to_s, "").split("/").drop(1)
schema_name = root_spec.dig(*schema_path).find { |k, v| v["$ref"] == schema_file }.first
schema_ref = path.join(ref_path).parent.join(schema_name).to_s.sub(root_path.to_s, "#")
{ spec.keys.first => schema_ref }
else
spec
end
else
spec.map { |k, v| [k, resolve_refs(v, path: path, root_path: root_path, root_spec: root_spec)] }.to_h
end
elsif spec.is_a?(Array)
spec.map { |v| resolve_refs(v, path: path, root_path: root_path, root_spec: root_spec) }
else
spec
end
end
end
end