feat: Add struct conversion code
This commit is contained in:
parent
bef0d41f0e
commit
68cc47ba2e
11 changed files with 293 additions and 83 deletions
86
lib/converter/date_time.ex
Normal file
86
lib/converter/date_time.ex
Normal file
|
@ -0,0 +1,86 @@
|
|||
defmodule Kindling.Converter.DateTime do
|
||||
defstruct year: "",
|
||||
month: "",
|
||||
day: "",
|
||||
hour: "",
|
||||
minute: "",
|
||||
second: "",
|
||||
zone: ""
|
||||
|
||||
def parse(value) do
|
||||
value
|
||||
|> String.codepoints()
|
||||
|> do_year(%__MODULE__{})
|
||||
|> set_defaults()
|
||||
|> to_iso_string()
|
||||
|> DateTime.from_iso8601()
|
||||
end
|
||||
|
||||
def to_iso_string(%{
|
||||
year: year,
|
||||
month: month,
|
||||
day: day,
|
||||
hour: hour,
|
||||
minute: minute,
|
||||
second: second,
|
||||
zone: zone
|
||||
}) do
|
||||
"#{year}-#{month}-#{day}T#{hour}:#{minute}:#{second}#{zone}"
|
||||
end
|
||||
|
||||
def set_defaults(%{
|
||||
year: year,
|
||||
month: month,
|
||||
day: day,
|
||||
hour: hour,
|
||||
minute: minute,
|
||||
second: second,
|
||||
zone: zone
|
||||
}) do
|
||||
%__MODULE__{
|
||||
year: format(year, "0000"),
|
||||
month: format(month, "01"),
|
||||
day: format(day, "01"),
|
||||
hour: format(hour, "00"),
|
||||
minute: format(minute, "00"),
|
||||
second: format(second, "00"),
|
||||
zone: if(zone == "", do: "Z", else: zone)
|
||||
}
|
||||
end
|
||||
|
||||
defp format("", default), do: default
|
||||
defp format(string, default), do: String.pad_leading(string, String.length(default), "0")
|
||||
|
||||
def do_year([], data), do: data
|
||||
def do_year(["-" | tail], data), do: do_month(tail, data)
|
||||
def do_year([hd | tail], %{year: year} = data), do: do_year(tail, %{data | year: year <> hd})
|
||||
|
||||
def do_month([], data), do: data
|
||||
def do_month(["-" | tail], data), do: do_day(tail, data)
|
||||
|
||||
def do_month([hd | tail], %{month: month} = data),
|
||||
do: do_month(tail, %{data | month: month <> hd})
|
||||
|
||||
def do_day([], data), do: data
|
||||
def do_day(["T" | tail], data), do: do_hour(tail, data)
|
||||
def do_day([hd | tail], %{day: day} = data), do: do_day(tail, %{data | day: day <> hd})
|
||||
|
||||
def do_hour([], data), do: data
|
||||
def do_hour([":" | tail], data), do: do_minute(tail, data)
|
||||
def do_hour([hd | tail], %{hour: hour} = data), do: do_hour(tail, %{data | hour: hour <> hd})
|
||||
|
||||
def do_minute([], data), do: data
|
||||
def do_minute([":" | tail], data), do: do_second(tail, data)
|
||||
|
||||
def do_minute([hd | tail], %{minute: minute} = data),
|
||||
do: do_minute(tail, %{data | minute: minute <> hd})
|
||||
|
||||
def do_second([], data), do: data
|
||||
def do_second([c | tail], data) when c in ["+", "-", "Z"], do: do_zone(tail, data)
|
||||
|
||||
def do_second([hd | tail], %{second: second} = data),
|
||||
do: do_second(tail, %{data | second: second <> hd})
|
||||
|
||||
def do_zone([], data), do: data
|
||||
def do_zone([hd | tail], %{zone: zone} = data), do: do_zone(tail, %{data | zone: zone <> hd})
|
||||
end
|
43
lib/kindling/client.ex
Normal file
43
lib/kindling/client.ex
Normal file
|
@ -0,0 +1,43 @@
|
|||
defmodule Kindling.Client do
|
||||
alias Kindling.Converter
|
||||
|
||||
defstruct [:base_url, :access_token, auth_mode: :bearer]
|
||||
|
||||
def read(client, resource_module, id, opts \\ []) do
|
||||
base_uri = URI.parse(client.base_url)
|
||||
uri = base_uri |> URI.append_path(resource_module.path()) |> URI.append_path("/#{id}")
|
||||
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 ->
|
||||
[format_header() | more_headers]
|
||||
|
||||
_other ->
|
||||
[auth_header(client) | [format_header() | more_headers]]
|
||||
end
|
||||
end
|
||||
|
||||
def auth_header(%{auth_mode: :bearer, access_token: token}),
|
||||
do: {"Authorization", "Bearer #{token}"}
|
||||
|
||||
def auth_header(%{auth_mode: :basic, access_token: token}),
|
||||
do: {"Authorization", "Basic #{token}"}
|
||||
|
||||
def format_header do
|
||||
{"Accept", "application/json"}
|
||||
end
|
||||
end
|
|
@ -1,19 +1,3 @@
|
|||
defmodule Kindling.Config do
|
||||
@default_embedded_resources [
|
||||
"Coding",
|
||||
"Duration",
|
||||
"Extension",
|
||||
"Identifier",
|
||||
"Meta",
|
||||
"Element",
|
||||
"CodeableConcept",
|
||||
"Narrative",
|
||||
"Period",
|
||||
"Reference",
|
||||
"ResourceList"
|
||||
]
|
||||
|
||||
def embedded_resources() do
|
||||
Application.get_env(:kindling, :embedded_resources, @default_embedded_resources)
|
||||
end
|
||||
def root_resources, do: Application.get_env(:kindling, :root_resources, ["Encounter"])
|
||||
end
|
||||
|
|
89
lib/kindling/converter.ex
Normal file
89
lib/kindling/converter.ex
Normal file
|
@ -0,0 +1,89 @@
|
|||
defmodule Kindling.Converter do
|
||||
alias Kindling.Schema.Resource
|
||||
|
||||
def convert(version_namespace, %{"resourceType" => resource_type} = resource_json) do
|
||||
resource_module = Module.concat(version_namespace, Resource.class_name(resource_type))
|
||||
|
||||
structify(resource_module, resource_json)
|
||||
end
|
||||
|
||||
def structify(resource_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)}
|
||||
end)
|
||||
|> Map.new()
|
||||
|
||||
struct!(resource_module, atom_map)
|
||||
end
|
||||
|
||||
def convert_field(resource_module, field, value) do
|
||||
cond do
|
||||
field in resource_module.__schema__(:associations) ->
|
||||
convert_association(resource_module, field, value)
|
||||
|
||||
field in resource_module.__schema__(:embeds) ->
|
||||
convert_embed(resource_module, field, value)
|
||||
|
||||
field in resource_module.__schema__(:fields) ->
|
||||
cast_field(resource_module, field, value)
|
||||
|
||||
true ->
|
||||
value
|
||||
end
|
||||
end
|
||||
|
||||
def cast_field(resource_module, field, value) do
|
||||
type = resource_module.__schema__(:type, field)
|
||||
|
||||
do_cast_field(type, value)
|
||||
end
|
||||
|
||||
defp do_cast_field(:utc_datetime_usec, value) do
|
||||
case Kindling.Converter.DateTime.parse(value) do
|
||||
{:ok, v, _} ->
|
||||
v
|
||||
|
||||
other ->
|
||||
other
|
||||
end
|
||||
end
|
||||
|
||||
defp do_cast_field(type, value) do
|
||||
case Ecto.Type.cast(type, value) do
|
||||
{:ok, v} ->
|
||||
v
|
||||
|
||||
other ->
|
||||
other
|
||||
end
|
||||
end
|
||||
|
||||
def convert_association(resource_module, field, value) do
|
||||
%{cardinality: cardinality, related: type} = resource_module.__schema__(:association, field)
|
||||
|
||||
case cardinality do
|
||||
:many ->
|
||||
Enum.map(value, &structify(type, &1))
|
||||
|
||||
:one ->
|
||||
structify(type, value)
|
||||
end
|
||||
end
|
||||
|
||||
def convert_embed(resource_module, field, value) do
|
||||
%{cardinality: cardinality, related: type} = resource_module.__schema__(:embed, field)
|
||||
|
||||
case cardinality do
|
||||
:many ->
|
||||
Enum.map(value, &structify(type, &1))
|
||||
|
||||
:one ->
|
||||
structify(type, value)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -3,10 +3,10 @@ defmodule <%= @namespace %>.<%= @version %>.<%= class_name(@resource_name) %> do
|
|||
import Ecto.Changeset
|
||||
|
||||
@fields [
|
||||
<%= @all_fields |> Enum.map(fn name -> ~s("#{Recase.to_snake(name)}") end) |> Enum.join(",\n") %>
|
||||
<%= @all_fields |> Enum.map(fn name -> ~s(:#{Recase.to_snake(name)}) end) |> Enum.join(",\n") %>
|
||||
]
|
||||
@required_fields [
|
||||
<%= @required_fields |> Enum.map(fn name -> ~s("#{Recase.to_snake(name)}") end) |> Enum.join(",\n") %>
|
||||
<%= @required_fields |> Enum.map(fn name -> ~s(:#{Recase.to_snake(name)}) end) |> Enum.join(",\n") %>
|
||||
]
|
||||
|
||||
embedded_schema do
|
||||
|
@ -21,11 +21,11 @@ defmodule <%= @namespace %>.<%= @version %>.<%= class_name(@resource_name) %> do
|
|||
<%= if @properties.enum != [] do %># Enum<% end %>
|
||||
<%= for {name, df, _} <- @properties.enum do %>field :<%= Recase.to_snake(name) %>, Ecto.Enum, values: <%= inspect(df["enum"] |> Enum.map(&Recase.to_snake(&1)) |> Enum.map(&String.to_atom/1)) %>
|
||||
<% end %>
|
||||
<%= if @properties.embed_one != [] do %># Embed One<% end %>
|
||||
<%= for {name, df, _} <- @properties.embeds_one do %>embed_one :<%= Recase.to_snake(name) %>, <%= @namespace %>.<%= @version %>.<%= ref_to_class_name(df["$ref"]) %>
|
||||
<%= if @properties.embeds_one != [] do %># Embed One<% end %>
|
||||
<%= for {name, df, _} <- @properties.embeds_one do %>embeds_one :<%= Recase.to_snake(name) %>, <%= @namespace %>.<%= @version %>.<%= ref_to_class_name(df["$ref"]) %>
|
||||
<% end %>
|
||||
<%= if @properties.embed_many != [] do %># Embed Many<% end %>
|
||||
<%= for {name, df, _} <- @properties.embed_many do %>embed_many :<%= Recase.to_snake(name) %>, <%= @namespace %>.<%= @version %>.<%= ref_to_class_name(df["$ref"]) %>
|
||||
<%= if @properties.embeds_many != [] do %># Embed Many<% end %>
|
||||
<%= for {name, df, _} <- @properties.embeds_many do %>embeds_many :<%= Recase.to_snake(name) %>, <%= @namespace %>.<%= @version %>.<%= ref_to_class_name(df["items"]["$ref"]) %>
|
||||
<% end %>
|
||||
<%= if @properties.has_one != [] do %># Has One<% end %>
|
||||
<%= for {name, df, _} <- @properties.has_one do %>has_one :<%= Recase.to_snake(name) %>, <%= @namespace %>.<%= @version %>.<%= ref_to_class_name(df["$ref"]) %>
|
||||
|
@ -33,9 +33,6 @@ defmodule <%= @namespace %>.<%= @version %>.<%= class_name(@resource_name) %> do
|
|||
<%= if @properties.has_many != [] do %># Has Many<% end %>
|
||||
<%= for {name, df, _} <- @properties.has_many do %>has_many :<%= Recase.to_snake(name) %>, <%= @namespace %>.<%= @version %>.<%= ref_to_class_name(df["items"]["$ref"]) %>
|
||||
<% end %>
|
||||
<%= if @backlinks != [] do %># belongs_to<% end %>
|
||||
<%= for name <- @backlinks do %>belongs_to :<%= Recase.to_snake(name) %>, <%= @namespace %>.<%= @version %>.<%= class_name(name) %>
|
||||
<% end %>
|
||||
end
|
||||
|
||||
def base_changeset(data \\ %__MODULE__{}, attrs) do
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
defmodule Kindling.Schema do
|
||||
alias Kindling.Config
|
||||
alias Kindling.Version
|
||||
alias Kindling.Schema.Resource
|
||||
|
||||
|
@ -23,7 +22,6 @@ defmodule Kindling.Schema do
|
|||
|
||||
defs =
|
||||
schema["definitions"]
|
||||
|> Map.drop(Config.embedded_resources())
|
||||
|> Enum.reduce(schema["definitions"], fn {name, df}, definitions ->
|
||||
refs = Resource.refs(df)
|
||||
|
||||
|
@ -38,10 +36,14 @@ defmodule Kindling.Schema do
|
|||
Map.put(schema, "definitions", defs)
|
||||
end
|
||||
|
||||
def refs_recursive(schema, root_name) do
|
||||
def refs_recursive(schema, root_name) when is_binary(root_name) do
|
||||
do_recurse(schema, MapSet.new([root_name]), [root_name])
|
||||
end
|
||||
|
||||
def refs_recursive(schema, roots) when is_list(roots) do
|
||||
do_recurse(schema, MapSet.new(roots), roots)
|
||||
end
|
||||
|
||||
defp do_recurse(_schema, visited, []), do: visited
|
||||
|
||||
defp do_recurse(schema, visited, [hd | tail]) do
|
||||
|
|
|
@ -1,18 +1,25 @@
|
|||
defmodule Kindling.Schema.Resource do
|
||||
alias Kindling.Config
|
||||
|
||||
@empty_properties %{array: [], const: [], has_one: [], has_many: [], enum: [], value: []}
|
||||
@empty_properties %{
|
||||
array: [],
|
||||
const: [],
|
||||
embeds_one: [],
|
||||
embeds_many: [],
|
||||
has_one: [],
|
||||
has_many: [],
|
||||
enum: [],
|
||||
value: []
|
||||
}
|
||||
|
||||
def properties(df) do
|
||||
df["properties"]
|
||||
end
|
||||
|
||||
def grouped_properties(df) do
|
||||
def grouped_properties(df, roots) do
|
||||
properties =
|
||||
(df["properties"] || %{})
|
||||
|> Map.delete("id")
|
||||
|> Enum.reject(&is_element/1)
|
||||
|> Enum.map(fn {key, value} -> {key, value, property_type(value)} end)
|
||||
|> Enum.map(fn {key, value} -> {key, value, property_type(value, roots)} end)
|
||||
|> Enum.group_by(fn {_key, _value, type} ->
|
||||
type
|
||||
end)
|
||||
|
@ -23,7 +30,7 @@ defmodule Kindling.Schema.Resource do
|
|||
def all_fields(df) do
|
||||
(df["properties"] || %{})
|
||||
|> Enum.filter(fn {_name, definition} ->
|
||||
property_type(definition) in [:array, :enum, :value]
|
||||
property_type(definition, []) in [:array, :enum, :value]
|
||||
end)
|
||||
|> Enum.map(fn {name, _} -> name end)
|
||||
end
|
||||
|
@ -32,7 +39,7 @@ defmodule Kindling.Schema.Resource do
|
|||
df
|
||||
|> required()
|
||||
|> Enum.filter(fn {_name, definition} ->
|
||||
property_type(definition) in [:array, :enum, :value]
|
||||
property_type(definition, []) in [:array, :enum, :value]
|
||||
end)
|
||||
|> Enum.map(fn {name, _} -> name end)
|
||||
end
|
||||
|
@ -45,37 +52,35 @@ defmodule Kindling.Schema.Resource do
|
|||
key in df["required"]
|
||||
end
|
||||
|
||||
def property_type(%{"const" => _}), do: :const
|
||||
def property_type(%{"const" => _}, _roots), do: :const
|
||||
|
||||
for embed <- Config.embedded_resources() do
|
||||
dbg(embed)
|
||||
|
||||
def property_type(%{"$ref" => "#/definitions/" <> unquote(embed)}), do: :embed_one
|
||||
|
||||
def property_type(%{"items" => %{"$ref" => "#/definitions/" <> unquote(embed)}}) do
|
||||
:embed_many
|
||||
end
|
||||
end
|
||||
|
||||
def property_type(%{"$ref" => "#/definitions/" <> name}) do
|
||||
def property_type(%{"$ref" => "#/definitions/" <> name}, roots) do
|
||||
if is_class_name(name) do
|
||||
if name in roots do
|
||||
:has_one
|
||||
else
|
||||
:embeds_one
|
||||
end
|
||||
else
|
||||
:value
|
||||
end
|
||||
end
|
||||
|
||||
def property_type(%{"items" => %{"$ref" => "#/definitions/" <> name}}) do
|
||||
def property_type(%{"items" => %{"$ref" => "#/definitions/" <> name}}, roots) do
|
||||
if is_class_name(name) do
|
||||
if name in roots do
|
||||
:has_many
|
||||
else
|
||||
:embeds_many
|
||||
end
|
||||
else
|
||||
:array
|
||||
end
|
||||
end
|
||||
|
||||
def property_type(%{"items" => %{"enum" => _}}), do: :array
|
||||
def property_type(%{"enum" => _}), do: :enum
|
||||
def property_type(_), do: :value
|
||||
def property_type(%{"items" => %{"enum" => _}}, _roots), do: :array
|
||||
def property_type(%{"enum" => _}, _roots), do: :enum
|
||||
def property_type(_, _roots), do: :value
|
||||
|
||||
def refs(df) do
|
||||
(df["properties"] || %{})
|
||||
|
@ -95,10 +100,16 @@ defmodule Kindling.Schema.Resource do
|
|||
end
|
||||
|
||||
def is_class_name(name) do
|
||||
!(name in Config.embedded_resources()) && Regex.match?(~r/^[A-Z]/, name)
|
||||
Regex.match?(~r/^[A-Z]/, name)
|
||||
end
|
||||
|
||||
def is_element({_name, %{"$ref" => "#/definitions/Element"}}), do: true
|
||||
def is_element({name, %{"items" => items}}), do: is_element({name, items})
|
||||
def is_element(_), do: false
|
||||
|
||||
def ref_to_class_name("#/definitions/" <> name),
|
||||
do: class_name(name)
|
||||
|
||||
def class_name(name),
|
||||
do: name |> String.split("_") |> Enum.map(&Recase.to_pascal/1) |> Enum.join(".")
|
||||
end
|
||||
|
|
|
@ -3,10 +3,10 @@ defmodule <%= @namespace %>.<%= @version %>.<%= class_name(@resource_name) %> do
|
|||
import Ecto.Changeset
|
||||
|
||||
@fields [
|
||||
<%= @all_fields |> Enum.map(fn name -> ~s("#{Recase.to_snake(name)}") end) |> Enum.join(",\n") %>
|
||||
<%= @all_fields |> Enum.map(fn name -> ~s(:#{Recase.to_snake(name)}) end) |> Enum.join(",\n") %>
|
||||
]
|
||||
@required_fields [
|
||||
<%= @required_fields |> Enum.map(fn name -> ~s("#{Recase.to_snake(name)}") end) |> Enum.join(",\n") %>
|
||||
<%= @required_fields |> Enum.map(fn name -> ~s(:#{Recase.to_snake(name)}) end) |> Enum.join(",\n") %>
|
||||
]
|
||||
|
||||
@primary_key {:id, :binary_id, autogenerate: true}
|
||||
|
@ -22,11 +22,11 @@ defmodule <%= @namespace %>.<%= @version %>.<%= class_name(@resource_name) %> do
|
|||
<%= if @properties.enum != [] do %># Enum<% end %>
|
||||
<%= for {name, df, _} <- @properties.enum do %>field :<%= Recase.to_snake(name) %>, Ecto.Enum, values: <%= inspect(df["enum"] |> Enum.map(&Recase.to_snake(&1)) |> Enum.map(&String.to_atom/1)) %>
|
||||
<% end %>
|
||||
<%= if @properties.embed_one != [] do %># Embed One<% end %>
|
||||
<%= for {name, df, _} <- @properties.embed_one do %>embeds_one :<%= Recase.to_snake(name) %>, <%= @namespace %>.<%= @version %>.<%= ref_to_class_name(df["$ref"]) %>
|
||||
<%= if @properties.embeds_one != [] do %># Embed One<% end %>
|
||||
<%= for {name, df, _} <- @properties.embeds_one do %>embeds_one :<%= Recase.to_snake(name) %>, <%= @namespace %>.<%= @version %>.<%= ref_to_class_name(df["$ref"]) %>
|
||||
<% end %>
|
||||
<%= if @properties.embed_many != [] do %># Embed Many<% end %>
|
||||
<%= for {name, df, _} <- @properties.embed_many do %>embed_many :<%= Recase.to_snake(name) %>, <%= @namespace %>.<%= @version %>.<%= ref_to_class_name(df["items"]["$ref"]) %>
|
||||
<%= if @properties.embeds_many != [] do %># Embed Many<% end %>
|
||||
<%= for {name, df, _} <- @properties.embeds_many do %>embeds_many :<%= Recase.to_snake(name) %>, <%= @namespace %>.<%= @version %>.<%= ref_to_class_name(df["items"]["$ref"]) %>
|
||||
<% end %>
|
||||
<%= if @properties.has_one != [] do %># Has One<% end %>
|
||||
<%= for {name, df, _} <- @properties.has_one do %>has_one :<%= Recase.to_snake(name) %>, <%= @namespace %>.<%= @version %>.<%= ref_to_class_name(df["$ref"]) %>
|
||||
|
@ -39,6 +39,9 @@ defmodule <%= @namespace %>.<%= @version %>.<%= class_name(@resource_name) %> do
|
|||
<% end %>
|
||||
end
|
||||
|
||||
def version, do: <%= @namespace %>.<%= @version %>
|
||||
def path, do: "/<%= @resource_name %>"
|
||||
|
||||
def base_changeset(data \\ %__MODULE__{}, attrs) do
|
||||
data
|
||||
|> cast(attrs, @fields)
|
||||
|
|
|
@ -2,41 +2,41 @@ defmodule Kindling.Templates do
|
|||
require EEx
|
||||
|
||||
import Kindling.Templates.Functions
|
||||
import Kindling.Schema.Resource
|
||||
|
||||
alias Kindling.Config
|
||||
alias Kindling.Schema.Resource
|
||||
|
||||
EEx.function_from_file(:def, :render, "lib/kindling/template.eex", [:assigns])
|
||||
EEx.function_from_file(:def, :render_embedded, "lib/kindling/embed_template.eex", [:assigns])
|
||||
|
||||
def resource_code(namespace, version, resource_name, resource) do
|
||||
def resource_code(namespace, version, roots, resource_name, resource) do
|
||||
assigns = %{
|
||||
namespace: namespace,
|
||||
version: version,
|
||||
resource_name: resource_name,
|
||||
properties: Resource.grouped_properties(resource),
|
||||
properties: Resource.grouped_properties(resource, roots),
|
||||
all_fields: Resource.all_fields(resource),
|
||||
required_fields: Resource.required_fields(resource),
|
||||
backlinks: resource["__backlinks"]
|
||||
backlinks: Enum.filter(resource["__backlinks"], &(&1 in roots))
|
||||
}
|
||||
|
||||
if resource_name in Config.embedded_resources() do
|
||||
assigns
|
||||
|> render_embedded()
|
||||
|> Code.format_string!(file: "#{resource_name}.ex")
|
||||
else
|
||||
if resource_name in roots do
|
||||
assigns
|
||||
|> render()
|
||||
|> Code.format_string!(file: "#{resource_name}.ex")
|
||||
else
|
||||
assigns
|
||||
|> render_embedded()
|
||||
|> Code.format_string!(file: "#{resource_name}.ex")
|
||||
end
|
||||
end
|
||||
|
||||
def write_code(namespace, version, resource_name, resource) do
|
||||
def write_code(namespace, version, roots, resource_name, resource) do
|
||||
dir = Path.join(["lib", String.downcase(namespace), String.downcase(version)])
|
||||
file = Path.join([dir | to_source_file_name(resource_name)])
|
||||
|
||||
File.mkdir_p!(Path.dirname(file))
|
||||
File.write!(file, resource_code(namespace, version, resource_name, resource))
|
||||
File.write!(file, resource_code(namespace, version, roots, resource_name, resource))
|
||||
end
|
||||
|
||||
def to_source_file_name(resource_name) do
|
||||
|
|
|
@ -40,10 +40,4 @@ defmodule Kindling.Templates.Functions do
|
|||
|
||||
def fhir_type_to_ecto(%{"type" => "array", "items" => items}),
|
||||
do: {:array, fhir_type_to_ecto(items)}
|
||||
|
||||
def ref_to_class_name("#/definitions/" <> name),
|
||||
do: class_name(name)
|
||||
|
||||
def class_name(name),
|
||||
do: name |> String.split("_") |> Enum.map(&Recase.to_pascal/1) |> Enum.join(".")
|
||||
end
|
||||
|
|
|
@ -6,22 +6,23 @@ defmodule Mix.Tasks.Kindling.GenerateSchemas do
|
|||
|
||||
@impl Mix.Task
|
||||
def run(args) do
|
||||
if Enum.count(args) != 3 do
|
||||
Mix.shell().error(
|
||||
"usage: mix mix kindling.generate_schemas <namespace> <R5|R4|R3> <root resource name>"
|
||||
)
|
||||
if Enum.count(args) != 2 do
|
||||
Mix.shell().error("usage: mix mix kindling.generate_schemas <namespace> <R5|R4|R3>")
|
||||
|
||||
raise "Argument error."
|
||||
end
|
||||
|
||||
[namespace, version, root] = args
|
||||
[namespace, version] = args
|
||||
|
||||
schema = Kindling.Schema.schema_object(version)
|
||||
roots = Kindling.Config.root_resources()
|
||||
|
||||
to_generate =
|
||||
Kindling.Schema.refs_recursive(schema, root)
|
||||
Kindling.Schema.refs_recursive(schema, roots)
|
||||
|
||||
Enum.each(
|
||||
to_generate,
|
||||
&Kindling.Templates.write_code(namespace, version, &1, schema["definitions"][&1])
|
||||
&Kindling.Templates.write_code(namespace, version, roots, &1, schema["definitions"][&1])
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue