Skip to content

Commit 5c56490

Browse files
authored
Fix: object type + config for backwards compat + a regression in deps update (#413)
* feat: add config to use correct `object` type for filter schemas The filter schema type `deepObject` is technically invalid per the OpenAPI spec (it's only valid for the `style` property, not `type`), but works better with Swagger UI. This adds a config option to opt out of the `deepObject` type: config :ash_json_api, use_deep_object_for_filter_type?: false The default remains `deepObject` (true) for backwards compatibility with Swagger UI. * test: add is_distinct_from and is_not_distinct_from to filter type tests
1 parent 2fbbc02 commit 5c56490

4 files changed

Lines changed: 60 additions & 8 deletions

File tree

documentation/topics/open-api.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,16 @@ use AshJsonApi.Router,
176176
open_api_file: open_api_file
177177
```
178178

179+
## Configuration
180+
181+
### Filter Schema Type
182+
183+
By default, the filter schema uses `deepObject` as its type, which works well with Swagger UI but is technically invalid per the OpenAPI spec (`deepObject` is only valid for the `style` property, not `type`). If you need a spec-compliant schema, you can disable this:
184+
185+
```elixir
186+
config :ash_json_api, use_deep_object_for_filter_type?: false
187+
```
188+
179189
## Known issues/limitations
180190

181191
### Swagger UI

lib/ash_json_api/json_schema/open_api.ex

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,12 +255,19 @@ if Code.ensure_loaded?(OpenApiSpex) do
255255
defp resource_filter_schemas(domains, resource, acc) do
256256
{field_types, acc} = filter_field_types(resource, acc)
257257

258+
filter_schema_type =
259+
if Application.get_env(:ash_json_api, :use_deep_object_for_filter_type?, true) do
260+
:deepObject
261+
else
262+
:object
263+
end
264+
258265
schemas =
259266
[
260267
{
261268
"#{AshJsonApi.Resource.Info.type(resource)}-filter",
262269
%Schema{
263-
type: :deepObject,
270+
type: filter_schema_type,
264271
properties: resource_filter_fields(resource, domains),
265272
example: "",
266273
additionalProperties: false,

test/acceptance/open_api_test.exs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,9 @@ defmodule Test.Acceptance.OpenApiTest do
500500
end
501501

502502
describe "Index route" do
503-
test "filter parameter", %{open_api_spec: %OpenApi{} = api_spec} do
503+
test "filter parameter uses :deepObject type by default", %{
504+
open_api_spec: %OpenApi{} = api_spec
505+
} do
504506
%Operation{} = operation = api_spec.paths["/posts"].get
505507
%Parameter{} = filter = operation.parameters |> Enum.find(&(&1.name == "filter"))
506508
assert api_spec.components.schemas["author-filter-name"].properties[:contains]
@@ -555,6 +557,27 @@ defmodule Test.Acceptance.OpenApiTest do
555557
refute Enum.any?(operation.parameters, &(&1.name == :filter))
556558
end
557559

560+
test "filter schema type uses :object when use_deep_object_for_filter_type? config is false" do
561+
original_value = Application.get_env(:ash_json_api, :use_deep_object_for_filter_type?)
562+
Application.put_env(:ash_json_api, :use_deep_object_for_filter_type?, false)
563+
564+
try do
565+
api_spec =
566+
AshJsonApi.Controllers.OpenApi.spec(%{private: %{}},
567+
domains: [Blogs]
568+
)
569+
570+
assert schema = api_spec.components.schemas["post-filter"]
571+
assert schema.type == :object
572+
after
573+
if original_value == nil do
574+
Application.delete_env(:ash_json_api, :use_deep_object_for_filter_type?)
575+
else
576+
Application.put_env(:ash_json_api, :use_deep_object_for_filter_type?, original_value)
577+
end
578+
end
579+
end
580+
558581
test "sort parameter", %{open_api_spec: %OpenApi{} = api_spec} do
559582
%Operation{} = operation = api_spec.paths["/posts"].get
560583
%Parameter{} = sort = operation.parameters |> Enum.find(&(&1.name == "sort"))

test/ash_json_api/json_schema/open_api_test.exs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,9 @@ defmodule AshJsonApi.OpenApiTest do
108108
less_than: %OpenApiSpex.Schema{type: :integer},
109109
greater_than: %OpenApiSpex.Schema{type: :integer},
110110
less_than_or_equal: %OpenApiSpex.Schema{type: :integer},
111-
greater_than_or_equal: %OpenApiSpex.Schema{type: :integer}
111+
greater_than_or_equal: %OpenApiSpex.Schema{type: :integer},
112+
is_distinct_from: %OpenApiSpex.Schema{type: :string},
113+
is_not_distinct_from: %OpenApiSpex.Schema{type: :string}
112114
},
113115
additionalProperties: false
114116
}}
@@ -137,7 +139,9 @@ defmodule AshJsonApi.OpenApiTest do
137139
less_than: %OpenApiSpex.Schema{type: :integer},
138140
greater_than: %OpenApiSpex.Schema{type: :integer},
139141
less_than_or_equal: %OpenApiSpex.Schema{type: :integer},
140-
greater_than_or_equal: %OpenApiSpex.Schema{type: :integer}
142+
greater_than_or_equal: %OpenApiSpex.Schema{type: :integer},
143+
is_distinct_from: %OpenApiSpex.Schema{type: :string},
144+
is_not_distinct_from: %OpenApiSpex.Schema{type: :string}
141145
},
142146
additionalProperties: false,
143147
description: "Count of posts"
@@ -169,7 +173,9 @@ defmodule AshJsonApi.OpenApiTest do
169173
greater_than: %OpenApiSpex.Schema{type: :string},
170174
less_than_or_equal: %OpenApiSpex.Schema{type: :string},
171175
greater_than_or_equal: %OpenApiSpex.Schema{type: :string},
172-
contains: %OpenApiSpex.Schema{type: :string}
176+
contains: %OpenApiSpex.Schema{type: :string},
177+
is_distinct_from: %OpenApiSpex.Schema{type: :string},
178+
is_not_distinct_from: %OpenApiSpex.Schema{type: :string}
173179
},
174180
required: [],
175181
additionalProperties: false
@@ -196,7 +202,9 @@ defmodule AshJsonApi.OpenApiTest do
196202
less_than: %OpenApiSpex.Schema{type: :integer},
197203
greater_than: %OpenApiSpex.Schema{type: :integer},
198204
less_than_or_equal: %OpenApiSpex.Schema{type: :integer},
199-
greater_than_or_equal: %OpenApiSpex.Schema{type: :integer}
205+
greater_than_or_equal: %OpenApiSpex.Schema{type: :integer},
206+
is_distinct_from: %OpenApiSpex.Schema{type: :string},
207+
is_not_distinct_from: %OpenApiSpex.Schema{type: :string}
200208
},
201209
additionalProperties: false
202210
}
@@ -218,7 +226,9 @@ defmodule AshJsonApi.OpenApiTest do
218226
not_eq: %OpenApiSpex.Schema{type: :integer},
219227
less_than: %OpenApiSpex.Schema{type: :integer},
220228
less_than_or_equal: %OpenApiSpex.Schema{type: :integer},
221-
greater_than_or_equal: %OpenApiSpex.Schema{type: :integer}
229+
greater_than_or_equal: %OpenApiSpex.Schema{type: :integer},
230+
is_distinct_from: %OpenApiSpex.Schema{type: :string},
231+
is_not_distinct_from: %OpenApiSpex.Schema{type: :string}
222232
},
223233
additionalProperties: false,
224234
description: "Count of posts"
@@ -243,7 +253,9 @@ defmodule AshJsonApi.OpenApiTest do
243253
greater_than: %OpenApiSpex.Schema{type: :string},
244254
less_than_or_equal: %OpenApiSpex.Schema{type: :string},
245255
greater_than_or_equal: %OpenApiSpex.Schema{type: :string},
246-
contains: %OpenApiSpex.Schema{type: :string}
256+
contains: %OpenApiSpex.Schema{type: :string},
257+
is_distinct_from: %OpenApiSpex.Schema{type: :string},
258+
is_not_distinct_from: %OpenApiSpex.Schema{type: :string}
247259
},
248260
required: [],
249261
additionalProperties: false

0 commit comments

Comments
 (0)