feat: Implement embedded schemas
This commit is contained in:
		
							parent
							
								
									a6016e31fd
								
							
						
					
					
						commit
						0bd0153204
					
				
					 11 changed files with 192 additions and 7 deletions
				
			
		
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							|  | @ -24,3 +24,5 @@ kindling-*.tar | ||||||
| 
 | 
 | ||||||
| # Temporary files, for example, from tests. | # Temporary files, for example, from tests. | ||||||
| /tmp/ | /tmp/ | ||||||
|  | 
 | ||||||
|  | /lib/fhir/ | ||||||
|  |  | ||||||
							
								
								
									
										19
									
								
								lib/kindling/config.ex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								lib/kindling/config.ex
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | ||||||
|  | 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 | ||||||
|  | end | ||||||
							
								
								
									
										50
									
								
								lib/kindling/embed_template.eex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								lib/kindling/embed_template.eex
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,50 @@ | ||||||
|  | defmodule <%= @namespace %>.<%= @version %>.<%= class_name(@resource_name) %> do | ||||||
|  |   use Ecto.Schema | ||||||
|  |   import Ecto.Changeset | ||||||
|  | 
 | ||||||
|  |   @fields [ | ||||||
|  |     <%= @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") %> | ||||||
|  |   ] | ||||||
|  | 
 | ||||||
|  |   embedded_schema do | ||||||
|  |     <%= if @properties.const != [] do %># Constants<% end %> | ||||||
|  |     <%= for {name, df, _} <- @properties.const do %>field :<%= Recase.to_snake(name) %>, :string, virtual: true, default: "<%= df["const"] %>" | ||||||
|  |     <% end %> | ||||||
|  |     <%= if @properties.value != [] do %># Fields<% end %> | ||||||
|  |     <%= for {name, df, _} <- @properties.value do %>field :<%= Recase.to_snake(name) %>, :<%= fhir_type_to_ecto(df) %> | ||||||
|  |     <% end %> | ||||||
|  |     <%= for {name, df, _} <- @properties.array do %>field :<%= Recase.to_snake(name) %>, <%= inspect(fhir_type_to_ecto(df)) %> | ||||||
|  |     <% end %> | ||||||
|  |     <%= 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 %>embed_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"]) %> | ||||||
|  |     <% 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"]) %> | ||||||
|  |     <% end %> | ||||||
|  |     <%= 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 | ||||||
|  |     data | ||||||
|  |     |> cast(attrs, @fields) | ||||||
|  |     <%= for {name, df, _} <- @properties.has_one do %>|> cast_assoc(:<%= Recase.to_snake(name) %>, with: &<%= @namespace %>.<%= @version %>.<%= ref_to_class_name(df["$ref"]) %>.base_changeset/1) | ||||||
|  |     <% end %> | ||||||
|  |     <%= for {name, df, _} <- @properties.has_many do %>|> cast_assoc(:<%= Recase.to_snake(name) %>, with: &<%= @namespace %>.<%= @version %>.<%= ref_to_class_name(df["items"]["$ref"]) %>.base_changeset/1) | ||||||
|  |     <% end %> | ||||||
|  |     |> validate_required(@required_fields) | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| defmodule Kindling.Schema do | defmodule Kindling.Schema do | ||||||
|  |   alias Kindling.Config | ||||||
|   alias Kindling.Version |   alias Kindling.Version | ||||||
|   alias Kindling.Schema.Resource |   alias Kindling.Schema.Resource | ||||||
| 
 | 
 | ||||||
|  | @ -8,6 +9,33 @@ defmodule Kindling.Schema do | ||||||
|     filename |     filename | ||||||
|     |> File.read!() |     |> File.read!() | ||||||
|     |> Jason.decode!() |     |> Jason.decode!() | ||||||
|  |     |> build_backlinks() | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def build_backlinks(schema) do | ||||||
|  |     new_defs = | ||||||
|  |       schema["definitions"] | ||||||
|  |       |> Enum.map(fn {name, def} -> {name, Map.put(def, "__backlinks", [])} end) | ||||||
|  |       |> Map.new() | ||||||
|  | 
 | ||||||
|  |     schema = | ||||||
|  |       Map.put(schema, "definitions", new_defs) | ||||||
|  | 
 | ||||||
|  |     defs = | ||||||
|  |       schema["definitions"] | ||||||
|  |       |> Map.drop(Config.embedded_resources()) | ||||||
|  |       |> Enum.reduce(schema["definitions"], fn {name, df}, definitions -> | ||||||
|  |         refs = Resource.refs(df) | ||||||
|  | 
 | ||||||
|  |         Enum.reduce(refs, definitions, fn ref, definitions -> | ||||||
|  |           prior_backlinks = definitions[ref]["__backlinks"] | ||||||
|  |           new_backlinks = [name | prior_backlinks] | ||||||
|  |           new_def = Map.put(Map.get(definitions, ref), "__backlinks", new_backlinks) | ||||||
|  |           Map.put(definitions, ref, new_def) | ||||||
|  |         end) | ||||||
|  |       end) | ||||||
|  | 
 | ||||||
