Skip to content

Commit

Permalink
Implement Extendable protocol for all structs that can have extensions (
Browse files Browse the repository at this point in the history
open-api-spex#415)

See https://swagger.io/docs/specification/openapi-extensions/

Fix open-api-spex#342

Co-authored-by: Alberto Sartori <alberto.sartori@athonet.com>
  • Loading branch information
2 people authored and lucacorti committed Feb 13, 2022
1 parent 20e8814 commit 392d012
Show file tree
Hide file tree
Showing 10 changed files with 49 additions and 15 deletions.
8 changes: 7 additions & 1 deletion lib/open_api_spex/controller_specs.ex
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,11 @@ defmodule OpenApiSpex.ControllerSpecs do
shared_security -> List.flatten(shared_security)
end

extensions =
spec
|> Enum.filter(fn {key, _val} -> is_atom(key) && String.starts_with?(to_string(key), "x-") end)
|> Map.new(fn {key, value} -> {to_string(key), value} end)

%Operation{
callbacks: Map.get(spec, :callbacks, %{}),
description: Map.get(spec, :description),
Expand All @@ -287,7 +292,8 @@ defmodule OpenApiSpex.ControllerSpecs do
responses: OperationBuilder.build_responses(spec),
security: OperationBuilder.build_security(spec, %{security: security}),
summary: Map.get(spec, :summary),
tags: OperationBuilder.build_tags(spec, %{tags: shared_tags})
tags: OperationBuilder.build_tags(spec, %{tags: shared_tags}),
extensions: extensions
}
end
end
12 changes: 11 additions & 1 deletion lib/open_api_spex/extendable.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,17 @@ defimpl OpenApiSpex.Extendable, for: Any do
def to_map(struct), do: Map.from_struct(struct)
end

defimpl OpenApiSpex.Extendable, for: [OpenApiSpex.Info, OpenApiSpex.OpenApi] do
defimpl OpenApiSpex.Extendable,
for: [
OpenApiSpex.Info,
OpenApiSpex.OpenApi,
OpenApiSpex.Operation,
OpenApiSpex.Parameter,
OpenApiSpex.PathItem,
OpenApiSpex.Response,
OpenApiSpex.SecurityScheme,
OpenApiSpex.Tag
] do
def to_map(struct = %{extensions: e}) do
struct
|> Map.from_struct()
Expand Down
6 changes: 4 additions & 2 deletions lib/open_api_spex/operation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ defmodule OpenApiSpex.Operation do
callbacks: %{},
deprecated: false,
security: nil,
servers: nil
servers: nil,
extensions: nil

@typedoc """
[Operation Object](https://swagger.io/specification/#operationObject)
Expand All @@ -51,7 +52,8 @@ defmodule OpenApiSpex.Operation do
callbacks: %{String.t() => Callback.t() | Reference.t()},
deprecated: boolean,
security: [SecurityRequirement.t()] | nil,
servers: [Server.t()] | nil
servers: [Server.t()] | nil,
extensions: %{String.t() => any()} | nil
}

@doc """
Expand Down
6 changes: 4 additions & 2 deletions lib/open_api_spex/parameter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ defmodule OpenApiSpex.Parameter do
:schema,
:example,
:examples,
:content
:content,
:extensions
]

@typedoc """
Expand Down Expand Up @@ -67,7 +68,8 @@ defmodule OpenApiSpex.Parameter do
schema: Schema.t() | Reference.t() | atom | nil,
example: any,
examples: %{String.t() => Example.t() | Reference.t()} | nil,
content: %{String.t() => MediaType.t()} | nil
content: %{String.t() => MediaType.t()} | nil,
extensions: %{String.t() => any()} | nil
}

@type parameters :: %{String.t() => t | Reference.t()} | nil
Expand Down
6 changes: 4 additions & 2 deletions lib/open_api_spex/path_item.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ defmodule OpenApiSpex.PathItem do
:patch,
:trace,
:servers,
:parameters
:parameters,
:extensions
]

@typedoc """
Expand All @@ -42,7 +43,8 @@ defmodule OpenApiSpex.PathItem do
patch: Operation.t() | nil,
trace: Operation.t() | nil,
servers: [Server.t()] | nil,
parameters: [Parameter.t() | Reference.t()] | nil
parameters: [Parameter.t() | Reference.t()] | nil,
extensions: %{String.t() => any()} | nil
}

@typedoc """
Expand Down
6 changes: 4 additions & 2 deletions lib/open_api_spex/response.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ defmodule OpenApiSpex.Response do
:description,
:headers,
:content,
:links
:links,
:extensions
]

@typedoc """
Expand All @@ -22,7 +23,8 @@ defmodule OpenApiSpex.Response do
description: String.t(),
headers: %{String.t() => Header.t() | Reference.t()} | nil,
content: %{String.t() => MediaType.t()} | nil,
links: %{String.t() => Link.t() | Reference.t()} | nil
links: %{String.t() => Link.t() | Reference.t()} | nil,
extensions: %{String.t() => any()} | nil
}

@doc """
Expand Down
6 changes: 4 additions & 2 deletions lib/open_api_spex/security_scheme.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ defmodule OpenApiSpex.SecurityScheme do
:scheme,
:bearerFormat,
:flows,
:openIdConnectUrl
:openIdConnectUrl,
:extensions
]

@typedoc """
Expand All @@ -31,6 +32,7 @@ defmodule OpenApiSpex.SecurityScheme do
scheme: String.t() | nil,
bearerFormat: String.t() | nil,
flows: OAuthFlows.t() | nil,
openIdConnectUrl: String.t() | nil
openIdConnectUrl: String.t() | nil,
extensions: %{String.t() => any()} | nil
}
end
6 changes: 4 additions & 2 deletions lib/open_api_spex/tag.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ defmodule OpenApiSpex.Tag do
defstruct [
:name,
:description,
:externalDocs
:externalDocs,
:extensions
]

@typedoc """
Expand All @@ -21,6 +22,7 @@ defmodule OpenApiSpex.Tag do
@type t :: %__MODULE__{
name: String.t(),
description: String.t() | nil,
externalDocs: ExternalDocumentation.t() | nil
externalDocs: ExternalDocumentation.t() | nil,
extensions: %{String.t() => any()} | nil
}
end
5 changes: 5 additions & 0 deletions test/controller_specs_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -101,5 +101,10 @@ defmodule OpenApiSpex.ControllerSpecsTest do
assert %OpenApiSpex.Operation{operationId: "OpenApiSpexTest.DslController.index"} =
DslController.open_api_operation(:index)
end

test "supports extensions" do
assert %OpenApiSpex.Operation{extensions: %{"x-foo" => "bar"}} =
DslController.open_api_operation(:index)
end
end
end
3 changes: 2 additions & 1 deletion test/support/dsl_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ defmodule OpenApiSpexTest.DslController do
],
responses: [
ok: {"Users index response", "application/json", UsersIndexResponse}
]
],
"x-foo": "bar"

def index(conn, _) do
json(conn, [])
Expand Down

0 comments on commit 392d012

Please sign in to comment.