feat: Support Bundle conversion and Search endpoints

This commit is contained in:
Robert Prehn 2024-03-01 11:39:16 -06:00
parent 68cc47ba2e
commit c7c6568e37
No known key found for this signature in database
4 changed files with 53 additions and 13 deletions

View file

@ -21,6 +21,25 @@ defmodule Kindling.Client do
end
end
def search(client, resource_module, params \\ [], opts \\ []) do
base_uri = URI.parse(client.base_url)
query = URI.encode_query(params)
uri = base_uri |> URI.append_path(resource_module.path()) |> URI.append_query(query)
more_headers = Keyword.get(opts, :headers, [])
headers = headers(client, more_headers)
uri
|> Req.get(headers: headers)
|> case do
{:ok, %{status: status} = response} when status >= 200 and status < 300 ->
Converter.convert(resource_module.version(), response.body)
other ->
other
end
end
def headers(client, more_headers) do
case client.auth_mode do
:open ->

View file

@ -1,3 +1,4 @@
defmodule Kindling.Config do
def root_resources, do: Application.get_env(:kindling, :root_resources, ["Encounter"])
def root_resources,
do: Application.get_env(:kindling, :root_resources, ["Bundle", "Patient", "Encounter"])
end

View file

@ -3,31 +3,50 @@ defmodule Kindling.Converter do
def convert(version_namespace, %{"resourceType" => resource_type} = resource_json) do
resource_module = Module.concat(version_namespace, Resource.class_name(resource_type))
resource_list_module = Module.concat(version_namespace, "ResourceList")
structify(resource_module, resource_json)
structify(resource_module, resource_list_module, resource_json)
end
def structify(resource_module, resource_json) do
def structify(
resource_module,
resource_list_module,
%{"resourceType" => resource_type} = resource_json
)
when resource_module == resource_list_module do
version_namespace =
resource_module
|> Module.split()
|> Enum.reverse()
|> tl()
|> Enum.reverse()
|> Module.concat()
resource_module = Module.concat(version_namespace, Resource.class_name(resource_type))
structify(resource_module, resource_list_module, resource_json)
end
def structify(resource_module, resource_list_module, resource_json) do
Code.ensure_loaded!(resource_module)
atom_map =
resource_json
|> Enum.map(fn {key_string, value} ->
key_atom = key_string |> Recase.to_snake() |> String.to_existing_atom()
{key_atom, convert_field(resource_module, key_atom, value)}
{key_atom, convert_field(resource_module, resource_list_module, key_atom, value)}
end)
|> Map.new()
struct!(resource_module, atom_map)
end
def convert_field(resource_module, field, value) do
def convert_field(resource_module, resource_list_module, field, value) do
cond do
field in resource_module.__schema__(:associations) ->
convert_association(resource_module, field, value)
convert_association(resource_module, resource_list_module, field, value)
field in resource_module.__schema__(:embeds) ->
convert_embed(resource_module, field, value)
convert_embed(resource_module, resource_list_module, field, value)
field in resource_module.__schema__(:fields) ->
cast_field(resource_module, field, value)
@ -63,27 +82,27 @@ defmodule Kindling.Converter do
end
end
def convert_association(resource_module, field, value) do
def convert_association(resource_module, resource_list_module, field, value) do
%{cardinality: cardinality, related: type} = resource_module.__schema__(:association, field)
case cardinality do
:many ->
Enum.map(value, &structify(type, &1))
Enum.map(value, &structify(type, resource_list_module, &1))
:one ->
structify(type, value)
structify(type, resource_list_module, value)
end
end
def convert_embed(resource_module, field, value) do
def convert_embed(resource_module, resource_list_module, field, value) do
%{cardinality: cardinality, related: type} = resource_module.__schema__(:embed, field)
case cardinality do
:many ->
Enum.map(value, &structify(type, &1))
Enum.map(value, &structify(type, resource_list_module, &1))
:one ->
structify(type, value)
structify(type, resource_list_module, value)
end
end
end

View file

@ -30,6 +30,7 @@ defmodule Kindling.Templates.Functions do
def fhir_type_to_ecto(%{"$ref" => "#/definitions/xhtml"}), do: :string
def fhir_type_to_ecto(%{"$ref" => "#/definitions/markdown"}), do: :string
def fhir_type_to_ecto(%{"$ref" => "#/definitions/base64Binary"}), do: :string
def fhir_type_to_ecto(%{"$ref" => "#/definitions/date"}), do: :date
def fhir_type_to_ecto(%{"$ref" => "#/definitions/dateTime"}), do: :utc_datetime_usec
def fhir_type_to_ecto(%{"$ref" => "#/definitions/instant"}), do: :utc_datetime_usec
def fhir_type_to_ecto(%{"$ref" => "#/definitions/time"}), do: :time_usec