|  |     Map.put(schema, "definitions", defs) | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def refs_recursive(schema, root_name) do |   def refs_recursive(schema, root_name) do | ||||||
|  |  | ||||||
|  | @ -1,4 +1,6 @@ | ||||||
| defmodule Kindling.Schema.Resource do | defmodule Kindling.Schema.Resource do | ||||||
|  |   alias Kindling.Config | ||||||
|  | 
 | ||||||
|   @empty_properties %{array: [], const: [], has_one: [], has_many: [], enum: [], value: []} |   @empty_properties %{array: [], const: [], has_one: [], has_many: [], enum: [], value: []} | ||||||
| 
 | 
 | ||||||
|   def properties(df) do |   def properties(df) do | ||||||
|  | @ -8,6 +10,8 @@ defmodule Kindling.Schema.Resource do | ||||||
|   def grouped_properties(df) do |   def grouped_properties(df) do | ||||||
|     properties = |     properties = | ||||||
|       (df["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)} end) | ||||||
|       |> Enum.group_by(fn {_key, _value, type} -> |       |> Enum.group_by(fn {_key, _value, type} -> | ||||||
|         type |         type | ||||||
|  | @ -42,8 +46,31 @@ defmodule Kindling.Schema.Resource do | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def property_type(%{"const" => _}), do: :const |   def property_type(%{"const" => _}), do: :const | ||||||
|   def property_type(%{"$ref" => _}), do: :has_one | 
 | ||||||
|   def property_type(%{"items" => %{"$ref" => _}}), do: :has_many |   def property_type(%{"$ref" => "#/definitions/" <> name}) do | ||||||
|  |     if is_class_name(name) do | ||||||
|  |       :has_one | ||||||
|  |     else | ||||||
|  |       :value | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   for embed <- Config.embedded_resources() do | ||||||
|  |     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(%{"items" => %{"$ref" => "#/definitions/" <> name}}) do | ||||||
|  |     if is_class_name(name) do | ||||||
|  |       :has_many | ||||||
|  |     else | ||||||
|  |       :array | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|   def property_type(%{"items" => %{"enum" => _}}), do: :array |   def property_type(%{"items" => %{"enum" => _}}), do: :array | ||||||
|   def property_type(%{"enum" => _}), do: :enum |   def property_type(%{"enum" => _}), do: :enum | ||||||
|   def property_type(_), do: :value |   def property_type(_), do: :value | ||||||
|  | @ -61,6 +88,15 @@ defmodule Kindling.Schema.Resource do | ||||||
|         nil |         nil | ||||||
|     end) |     end) | ||||||
|     |> Enum.reject(&is_nil/1) |     |> Enum.reject(&is_nil/1) | ||||||
|  |     |> Enum.filter(&is_class_name/1) | ||||||
|     |> MapSet.new() |     |> MapSet.new() | ||||||
|   end |   end | ||||||
|  | 
 | ||||||
|  |   def is_class_name(name) do | ||||||
|  |     !(name in Config.embedded_resources()) && 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 | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| defmodule <%= @namespace %>.<%= @version %>.<%= @resource_name %> do | defmodule <%= @namespace %>.<%= @version %>.<%= class_name(@resource_name) %> do | ||||||
|   use Ecto.Schema |   use Ecto.Schema | ||||||
|   import Ecto.Changeset |   import Ecto.Changeset | ||||||
| 
 | 
 | ||||||
|  | @ -9,6 +9,7 @@ defmodule <%= @namespace %>.<%= @version %>.<%= @resource_name %> do | ||||||
|     <%= @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} | ||||||
|   schema "<%= Recase.to_snake(@resource_name) %>" do |   schema "<%= Recase.to_snake(@resource_name) %>" do | ||||||
|     <%= if @properties.const != [] do %># Constants<% end %> |     <%= if @properties.const != [] do %># Constants<% end %> | ||||||
|     <%= for {name, df, _} <- @properties.const do %>field :<%= Recase.to_snake(name) %>, :string, virtual: true, default: "<%= df["const"] %>" |     <%= for {name, df, _} <- @properties.const do %>field :<%= Recase.to_snake(name) %>, :string, virtual: true, default: "<%= df["const"] %>" | ||||||
|  | @ -21,12 +22,21 @@ defmodule <%= @namespace %>.<%= @version %>.<%= @resource_name %> do | ||||||
|     <%= if @properties.enum != [] do %># Enum<% end %> |     <%= 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)) %> |     <%= 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 %> |     <% end %> | ||||||
|  |     <%= if @properties.embed_one != [] do %># Embed One<% end %> | ||||||
|  |     <%= for {name, df, _} <- @properties.embed_one do %>embed_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"]) %> | ||||||
|  |     <% end %> | ||||||
|     <%= if @properties.has_one != [] do %># Has One<% 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"]) %> |     <%= for {name, df, _} <- @properties.has_one do %>has_one :<%= Recase.to_snake(name) %>, <%= @namespace %>.<%= @version %>.<%= ref_to_class_name(df["$ref"]) %> | ||||||
|     <% end %> |     <% end %> | ||||||
|     <%= if @properties.has_many != [] do %># Has Many<% end %> |     <%= 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"]) %> |     <%= for {name, df, _} <- @properties.has_many do %>has_many :<%= Recase.to_snake(name) %>, <%= @namespace %>.<%= @version %>.<%= ref_to_class_name(df["items"]["$ref"]) %> | ||||||
|     <% end %> |     <% end %> | ||||||
|  |     <%= if @backlinks != [] do %># belongs_to<% end %> | ||||||
|  |     <%= for name <- @backlinks do %>belongs_to :<%= Recase.to_snake(name) %>, <%= @namespace %>.<%= @version %>.<%= class_name(name) %> | ||||||
|  |     <% end %> | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def base_changeset(data \\ %__MODULE__{}, attrs) do |   def base_changeset(data \\ %__MODULE__{}, attrs) do | ||||||
|  |  | ||||||
|  | @ -3,9 +3,11 @@ defmodule Kindling.Templates do | ||||||
| 
 | 
 | ||||||
|   import Kindling.Templates.Functions |   import Kindling.Templates.Functions | ||||||
| 
 | 
 | ||||||
|  |   alias Kindling.Config | ||||||
|   alias Kindling.Schema.Resource |   alias Kindling.Schema.Resource | ||||||
| 
 | 
 | ||||||
|   EEx.function_from_file(:def, :render, "lib/kindling/template.eex", [:assigns]) |   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, resource_name, resource) do | ||||||
|     assigns = %{ |     assigns = %{ | ||||||
|  | @ -14,10 +16,19 @@ defmodule Kindling.Templates do | ||||||
|       resource_name: resource_name, |       resource_name: resource_name, | ||||||
|       properties: Resource.grouped_properties(resource), |       properties: Resource.grouped_properties(resource), | ||||||
|       all_fields: Resource.all_fields(resource), |       all_fields: Resource.all_fields(resource), | ||||||
|       required_fields: Resource.required_fields(resource) |       required_fields: Resource.required_fields(resource), | ||||||
|  |       backlinks: resource["__backlinks"] | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     assigns |> render() |> Code.format_string!(file: "#{resource_name}.ex") |     if resource_name in Config.embedded_resources() do | ||||||
|  |       assigns | ||||||
|  |       |> render_embedded() | ||||||
|  |       |> Code.format_string!(file: "#{resource_name}.ex") | ||||||
|  |     else | ||||||
|  |       assigns | ||||||
|  |       |> render() | ||||||
|  |       |> Code.format_string!(file: "#{resource_name}.ex") | ||||||
|  |     end | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def write_code(namespace, version, resource_name, resource) do |   def write_code(namespace, version, resource_name, resource) do | ||||||
|  |  | ||||||
|  | @ -18,8 +18,32 @@ defmodule Kindling.Templates.Functions do | ||||||
|       when pattern in @decimal_patterns, |       when pattern in @decimal_patterns, | ||||||
|       do: :decimal |       do: :decimal | ||||||
| 
 | 
 | ||||||
|  |   def fhir_type_to_ecto(%{"$ref" => "#/definitions/boolean"}), do: :boolean | ||||||
|  |   def fhir_type_to_ecto(%{"$ref" => "#/definitions/string"}), do: :string | ||||||
|  |   def fhir_type_to_ecto(%{"$ref" => "#/definitions/integer"}), do: :integer | ||||||
|  |   def fhir_type_to_ecto(%{"$ref" => "#/definitions/positiveInt"}), do: :integer | ||||||
|  |   def fhir_type_to_ecto(%{"$ref" => "#/definitions/unsignedInt"}), do: :integer | ||||||
|  |   def fhir_type_to_ecto(%{"$ref" => "#/definitions/decimal"}), do: :decimal | ||||||
|  |   def fhir_type_to_ecto(%{"$ref" => "#/definitions/code"}), do: :string | ||||||
|  |   def fhir_type_to_ecto(%{"$ref" => "#/definitions/uri"}), do: :string | ||||||
|  |   def fhir_type_to_ecto(%{"$ref" => "#/definitions/url"}), do: :string | ||||||
|  |   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/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 | ||||||
|  |   def fhir_type_to_ecto(%{"$ref" => "#/definitions/canonical"}), do: :string | ||||||
|  |   def fhir_type_to_ecto(%{"$ref" => "#/definitions/id"}), do: :binary_id | ||||||
|  | 
 | ||||||
|   def fhir_type_to_ecto(%{"type" => "array", "items" => %{"enum" => _}}), do: {:array, :string} |   def fhir_type_to_ecto(%{"type" => "array", "items" => %{"enum" => _}}), do: {:array, :string} | ||||||
| 
 | 
 | ||||||
|  |   def fhir_type_to_ecto(%{"type" => "array", "items" => items}), | ||||||
|  |     do: {:array, fhir_type_to_ecto(items)} | ||||||
|  | 
 | ||||||
|   def ref_to_class_name("#/definitions/" <> name), |   def ref_to_class_name("#/definitions/" <> name), | ||||||
|     do: name |> String.replace("_", ".") |> Recase.to_pascal() |     do: class_name(name) | ||||||
|  | 
 | ||||||
|  |   def class_name(name), | ||||||
|  |     do: name |> String.split("_") |> Enum.map(&Recase.to_pascal/1) |> Enum.join(".") | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -15,7 +15,9 @@ defmodule Mix.Tasks.Kindling.GenerateSchemas do | ||||||
|     [namespace, version, root] = args |     [namespace, version, root] = args | ||||||
| 
 | 
 | ||||||
|     schema = Kindling.Schema.schema_object(version) |     schema = Kindling.Schema.schema_object(version) | ||||||
|     to_generate = Kindling.Schema.refs_recursive(schema, root) | 
 | ||||||
|  |     to_generate = | ||||||
|  |       Kindling.Schema.refs_recursive(schema, root) | ||||||
| 
 | 
 | ||||||
|     Enum.each( |     Enum.each( | ||||||
|       to_generate, |       to_generate, | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								mix.exs
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								mix.exs
									
									
									
									
									
								
							|  | @ -21,6 +21,7 @@ defmodule Kindling.MixProject do | ||||||
|   # Run "mix help deps" to learn about dependencies. |   # Run "mix help deps" to learn about dependencies. | ||||||
|   defp deps do |   defp deps do | ||||||
|     [ |     [ | ||||||
|  |       {:ecto, "~> 3.11", only: [:dev, :test]}, | ||||||
|       {:jason, "~> 1.4"}, |       {:jason, "~> 1.4"}, | ||||||
|       {:recase, "~> 0.7.0"}, |       {:recase, "~> 0.7.0"}, | ||||||
|       {:req, "~> 0.4.11"} |       {:req, "~> 0.4.11"} | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								mix.lock
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								mix.lock
									
									
									
									
									
								
							|  | @ -1,5 +1,7 @@ | ||||||
| %{ | %{ | ||||||
|   "castore": {:hex, :castore, "1.0.5", "9eeebb394cc9a0f3ae56b813459f990abb0a3dedee1be6b27fdb50301930502f", [:mix], [], "hexpm", "8d7c597c3e4a64c395980882d4bca3cebb8d74197c590dc272cfd3b6a6310578"}, |   "castore": {:hex, :castore, "1.0.5", "9eeebb394cc9a0f3ae56b813459f990abb0a3dedee1be6b27fdb50301930502f", [:mix], [], "hexpm", "8d7c597c3e4a64c395980882d4bca3cebb8d74197c590dc272cfd3b6a6310578"}, | ||||||
|  |   "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, | ||||||
|  |   "ecto": {:hex, :ecto, "3.11.1", "4b4972b717e7ca83d30121b12998f5fcdc62ba0ed4f20fd390f16f3270d85c3e", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ebd3d3772cd0dfcd8d772659e41ed527c28b2a8bde4b00fe03e0463da0f1983b"}, | ||||||
|   "finch": {:hex, :finch, "0.18.0", "944ac7d34d0bd2ac8998f79f7a811b21d87d911e77a786bc5810adb75632ada4", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "69f5045b042e531e53edc2574f15e25e735b522c37e2ddb766e15b979e03aa65"}, |   "finch": {:hex, :finch, "0.18.0", "944ac7d34d0bd2ac8998f79f7a811b21d87d911e77a786bc5810adb75632ada4", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "69f5045b042e531e53edc2574f15e25e735b522c37e2ddb766e15b979e03aa65"}, | ||||||
|   "hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"}, |   "hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"}, | ||||||
|   "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, |   "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Robert Prehn
						Robert Prehn