Skip to content

Commit 57fd0c1

Browse files
authored
Avoid trimming inputs and converting to atom keys (#32)
1 parent 7c9015a commit 57fd0c1

99 files changed

Lines changed: 1389 additions & 850 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.dialyzer_ignore.exs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
[
2+
{"lib/open_api_typesense/plugins/field.ex", "Unknown type: OpenAPI.Processor.Type.t/0."},
3+
{"lib/open_api_typesense/plugins/processor.ex", "Callback info about the OpenAPI.Processor behaviour is not available."},
4+
{"lib/open_api_typesense/plugins/processor.ex", "Function OpenAPI.Processor.ignore_operation?/2 does not exist."},
5+
{"lib/open_api_typesense/plugins/processor.ex", "Function OpenAPI.Processor.ignore_schema?/2 does not exist."},
6+
{"lib/open_api_typesense/plugins/processor.ex", "Function OpenAPI.Processor.operation_docstring/3 does not exist."},
7+
{"lib/open_api_typesense/plugins/processor.ex", "Function OpenAPI.Processor.operation_function_name/2 does not exist."},
8+
{"lib/open_api_typesense/plugins/processor.ex", "Function OpenAPI.Processor.operation_module_names/2 does not exist."},
9+
{"lib/open_api_typesense/plugins/processor.ex", "Function OpenAPI.Processor.operation_request_body/2 does not exist."},
10+
{"lib/open_api_typesense/plugins/processor.ex", "Function OpenAPI.Processor.operation_request_method/2 does not exist."},
11+
{"lib/open_api_typesense/plugins/processor.ex", "Function OpenAPI.Processor.operation_response_body/2 does not exist."},
12+
{"lib/open_api_typesense/plugins/processor.ex", "Function OpenAPI.Processor.schema_format/2 does not exist."},
13+
{"lib/open_api_typesense/plugins/processor.ex", "Function OpenAPI.Processor.Naming.merge_schema/2 does not exist."},
14+
{"lib/open_api_typesense/plugins/processor.ex", "Function OpenAPI.Processor.Naming.rename_schema/2 does not exist."},
15+
{"lib/open_api_typesense/plugins/processor.ex", "Function OpenAPI.Processor.Naming.group_schema/2 does not exist."},
16+
{"lib/open_api_typesense/plugins/processor.ex", "Function OpenAPI.Processor.Naming.readable_content_type/1 does not exist."},
17+
{"lib/open_api_typesense/plugins/processor.ex", "Function OpenAPI.Processor.Naming.normalize_identifier/2 does not exist."},
18+
{"lib/open_api_typesense/plugins/processor.ex", "Unknown type: OpenAPI.Processor.State.t/0."},
19+
{"lib/open_api_typesense/plugins/processor.ex", "Unknown type: OpenAPI.Processor.Schema.t/0."},
20+
{"lib/open_api_typesense/plugins/processor.ex", "Unknown type: OpenAPI.Spec.Schema.t/0."},
21+
{"lib/open_api_typesense/plugins/renderer.ex", "Callback info about the OpenAPI.Renderer behaviour is not available."},
22+
{"lib/open_api_typesense/plugins/renderer.ex", "Function OpenAPI.Renderer.format/2 does not exist."},
23+
{"lib/open_api_typesense/plugins/renderer.ex", "Function OpenAPI.Renderer.location/2 does not exist."},
24+
{"lib/open_api_typesense/plugins/renderer.ex", "Function OpenAPI.Renderer.render/2 does not exist."},
25+
{"lib/open_api_typesense/plugins/renderer.ex", "Function OpenAPI.Renderer.render_default_client/2 does not exist."},
26+
{"lib/open_api_typesense/plugins/renderer.ex", "Function OpenAPI.Renderer.render_moduledoc/2 does not exist."},
27+
{"lib/open_api_typesense/plugins/renderer.ex", "Function OpenAPI.Renderer.render_operation/2 does not exist."},
28+
{"lib/open_api_typesense/plugins/renderer.ex", "Function OpenAPI.Renderer.render_operation_doc/2 does not exist."},
29+
{"lib/open_api_typesense/plugins/renderer.ex", "Function OpenAPI.Renderer.render_operations/2 does not exist."},
30+
{"lib/open_api_typesense/plugins/renderer.ex", "Function OpenAPI.Renderer.render_schema/2 does not exist."},
31+
{"lib/open_api_typesense/plugins/renderer.ex", "Function OpenAPI.Renderer.render_schema_field_function/2 does not exist."},
32+
{"lib/open_api_typesense/plugins/renderer.ex", "Function OpenAPI.Renderer.render_using/2 does not exist."},
33+
{"lib/open_api_typesense/plugins/renderer.ex", "Function OpenAPI.Renderer.write/2 does not exist."},
34+
{"lib/open_api_typesense/plugins/renderer.ex", "Function OpenAPI.Processor.Naming.normalize_identifier/1 does not exist."},
35+
{"lib/open_api_typesense/plugins/renderer.ex", "Function OpenAPI.Renderer.Operation.render_query/1 does not exist."},
36+
{"lib/open_api_typesense/plugins/renderer.ex", "Function OpenAPI.Renderer.Util.clean_list/1 does not exist."},
37+
{"lib/open_api_typesense/plugins/renderer.ex", "Function OpenAPI.Renderer.Operation.render_call_request_info/3 does not exist."},
38+
{"lib/open_api_typesense/plugins/renderer.ex", "Function OpenAPI.Renderer.Util.to_readable_type/2 does not exist."},
39+
{"lib/open_api_typesense/plugins/renderer.ex", "Function OpenAPI.Renderer.Util.to_type/2 does not exist."},
40+
{"lib/open_api_typesense/plugins/renderer.ex", "Function OpenAPI.Renderer.Util.put_newlines/1 does not exist."},
41+
{"lib/open_api_typesense/plugins/renderer.ex", "Unknown type: OpenAPI.Renderer.State.t/0."},
42+
{"lib/open_api_typesense/plugins/renderer.ex", "Unknown type: OpenAPI.Processor.Operation.t/0."},
43+
{"lib/open_api_typesense/plugins/renderer.ex", "Unknown type: OpenAPI.Processor.Schema.t/0."},
44+
{"lib/open_api_typesense/plugins/renderer.ex", "Unknown type: OpenAPI.Processor.Schema.Field.t/0."},
45+
]

config/dev.exs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,17 @@ config :open_api_typesense,
1212

1313
config :oapi_generator,
1414
default: [
15+
# processor: OpenApiTypesense.Plugins.Processor,
16+
renderer: OpenApiTypesense.Plugins.Renderer,
17+
# naming: [
18+
# field_casing: :snake
19+
# ],
1520
output: [
1621
base_module: OpenApiTypesense,
1722
location: "lib/open_api_typesense",
1823
operation_subdirectory: "operations/",
19-
schema_subdirectory: "schemas/"
24+
schema_subdirectory: "schemas/",
25+
schema_use: OpenApiTypesense.Encoder
26+
# extra_fields: [__info__: :map]
2027
]
2128
]

coveralls.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
"skip_files": [
33
"test",
44
"deps",
5+
"lib/open_api_typesense.ex",
56
"lib/open_api_typesense/schemas",
6-
"lib/open_api_typesense.ex"
7+
"lib/open_api_typesense/encoder.ex"
78
]
89
}

lib/open_api_typesense/client.ex

Lines changed: 62 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -114,119 +114,91 @@ defmodule OpenApiTypesense.Client do
114114

115115
defp req_request(req_client, opts) do
116116
{_req, resp} = Req.Request.run_request(req_client)
117-
parse_resp(resp, opts[:response])
117+
parse_resp(resp, opts)
118118
end
119119

120-
defp encode_body(opts) do
121-
if opts[:request] do
122-
[content_type] = opts[:request]
123-
parse_content_type(content_type, opts[:args][:body])
124-
else
125-
Jason.encode_to_iodata!(opts[:args][:body])
126-
end
127-
end
128-
129-
defp parse_content_type({"application/octet-stream", {:string, :generic}}, body) do
130-
Enum.map_join(body, "\n", &Jason.encode_to_iodata!/1)
131-
end
132-
133-
defp parse_content_type({"application/json", {mod, :t}}, body) when is_atom(mod) do
134-
atom_keys = Map.keys(mod.__struct__()) |> Enum.reject(&(&1 == :__struct__))
135-
string_keys = Enum.map(atom_keys, &to_string/1)
136-
keys = atom_keys ++ string_keys
120+
defp parse_resp(%Req.Response{status: code, body: list}, %{response: resp})
121+
when is_list(list) and code in 200..299 do
122+
response =
123+
Enum.find_value(resp, fn {status, [{mod, _t}]} ->
124+
if status === code do
125+
Enum.map(list, fn body ->
126+
struct(mod, body)
127+
end)
128+
end
129+
end)
137130

138-
body
139-
|> Map.take(keys)
140-
|> OpenApiTypesense.Converter.to_atom_keys(safe: false)
141-
|> Jason.encode_to_iodata!()
131+
{:ok, response}
142132
end
143133

144-
defp parse_content_type({"application/json", _}, body) do
145-
Jason.encode_to_iodata!(body)
146-
end
134+
defp parse_resp(%Req.Response{status: code, body: body}, %{response: resp})
135+
when code in 200..299 do
136+
response =
137+
Enum.find_value(resp, fn resp ->
138+
case {resp, body} do
139+
{{status, {:string, :generic}}, ""} when status === code ->
140+
body
147141

148-
# Some resources are missing 4xx descriptions, hence we will set a default
149-
# instead so we can see the actual error message instead of stacktrace.
150-
# See https://github.com/typesense/typesense-api-spec/pull/84
151-
defp parse_resp(%Req.Response{} = resp, status_type) do
152-
{status, type} =
153-
status_type
154-
|> Enum.find(fn {status, _type} -> status == resp.status end) ||
155-
{resp.status, :map}
142+
{{status, {mod, t}}, _} when status === code and t !== :generic ->
143+
struct(mod, body)
156144

157-
parse_values(status, type, resp.body)
158-
end
145+
{{status, [{_mod, t}]}, nil} when status === code and t !== :generic ->
146+
[]
159147

160-
defp parse_resp(error, _opts_resp) do
161-
{:error, Exception.message(error)}
162-
end
148+
{{status, :map}, _} when status === code ->
149+
body
163150

164-
@spec parse_values(
165-
non_neg_integer(),
166-
atom() | list() | tuple(),
167-
map() | String.t() | list()
168-
) ::
169-
{:ok, any()} | {:error, any()}
170-
defp parse_values(code, :map, body) do
171-
status = if code in 200..299, do: :ok, else: :error
151+
{_, _} ->
152+
body
153+
|> String.splitter("\n")
154+
|> Enum.map(&Jason.decode!/1)
155+
end
156+
end)
172157

173-
{status, body}
158+
{:ok, response}
174159
end
175160

176-
defp parse_values(code, values, body) when is_list(values) do
177-
status = if code in 200..299, do: :ok, else: :error
178-
179-
resp =
180-
values
181-
|> Enum.map(fn {module, _func_name} ->
182-
cond do
183-
is_list(body) ->
184-
Enum.map(body, fn single_body ->
185-
struct(module, single_body)
186-
end)
187-
188-
is_nil(body) ->
189-
[]
190-
191-
true ->
192-
struct(module, body)
161+
defp parse_resp(%Req.Response{status: code, body: body}, %{response: resp}) do
162+
message =
163+
Enum.find_value(resp, fn {status, type} ->
164+
if status === code do
165+
{mod, _t} = type
166+
struct(mod, body)
193167
end
194168
end)
195-
|> List.flatten()
196169

197-
{status, resp}
170+
{:error, message}
198171
end
199172

200-
defp parse_values(code, {module, _func_name} = _values, body) when module == :string do
201-
status = if code in 200..299, do: :ok, else: :error
202-
203-
case status do
204-
:ok ->
205-
resp =
206-
body
207-
|> String.splitter("\n")
208-
|> Enum.map(&Jason.decode!/1)
209-
210-
{status, resp}
173+
defp parse_resp(error, _opts_resp) do
174+
{:error, Exception.message(error)}
175+
end
211176

212-
:error ->
213-
{status, struct(ApiResponse, message: Jason.decode!(body)["error"])}
177+
defp encode_body(opts) do
178+
if opts[:request] do
179+
[content_type] = opts[:request]
180+
parse_content_type(content_type, opts[:args][:body])
181+
else
182+
Jason.encode_to_iodata!(opts[:args][:body])
214183
end
215184
end
216185

217-
defp parse_values(
218-
code,
219-
{module, _func_name} = _values,
220-
%{hits: results, union_request_params: _} = _body
221-
) do
222-
status = if code in 200..299, do: :ok, else: :error
223-
224-
{status, struct(module, %{results: results})}
186+
defp parse_content_type({"application/octet-stream", {:string, :generic}}, body) do
187+
Enum.map_join(body, "\n", &Jason.encode_to_iodata!/1)
225188
end
226189

227-
defp parse_values(code, {module, _func_name} = _values, body) do
228-
status = if code in 200..299, do: :ok, else: :error
190+
# defp parse_content_type({"application/json", {module, :t}}, body) when is_atom(module) do
191+
# atom_keys = Map.keys(mod.__struct__()) |> Enum.reject(&(&1 == :__struct__))
192+
# string_keys = Enum.map(atom_keys, &to_string/1)
193+
# keys = atom_keys ++ string_keys
194+
195+
# body
196+
# |> Map.take(keys)
197+
# |> OpenApiTypesense.Converter.to_atom_keys(safe: false)
198+
# |> Jason.encode_to_iodata!()
199+
# end
229200

230-
{status, struct(module, body)}
201+
defp parse_content_type({"application/json", _}, body) do
202+
Jason.encode_to_iodata!(body)
231203
end
232204
end

0 commit comments

Comments
 (0)