diff --git a/.github/workflows/publish_hex.yml b/.github/workflows/publish_hex.yml index d7e4d59..2adeaaa 100644 --- a/.github/workflows/publish_hex.yml +++ b/.github/workflows/publish_hex.yml @@ -2,7 +2,7 @@ name: Publish package to Hex 📦 on: push: tags: - - "v[0-9]+.[0-9]+.[0-9]+" + - "v[0-9]+.[0-9]+.[0-9]*" jobs: publish: @@ -14,10 +14,10 @@ jobs: - name: Set up Elixir uses: erlef/setup-beam@v1 with: - elixir-version: '1.13.4' - otp-version: '24.3' + elixir-version: "1.13.4" + otp-version: "24.3" - name: Restore dependencies cache - uses: actions/cache@v3.3.1 + uses: actions/cache@v4 with: path: deps key: ${{ runner.os }}-mix-${{ hashFiles('**/mix.lock') }} @@ -31,4 +31,4 @@ jobs: - name: Release & Publish run: mix hex.publish --yes env: - HEX_API_KEY: ${{ secrets.HEX_API_KEY }} \ No newline at end of file + HEX_API_KEY: ${{ secrets.HEX_API_KEY }} diff --git a/lib/arke/core/link.ex b/lib/arke/core/link.ex index f984f6f..2e34473 100644 --- a/lib/arke/core/link.ex +++ b/lib/arke/core/link.ex @@ -22,6 +22,26 @@ defmodule Arke.Core.Link do arke id: :arke_link do end + @enforce_keys [:parent_id, :child_id, :type] + defstruct [:parent_id, :child_id, :type, metadata: %{}] + + def new(parent_id, child_id, type, metadata \\ %{}) do + __struct__(parent_id: parent_id, child_id: child_id, type: type, metadata: metadata) + end + + def load(arke_link, %Arke.Core.Unit{arke_id: :arke_link} = unit) do + new(unit.data.parent_id, unit.data.child_id, unit.data.type, unit.metadata) + end + + def load(arke_link, opts) do + {parent_id, opts} = Map.pop(opts, :parent_id, nil) + {child_id, opts} = Map.pop(opts, :child_id, nil) + {type, opts} = Map.pop(opts, :type, nil) + {metadata, opts} = Map.pop(opts, :metadata, arke_link.metadata) + + new(parent_id, child_id, type, metadata) + end + def on_create( _, %{ diff --git a/lib/arke/core/query.ex b/lib/arke/core/query.ex index 56926e8..40e57d2 100644 --- a/lib/arke/core/query.ex +++ b/lib/arke/core/query.ex @@ -51,11 +51,13 @@ defmodule Arke.Core.Query do - parameter => %Arke.Core.Parameter.`ParameterType` => refer to `Arke.Core.Parameter` - operator => refer to [operators](#module-operators) - value => any => the value that the query will search for - - negate => boolean => used to figure out whether the condition is to be denied \n + - negate => boolean => used to figure out whether the condition is to be denied + - path => [Arke.Core.Parameter.ParameterType] => the path of the parameter + \n It is used to keep the same logic structure across all the Filter """ - defstruct ~w[parameter operator value negate]a + defstruct ~w[parameter operator value negate path]a @type t() :: %Arke.Core.Query.BaseFilter{} @doc """ @@ -79,14 +81,16 @@ defmodule Arke.Core.Query do parameter :: Arke.Core.Parameter.ParameterType, operator :: atom(), value :: any, - negate :: boolean + negate :: boolean(), + path :: [Arke.Core.Parameter.ParameterType] ) :: Arke.Core.Query.BaseFilter.t() - def new(parameter, operator, value, negate) do + def new(parameter, operator, value, negate, path) do %__MODULE__{ parameter: parameter, operator: operator, value: cast_value(parameter, value), - negate: negate + negate: negate, + path: path } end @@ -111,10 +115,12 @@ defmodule Arke.Core.Query do @moduledoc """ Base struct Order: - parameter => %Arke.Core.Parameter.`ParameterType` => refer to `Arke.Core.Parameter` - - direction => "child" | "parent" => the direction the query will use to search \n + - direction => "child" | "parent" => the direction the query will use to search + - path => [Arke.Core.Parameter.ParameterType] => the path of the parameter + \n It is used to define the return order of a Query """ - defstruct ~w[parameter direction]a + defstruct ~w[parameter direction path]a @type t() :: %Arke.Core.Query.Order{} end @@ -133,18 +139,19 @@ defmodule Arke.Core.Query do %Arke.Core.Query{} """ - @spec new(arke :: %Arke.Core.Arke{}, project :: atom(), distinct :: atom()) :: Arke.Core.Query.t() + @spec new(arke :: %Arke.Core.Arke{}, project :: atom(), distinct :: atom()) :: + Arke.Core.Query.t() def new(arke, project, distinct \\ nil), - do: %__MODULE__{ - project: project, - arke: arke, - distinct: distinct, - persistence: nil, - filters: [], - orders: [], - offset: nil, - limit: nil - } + do: %__MODULE__{ + project: project, + arke: arke, + distinct: distinct, + persistence: nil, + filters: [], + orders: [], + offset: nil, + limit: nil + } @doc """ Add a new link filter @@ -303,8 +310,8 @@ defmodule Arke.Core.Query do # TODO: standardize parameter # if it is a string convert it to existing atom and get it from paramater manager # if it is an atom get it from paramater manaager - def new_base_filter(parameter, operator, value, negate) do - BaseFilter.new(parameter, operator, value, negate) + def new_base_filter(parameter, operator, value, negate, path \\ []) do + BaseFilter.new(parameter, operator, value, negate, path) end defp parse_base_filters(base_filters) when is_list(base_filters), do: base_filters @@ -327,6 +334,16 @@ defmodule Arke.Core.Query do ## Return %Arke.Core.Query{ ... orders: [ %Arke.Core.Query.Order{} ] ... } """ + + def add_order(query, parameter, direction) when is_list(parameter) do + {parameter, path} = List.pop_at(parameter, -1) + + %{ + query + | orders: [%Order{parameter: parameter, direction: direction, path: path} | query.orders] + } + end + def add_order(query, parameter, direction) do %{ query diff --git a/lib/arke/core/unit.ex b/lib/arke/core/unit.ex index 167e393..b8233d5 100644 --- a/lib/arke/core/unit.ex +++ b/lib/arke/core/unit.ex @@ -169,8 +169,17 @@ defmodule Arke.Core.Unit do defp handle_default_value(_), do: nil - defp get_link(%{depth: depth, link_metadata: link_metadata,starting_unit: starting_unit} = args), - do: {%{depth: depth, metadata: link_metadata,starting_unit: starting_unit}, args} + defp get_link( + %{ + depth: depth, + link_metadata: link_metadata, + starting_unit: starting_unit, + link_type: link_type + } = args + ), + do: + {%{depth: depth, metadata: link_metadata, starting_unit: starting_unit, type: link_type}, + args} defp get_link(args), do: {nil, args} @@ -289,11 +298,11 @@ defmodule Arke.Core.Unit do defp update_encoded_unit_data(%{data: %{only_runtime: true}}, data, _), do: data defp update_encoded_unit_data(%{id: id}, data, value), - do: - Map.put_new(data, Atom.to_string(id), %{ - :value => value, - :datetime => Arke.DatetimeHandler.now(:datetime) - }) + do: + Map.put_new(data, Atom.to_string(id), %{ + :value => value, + :datetime => Arke.DatetimeHandler.now(:datetime) + }) defp update_encoded_unit_data(_, data, _), do: data @@ -373,7 +382,6 @@ defmodule Arke.Core.Unit do defp parse_value(value, %{arke_id: :atom}) when is_binary(value), do: String.to_existing_atom(value) - defp parse_value(value, %{arke_id: :date}) do with {:ok, date} <- DatetimeHandler.parse_date(value), do: date, diff --git a/lib/arke/group.ex b/lib/arke/group.ex index b7dd991..881edbb 100644 --- a/lib/arke/group.ex +++ b/lib/arke/group.ex @@ -26,8 +26,11 @@ defmodule Arke.System.Group do # @before_compile unquote(__MODULE__) - def group_from_attr(), do: Keyword.get(__MODULE__.__info__(:attributes), :group, []) |> List.first() - def is_group?(), do: Keyword.get(__MODULE__.__info__(:attributes), :system_group, []) |> List.first() + def group_from_attr(), + do: Keyword.get(__MODULE__.__info__(:attributes), :group, []) |> List.first() + + def is_group?(), + do: Keyword.get(__MODULE__.__info__(:attributes), :system_group, []) |> List.first() def on_unit_load(arke, data, _persistence_fn), do: {:ok, data} def before_unit_load(_arke, data, _persistence_fn), do: {:ok, data} @@ -41,6 +44,13 @@ defmodule Arke.System.Group do def on_unit_delete(_arke, unit), do: {:ok, unit} def before_unit_delete(_arke, unit), do: {:ok, unit} + def before_unit_bulk_create(_arke, valid, errors), do: {:ok, valid, errors} + def on_unit_bulk_create(_arke, valid, errors), do: {:ok, valid, errors} + def before_unit_bulk_update(_arke, valid, errors), do: {:ok, valid, errors} + def on_unit_bulk_update(_arke, valid, errors), do: {:ok, valid, errors} + def before_unit_bulk_delete(_arke, valid, errors), do: {:ok, valid, errors} + def on_unit_bulk_delete(_arke, valid, errors), do: {:ok, valid, errors} + defoverridable on_unit_load: 3, before_unit_load: 3, on_unit_validate: 2, @@ -51,7 +61,13 @@ defmodule Arke.System.Group do on_unit_update: 2, before_unit_update: 2, on_unit_delete: 2, - before_unit_delete: 2 + before_unit_delete: 2, + before_unit_bulk_create: 3, + on_unit_bulk_create: 3, + before_unit_bulk_update: 3, + on_unit_bulk_update: 3, + before_unit_bulk_delete: 3, + on_unit_bulk_delete: 3 end end @@ -96,7 +112,7 @@ defmodule Arke.System.Group do unquote(block) @group %{ - id: id, + id: id } end end @@ -114,7 +130,7 @@ defmodule Arke.System.Group do See example above `arke/2` """ - @spec parameter(id :: atom(), type:: atom(), opts :: list()) :: Macro.t() + @spec parameter(id :: atom(), type :: atom(), opts :: list()) :: Macro.t() defmacro parameter(id, type, opts \\ []) do # parameter_dict = Arke.System.BaseParameter.parameter_options(opts, id, type) quote bind_quoted: [id: id, type: type, opts: opts] do diff --git a/lib/arke/link_manager.ex b/lib/arke/link_manager.ex index 7225984..551839a 100644 --- a/lib/arke/link_manager.ex +++ b/lib/arke/link_manager.ex @@ -14,91 +14,183 @@ defmodule Arke.LinkManager do @moduledoc false - @record_fields [:id, :data, :metadata, :inserted_at, :updated_at] alias Arke.Boundary.ArkeManager alias Arke.Utils.ErrorGenerator, as: Error alias Arke.QueryManager alias Arke.Core.Unit + alias Arke.Core.Query + alias Arke.Core.Link - def add_node(project, %Unit{} = parent, %Unit{} = child, type \\ "link", metadata \\ %{}) do + def add_node(project, parent, child, type \\ "link", metadata \\ %{}) do arke_link = ArkeManager.get(:arke_link, project) + link = %{"parent" => parent, "child" => child, "type" => type, "metadata" => metadata} + + with {valid, _} <- + validate_links(project, arke_link, [link]), + {[link], _} <- validate_existing(project, arke_link, valid, []), + do: + QueryManager.create(project, arke_link, + parent_id: link.parent_id, + child_id: link.child_id, + type: link.type, + metadata: link.metadata + ), + else: (_ -> Error.create(:link, "link already exists")) + end + def add_node(_project, _parent, _child, _type, _metadata), + do: Error.create(:link, "invalid parameters") - case check_link(project, parent, child, type, arke_link) do - {_, nil} -> - QueryManager.create(project, arke_link, - parent_id: Atom.to_string(parent.id), - child_id: Atom.to_string(child.id), - type: type, - metadata: metadata - ) + def add_node_bulk(project, link_list) do + arke_link = ArkeManager.get(:arke_link, project) - {:ok, _} -> - Error.create(:link, "link already exists") + with {valid, errors} <- validate_links(project, arke_link, link_list), + {valid, errors} <- validate_existing(project, arke_link, valid, errors), + {:ok, inserted_count, valid, insert_errors} <- + QueryManager.create_bulk(project, arke_link, prepare_link_data(valid), []) do + {:ok, inserted_count, valid, errors ++ insert_errors} + else + {:error, errors} -> {:error, errors} end end - def add_node(project, parent, child, type, metadata) - when is_binary(parent) and is_binary(child) do - with %Unit{}=unit_parent <- QueryManager.get_by(id: parent, project: project), - %Unit{}=unit_child <- QueryManager.get_by(id: child, project: project) do - add_node(project, unit_parent, unit_child, type, metadata) - else - _ -> Error.create(:link, "parent: `#{parent}` or child: `#{child}` not found") + def update_node(project, parent, child, type, metadata) do + arke_link = ArkeManager.get(:arke_link, :arke_system) + link = %{"parent" => parent, "child" => child, "type" => type, "metadata" => metadata} + + with {[valid_link], _} <- validate_links(project, arke_link, [link]), + [existing_link] <- existing_links(project, arke_link, [valid_link]) do + QueryManager.update(existing_link, metadata: metadata) + else + _ -> Error.create(:link, "link not found") end end - def add_node(_project, _parent, _child, _type, _metadata), do: Error.create(:link, "invalid parameters") + def update_node(_project, _parent, _child, _type, _metadata), + do: Error.create(:link, "invalid parameters") - def update_node(project, %Unit{} = parent, %Unit{} = child, type, metadata) do - arke_link = ArkeManager.get(:arke_link, :arke_system) + def update_node_bulk(project, link_list) do + arke_link = ArkeManager.get(:arke_link, project) - case check_link(project, parent, child, type, arke_link) do - {:error, _} -> Error.create(:link, "link not found") - {:ok, link} -> QueryManager.update(link, metadata: metadata, type: type) - end + {valid, errors} = validate_links(project, arke_link, link_list) + existing = existing_links(project, arke_link, valid) + + QueryManager.update_bulk(project, arke_link, existing, prepare_link_data(valid)) end - def update_node(project, parent, child, type, metadata) - when is_binary(parent) and is_binary(child) do - unit_parent = QueryManager.get_by(id: parent, project: project) - unit_child = QueryManager.get_by(id: child, project: project) + def delete_node(project, parent, child, type, metadata \\ %{}) do + arke_link = ArkeManager.get(:arke_link, :arke_system) + link = %{"parent" => parent, "child" => child, "type" => type, "metadata" => metadata} - update_node(project, unit_parent, unit_child, type, metadata) + with {[valid_link], _} <- validate_links(project, arke_link, [link]), + [existing_link] <- existing_links(project, arke_link, [valid_link]) do + QueryManager.delete(project, existing_link) + else + _ -> Error.create(:link, "link not found") + end end - def update_node(_project, _parent, _child, _type, _metadata), + def delete_node(_project, _parent, _child, _type, _metadata), do: Error.create(:link, "invalid parameters") - def delete_node(project, %Unit{} = parent, %Unit{} = child, type, metadata \\ %{}) do + def delete_node_bulk(project, link_list) do arke_link = ArkeManager.get(:arke_link, :arke_system) + {valid, _} = validate_links(project, arke_link, link_list) - case check_link(project, parent, child, type, arke_link) do - {:error, _} -> Error.create(:link, "link not found") - {:ok, link} -> QueryManager.delete(project, link) - end + QueryManager.delete_bulk(project, existing_links(project, arke_link, valid)) end - def delete_node(project, parent, child, type, metadata) - when is_binary(parent) and is_binary(child) do - unit_parent = QueryManager.get_by(id: parent, project: project) - unit_child = QueryManager.get_by(id: child, project: project) + @spec validate_links(atom(), Arke.t(), list()) :: {list(Link.t()), list(map())} + defp validate_links(project, arke_link, [%Link{} | _] = link_list), + do: {link_list, []} - delete_node(project, unit_parent, unit_child, type, metadata) + defp validate_links(project, arke_link, [%Unit{} | _] = unit_list) do + links = + Enum.map(unit_list, fn unit -> + Link.load(project, unit) + end) + + {links, []} end - def delete_node(_project, _parent, _child, _type, _metadata), - do: Error.create(:link, "invalid parameters") + defp validate_links(project, arke_link, link_list) do + Enum.reduce(link_list, {[], []}, fn link, {valid, errors} -> + parent = link["parent"] + child = link["child"] + type = Map.get(link, "type", "link") + metadata = Map.get(link, "metadata", %{}) + + case {parent, child} do + {parent, child} when is_binary(parent) and is_binary(child) -> + {[Link.new(parent, child, type, metadata) | valid], errors} + + {nil, nil} -> + {valid, [%{link: link, error: "invalid parent and child"} | errors]} + + {nil, _} -> + {valid, [%{link: link, error: "invalid parent"} | errors]} + + {_, nil} -> + {valid, [%{link: link, error: "invalid child"} | errors]} + + _ -> + {valid, [%{link: link, error: "invalid parent and child format"} | errors]} + end + end) + end + + @spec existing_links(project :: atom(), arke_link :: Arke.t(), link_list :: list(Link.t())) :: + list(Arke.Core.Unit.t()) + + defp existing_links(_project, _arke_link, []), do: [] + + defp existing_links(project, arke_link, link_list) do + parameters = ArkeManager.get_parameters(arke_link) + parent_id = Enum.find(parameters, fn p -> p.id == :parent_id end) + child_id = Enum.find(parameters, fn p -> p.id == :child_id end) + type = Enum.find(parameters, fn p -> p.id == :type end) + + # todo: handle type default_string ? + + Arke.QueryManager.query(project: project, arke: arke_link) + |> Arke.Core.Query.add_filter( + :or, + false, + Enum.map(link_list, fn link -> + Arke.Core.Query.new_filter(:and, false, [ + Arke.QueryManager.condition(parent_id, :eq, link.parent_id, false), + Arke.QueryManager.condition(child_id, :eq, link.child_id, false), + Arke.QueryManager.condition(type, :eq, link.type, false) + ]) + end) + ) + |> Arke.QueryManager.all() + end + + @spec validate_existing(atom(), Arke.t(), list(Unit.t()), list()) :: + {list(Link.t()), list()} + defp validate_existing(project, arke_link, link_list, errors) do + existing = + existing_links(project, arke_link, link_list) + |> Enum.reduce(MapSet.new(), fn link, acc -> + MapSet.put(acc, {link.data.parent_id, link.data.child_id, link.data.type}) + end) + + Enum.reduce(link_list, {[], errors}, fn link, {valid_acc, errors_acc} -> + case MapSet.member?(existing, {link.parent_id, link.child_id, link.type}) do + true -> {valid_acc, [data_to_map(link) | errors_acc]} + false -> {[data_to_map(link) | valid_acc], errors_acc} + end + end) + end + + @spec prepare_link_data(list(Link.t())) :: list(map()) + defp prepare_link_data(link_list) do + Enum.map(link_list, &data_to_map/1) + end - defp check_link(project, parent, child, type, arke_link) do - with %Arke.Core.Unit{} = link <- - Arke.QueryManager.query(project: project, arke: arke_link) - |> Arke.QueryManager.filter(:parent_id, :eq, Atom.to_string(parent.id), false) - |> Arke.QueryManager.filter(:child_id, :eq, Atom.to_string(child.id), false) - |> Arke.QueryManager.filter(:type, :eq, type, false) - |> Arke.QueryManager.one(), - do: {:ok, link}, - else: (_ -> {:error, nil}) + defp data_to_map(link) do + Map.take(link, [:parent_id, :child_id, :type, :metadata]) end end diff --git a/lib/arke/query_manager.ex b/lib/arke/query_manager.ex index 7b14e83..35db08b 100644 --- a/lib/arke/query_manager.ex +++ b/lib/arke/query_manager.ex @@ -44,7 +44,7 @@ defmodule Arke.QueryManager do alias Arke.Utils.DatetimeHandler, as: DatetimeHandler alias Arke.Errors.ArkeError alias Arke.Utils.ErrorGenerator, as: Error - alias Arke.Core.{Arke, Unit, Query, Parameter} + alias Arke.Core.{Arke, Unit, Query, Parameter, Link} @persistence Application.get_env(:arke, :persistence) @record_fields [:id, :data, :metadata, :inserted_at, :updated_at] @@ -149,92 +149,85 @@ defmodule Arke.QueryManager do {:ok, unit} <- Validator.validate(unit, :create, project), {:ok, unit} <- ArkeManager.call_func(arke, :before_create, [arke, unit]), {:ok, unit} <- handle_group_call_func(arke, unit, :before_unit_create), - {:ok, unit} <- handle_link_parameters_unit(arke, unit), - {:ok, unit} <- persistence_fn.(project, unit), + {:ok, unit} <- persistence_fn.(project, unit, []), + {:ok, unit} <- handle_link_parameters(arke, unit), {:ok, unit} <- ArkeManager.call_func(arke, :on_create, [arke, unit]), - {:ok, unit} <- handle_link_parameters(unit, %{}), - {:ok, unit} <- handle_group_call_func(arke, unit, :on_unit_create), - do: {:ok, unit}, - else: ({:error, errors} -> {:error, errors}) + {:ok, unit} <- handle_group_call_func(arke, unit, :on_unit_create) do + {:ok, unit} + else + {:error, errors} -> {:error, errors} + %{errors: [{_, err} | _], valid: _} -> {:error, err} + end end - defp handle_link_parameters_unit(%{id: :arke_link} = _, unit), do: {:ok, unit} - defp handle_link_parameters_unit(%{id: :parameter_value} = _, unit), do: {:ok, unit} - - defp handle_link_parameters_unit( - %{data: parameters} = arke, - %{metadata: %{project: project}} = unit - ) do - {errors, link_units} = - Enum.filter(ArkeManager.get_parameters(arke), fn p -> p.arke_id == :link end) - |> Enum.reduce({[], []}, fn p, {errors, link_units} -> - arke = ArkeManager.get(String.to_existing_atom(p.data.arke_or_group_id), project) - - case handle_create_on_link_parameters_unit( - project, - unit, - p, - arke, - Unit.get_value(unit, p.id) - ) do - {:ok, parameter, %Unit{} = link_unit} -> {errors, [{parameter, link_unit} | link_units]} - {:ok, parameter, link_unit} -> {errors, link_units} - {:error, e} -> {[e | errors], link_units} - end - end) - - case length(errors) > 0 do - true -> - Enum.map(link_units, fn {p, u} -> - delete(project, u) - end) - - {:error, errors} - - false -> - args = - Enum.reduce(link_units, %{}, fn {p, u}, args -> - Map.put(args, p.id, Atom.to_string(u.id)) - end) + @spec create_bulk(project :: atom(), arke :: Arke.t(), data :: list(Arke.t()), args :: list()) :: + func_return() + def create_bulk(project, arke, data, args \\ []) do + persistence_fn = @persistence[:arke_postgres][:create] - {:ok, Unit.update(unit, args)} + with {:ok, valid, errors} <- prepare_create_bulk_units(arke, data, args), + {:ok, valid, errors} <- Validator.validate(valid, :create, project), + {:ok, valid, errors} <- + ArkeManager.call_func(arke, :before_bulk_create, [arke, valid, errors]), + {:ok, valid, errors} <- + handle_group_call_func(valid, errors, arke, :before_unit_bulk_create), + {:ok, inserted_count, valid, persistence_errors} <- + persistence_fn.(project, valid, bulk: true), + {:ok, valid, errors} <- + handle_bulk_link_parameters(valid, errors, arke), + {:ok, valid, errors} <- + ArkeManager.call_func(arke, :on_bulk_create, [arke, valid, errors]), + {:ok, valid, errors} <- handle_group_call_func(valid, errors, arke, :on_unit_bulk_create) do + {:ok, inserted_count, valid, errors} + else + {:error, errors} -> {:error, errors} end end - defp handle_create_on_link_parameters_unit(project, unit, parameter, arke, value) - when is_nil(value), - do: {:ok, parameter, value} + defp prepare_create_bulk_units(arke, units, args) do + result = + Enum.reduce(units, %{valid: [], errors: []}, fn item, acc -> + case Unit.load(arke, data_as_klist(item) ++ args, :create) do + %Unit{} = unit -> Map.put(acc, :valid, [unit | acc.valid]) + {:error, error} -> Map.put(acc, :errors, [error | acc.errors]) + end + end) - defp handle_create_on_link_parameters_unit(project, unit, parameter, arke, value) - when is_binary(value), - do: {:ok, parameter, value} + {:ok, result.valid, result.errors} + end - defp handle_create_on_link_parameters_unit(project, unit, parameter, arke, value) - when is_map(value) do - value = Map.put(value, :runtime_data, %{link: unit, link_parameter: parameter}) + # todo: remove after atoms removal + defp data_as_klist(data) do + Enum.map(data, fn {key, value} -> + case is_atom(key) do + true -> {key, value} + false -> {String.to_existing_atom(key), value} + end + end) + end - case create(project, arke, value) do - {:ok, unit} -> {:ok, parameter, unit} - {:error, error} -> {:error, error} + defp handle_group_call_func(arke, unit, func) do + case GroupManager.get_groups_by_arke(arke) + |> Enum.reduce_while(unit, fn group, new_unit -> + with {:ok, new_unit} <- GroupManager.call_func(group, func, [arke, new_unit]), + do: {:cont, new_unit}, + else: ({:error, errors} -> {:halt, {:error, errors}}) + end) do + {:error, errors} -> {:error, errors} + unit -> {:ok, unit} end end - defp handle_create_on_link_parameters_unit(_, _, parameter, _, value), - do: {:ok, parameter, value} - - def handle_group_call_func(arke, unit, func) do + defp handle_group_call_func(valid, errors, arke, func) do GroupManager.get_groups_by_arke(arke) - |> Enum.reduce_while(unit, fn group, new_unit -> - with {:ok, new_unit} <- GroupManager.call_func(group, func, [arke, new_unit]), - do: {:cont, new_unit}, + |> Enum.reduce_while({:ok, valid, errors}, fn group, {:ok, valid, errors} -> + with {:ok, valid, errors} <- + GroupManager.call_func(group, func, [arke, valid, errors]), + do: {:cont, {:ok, valid, errors}}, else: ({:error, errors} -> {:halt, {:error, errors}}) end) - |> check_group_manager_functions_errors() end - def check_group_manager_functions_errors({:error, errors} = _), do: {:error, errors} - def check_group_manager_functions_errors(unit), do: {:ok, unit} - @doc """ Function to update an element @@ -262,13 +255,101 @@ defmodule Arke.QueryManager do {:ok, unit} <- Validator.validate(unit, :update, project), {:ok, unit} <- ArkeManager.call_func(arke, :before_update, [arke, current_unit, unit]), {:ok, unit} <- handle_group_call_func(arke, unit, :before_unit_update), - {:ok, unit} <- handle_link_parameters_unit(arke, unit), - {:ok, unit} <- persistence_fn.(project, unit), + {:ok, unit} <- persistence_fn.(project, unit, []), {:ok, unit} <- ArkeManager.call_func(arke, :on_update, [arke, current_unit, unit]), - {:ok, unit} <- handle_link_parameters(unit, data), - {:ok, unit} <- handle_group_call_func(arke, unit, :on_unit_update), - do: {:ok, unit}, - else: ({:error, errors} -> {:error, errors}) + {:ok, unit} <- handle_link_parameters(arke, unit, data), + {:ok, unit} <- handle_group_call_func(arke, unit, :on_unit_update) do + {:ok, unit} + else + {:error, errors} -> {:error, errors} + %{errors: [{_, err} | _], valid: _} -> {:error, err} + end + end + + defp update_at_on_update(unit) do + updated_at = DatetimeHandler.now(:datetime) + {:ok, Unit.update(unit, updated_at: updated_at)} + end + + def update_bulk(_, _, [], _), do: {:ok, 0, [], []} + + def update_bulk(project, arke, unit_list, data) do + persistence_fn = @persistence[:arke_postgres][:update] + + with {:ok, valid, errors} <- prepare_update_bulk_units(arke, unit_list, data), + {:ok, valid, errors} <- Validator.validate(valid, :update, project), + {:ok, valid, errors} <- + ArkeManager.call_func(arke, :before_bulk_update, [arke, valid, errors]), + {:ok, valid, errors} <- + handle_group_call_func(valid, errors, arke, :before_unit_bulk_update), + {:ok, updated_count, valid, persistence_errors} <- + persistence_fn.(project, valid, bulk: true), + {:ok, valid, errors} <- + handle_bulk_link_parameters(valid, errors, arke, unit_list), + {:ok, valid, errors} <- + ArkeManager.call_func(arke, :on_bulk_update, [arke, unit_list, valid, errors]), + {:ok, valid, errors} <- + handle_group_call_func(valid, errors, arke, :on_unit_bulk_update) do + {:ok, updated_count, valid, errors} + else + {:error, errors} -> {:error, errors} + end + end + + # todo: enhance for different arke types that acts as tables + defp prepare_update_bulk_units(%{id: :arke_link} = arke, unit_list, data) do + data_map = + data + |> Enum.map(fn d -> + key = {d.parent_id, d.child_id, d.type} + {key, d} + end) + |> Map.new() + + updated_at = DatetimeHandler.now(:datetime) + + result = + Enum.reduce(unit_list, %{valid: [], errors: []}, fn unit, acc -> + key = {unit.data.parent_id, unit.data.child_id, unit.data.type} + + case data_map[key] do + nil -> + acc + + item -> + case Unit.update(unit, data_as_klist(item)) do + %Unit{} = unit -> Map.put(acc, :valid, [unit | acc.valid]) + {:error, error} -> Map.put(acc, :errors, [error | acc.errors]) + end + end + end) + + {:ok, result.valid, result.errors} + end + + defp prepare_update_bulk_units(arke, unit_list, data) do + data_map = + data + |> Enum.map(fn d -> {Map.get(d, "id"), d} end) + |> Map.new() + + updated_at = DatetimeHandler.now(:datetime) + + result = + Enum.reduce(unit_list, %{valid: [], errors: []}, fn unit, acc -> + case data_map[to_string(unit.id)] do + nil -> + acc + + item -> + case Unit.update(unit, data_as_klist(item) ++ [updated_at: updated_at]) do + %Unit{} = unit -> Map.put(acc, :valid, [unit | acc.valid]) + {:error, error} -> Map.put(acc, :errors, [error | acc.errors]) + end + end + end) + + {:ok, result.valid, result.errors} end defp update_at_on_update(unit) do @@ -296,13 +377,33 @@ defmodule Arke.QueryManager do with {:ok, unit} <- ArkeManager.call_func(arke, :before_delete, [arke, unit]), {:ok, unit} <- handle_group_call_func(arke, unit, :before_unit_delete), - {:ok, nil} <- persistence_fn.(project, unit), - {:ok, unit} <- handle_group_call_func(arke, unit, :on_unit_delete), - {:ok, _unit} <- ArkeManager.call_func(arke, :on_delete, [arke, unit]), + {:ok, _} <- persistence_fn.(project, unit, []), + {:ok, _} <- handle_group_call_func(arke, unit, :on_unit_delete), + {:ok, _} <- ArkeManager.call_func(arke, :on_delete, [arke, unit]), do: {:ok, nil}, else: ({:error, errors} -> {:error, errors}) end + @spec delete_bulk(project :: atom(), [Unit.t()]) :: {:ok, [any()], [any()]} + def delete_bulk(project, []), do: {:ok, [], []} + + def delete_bulk(project, [%{arke_id: arke_id} | _] = unit_list) do + arke = ArkeManager.get(arke_id, project) + persistence_fn = @persistence[:arke_postgres][:delete] + + with {:ok, valid, errors} <- + ArkeManager.call_func(arke, :before_bulk_delete, [arke, unit_list, []]), + {:ok, valid, errors} <- + handle_group_call_func(valid, errors, arke, :before_unit_bulk_delete), + {:ok, _} <- persistence_fn.(project, valid, bulk: true), + {:ok, valid, errors} <- + handle_group_call_func(valid, errors, arke, :on_unit_bulk_delete), + {:ok, valid, errors} <- + ArkeManager.call_func(arke, :on_bulk_delete, [arke, valid, errors]), + do: {:ok, valid, errors}, + else: ({:error, errors} -> {:error, errors}) + end + @doc """ Function to get a single element identified by the opts. Use `Arke.QueryManager.filter_by` if more than one element is returned ## Parameters @@ -409,7 +510,7 @@ defmodule Arke.QueryManager do defp parse_base_filters(query, filters) do Enum.reduce(filters, [], fn f, new_filters -> parameter = get_parameter(query, f.parameter) - [Query.new_base_filter(parameter, f.operator, f.value, f.negate) | new_filters] + [Query.new_base_filter(parameter, f.operator, f.value, f.negate, f.path) | new_filters] end) end @@ -432,10 +533,11 @@ defmodule Arke.QueryManager do parameter :: Arke.t() | atom(), negate :: boolean(), value :: String.t() | boolean() | nil, - negate :: boolean() + negate :: boolean(), + path :: [Arke.t()] ) :: Query.BaseFilter.t() - def condition(parameter, operator, value, negate \\ false), - do: Query.new_base_filter(parameter, operator, value, negate) + def condition(parameter, operator, value, negate \\ false, path \\ []), + do: Query.new_base_filter(parameter, operator, value, negate, path) @doc """ Create a list of `Arke.Core.Query.BaseFilter` @@ -570,9 +672,18 @@ defmodule Arke.QueryManager do """ @spec order( query :: Query.t(), - parameter :: Arke.t() | String.t() | atom(), + parameter :: Arke.t() | String.t() | atom() | [Arke.t()] | [String.t()] | [atom()], direction :: atom() ) :: Query.t() + def order(query, parameter, direction) when is_list(parameter) do + [head | tail] = parameter + + parameters = + [get_parameter(query, head)] ++ Enum.map(tail, &get_parameter(%{query | arke: nil}, &1)) + + Query.add_order(query, parameters, direction) + end + def order(query, parameter, direction), do: Query.add_order(query, get_parameter(query, parameter), direction) @@ -700,20 +811,106 @@ defmodule Arke.QueryManager do ArkeManager.get_parameter(arke, project, key) end - defp handle_link_parameters( - %{arke_id: arke_id, metadata: %{project: project}, data: new_data, id: id} = unit, - old_data + defp handle_create_on_link_parameters_unit(project, unit, parameter, arke, value) + when is_nil(value), + do: {:ok, parameter, value} + + defp handle_create_on_link_parameters_unit(project, unit, parameter, arke, value) + when is_binary(value), + do: {:ok, parameter, value} + + defp handle_create_on_link_parameters_unit(project, unit, parameter, arke, value) + when is_map(value) do + value = Map.put(value, :runtime_data, %{link: unit, link_parameter: parameter}) + + case create(project, arke, value) do + {:ok, unit} -> {:ok, parameter, unit} + {:error, error} -> {:error, error} + end + end + + defp handle_create_on_link_parameters_unit(_, _, parameter, _, value), + do: {:ok, parameter, value} + + defp handle_link_parameters(arke, unit, current_unit \\ nil) do + old_data = if current_unit, do: [Map.put(current_unit, :id, unit.id)], else: [] + + case handle_bulk_link_parameters([unit], [], arke, old_data) do + {:ok, [unit], []} -> {:ok, unit} + {:ok, _, errors} -> {:error, errors} + {:error, errors} -> {:error, errors} + end + end + + defp handle_bulk_link_parameters([], errors, _arke, _old_data), do: {:ok, [], errors} + + defp handle_bulk_link_parameters(valid, errors, %Unit{id: :arke_link}, _old_data), + do: {:ok, valid, errors} + + defp handle_bulk_link_parameters( + [%{metadata: %{project: project}} | _] = valid, + errors, + %{arke_id: arke_id} = unit, + current_units \\ [] ) do arke = ArkeManager.get(arke_id, project) - Enum.filter(ArkeManager.get_parameters(arke), fn p -> p.arke_id == :link end) - |> Enum.each(fn p -> - old_value = Map.get(old_data, p.id, nil) - new_value = Map.get(new_data, p.id, nil) - handle_link_parameter(unit, p, old_value, new_value) - end) + link_parameters = + Enum.filter(ArkeManager.get_parameters(arke), fn p -> p.arke_id == :link end) - {:ok, unit} + {to_add, to_delete} = + Enum.reduce(link_parameters, {[], []}, fn p, {to_add_acc, to_delete_acc} -> + Enum.reduce(valid, {to_add_acc, to_delete_acc}, fn unit, {add_acc, del_acc} -> + current_unit = Enum.find(current_units, &(&1.id == unit.id)) + old_value = if current_unit, do: Unit.get_value(current_unit, p.id), else: nil + new_value = get_in(unit.data, [p.id]) + {new_add, new_del} = build_link_entries(p, unit, old_value, new_value) + {add_acc ++ new_add, del_acc ++ new_del} + end) + end) + + with {:ok, del_valid, _del_errors} <- LinkManager.delete_node_bulk(project, to_delete), + {:ok, _add_count, _add_valid, []} <- LinkManager.add_node_bulk(project, to_add) do + # todo: better error handling + {:ok, valid, errors} + else + {:error, err} -> {:error, err} + end + end + + defp build_link_entries(%{data: %{multiple: true}} = parameter, unit, old_value, new_value) do + {Enum.map(new_value || [], &update_link_entry(parameter, unit, &1)), + Enum.map(old_value || [], &update_link_entry(parameter, unit, &1))} + end + + defp build_link_entries(_parameter, _unit, old_value, new_value) when old_value == new_value, + do: {[], []} + + defp build_link_entries(parameter, unit, old_value, new_value) when is_nil(new_value) do + {[], [update_link_entry(parameter, unit, old_value)]} + end + + defp build_link_entries(parameter, unit, old_value, new_value) when is_nil(old_value) do + {[update_link_entry(parameter, unit, new_value)], []} + end + + defp build_link_entries(parameter, unit, old_value, new_value) do + {[update_link_entry(parameter, unit, new_value)], + [update_link_entry(parameter, unit, old_value)]} + end + + defp update_link_entry( + %{data: %{connection_type: type, direction: direction}, id: id}, + unit, + new_value + ) do + {parent_id, child_id} = + case direction do + "child" -> {normalize_value(unit.id), normalize_value(new_value)} + "parent" -> {normalize_value(new_value), normalize_value(unit.id)} + end + + Link.new(parent_id, child_id, type, %{parameter_id: id}) end defp handle_link_parameter(_, nil, _, _), do: nil @@ -811,6 +1008,12 @@ defmodule Arke.QueryManager do }) end + defp prepare_link("child", starting_unit, linked_unit_id), + do: %{parent_id: starting_unit.id, child_id: linked_unit_id} + + defp prepare_link("parent", starting_unit, linked_unit_id), + do: %{parent_id: linked_unit_id, child_id: starting_unit.id} + # Function to get only the parameter id from `handle_link_parameter` defp normalize_value(nil), do: nil diff --git a/lib/arke/system.ex b/lib/arke/system.ex index 37fc78b..c0a39ce 100644 --- a/lib/arke/system.ex +++ b/lib/arke/system.ex @@ -13,6 +13,8 @@ # limitations under the License. defmodule Arke.System do + @default_import_mode "default" + defmacro __using__(_) do quote do # @after_compile __MODULE__ @@ -51,12 +53,22 @@ defmodule Arke.System do def on_delete(arke, unit), do: {:ok, unit} def before_delete(arke, unit), do: {:ok, unit} + def before_bulk_create(arke, valid, errors), do: {:ok, valid, errors} + def on_bulk_create(arke, valid, errors), do: {:ok, valid, errors} + def before_bulk_update(arke, valid, errors), do: {:ok, valid, errors} + def on_bulk_update(arke, old_units, valid, errors), do: {:ok, valid, errors} + def before_bulk_delete(arke, valid, errors), do: {:ok, valid, errors} + def on_bulk_delete(arke, valid, errors), do: {:ok, valid, errors} + def after_get_struct(arke, unit, struct), do: struct def after_get_struct(arke, struct), do: struct - def import(%{runtime_data: %{conn: %{method: "POST"}=conn}, metadata: %{project: project}} = arke) do + def import( + %{runtime_data: %{conn: %{method: "POST"} = conn}, metadata: %{project: project}} = + arke + ) do member = ArkeAuth.Guardian.Plug.current_resource(conn) - mode = Map.get(conn.body_params, "mode", "default") + mode = Map.get(conn.body_params, "mode", @default_import_mode) case Map.get(conn.body_params, "file", nil) do nil -> {:error, "file is required", 400} @@ -66,37 +78,55 @@ defmodule Arke.System do defp import_units(arke, project, member, file, mode) do {:ok, ref} = Enum.at(Xlsxir.multi_extract(file.path), 0) - all_units = get_all_units_for_import(project) + all_units = get_all_units_for_import(project, mode) file_as_list = Xlsxir.get_list(ref) header_file = Enum.at(file_as_list, 0) rows = file_as_list |> List.delete_at(0) - header = get_header_for_import(project, arke, header_file) |> parse_haeder_for_import(header_file) - - {correct_units, error_units} = Enum.with_index(rows) |> Enum.reduce({[], []}, fn {row, index}, {correct_units, error_units} -> - case Enum.filter(row, & !is_nil(&1)) do - [] -> {correct_units, error_units} - _ -> case load_units(project, arke, header, row, all_units, mode) do - {:error, args, errors} -> - m = Enum.reduce(header, %{}, fn {h, index}, acc -> - acc = Map.put(acc, h, parse_cell(Enum.at(row, index))) - end) |> Map.put("errors", errors) - {correct_units, [m | error_units]} - {:ok, unit_args} -> {[unit_args | correct_units], error_units} - end - end - end) + header = + get_header_for_import(project, arke, header_file, mode) + |> parse_haeder_for_import(header_file) + + {correct_units, error_units} = + Enum.with_index(rows) + |> Enum.reduce({[], []}, fn {row, index}, {correct_units, error_units} -> + case Enum.filter(row, &(!is_nil(&1))) do + [] -> + {correct_units, error_units} + + _ -> + case load_units(project, arke, header, row, all_units, mode) do + {:error, args, errors} -> + m = + Enum.reduce(header, %{}, fn {h, index}, acc -> + acc = Map.put(acc, h, parse_cell(Enum.at(row, index))) + end) + |> Map.put("errors", errors) + + {correct_units, [m | error_units]} + + {:ok, unit_args} -> + {[unit_args | correct_units], error_units} + end + end + end) existing_units = get_existing_units_for_import(project, arke, header, correct_units) - units_args = Enum.filter(correct_units, fn u -> check_existing_units_for_import(project, arke, header, u, existing_units) == false end) - {existing_units,units_args,error_units} = handle_insert(project,existing_units,units_args,error_units) - count_inserted = length(units_args) - count_existing = length(existing_units) - count_error = length(error_units) - total_count = count_inserted + count_error + count_existing + units_args = + Enum.filter(correct_units, fn u -> + check_existing_units_for_import(project, arke, header, u, existing_units) == false + end) + + {existing_units, units_args, error_units} = + handle_insert(project, arke, existing_units, units_args, error_units) + + count_inserted = length(units_args) + count_existing = length(existing_units) + count_error = length(error_units) + total_count = count_inserted + count_error + count_existing res = %{ count_inserted: count_inserted, @@ -105,22 +135,36 @@ defmodule Arke.System do total_count: total_count, error_units: error_units } + {:ok, res, 201} end - defp handle_insert(project,existing_units,units_args,error_units) when length(units_args) > 0 do - {existing_units,units_args,error_units} = before_unit_import(project,existing_units,units_args,error_units) - Enum.map(Stream.chunk_every(units_args, 5000) |> Enum.to_list(), fn chunk -> - ArkePostgres.Repo.insert_all("arke_unit", chunk, prefix: Atom.to_string(project)) - end) - on_unit_import(project,existing_units,units_args,error_units) + defp handle_insert(project, arke, existing_units, units_args, error_units) + when length(units_args) > 0 do + {existing_units, units_args, error_units} = + before_unit_import(project, existing_units, units_args, error_units) + + units_args_maps = + Enum.map(units_args, fn unit_arg -> + unit_arg + |> Keyword.get(:data, %{}) + |> Enum.reduce(%{}, fn {key, %{value: value}}, acc -> + Map.put(acc, key, value) + end) + end) + + res = Arke.QueryManager.create_bulk(project, arke, units_args_maps) + + on_unit_import(project, existing_units, units_args, error_units) end - defp handle_insert(_project,existing_units,units_args,error_units), do: {existing_units,units_args,error_units} + + defp handle_insert(_project, _arke, existing_units, units_args, error_units), + do: {existing_units, units_args, error_units} defp parse_cell(value) when is_tuple(value), do: Kernel.inspect(value) defp parse_cell(value), do: value - defp get_header_for_import(project, arke, header_file) do + defp get_header_for_import(project, arke, header_file, @default_import_mode) do Enum.reduce(Enum.with_index(header_file), [], fn {cell, index}, acc -> case Arke.Boundary.ArkeManager.get_parameter(arke, project, cell) do nil -> acc @@ -128,11 +172,16 @@ defmodule Arke.System do end end) end + defp parse_haeder_for_import(header, header_file) do Enum.reduce(Enum.with_index(header_file), [], fn {cell, index}, acc -> case cell do - nil -> acc - "" -> acc + nil -> + acc + + "" -> + acc + cell -> case cell in header do nil -> acc @@ -142,27 +191,35 @@ defmodule Arke.System do end) end - defp get_all_units_for_import(project), do: [] + defp get_all_units_for_import(_project, _mode), do: [] - defp load_units(project, arke, header, row, _, "default") do - args = Enum.reduce(header, [], fn {parameter_id, index}, acc -> - acc = Keyword.put(acc, String.to_existing_atom(parameter_id), Enum.at(row, index)) - end) + defp load_units(project, arke, header, row, _, @default_import_mode) do + args = + Enum.reduce(header, [], fn {parameter_id, index}, acc -> + acc = Keyword.put(acc, String.to_existing_atom(parameter_id), Enum.at(row, index)) + end) with %Arke.Core.Unit{} = unit <- Arke.Core.Unit.load(arke, args, :create), {:ok, unit} <- Arke.Validator.validate(unit, :create, project), do: {:ok, args}, else: ({:error, errors} -> {:error, args, errors}) end + defp get_existing_units_for_import(project, arke, header, units_args), do: [] - defp check_existing_units_for_import(project, arke, header, units_args, existing_units), do: true + + defp check_existing_units_for_import(project, arke, header, units_args, existing_units), + do: true + defp get_import_value(header, row, column) do index = Enum.find(header, fn {k, v} -> k == column end) |> elem(1) Enum.at(row, index) end - defp before_unit_import(_project,existing_units,units_args,error_units), do: {existing_units,units_args,error_units} - defp on_unit_import(_project,existing_units,units_args,error_units), do: {existing_units,units_args,error_units} + defp before_unit_import(_project, existing_units, units_args, error_units), + do: {existing_units, units_args, error_units} + + defp on_unit_import(_project, existing_units, units_args, error_units), + do: {existing_units, units_args, error_units} defoverridable on_load: 2, before_load: 2, @@ -177,23 +234,28 @@ defmodule Arke.System do before_update: 3, on_delete: 2, before_delete: 2, + before_bulk_create: 3, + on_bulk_create: 3, + before_bulk_update: 3, + on_bulk_update: 4, + before_bulk_delete: 3, + on_bulk_delete: 3, after_get_struct: 2, after_get_struct: 3, - # Import - import: 1, - import_units: 5, - get_header_for_import: 3, - get_all_units_for_import: 1, - load_units: 6, - get_existing_units_for_import: 4, - check_existing_units_for_import: 5, - before_unit_import: 4, - on_unit_import: 4 + # Import + import: 1, + import_units: 5, + get_header_for_import: 4, + get_all_units_for_import: 2, + load_units: 6, + get_existing_units_for_import: 4, + check_existing_units_for_import: 5, + before_unit_import: 4, + on_unit_import: 4 end end - ###################################################################################################################### # ARKE MACRO ######################################################################################################### ###################################################################################################################### @@ -256,9 +318,8 @@ defmodule Arke.System do @arke %{ id: id, data: %{label: label, active: active, type: type, parameters: @parameters}, - metadata: metadata, + metadata: metadata } - end end @@ -366,15 +427,18 @@ defmodule Arke.System.BaseParameter do %{type: type, opts: opts} end - def check_enum(type, opts) when is_binary(type), do: check_enum(String.to_atom(type),opts) + def check_enum(type, opts) when is_binary(type), do: check_enum(String.to_atom(type), opts) + def check_enum(type, opts) do enum_parameters = [:string, :integer, :float] + case type in enum_parameters do true -> __enum_parameter__(opts, type) - false -> opts - end + false -> + opts + end end defp parameter_option_common(opts, id) do @@ -429,10 +493,14 @@ defmodule Arke.System.BaseParameter do Keyword.put_new(opts, key, default) end - def __enum_parameter__(opts, type) when is_map(opts), do: __enum_parameter__(Map.to_list(opts),type) + def __enum_parameter__(opts, type) when is_map(opts), + do: __enum_parameter__(Map.to_list(opts), type) + def __enum_parameter__(opts, type) do case Keyword.has_key?(opts, :values) do - true -> __validate_values__(opts, opts[:values], type) + true -> + __validate_values__(opts, opts[:values], type) + false -> opts end @@ -444,9 +512,7 @@ defmodule Arke.System.BaseParameter do when not is_nil(value), do: __validate_values__(opts, value, type) - defp __validate_values__(opts, [h | _t] = values, type) when is_map(h) do - condition = cond do type == :string -> @@ -458,11 +524,12 @@ defmodule Arke.System.BaseParameter do type == :float -> fn l, v -> is_binary(l) and is_number(v) end end + case Enum.all?(values, fn map -> Enum.map([:label, :value], fn key -> Map.has_key?(map, key) end) end) do true -> - __create_map_values__(__check_map__(values), opts, type, condition) + __create_map_values__(__check_map__(values), opts, type, condition) # FARE RAISE ECCEZIONE DA GESTIRE. CHIAVI DEVONO ESSERE TUTTE UGUALI _ -> @@ -481,7 +548,6 @@ defmodule Arke.System.BaseParameter do __values_from_list__(values, opts, condition) end - # CONVERT ALL STRINGS KEY TO ATOMS (string are received from API) defp __check_map__([%{"label" => _l, "value" => _v} | _h] = values) do Enum.map( diff --git a/lib/arke/validator.ex b/lib/arke/validator.ex index af874b9..4124f90 100644 --- a/lib/arke/validator.ex +++ b/lib/arke/validator.ex @@ -43,32 +43,52 @@ defmodule Arke.Validator do %{:error, [message]} """ - @spec validate(unit :: Unit.t(), peristence_fn :: (() -> any()), project :: atom()) :: + @spec validate(unit :: Unit.t() | [Unit.t()], peristence_fn :: (-> any()), project :: atom()) :: func_return() - def validate(%{arke_id: arke_id} = unit, persistence_fn, project \\ :arke_system) do - with {:ok, unit} <- check_duplicate_unit(unit, project, persistence_fn) do - {%{data: data} = unit, errors} = before_validate(unit, project) - %{data: arke_data} = arke = ArkeManager.get(arke_id, project) - - unit_parameters = - Enum.filter(ArkeManager.get_parameters(arke), fn %{data: %{persistence: persistence}} -> - persistence == "arke_parameter" - end) - res = - Enum.reduce(unit_parameters, {unit, errors}, fn p, {new_unit, errors} = _res -> - {value, err} = validate_parameter(arke, p, Unit.get_value(data, p.id), project) - {Unit.update(new_unit, [{p.id, value}]), errors ++ err} - end) + def validate(unit, persistence_fn, project \\ :arke_system) + + def validate(%Unit{} = unit, persistence_fn, project) do + case validate([unit], persistence_fn, project) do + {:ok, [unit], []} -> {:ok, unit} + {:ok, [], errors} -> Error.create(:parameter_validation, errors) + end + end - {new_unit, errors} = res - filtered_errors = check_old_values(errors, data, new_unit.data, persistence_fn) + def validate([], _persistence_fn, _project), + do: {:ok, [], []} - get_result({new_unit, filtered_errors}) - else - {:error, errors} -> get_result({unit, errors}) + def validate( + [%Unit{arke_id: arke_id} | _] = unit_list, + persistence_fn, + project + ) do + %{data: arke_data} = arke = ArkeManager.get(arke_id, project) + + parameter_list = + Enum.filter(ArkeManager.get_parameters(arke), fn %{data: %{persistence: persistence}} -> + persistence == "arke_parameter" + end) + + with {:ok, valid, errors} <- check_duplicate_units(unit_list, project, persistence_fn), + {:ok, valid, errors} <- apply_before_validate(valid, errors, project), + {:ok, valid, errors} <- + check_bulk_parameters(valid, errors, arke, parameter_list, project), + {:ok, valid, errors} <- + check_unique_parameters(valid, errors, arke, parameter_list, project) do + {:ok, valid, errors} end + end - # TODO: handle after validate + defp apply_before_validate(valid, errors, project) do + Enum.reduce_while(valid, {:ok, [], errors}, fn u, {:ok, acc_valid, acc_errors} -> + case before_validate(u, project) do + {unit, []} -> + {:cont, {:ok, [unit | acc_valid], acc_errors}} + + {unit, unit_errors} -> + {:cont, {:ok, acc_valid, [{unit, unit_errors} | acc_errors]}} + end + end) end defp before_validate(%{arke_id: arke_id} = unit, project) do @@ -79,36 +99,187 @@ defmodule Arke.Validator do else: ({:error, errors} -> {unit, errors}) end - defp check_duplicate_unit(%{id: unit_id} = unit, _project, :create) when is_nil(unit_id), - do: {:ok, unit} + defp check_duplicate_units(unit_list, project, :create) do + ids_to_check = + Enum.filter(unit_list, fn u -> not is_nil(u.id) end) |> Enum.map(&to_string(&1.id)) - defp check_duplicate_unit(%{id: unit_id} = unit, project, :create) do - with nil <- QueryManager.get_by(%{:id => unit_id, :project => project}), - do: {:ok, unit}, - else: (_ -> {:error, [{"You can not create Unit with same id", unit_id}]}) - end - - defp check_duplicate_unit(%{id: unit_id} = unit, _project, _persistence_fn), do: {:ok, unit} + duplicates = QueryManager.filter_by(%{:id__in => ids_to_check, :project => project}) - defp check_old_values(errors, old_unit_data, new_unit_data, :update) do - duplicate_list = - Enum.filter(errors, fn {k, v} -> - is_binary(k) and String.contains?(k, "duplicate") and is_atom(v) + valid = + Enum.reduce(unit_list, [], fn item, acc -> + case Enum.find(duplicates, fn d -> d.id == item.id end) do + nil -> [item | acc] + _ -> acc + end end) - same_value = - Enum.filter(duplicate_list, fn {_k, v} -> old_unit_data[v] == new_unit_data[v] end) + errors = Enum.map(duplicates, fn d -> {d, "value not allowed for #{d.id}"} end) - :ordsets.subtract(errors, same_value) + {:ok, valid, errors} end - defp check_old_values(errors, _old_unit_data, _new_unit_data, :create), do: errors + defp check_duplicate_units(unit_list, _project, _persistence_fn), + do: {:ok, unit_list, []} defp get_result({_unit, errors} = _res) when is_list(errors) and length(errors) > 0, do: Error.create(:parameter_validation, errors) defp get_result({unit, _errors} = _res), do: {:ok, unit} + defp check_bulk_parameters(valid, errors, arke, parameter_list, project) do + result = + Enum.reduce(valid, {[], errors}, fn unit, {acc_valid, acc_errors} -> + case Enum.reduce(parameter_list, {unit, []}, fn parameter, {unit, errors} -> + {value, err} = + validate_parameter( + arke, + parameter, + Unit.get_value(unit.data, parameter.id), + project + ) + + {Unit.update(unit, [{parameter.id, value}]), errors ++ err} + end) do + {unit, []} -> + {[unit | acc_valid], acc_errors} + + {unit, unit_errors} -> + {acc_valid, + [ + {unit, + Enum.map(unit_errors, fn {parameter_id, error} -> + "#{parameter_id} #{error}" + end)} + | acc_errors + ]} + end + end) + + case result do + {valid, errors} -> {:ok, valid, errors} + end + end + + defp create_unique_map(parameter_list, unit_list) do + Map.new(Enum.filter(parameter_list, fn p -> p.data[:unique] end), fn p -> + {p.id, + Enum.reduce(unit_list, [], fn unit, acc -> + case Map.get(unit.data, p.id) do + nil -> acc + v -> [{unit.id, v} | acc] + end + end)} + end) + end + + defp check_unique_parameters(valid, errors, arke, parameter_list, project) do + unique_map = create_unique_map(parameter_list, valid) + + with {:ok, valid, errors} <- validate_unique_input(valid, [], errors, unique_map), + {:ok, valid, errors} <- + validate_and_filter_unique_units( + valid, + errors, + unique_map, + arke, + project, + parameter_list + ) do + {:ok, valid, errors} + end + end + + defp validate_and_filter_unique_units( + valid, + errors, + unique_map, + arke, + project, + parameter_list + ) + when map_size(unique_map) == 0, + do: {:ok, valid, errors} + + defp validate_and_filter_unique_units( + valid, + errors, + unique_map, + arke, + project, + parameter_list + ) do + db_units = + QueryManager.query(arke: arke.id, project: project) + |> QueryManager.or_( + false, + Enum.map(unique_map, fn {parameter_id, uniques} -> + QueryManager.condition(parameter_id, :in, Enum.map(uniques, fn {_, v} -> v end)) + end) + ) + |> QueryManager.all() + + parameter_already_present = create_unique_map(parameter_list, db_units) + + Enum.reduce(valid, {:ok, [], errors}, fn unit, {:ok, acc_valid, acc_errors} -> + {non_unique_parameters, unit_errors} = + parameter_already_present + |> Enum.reduce({[], []}, fn {parameter_id, uniques}, {non_unique, errors} -> + case Enum.find(uniques, fn {unit_id, value} -> + to_string(unit_id) != to_string(unit.id) and + value == Map.get(unit.data, parameter_id) + end) do + nil -> + {non_unique, errors} + + _ -> + {[{parameter_id, uniques} | non_unique], + [ + "value not allowed for parameter #{parameter_id}: #{Map.get(unit.data, parameter_id)}" + | errors + ]} + end + end) + + if non_unique_parameters == [] do + {:ok, [unit | acc_valid], acc_errors} + else + {:ok, acc_valid, [{unit, unit_errors} | acc_errors]} + end + end) + end + + defp validate_unique_input(unit_list, _valid, errors, unique_map) + when map_size(unique_map) == 0, + do: {:ok, unit_list, errors} + + defp validate_unique_input([], valid, errors, _unique_map), + do: {:ok, valid, errors} + + defp validate_unique_input([unit | tail], valid, errors, unique_map) do + unit_errors = + Enum.reduce(unique_map, [], fn {parameter_id, uniques}, acc -> + case Map.get(unit.data, parameter_id) do + nil -> + acc + + value -> + if Enum.count(uniques, fn {_, parameter_value} -> parameter_value == value end) > 1 do + [ + "value not allowed for parameter #{parameter_id}: #{value}" + | acc + ] + else + acc + end + end + end) + + case unit_errors do + [] -> validate_unique_input(tail, [unit | valid], errors, unique_map) + _ -> {:ok, valid, [{unit, unit_errors} | errors]} + end + end + @doc """ Check if the value can be assigned to a given parameter in a specific schema struct. @@ -135,7 +306,7 @@ defmodule Arke.Validator do def validate_parameter(arke, parameter, value, project) when is_atom(parameter) do parameter = get_parameter(arke, parameter, project) - check_parameter(parameter, value, project,arke) + check_parameter(parameter, value, project, arke) end defp get_parameter(nil, parameter_id, project), @@ -145,20 +316,20 @@ defmodule Arke.Validator do do: ArkeManager.get_parameter(arke, parameter_id) def validate_parameter(arke, parameter, value, project) do - check_parameter(parameter, value, project,arke) + check_parameter(parameter, value, project, arke) end - defp check_parameter(parameter, value, project,arke) do + defp check_parameter(parameter, value, project, arke) do value = get_default_value(parameter, value) value = parse_value(parameter, value) value = check_whitespace(parameter, value) - value = check_lowercase(parameter,value) + value = check_lowercase(parameter, value) errors = [] |> check_required_parameter(parameter, value) |> check_by_type(parameter, value) - |> check_duplicate(parameter, value, project,arke) + |> check_unique(parameter, value) {value, errors} end @@ -168,7 +339,7 @@ defmodule Arke.Validator do defp parse_value(%{arke_id: :integer, data: %{multiple: false} = data} = _, value) when not is_integer(value) and not is_nil(value) do - case Integer.parse(value) do + case to_string(value) |> Integer.parse() do :error -> value {v, _e} -> v end @@ -176,7 +347,7 @@ defmodule Arke.Validator do defp parse_value(%{arke_id: :float, data: %{multiple: false} = data} = _, value) when not is_number(value) and not is_nil(value) do - case Float.parse(value) do + case to_string(value) |> Float.parse() do :error -> value {v, _e} -> v end @@ -221,16 +392,10 @@ defmodule Arke.Validator do defp check_required_parameter(errors, _parameter, _value), do: errors - defp check_duplicate(errors, %{id: id, data: %{unique: true}} = _parameter, nil, project), - do: errors ++ [{"value must not be null for", id}] + defp check_unique(errors, %{id: id, data: %{unique: true}} = _parameter, nil), + do: errors ++ [{"value must not be null for", id}] - defp check_duplicate(errors, %{id: id, data: %{unique: true}} = parameter, value, project,arke) do - with nil <- QueryManager.get_by(%{id => value, :project => project, :arke_id => arke.id}), - do: errors, - else: (_ -> errors ++ [{"duplicate values are not allowed for", id}]) - end - - defp check_duplicate(errors, _parameter, _value, _project,_arke), do: errors + defp check_unique(errors, _parameter, _value), do: errors defp check_by_type(errors, _parameter, value) when is_nil(value), do: errors @@ -259,11 +424,12 @@ defmodule Arke.Validator do defp check_values( errors, - %{arke_id: type, data: %{values: values, label: label,multiple: true}} = parameter, + %{arke_id: type, data: %{values: values, label: label, multiple: true}} = parameter, value ) when is_list(value) do admitted_values = Enum.map(values, fn %{label: _l, value: v} -> v end) + with true <- check_values_type(value, type) do with [] <- value -- admitted_values do errors @@ -288,7 +454,8 @@ defmodule Arke.Validator do value ), do: errors ++ [{value, "#{label} must be a list of #{type}}"}] - defp check_values(errors,_parameter,_value), do: errors + + defp check_values(errors, _parameter, _value), do: errors defp check_values_type(value, type) do condition = @@ -300,18 +467,32 @@ defmodule Arke.Validator do Enum.all?(value, &condition.(&1)) end + # --- end Enum --- # --- start Multiple --- - defp check_multiple(errors, %{id: id, data: %{multiple: false}} = _parameter, value) when is_list(value), do: errors ++ [{"multiple values are not allowed for", id}] - defp check_multiple(errors, %{id: id, data: %{multiple: true}} = parameter, value) when not is_list(value), do: check_multiple(errors, parameter, [value]) - defp check_multiple(errors, %{id: id, arke_id: type, data: %{ multiple: true}} = parameter, value) do - case check_values_type(value,type) do - true -> errors + defp check_multiple(errors, %{id: id, data: %{multiple: false}} = _parameter, value) + when is_list(value), + do: errors ++ [{"multiple values are not allowed for", id}] + + defp check_multiple(errors, %{id: id, data: %{multiple: true}} = parameter, value) + when not is_list(value), + do: check_multiple(errors, parameter, [value]) + + defp check_multiple( + errors, + %{id: id, arke_id: type, data: %{multiple: true}} = parameter, + value + ) do + case check_values_type(value, type) do + true -> + errors + false -> - errors ++ [{"[#{Enum.join(value,",")}]", "#{id} must be a list of #{type} "}] + errors ++ [{"[#{Enum.join(value, ",")}]", "#{id} must be a list of #{type} "}] end end - defp check_multiple(errors,_parameter,_value), do: errors + + defp check_multiple(errors, _parameter, _value), do: errors # --- end Multiple --- defp check_whitespace(%{data: %{strip: true}} = parameter, value) when is_atom(value) do @@ -353,7 +534,8 @@ defmodule Arke.Validator do value ) do # todo: used to parse override in metadata which can be written as string - max = parse_value(%{arke_id: :integer, data: %{multiple: false}},max_length) + max = parse_value(%{arke_id: :integer, data: %{multiple: false}}, max_length) + if String.length(value) > max do errors ++ [{label, "max length is #{max_length}"}] else @@ -371,7 +553,8 @@ defmodule Arke.Validator do value ) do # todo: used to parse override in metadata which can be written as string - min = parse_value(%{arke_id: :integer, data: %{multiple: false}},min_length) + min = parse_value(%{arke_id: :integer, data: %{multiple: false}}, min_length) + if String.length(value) < min do errors ++ [{label, "min length is #{min_length}"}] else @@ -420,7 +603,8 @@ defmodule Arke.Validator do defp check_max(errors, %{data: %{max: max}} = parameter, _) when is_nil(max), do: errors defp check_max(errors, %{data: %{max: max, label: label}} = parameter, value) do - parsed_max = parse_value(parameter,max) + parsed_max = parse_value(parameter, max) + if value > parsed_max do errors ++ [{label, "max is #{max}"}] else @@ -431,7 +615,8 @@ defmodule Arke.Validator do defp check_min(errors, %{data: %{min: min}} = parameter, _) when is_nil(min), do: errors defp check_min(errors, %{data: %{min: min, label: label}} = parameter, value) do - parsed_min = parse_value(parameter,min) + parsed_min = parse_value(parameter, min) + if value < parsed_min do errors ++ [{label, "min is #{min}"}] else diff --git a/lib/registry/shared/arke.json b/lib/registry/shared/arke.json index 7317a39..73cc5da 100644 --- a/lib/registry/shared/arke.json +++ b/lib/registry/shared/arke.json @@ -1,50 +1,52 @@ -{"arke": [{ - "id": "arke_file", - - "label": "Arke File", - "parameters": [ +{ + "arke": [ { - "id": "name", - "metadata": { - "required": true - } - }, - { - "id": "path", - "metadata": { - "required": true - } - }, - { - "id": "provider", - "metadata": { - "values": [ - "local", - "gcloud", - "aws" - ], - "default": "gcloud" - } - }, - { - "id": "size", - "metadata": { - "required": false - } - }, - { - "id": "binary_data", - "metadata": { - "required": true, - "only_runtime": true - } - }, - { - "id": "extension", - "metadata": { - "required": false - } + "id": "arke_file", + "label": "Arke File", + "parameters": [ + { + "id": "name", + "metadata": { + "required": true + } + }, + { + "id": "path", + "metadata": { + "required": true + } + }, + { + "id": "provider", + "metadata": { + "values": [ + "local", + "gcloud", + "aws" + ], + "default": "gcloud" + } + }, + { + "id": "size", + "metadata": { + "required": false + } + }, + { + "id": "binary_data", + "metadata": { + "required": true, + "only_runtime": true + } + }, + { + "id": "extension", + "metadata": { + "required": false + } + } + ] } ] -} -]} \ No newline at end of file +} \ No newline at end of file diff --git a/lib/registry/shared/group.json b/lib/registry/shared/group.json index 597bd02..38ac633 100644 --- a/lib/registry/shared/group.json +++ b/lib/registry/shared/group.json @@ -1 +1,3 @@ -{"group": []} \ No newline at end of file +{ + "group": [] +} \ No newline at end of file diff --git a/lib/registry/shared/parameter.json b/lib/registry/shared/parameter.json index 0de854d..ada6fbc 100644 --- a/lib/registry/shared/parameter.json +++ b/lib/registry/shared/parameter.json @@ -1,112 +1,113 @@ -{"parameter": [ - { - "default_string": null, - "type": "string", - "format": "attribute", - "helper_text": "Name", - "id": "name", - "is_primary": false, - "label": "Name", - "max_length": 100, - "min_length": 2, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "strip": false, -"lowercase": false, - "unique": false, - "values": null - }, - { - "default_string": "", - "type": "string", - "format": "attribute", - "helper_text": "Path", - "id": "path", - "is_primary": false, - "label": "Path", - "max_length": null, - "min_length": null, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "strip": false, -"lowercase": false, - "unique": false, - "values": null - }, - { - "default_string": "gcloud", - "type": "string", - "format": "attribute", - "helper_text": "Provider", - "id": "provider", - "is_primary": false, - "label": "Provider", - "max_length": null, - "min_length": null, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "strip": false, -"lowercase": false, - "unique": false, - "values": [ - "local", - "gcloud", - "aws" - ] - }, - { - "default_float": null, - "type": "float", - "format": "attribute", - "helper_text": "Size", - "id": "size", - "is_primary": false, - "label": "Size", - "max": null, - "min": 0, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "unique": false, - "values": null - }, - { - "default_binary": null, - "type": "binary", - "format": "attribute", - "helper_text": "Binary", - "id": "binary_data", - "is_primary": false, - "label": "Binary", - "nullable": true, - "persistence": "arke_parameter", - "required": false - }, - { - "default_string": "", - "type": "string", - "format": "attribute", - "helper_text": "Extension", - "id": "extension", - "is_primary": false, - "label": "Extension", - "max_length": null, - "min_length": null, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "strip": false, -"lowercase": false, - "unique": false, - "values": null - } - -]} \ No newline at end of file +{ + "parameter": [ + { + "default_string": null, + "type": "string", + "format": "attribute", + "helper_text": "Name", + "id": "name", + "is_primary": false, + "label": "Name", + "max_length": 100, + "min_length": 2, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "strip": false, + "lowercase": false, + "unique": false, + "values": null + }, + { + "default_string": "", + "type": "string", + "format": "attribute", + "helper_text": "Path", + "id": "path", + "is_primary": false, + "label": "Path", + "max_length": null, + "min_length": null, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "strip": false, + "lowercase": false, + "unique": false, + "values": null + }, + { + "default_string": "gcloud", + "type": "string", + "format": "attribute", + "helper_text": "Provider", + "id": "provider", + "is_primary": false, + "label": "Provider", + "max_length": null, + "min_length": null, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "strip": false, + "lowercase": false, + "unique": false, + "values": [ + "local", + "gcloud", + "aws" + ] + }, + { + "default_float": null, + "type": "float", + "format": "attribute", + "helper_text": "Size", + "id": "size", + "is_primary": false, + "label": "Size", + "max": null, + "min": 0, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "unique": false, + "values": null + }, + { + "default_binary": null, + "type": "binary", + "format": "attribute", + "helper_text": "Binary", + "id": "binary_data", + "is_primary": false, + "label": "Binary", + "nullable": true, + "persistence": "arke_parameter", + "required": false + }, + { + "default_string": "", + "type": "string", + "format": "attribute", + "helper_text": "Extension", + "id": "extension", + "is_primary": false, + "label": "Extension", + "max_length": null, + "min_length": null, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "strip": false, + "lowercase": false, + "unique": false, + "values": null + } + ] +} \ No newline at end of file diff --git a/lib/registry/system/arke.json b/lib/registry/system/arke.json index bdcdd0b..7983540 100644 --- a/lib/registry/system/arke.json +++ b/lib/registry/system/arke.json @@ -1,998 +1,986 @@ -{"arke": [ - { - "id": "arke", - +{ + "arke": [ + { + "id": "arke", "label": "Arke", -"parameters": [ - { - "id": "label", - "metadata": { - "required": true - } - }, - { - "id": "active", - "metadata": { - "default_boolean": true - } - }, - { - "id": "type", - "metadata": { - "required": true, - "default_string": "arke" - } - }, - { - "id": "parameters", - "metadata": { - "multiple": true, - "arke_or_group_id": "parameters", - "connection_type": "parameters", - "direction": "child", - "filter_keys": [ - "arke_id", - "id", - "label" - ], - "depth": 0, - "default_link": [] - } - } - ] - }, - { - "id": "arke_link", - "label": "Link", - "type": "table", - "parameters": [ - { - "id": "parent_id", - "metadata": { - "is_primary": true, - "required": true, - "persistence": "table_column" - } - }, - { - "id": "child_id", - "metadata": { - "is_primary": true, - "required": true, - "persistence": "table_column" - } - }, - { - "id": "type", - "metadata": { - "required": true, - "persistence": "table_column" - } - }, - { - "id": "metadata", - "metadata": { - "is_primary": true, - "default_dict": {}, - "persistence": "table_column" - } - } - ] - }, - { - "id": "integer", - + "parameters": [ + { + "id": "label", + "metadata": { + "required": true + } + }, + { + "id": "active", + "metadata": { + "default_boolean": true + } + }, + { + "id": "type", + "metadata": { + "required": true, + "default_string": "arke" + } + }, + { + "id": "parameters", + "metadata": { + "multiple": true, + "arke_or_group_id": "parameters", + "connection_type": "parameters", + "direction": "child", + "filter_keys": [ + "arke_id", + "id", + "label" + ], + "depth": 0, + "default_link": [] + } + } + ] + }, + { + "id": "arke_link", + "label": "Link", + "type": "table", + "parameters": [ + { + "id": "parent_id", + "metadata": { + "is_primary": true, + "required": true + } + }, + { + "id": "child_id", + "metadata": { + "is_primary": true, + "required": true + } + }, + { + "id": "type", + "metadata": { + "is_primary": true, + "required": true, + "persistence": "table_column", + "default_string": "link" + } + }, + { + "id": "metadata", + "metadata": { + "default_dict": {} + } + } + ] + }, + { + "id": "integer", "label": "Integer", -"parameters": [ - { - "id": "label", - "metadata": { - "required": true - } - }, - { - "id": "format", - "metadata": { - "default_string": "attribute" - } - }, - { - "id": "is_primary", - "metadata": { - "default_boolean": false - } - }, - { - "id": "nullable", - "metadata": { - "default_boolean": true - } - }, - { - "id": "required", - "metadata": { - "default_boolean": false - } - }, - { - "id": "persistence", - "metadata": { - "default_string": "arke_parameter" - } - }, - { - "id": "only_run_time", - "metadata": { - "default_boolean": false - } - }, - { - "id": "helper_text", - "metadata": { - "required": false - } - }, - { - "id": "min", - "metadata": { - "required": false - } - }, - { - "id": "max", - "metadata": { - "required": false - } - }, - { - "id": "values", - "metadata": { - "required": false - } - }, - { - "id": "multiple", - "metadata": { - "default_boolean": false - } - }, - { - "id": "default_integer", - "metadata": { - "default_integer": null - } - } - ] - }, - { - "id": "string", - + "parameters": [ + { + "id": "label", + "metadata": { + "required": true + } + }, + { + "id": "format", + "metadata": { + "default_string": "attribute" + } + }, + { + "id": "is_primary", + "metadata": { + "default_boolean": false + } + }, + { + "id": "nullable", + "metadata": { + "default_boolean": true + } + }, + { + "id": "required", + "metadata": { + "default_boolean": false + } + }, + { + "id": "persistence", + "metadata": { + "default_string": "arke_parameter" + } + }, + { + "id": "only_run_time", + "metadata": { + "default_boolean": false + } + }, + { + "id": "helper_text", + "metadata": { + "required": false + } + }, + { + "id": "min", + "metadata": { + "required": false + } + }, + { + "id": "max", + "metadata": { + "required": false + } + }, + { + "id": "values", + "metadata": { + "required": false + } + }, + { + "id": "multiple", + "metadata": { + "default_boolean": false + } + }, + { + "id": "default_integer", + "metadata": { + "default_integer": null + } + } + ] + }, + { + "id": "string", "label": "String", -"parameters": [ - { - "id": "label", - "metadata": { - "required": true - } - }, - { - "id": "format", - "metadata": { - "default_string": "attribute" - } - }, - { - "id": "is_primary", - "metadata": { - "default_boolean": false - } - }, - { - "id": "nullable", - "metadata": { - "default_boolean": true - } - }, - { - "id": "required", - "metadata": { - "default_boolean": false - } - }, - { - "id": "persistence", - "metadata": { - "default_string": "arke_parameter" - } - }, - { - "id": "only_run_time", - "metadata": { - "default_boolean": false - } - }, - { - "id": "helper_text", - "metadata": { - "required": false - } - }, - { - "id": "min_length", - "metadata": { - "required": false - } - }, - { - "id": "max_length", - "metadata": { - "required": false - } - }, - { - "id": "strip", - "metadata": { - "default_boolean": false - } - }, - { - "id": "values", - "metadata": { - "required": false - } - }, - { - "id": "multiple", - "metadata": { - "default_boolean": false - } - }, - { - "id": "unique", - "metadata": { - "required": false - } - }, - { - "id": "default_string", - "metadata": { - "default_string": null - } - } - ] - }, - { - "id": "dict", - + "parameters": [ + { + "id": "label", + "metadata": { + "required": true + } + }, + { + "id": "format", + "metadata": { + "default_string": "attribute" + } + }, + { + "id": "is_primary", + "metadata": { + "default_boolean": false + } + }, + { + "id": "nullable", + "metadata": { + "default_boolean": true + } + }, + { + "id": "required", + "metadata": { + "default_boolean": false + } + }, + { + "id": "persistence", + "metadata": { + "default_string": "arke_parameter" + } + }, + { + "id": "only_run_time", + "metadata": { + "default_boolean": false + } + }, + { + "id": "helper_text", + "metadata": { + "required": false + } + }, + { + "id": "min_length", + "metadata": { + "required": false + } + }, + { + "id": "max_length", + "metadata": { + "required": false + } + }, + { + "id": "strip", + "metadata": { + "default_boolean": false + } + }, + { + "id": "values", + "metadata": { + "required": false + } + }, + { + "id": "multiple", + "metadata": { + "default_boolean": false + } + }, + { + "id": "unique", + "metadata": { + "required": false + } + }, + { + "id": "default_string", + "metadata": { + "default_string": null + } + } + ] + }, + { + "id": "dict", "label": "Dict", -"parameters": [ - { - "id": "label", - "metadata": { - "required": true - } - }, - { - "id": "format", - "metadata": { - "default_string": "attribute" - } - }, - { - "id": "is_primary", - "metadata": { - "default_boolean": false - } - }, - { - "id": "nullable", - "metadata": { - "default_boolean": true - } - }, - { - "id": "required", - "metadata": { - "default_boolean": false - } - }, - { - "id": "persistence", - "metadata": { - "default_string": "arke_parameter" - } - }, - { - "id": "only_run_time", - "metadata": { - "default_boolean": false - } - }, - { - "id": "helper_text", - "metadata": { - "required": false - } - }, - { - "id": "default_dict", - "metadata": { - "required": false - } - } - ] - }, - { - "id": "date", - + "parameters": [ + { + "id": "label", + "metadata": { + "required": true + } + }, + { + "id": "format", + "metadata": { + "default_string": "attribute" + } + }, + { + "id": "is_primary", + "metadata": { + "default_boolean": false + } + }, + { + "id": "nullable", + "metadata": { + "default_boolean": true + } + }, + { + "id": "required", + "metadata": { + "default_boolean": false + } + }, + { + "id": "persistence", + "metadata": { + "default_string": "arke_parameter" + } + }, + { + "id": "only_run_time", + "metadata": { + "default_boolean": false + } + }, + { + "id": "helper_text", + "metadata": { + "required": false + } + }, + { + "id": "default_dict", + "metadata": { + "required": false + } + } + ] + }, + { + "id": "date", "label": "Date", -"parameters": [ - { - "id": "label", - "metadata": { - "required": true - } - }, - { - "id": "format", - "metadata": { - "default_string": "attribute" - } - }, - { - "id": "is_primary", - "metadata": { - "default_boolean": false - } - }, - { - "id": "nullable", - "metadata": { - "default_boolean": true - } - }, - { - "id": "required", - "metadata": { - "default_boolean": false - } - }, - { - "id": "persistence", - "metadata": { - "default_string": "arke_parameter" - } - }, - { - "id": "only_run_time", - "metadata": { - "default_boolean": false - } - }, - { - "id": "helper_text", - "metadata": { - "required": false - } - }, - { - "id": "default_date", - "metadata": { - "required": false - } - } - ] - }, - { - "id": "datetime", - + "parameters": [ + { + "id": "label", + "metadata": { + "required": true + } + }, + { + "id": "format", + "metadata": { + "default_string": "attribute" + } + }, + { + "id": "is_primary", + "metadata": { + "default_boolean": false + } + }, + { + "id": "nullable", + "metadata": { + "default_boolean": true + } + }, + { + "id": "required", + "metadata": { + "default_boolean": false + } + }, + { + "id": "persistence", + "metadata": { + "default_string": "arke_parameter" + } + }, + { + "id": "only_run_time", + "metadata": { + "default_boolean": false + } + }, + { + "id": "helper_text", + "metadata": { + "required": false + } + }, + { + "id": "default_date", + "metadata": { + "required": false + } + } + ] + }, + { + "id": "datetime", "label": "Datetime", -"parameters": [ - { - "id": "label", - "metadata": { - "required": true - } - }, - { - "id": "format", - "metadata": { - "default_string": "attribute" - } - }, - { - "id": "is_primary", - "metadata": { - "default_boolean": false - } - }, - { - "id": "nullable", - "metadata": { - "default_boolean": true - } - }, - { - "id": "required", - "metadata": { - "default_boolean": false - } - }, - { - "id": "persistence", - "metadata": { - "default_string": "arke_parameter" - } - }, - { - "id": "only_run_time", - "metadata": { - "default_boolean": false - } - }, - { - "id": "helper_text", - "metadata": { - "required": false - } - }, - { - "id": "default_datetime", - "metadata": { - "required": false - } - } - ] - }, - { - "id": "dynamic", - + "parameters": [ + { + "id": "label", + "metadata": { + "required": true + } + }, + { + "id": "format", + "metadata": { + "default_string": "attribute" + } + }, + { + "id": "is_primary", + "metadata": { + "default_boolean": false + } + }, + { + "id": "nullable", + "metadata": { + "default_boolean": true + } + }, + { + "id": "required", + "metadata": { + "default_boolean": false + } + }, + { + "id": "persistence", + "metadata": { + "default_string": "arke_parameter" + } + }, + { + "id": "only_run_time", + "metadata": { + "default_boolean": false + } + }, + { + "id": "helper_text", + "metadata": { + "required": false + } + }, + { + "id": "default_datetime", + "metadata": { + "required": false + } + } + ] + }, + { + "id": "dynamic", "label": "Dynamic", -"parameters": [ - { - "id": "label", - "metadata": { - "required": true - } - }, - { - "id": "format", - "metadata": { - "default_string": "attribute" - } - }, - { - "id": "is_primary", - "metadata": { - "default_boolean": false - } - }, - { - "id": "nullable", - "metadata": { - "default_boolean": true - } - }, - { - "id": "required", - "metadata": { - "default_boolean": false - } - }, - { - "id": "persistence", - "metadata": { - "default_string": "arke_parameter" - } - }, - { - "id": "only_run_time", - "metadata": { - "default_boolean": false - } - }, - { - "id": "helper_text", - "metadata": { - "required": false - } - }, - { - "id": "default_dynamic", - "metadata": { - "required": false - } - } - ] - }, - { - "id": "float", - + "parameters": [ + { + "id": "label", + "metadata": { + "required": true + } + }, + { + "id": "format", + "metadata": { + "default_string": "attribute" + } + }, + { + "id": "is_primary", + "metadata": { + "default_boolean": false + } + }, + { + "id": "nullable", + "metadata": { + "default_boolean": true + } + }, + { + "id": "required", + "metadata": { + "default_boolean": false + } + }, + { + "id": "persistence", + "metadata": { + "default_string": "arke_parameter" + } + }, + { + "id": "only_run_time", + "metadata": { + "default_boolean": false + } + }, + { + "id": "helper_text", + "metadata": { + "required": false + } + }, + { + "id": "default_dynamic", + "metadata": { + "required": false + } + } + ] + }, + { + "id": "float", "label": "Float", -"parameters": [ - { - "id": "label", - "metadata": { - "required": true - } - }, - { - "id": "format", - "metadata": { - "default_string": "attribute" - } - }, - { - "id": "is_primary", - "metadata": { - "default_boolean": false - } - }, - { - "id": "nullable", - "metadata": { - "default_boolean": true - } - }, - { - "id": "required", - "metadata": { - "default_boolean": false - } - }, - { - "id": "persistence", - "metadata": { - "default_string": "arke_parameter" - } - }, - { - "id": "only_run_time", - "metadata": { - "default_boolean": false - } - }, - { - "id": "helper_text", - "metadata": { - "required": false - } - }, - { - "id": "min", - "metadata": { - "required": false - } - }, - { - "id": "max", - "metadata": { - "required": false - } - }, - { - "id": "values", - "metadata": { - "required": false - } - }, - { - "id": "multiple", - "metadata": { - "default_boolean": false - } - }, - { - "id": "default_float", - "metadata": { - "default_float": null - } - } - ] - }, - { - "id": "boolean", - + "parameters": [ + { + "id": "label", + "metadata": { + "required": true + } + }, + { + "id": "format", + "metadata": { + "default_string": "attribute" + } + }, + { + "id": "is_primary", + "metadata": { + "default_boolean": false + } + }, + { + "id": "nullable", + "metadata": { + "default_boolean": true + } + }, + { + "id": "required", + "metadata": { + "default_boolean": false + } + }, + { + "id": "persistence", + "metadata": { + "default_string": "arke_parameter" + } + }, + { + "id": "only_run_time", + "metadata": { + "default_boolean": false + } + }, + { + "id": "helper_text", + "metadata": { + "required": false + } + }, + { + "id": "min", + "metadata": { + "required": false + } + }, + { + "id": "max", + "metadata": { + "required": false + } + }, + { + "id": "values", + "metadata": { + "required": false + } + }, + { + "id": "multiple", + "metadata": { + "default_boolean": false + } + }, + { + "id": "default_float", + "metadata": { + "default_float": null + } + } + ] + }, + { + "id": "boolean", "label": "Boolean", -"parameters": [ - { - "id": "label", - "metadata": { - "required": true - } - }, - { - "id": "format", - "metadata": { - "default_string": "attribute" - } - }, - { - "id": "is_primary", - "metadata": { - "default_boolean": false - } - }, - { - "id": "nullable", - "metadata": { - "default_boolean": true - } - }, - { - "id": "required", - "metadata": { - "default_boolean": false - } - }, - { - "id": "persistence", - "metadata": { - "default_string": "arke_parameter" - } - }, - { - "id": "only_run_time", - "metadata": { - "default_boolean": false - } - }, - { - "id": "helper_text", - "metadata": { - "required": false - } - }, - { - "id": "default_boolean", - "metadata": { - "default_boolean": null - } - } - ] - }, - { - "id": "list", - + "parameters": [ + { + "id": "label", + "metadata": { + "required": true + } + }, + { + "id": "format", + "metadata": { + "default_string": "attribute" + } + }, + { + "id": "is_primary", + "metadata": { + "default_boolean": false + } + }, + { + "id": "nullable", + "metadata": { + "default_boolean": true + } + }, + { + "id": "required", + "metadata": { + "default_boolean": false + } + }, + { + "id": "persistence", + "metadata": { + "default_string": "arke_parameter" + } + }, + { + "id": "only_run_time", + "metadata": { + "default_boolean": false + } + }, + { + "id": "helper_text", + "metadata": { + "required": false + } + }, + { + "id": "default_boolean", + "metadata": { + "default_boolean": null + } + } + ] + }, + { + "id": "list", "label": "List", -"parameters": [ - { - "id": "label", - "metadata": { - "required": true - } - }, - { - "id": "format", - "metadata": { - "default_string": "attribute" - } - }, - { - "id": "is_primary", - "metadata": { - "default_boolean": false - } - }, - { - "id": "nullable", - "metadata": { - "default_boolean": true - } - }, - { - "id": "required", - "metadata": { - "default_boolean": false - } - }, - { - "id": "persistence", - "metadata": { - "default_string": "arke_parameter" - } - }, - { - "id": "only_run_time", - "metadata": { - "default_boolean": false - } - }, - { - "id": "helper_text", - "metadata": { - "required": false - } - }, - { - "id": "default_list", - "metadata": { - "default_list": null - } - } - ] - }, - { - "id": "time", + "parameters": [ + { + "id": "label", + "metadata": { + "required": true + } + }, + { + "id": "format", + "metadata": { + "default_string": "attribute" + } + }, + { + "id": "is_primary", + "metadata": { + "default_boolean": false + } + }, + { + "id": "nullable", + "metadata": { + "default_boolean": true + } + }, + { + "id": "required", + "metadata": { + "default_boolean": false + } + }, + { + "id": "persistence", + "metadata": { + "default_string": "arke_parameter" + } + }, + { + "id": "only_run_time", + "metadata": { + "default_boolean": false + } + }, + { + "id": "helper_text", + "metadata": { + "required": false + } + }, + { + "id": "default_list", + "metadata": { + "default_list": null + } + } + ] + }, + { + "id": "time", "label": "Time", "parameters": [ - { - "id": "label", - "metadata": { - "required": true - } - }, - { - "id": "format", - "metadata": { - "default_string": "attribute" - } - }, - { - "id": "is_primary", - "metadata": { - "default_boolean": false - } - }, - { - "id": "nullable", - "metadata": { - "default_boolean": true - } - }, - { - "id": "required", - "metadata": { - "default_boolean": false - } - }, - { - "id": "persistence", - "metadata": { - "default_string": "arke_parameter" - } - }, - { - "id": "only_run_time", - "metadata": { - "default_boolean": false - } - }, - { - "id": "helper_text", - "metadata": { - "required": false - } - }, - { - "id": "default_time", - "metadata": { - "default_time": null - } - } - ] - }, - { - "id": "link", - "label": "Link", - "parameters": [ - { - "id": "label", - "metadata": { - "required": true - } - }, - { - "id": "format", - "metadata": { - "default_string": "attribute" - } - }, - { - "id": "is_primary", - "metadata": { - "default_boolean": false - } - }, - { - "id": "nullable", - "metadata": { - "default_boolean": true - } - }, - { - "id": "required", - "metadata": { - "default_boolean": false - } - }, - { - "id": "persistence", - "metadata": { - "default_string": "arke_parameter" - } - }, - { - "id": "only_run_time", - "metadata": { - "default_boolean": false - } - }, - { - "id": "helper_text", - "metadata": { - "required": false - } - }, - { - "id": "default_link", - "metadata": { - "default_link": null - } - }, - { - "id": "depth", - "metadata": { - "default_integer": 0 - } - }, - { - "id": "connection_type", - "metadata": { - "default_string": "link" - } - }, - { - "id": "arke_or_group_id", - "metadata": { - "default_string": "arke" - } - }, - { - "id": "filter_keys", - "metadata": { - "multiple": true, - "default_string": [ - "id", - "arke_id" - ] - } - }, - { - "id": "multiple", - "metadata": { - "default_boolean": false - } - }, - - { - "id": "direction", - "metadata": { - "default_string": "child" - } - } - ] - }, - { - "id": "binary", - "label": "Binary", - "parameters": [ - { - "id": "label", - "metadata": { - "required": true - } - }, - { - "id": "format", - "metadata": { - "default_string": "attribute" - } - }, - { - "id": "is_primary", - "metadata": { - "default_boolean": false - } - }, - { - "id": "nullable", - "metadata": { - "default_boolean": true - } - }, - { - "id": "required", - "metadata": { - "default_boolean": false - } - }, - { - "id": "persistence", - "metadata": { - "default_string": "arke_parameter" - } - }, - { - "id": "only_run_time", - "metadata": { - "default_boolean": false - } - }, - { - "id": "helper_text", - "metadata": { - "required": false - } - }, - { - "id": "default_binary", - "metadata": { - "default_binary": null - } - } - ] - }, - { - "id": "group", - + { + "id": "label", + "metadata": { + "required": true + } + }, + { + "id": "format", + "metadata": { + "default_string": "attribute" + } + }, + { + "id": "is_primary", + "metadata": { + "default_boolean": false + } + }, + { + "id": "nullable", + "metadata": { + "default_boolean": true + } + }, + { + "id": "required", + "metadata": { + "default_boolean": false + } + }, + { + "id": "persistence", + "metadata": { + "default_string": "arke_parameter" + } + }, + { + "id": "only_run_time", + "metadata": { + "default_boolean": false + } + }, + { + "id": "helper_text", + "metadata": { + "required": false + } + }, + { + "id": "default_time", + "metadata": { + "default_time": null + } + } + ] + }, + { + "id": "link", + "label": "Link", + "parameters": [ + { + "id": "label", + "metadata": { + "required": true + } + }, + { + "id": "format", + "metadata": { + "default_string": "attribute" + } + }, + { + "id": "is_primary", + "metadata": { + "default_boolean": false + } + }, + { + "id": "nullable", + "metadata": { + "default_boolean": true + } + }, + { + "id": "required", + "metadata": { + "default_boolean": false + } + }, + { + "id": "persistence", + "metadata": { + "default_string": "arke_parameter" + } + }, + { + "id": "only_run_time", + "metadata": { + "default_boolean": false + } + }, + { + "id": "helper_text", + "metadata": { + "required": false + } + }, + { + "id": "default_link", + "metadata": { + "default_link": null + } + }, + { + "id": "depth", + "metadata": { + "default_integer": 0 + } + }, + { + "id": "connection_type", + "metadata": { + "default_string": "link" + } + }, + { + "id": "arke_or_group_id", + "metadata": { + "default_string": "arke" + } + }, + { + "id": "filter_keys", + "metadata": { + "multiple": true, + "default_string": [ + "id", + "arke_id" + ] + } + }, + { + "id": "multiple", + "metadata": { + "default_boolean": false + } + }, + { + "id": "direction", + "metadata": { + "default_string": "child" + } + } + ] + }, + { + "id": "binary", + "label": "Binary", + "parameters": [ + { + "id": "label", + "metadata": { + "required": true + } + }, + { + "id": "format", + "metadata": { + "default_string": "attribute" + } + }, + { + "id": "is_primary", + "metadata": { + "default_boolean": false + } + }, + { + "id": "nullable", + "metadata": { + "default_boolean": true + } + }, + { + "id": "required", + "metadata": { + "default_boolean": false + } + }, + { + "id": "persistence", + "metadata": { + "default_string": "arke_parameter" + } + }, + { + "id": "only_run_time", + "metadata": { + "default_boolean": false + } + }, + { + "id": "helper_text", + "metadata": { + "required": false + } + }, + { + "id": "default_binary", + "metadata": { + "default_binary": null + } + } + ] + }, + { + "id": "group", "label": "Group", -"parameters": [ - { - "id": "label", - "metadata": { - "required": false - } - }, - { - "id": "description", - "metadata": { - "required": false - } - }, - { - "id": "arke_list", - "metadata": { - "multiple": true, - "arke_or_group_id": "arke", - "connection_type": "group", - "depth": 0, - "default_link": [] - } - } - ] - }, - { - "id": "arke_project", + "parameters": [ + { + "id": "label", + "metadata": { + "required": false + } + }, + { + "id": "description", + "metadata": { + "required": false + } + }, + { + "id": "arke_list", + "metadata": { + "multiple": true, + "arke_or_group_id": "arke", + "connection_type": "group", + "depth": 0, + "default_link": [] + } + } + ] + }, + { + "id": "arke_project", "label": "Project", -"parameters": [ - { - "id": "label", - "metadata": { - "required": true - } - }, - { - "id": "description", - "metadata": { - "required": false - } - }, - { - "id": "persistence", - "metadata": { - "required": true, - "values": null, - "default_dict": {} - } - }, - { - "id": "type", - "metadata": { - "required": true, - "default_string": "postgres_schema" - } - } - ] - } -]} \ No newline at end of file + "parameters": [ + { + "id": "label", + "metadata": { + "required": true + } + }, + { + "id": "description", + "metadata": { + "required": false + } + }, + { + "id": "persistence", + "metadata": { + "required": true, + "values": null, + "default_dict": {} + } + }, + { + "id": "type", + "metadata": { + "required": true, + "default_string": "postgres_schema" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/lib/registry/system/group.json b/lib/registry/system/group.json index 3506bfc..8ee9ba4 100644 --- a/lib/registry/system/group.json +++ b/lib/registry/system/group.json @@ -1,14 +1,32 @@ -{ "group": [ - { - "id": "parameter", - "label": "Parameter", - "description": "Parameter Group", - "arke_list": ["string","integer","float","list","dict","date","datetime","time","boolean","dynamic","link","binary"] - }, - { - "id": "arke_or_group", - "label": "Arke or Group", - "description": "Arke or Group", - "arke_list": ["arke","group"] - } -]} \ No newline at end of file +{ + "group": [ + { + "id": "parameter", + "label": "Parameter", + "description": "Parameter Group", + "arke_list": [ + "string", + "integer", + "float", + "list", + "dict", + "date", + "datetime", + "time", + "boolean", + "dynamic", + "link", + "binary" + ] + }, + { + "id": "arke_or_group", + "label": "Arke or Group", + "description": "Arke or Group", + "arke_list": [ + "arke", + "group" + ] + } + ] +} \ No newline at end of file diff --git a/lib/registry/system/parameter.json b/lib/registry/system/parameter.json index 04f5bd5..2c8cf0b 100644 --- a/lib/registry/system/parameter.json +++ b/lib/registry/system/parameter.json @@ -1,837 +1,846 @@ -{ "parameter": [ - { - "default_boolean": false, - "type": "boolean", - "format": "attribute", - "helper_text": "Multiple", - "id": "multiple", - "is_primary": false, - "label": "Multiple", - "nullable": false, - "persistence": "arke_parameter", - "required": false - }, - { - "default_boolean": false, - "type": "boolean", - "format": "attribute", - "helper_text": "Unique", - "id": "unique", - "is_primary": false, - "label": "Unique", - "nullable": false, - "persistence": "arke_parameter", - "required": false - }, - { - "default_boolean": false, - "type": "boolean", - "format": "attribute", - "helper_text": "Default", - "id": "default_boolean", - "is_primary": false, - "label": "Default", - "nullable": true, - "persistence": "arke_parameter", - "required": false - }, - { - "default_boolean": false, - "type": "boolean", - "format": "attribute", - "helper_text": "Nullable", - "id": "nullable", - "is_primary": false, - "label": "Nullable", - "nullable": false, - "persistence": "arke_parameter", - "required": true - }, - { - "default_boolean": false, - "type": "boolean", - "format": "attribute", - "helper_text": "Is Primary", - "id": "is_primary", - "is_primary": false, - "label": "Is Primary", - "nullable": false, - "persistence": "arke_parameter", - "required": false - }, - { - "default_boolean": false, - "type": "boolean", - "format": "attribute", - "helper_text": "Remove Whitespace", - "id": "strip", - "is_primary": false, - "label": "Remove Whitespace", - "nullable": true, - "persistence": "arke_parameter", - "required": false - }, - { - "default_boolean": false, - "type": "boolean", - "format": "attribute", - "helper_text": "Transform to lowercase", - "id": "lowercase", - "is_primary": false, - "label": "Lowercase", - "nullable": true, - "persistence": "arke_parameter", - "required": false - }, - { - "default_boolean": false, - "type": "boolean", - "format": "attribute", - "helper_text": "Active", - "id": "active", - "is_primary": false, - "label": "Active", - "nullable": false, - "persistence": "arke_parameter", - "required": false - }, - { - "default_boolean": false, - "type": "boolean", - "format": "attribute", - "helper_text": "Only run time", - "id": "only_run_time", - "is_primary": false, - "label": "Only run time", - "nullable": true, - "persistence": "arke_parameter", - "required": false - }, - { - "default_boolean": false, - "type": "boolean", - "format": "attribute", - "helper_text": "Required", - "id": "required", - "is_primary": false, - "label": "Required", - "nullable": false, - "persistence": "arke_parameter", - "required": false - }, - { - "default_datetime": null, - "type": "datetime", - "format": "attribute", - "helper_text": "Inserted at", - "id": "inserted_at", - "is_primary": false, - "label": "Inserted at", - "nullable": true, - "persistence": "table_column", - "required": false - }, - { - "default_datetime": null, - "type": "datetime", - "format": "attribute", - "helper_text": "Updated at", - "id": "updated_at", - "is_primary": false, - "label": "Updated at", - "nullable": true, - "persistence": "table_column", - "required": false - }, - { - "default_datetime": null, - "type": "datetime", - "format": "attribute", - "helper_text": "Default", - "id": "default_datetime", - "is_primary": false, - "label": "Default", - "nullable": true, - "persistence": "arke_parameter", - "required": false - }, - { - "default_date": null, - "type": "date", - "format": "attribute", - "helper_text": "Default", - "id": "default_date", - "is_primary": false, - "label": "Default", - "nullable": true, - "persistence": "arke_parameter", - "required": false - }, - { - "default_time": null, - "type": "time", - "format": "attribute", - "helper_text": "Default", - "id": "default_time", - "is_primary": false, - "label": "Default", - "nullable": true, - "persistence": "arke_parameter", - "required": false - }, - { - "arke_or_group_id": "arke", - "connection_type": "link", - "default_link": null, - "type": "link", - "depth": 0, - "direction": "child", - "format": "attribute", - "helper_text": "Default", - "id": "default_link", - "is_primary": false, - "label": "Default", - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "filter_keys": ["id","arke_id"] - }, - { - "arke_or_group_id": "arke", - "connection_type": "group", - "default_link": [], - "type": "link", - "depth": 0, - "direction": "child", - "format": "attribute", - "helper_text": "Arke List", - "id": "arke_list", - "is_primary": false, - "label": "Arke List", - "multiple": true, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "filter_keys": ["id","arke_id"] - }, - { - "connection_type": "link", - "default_link": [], - "type": "link", - "depth": 0, - "direction": "child", - "format": "attribute", - "helper_text": "Parameters", - "id": "parameters", - "is_primary": false, - "label": "Parameters", - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "arke_or_group_id": "parameter", - "required": false - }, - { - "arke_or_group_id": "arke_or_group", - "connection_type": "link", - "default_link": null, - "type": "link", - "depth": 0, - "direction": "child", - "format": "attribute", - "helper_text": "Arke or Group id", - "id": "arke_or_group_id", - "is_primary": false, - "label": "Arke or Group id", - "multiple": false, - "nullable": false, - "persistence": "arke_parameter", - "required": true, - "filter_keys": ["id","arke_id"] - - }, - { - "default_list": null, - "type": "dict", - "format": "attribute", - "helper_text": "Default", - "id": "default_dict", - "is_primary": false, - "label": "Default", - "nullable": true, - "persistence": "arke_parameter", - "required": false - }, - { - "default_list": null, - "type": "dict", - "format": "attribute", - "helper_text": "Address", - "id": "address", - "is_primary": false, - "label": "Address", - "nullable": true, - "persistence": "arke_parameter", - "required": false - }, - { - "default_dict": {}, - "type": "dict", - "format": "attribute", - "helper_text": "Metadata", - "id": "metadata", - "is_primary": false, - "label": "Metadata", - "nullable": true, - "persistence": "table_column", - "required": false - }, - { - "default_dynamic": null, - "type": "dynamic", - "format": "attribute", - "helper_text": "Default", - "id": "default_dynamic", - "is_primary": false, - "label": "Default", - "nullable": true, - "persistence": "arke_parameter", - "required": false - }, - { - "default_integer": null, - "type": "integer", - "format": "attribute", - "helper_text": "Default", - "id": "default_integer", - "is_primary": false, - "label": "Default", - "max": null, - "min": null, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "unique": false, - "values": null - }, - { - "default_integer": null, - "type": "integer", - "format": "attribute", - "helper_text": "Min Length", - "id": "min_length", - "is_primary": false, - "label": "Min Length", - "max": null, - "min": null, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "unique": false, - "values": null - }, - { - "default_integer": null, - "type": "integer", - "format": "attribute", - "helper_text": "Max Length", - "id": "max_length", - "is_primary": false, - "label": "Max Length", - "max": null, - "min": null, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "unique": false, - "values": null - }, - { - "default_integer": null, - "type": "integer", - "format": "attribute", - "helper_text": "Min", - "id": "min", - "is_primary": false, - "label": "Min", - "max": null, - "min": null, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "unique": false, - "values": null - }, - { - "default_integer": null, - "type": "integer", - "format": "attribute", - "helper_text": "Max", - "id": "max", - "is_primary": false, - "label": "Max", - "max": null, - "min": null, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "unique": false, - "values": null - }, - { - "default_integer": 0, - "type": "integer", - "format": "attribute", - "helper_text": "Depth", - "id": "depth", - "is_primary": false, - "label": "Depth", - "max": 100, - "min": 0, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "unique": false, - "values": null - }, - { - "default_float": null, - "type": "float", - "format": "attribute", - "helper_text": "Default", - "id": "default_float", - "is_primary": false, - "label": "Default", - "max": null, - "min": null, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "unique": false, - "values": null - }, - { - "default_list": null, - "type": "list", - "format": "attribute", - "helper_text": "Values", - "id": "values", - "is_primary": false, - "label": "Values", - "nullable": true, - "persistence": "arke_parameter", - "required": false - }, - { - "default_list": null, - "type": "list", - "format": "attribute", - "helper_text": "Default", - "id": "default_list", - "is_primary": false, - "label": "Default", - "nullable": true, - "persistence": "arke_parameter", - "required": false - }, - { - "default_binary": null, - "type": "binary", - "format": "attribute", - "helper_text": "Default", - "id": "default_binary", - "is_primary": false, - "label": "Default", - "nullable": true, - "persistence": "arke_parameter", - "required": false - }, - { - "default_string": null, - "type": "string", - "format": "attribute", - "helper_text": "Id", - "id": "id", - "is_primary": true, - "label": "Id", - "max_length": null, - "min_length": 2, - "multiple": false, - "nullable": false, - "persistence": "table_column", - "required": true, - "strip": true, -"lowercase": false, - "unique": true, - "values": null - }, - { - "default_string": null, - "type": "string", - "format": "attribute", - "helper_text": "Arke id", - "id": "arke_id", - "is_primary": false, - "label": "Arke id", - "max_length": null, - "min_length": 2, - "multiple": false, - "nullable": false, - "persistence": "table_column", - "required": true, - "strip": true, -"lowercase": false, - "unique": false, - "values": null - }, - { - "default_string": null, - "type": "string", - "format": "attribute", - "helper_text": "Label", - "id": "label", - "is_primary": false, - "label": "Label", - "max_length": 200, - "min_length": 2, - "multiple": false, - "nullable": false, - "persistence": "arke_parameter", - "required": true, - "strip": false, -"lowercase": false, - "unique": false, - "values": null - }, - { - "default_string": "attribute", - "type": "string", - "format": "attribute", - "helper_text": "Format", - "id": "format", - "is_primary": false, - "label": "Format", - "max_length": null, - "min_length": 2, - "multiple": false, - "nullable": false, - "persistence": "arke_parameter", - "required": false, - "strip": false, -"lowercase": false, - "unique": false, - "values": null - }, - { - "default_string": "arke_parameter", - "type": "string", - "format": "attribute", - "helper_text": "Persistence", - "id": "persistence", - "is_primary": false, - "label": "Persistence", - "max_length": null, - "min_length": 2, - "multiple": false, - "nullable": false, - "persistence": "arke_parameter", - "required": false, - "strip": false, -"lowercase": false, - "unique": false, - "values": [ - { - "label": "Arke Parameter", - "value": "arke_parameter" - }, - { - "label": "Table Column", - "value": "table_column" - } - ] - }, - { - "default_string": null, - "type": "string", - "format": "attribute", - "helper_text": "Helper text", - "id": "helper_text", - "is_primary": false, - "label": "Helper text", - "max_length": null, - "min_length": 2, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "strip": false, -"lowercase": false, - "unique": false, - "values": null - }, - { - "default_string": null, - "type": "string", - "format": "attribute", - "helper_text": "Default", - "id": "default_string", - "is_primary": false, - "label": "Default", - "max_length": null, - "min_length": null, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "strip": false, -"lowercase": false, - "unique": false, - "values": null - }, - { - "default_string": null, - "type": "string", - "format": "attribute", - "helper_text": "Description", - "id": "description", - "is_primary": false, - "label": "Description", - "max_length": 500, - "min_length": 0, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "strip": false, -"lowercase": false, - "unique": false, - "values": null - }, - { - "default_string": null, - "type": "string", - "format": "attribute", - "helper_text": "Child Id", - "id": "child_id", - "is_primary": false, - "label": "Child Id", - "max_length": null, - "min_length": 2, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "strip": true, -"lowercase": false, - "unique": false, - "values": null - }, - { - "default_string": null, - "type": "string", - "format": "attribute", - "helper_text": "Parent Id", - "id": "parent_id", - "is_primary": false, - "label": "Parent Id", - "max_length": null, - "min_length": 2, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "strip": true, -"lowercase": false, - "unique": false, - "values": null - }, - { - "default_string": null, - "type": "string", - "format": "attribute", - "helper_text": "Type", - "id": "type", - "is_primary": false, - "label": "Type", - "max_length": null, - "min_length": 2, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "strip": true, -"lowercase": false, - "unique": false, - "values": null - }, - { - "default_string": null, - "type": "string", - "format": "attribute", - "helper_text": "Public Key", - "id": "public_key", - "is_primary": false, - "label": "Public Key", - "max_length": null, - "min_length": 2, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "strip": false, -"lowercase": false, - "unique": false, - "values": null - }, - { - "default_string": null, - "type": "string", - "format": "attribute", - "helper_text": "Vat", - "id": "vat", - "is_primary": false, - "label": "Vat", - "max_length": null, - "min_length": 2, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "strip": false, -"lowercase": false, - "unique": false, - "values": null - }, - { - "default_string": null, - "type": "string", - "format": "attribute", - "helper_text": "Environment", - "id": "environment", - "is_primary": false, - "label": "Environment", - "max_length": null, - "min_length": 2, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "strip": false, -"lowercase": false, - "unique": false, - "values": null - }, - { - "default_string": null, - "type": "string", - "format": "attribute", - "helper_text": "Fiscal code", - "id": "fiscal_code", - "is_primary": false, - "label": "Fiscal code", - "max_length": null, - "min_length": 3, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "strip": false, -"lowercase": false, - "unique": false, - "values": null - }, - { - "default_string": null, - "type": "string", - "format": "attribute", - "helper_text": "Birth date", - "id": "birth_date", - "is_primary": false, - "label": "Birth date", - "max_length": null, - "min_length": 1, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "strip": false, -"lowercase": false, - "unique": false, - "values": null - }, - { - "default_string": "link", - "type": "string", - "format": "attribute", - "helper_text": "Connection type", - "id": "connection_type", - "is_primary": false, - "label": "Connection type", - "max_length": null, - "min_length": 1, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "strip": true, -"lowercase": false, - "unique": false, - "values": null - }, - { - "default_string": "child", - "type": "string", - "format": "attribute", - "helper_text": "Direction", - "id": "direction", - "is_primary": false, - "label": "Direction", - "max_length": null, - "min_length": 1, - "multiple": false, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "strip": true, -"lowercase": false, - "unique": false, - "values": [ - { - "label": "Child", - "value": "child" - }, - { - "label": "Parent", - "value": "parent" - } - ] - }, - { - "default_string": null, - "type": "string", - "format": "attribute", - "helper_text": "Filter keys", - "id": "filter_keys", - "is_primary": false, - "label": "Filter keys", - "max_length": null, - "min_length": null, - "multiple": true, - "nullable": true, - "persistence": "arke_parameter", - "required": false, - "strip": false, -"lowercase": false, - "unique": false, - "values": null - } -] +{ + "parameter": [ + { + "default_boolean": false, + "type": "boolean", + "format": "attribute", + "helper_text": "Multiple", + "id": "multiple", + "is_primary": false, + "label": "Multiple", + "nullable": false, + "persistence": "arke_parameter", + "required": false + }, + { + "default_boolean": false, + "type": "boolean", + "format": "attribute", + "helper_text": "Unique", + "id": "unique", + "is_primary": false, + "label": "Unique", + "nullable": false, + "persistence": "arke_parameter", + "required": false + }, + { + "default_boolean": false, + "type": "boolean", + "format": "attribute", + "helper_text": "Default", + "id": "default_boolean", + "is_primary": false, + "label": "Default", + "nullable": true, + "persistence": "arke_parameter", + "required": false + }, + { + "default_boolean": false, + "type": "boolean", + "format": "attribute", + "helper_text": "Nullable", + "id": "nullable", + "is_primary": false, + "label": "Nullable", + "nullable": false, + "persistence": "arke_parameter", + "required": true + }, + { + "default_boolean": false, + "type": "boolean", + "format": "attribute", + "helper_text": "Is Primary", + "id": "is_primary", + "is_primary": false, + "label": "Is Primary", + "nullable": false, + "persistence": "arke_parameter", + "required": false + }, + { + "default_boolean": false, + "type": "boolean", + "format": "attribute", + "helper_text": "Remove Whitespace", + "id": "strip", + "is_primary": false, + "label": "Remove Whitespace", + "nullable": true, + "persistence": "arke_parameter", + "required": false + }, + { + "default_boolean": false, + "type": "boolean", + "format": "attribute", + "helper_text": "Transform to lowercase", + "id": "lowercase", + "is_primary": false, + "label": "Lowercase", + "nullable": true, + "persistence": "arke_parameter", + "required": false + }, + { + "default_boolean": false, + "type": "boolean", + "format": "attribute", + "helper_text": "Active", + "id": "active", + "is_primary": false, + "label": "Active", + "nullable": false, + "persistence": "arke_parameter", + "required": false + }, + { + "default_boolean": false, + "type": "boolean", + "format": "attribute", + "helper_text": "Only run time", + "id": "only_run_time", + "is_primary": false, + "label": "Only run time", + "nullable": true, + "persistence": "arke_parameter", + "required": false + }, + { + "default_boolean": false, + "type": "boolean", + "format": "attribute", + "helper_text": "Required", + "id": "required", + "is_primary": false, + "label": "Required", + "nullable": false, + "persistence": "arke_parameter", + "required": false + }, + { + "default_datetime": null, + "type": "datetime", + "format": "attribute", + "helper_text": "Inserted at", + "id": "inserted_at", + "is_primary": false, + "label": "Inserted at", + "nullable": true, + "persistence": "table_column", + "required": false + }, + { + "default_datetime": null, + "type": "datetime", + "format": "attribute", + "helper_text": "Updated at", + "id": "updated_at", + "is_primary": false, + "label": "Updated at", + "nullable": true, + "persistence": "table_column", + "required": false + }, + { + "default_datetime": null, + "type": "datetime", + "format": "attribute", + "helper_text": "Default", + "id": "default_datetime", + "is_primary": false, + "label": "Default", + "nullable": true, + "persistence": "arke_parameter", + "required": false + }, + { + "default_date": null, + "type": "date", + "format": "attribute", + "helper_text": "Default", + "id": "default_date", + "is_primary": false, + "label": "Default", + "nullable": true, + "persistence": "arke_parameter", + "required": false + }, + { + "default_time": null, + "type": "time", + "format": "attribute", + "helper_text": "Default", + "id": "default_time", + "is_primary": false, + "label": "Default", + "nullable": true, + "persistence": "arke_parameter", + "required": false + }, + { + "arke_or_group_id": "arke", + "connection_type": "link", + "default_link": null, + "type": "link", + "depth": 0, + "direction": "child", + "format": "attribute", + "helper_text": "Default", + "id": "default_link", + "is_primary": false, + "label": "Default", + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "filter_keys": [ + "id", + "arke_id" + ] + }, + { + "arke_or_group_id": "arke", + "connection_type": "group", + "default_link": [], + "type": "link", + "depth": 0, + "direction": "child", + "format": "attribute", + "helper_text": "Arke List", + "id": "arke_list", + "is_primary": false, + "label": "Arke List", + "multiple": true, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "filter_keys": [ + "id", + "arke_id" + ] + }, + { + "connection_type": "link", + "default_link": [], + "type": "link", + "depth": 0, + "direction": "child", + "format": "attribute", + "helper_text": "Parameters", + "id": "parameters", + "is_primary": false, + "label": "Parameters", + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "arke_or_group_id": "parameter", + "required": false + }, + { + "arke_or_group_id": "arke_or_group", + "connection_type": "link", + "default_link": null, + "type": "link", + "depth": 0, + "direction": "child", + "format": "attribute", + "helper_text": "Arke or Group id", + "id": "arke_or_group_id", + "is_primary": false, + "label": "Arke or Group id", + "multiple": false, + "nullable": false, + "persistence": "arke_parameter", + "required": true, + "filter_keys": [ + "id", + "arke_id" + ] + }, + { + "default_list": null, + "type": "dict", + "format": "attribute", + "helper_text": "Default", + "id": "default_dict", + "is_primary": false, + "label": "Default", + "nullable": true, + "persistence": "arke_parameter", + "required": false + }, + { + "default_list": null, + "type": "dict", + "format": "attribute", + "helper_text": "Address", + "id": "address", + "is_primary": false, + "label": "Address", + "nullable": true, + "persistence": "arke_parameter", + "required": false + }, + { + "default_dict": {}, + "type": "dict", + "format": "attribute", + "helper_text": "Metadata", + "id": "metadata", + "is_primary": false, + "label": "Metadata", + "nullable": true, + "persistence": "table_column", + "required": false + }, + { + "default_dynamic": null, + "type": "dynamic", + "format": "attribute", + "helper_text": "Default", + "id": "default_dynamic", + "is_primary": false, + "label": "Default", + "nullable": true, + "persistence": "arke_parameter", + "required": false + }, + { + "default_integer": null, + "type": "integer", + "format": "attribute", + "helper_text": "Default", + "id": "default_integer", + "is_primary": false, + "label": "Default", + "max": null, + "min": null, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "unique": false, + "values": null + }, + { + "default_integer": null, + "type": "integer", + "format": "attribute", + "helper_text": "Min Length", + "id": "min_length", + "is_primary": false, + "label": "Min Length", + "max": null, + "min": null, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "unique": false, + "values": null + }, + { + "default_integer": null, + "type": "integer", + "format": "attribute", + "helper_text": "Max Length", + "id": "max_length", + "is_primary": false, + "label": "Max Length", + "max": null, + "min": null, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "unique": false, + "values": null + }, + { + "default_integer": null, + "type": "integer", + "format": "attribute", + "helper_text": "Min", + "id": "min", + "is_primary": false, + "label": "Min", + "max": null, + "min": null, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "unique": false, + "values": null + }, + { + "default_integer": null, + "type": "integer", + "format": "attribute", + "helper_text": "Max", + "id": "max", + "is_primary": false, + "label": "Max", + "max": null, + "min": null, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "unique": false, + "values": null + }, + { + "default_integer": 0, + "type": "integer", + "format": "attribute", + "helper_text": "Depth", + "id": "depth", + "is_primary": false, + "label": "Depth", + "max": 100, + "min": 0, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "unique": false, + "values": null + }, + { + "default_float": null, + "type": "float", + "format": "attribute", + "helper_text": "Default", + "id": "default_float", + "is_primary": false, + "label": "Default", + "max": null, + "min": null, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "unique": false, + "values": null + }, + { + "default_list": null, + "type": "list", + "format": "attribute", + "helper_text": "Values", + "id": "values", + "is_primary": false, + "label": "Values", + "nullable": true, + "persistence": "arke_parameter", + "required": false + }, + { + "default_list": null, + "type": "list", + "format": "attribute", + "helper_text": "Default", + "id": "default_list", + "is_primary": false, + "label": "Default", + "nullable": true, + "persistence": "arke_parameter", + "required": false + }, + { + "default_binary": null, + "type": "binary", + "format": "attribute", + "helper_text": "Default", + "id": "default_binary", + "is_primary": false, + "label": "Default", + "nullable": true, + "persistence": "arke_parameter", + "required": false + }, + { + "default_string": null, + "type": "string", + "format": "attribute", + "helper_text": "Id", + "id": "id", + "is_primary": true, + "label": "Id", + "max_length": null, + "min_length": 2, + "multiple": false, + "nullable": false, + "persistence": "table_column", + "required": true, + "strip": true, + "lowercase": false, + "unique": true, + "values": null + }, + { + "default_string": null, + "type": "string", + "format": "attribute", + "helper_text": "Arke id", + "id": "arke_id", + "is_primary": false, + "label": "Arke id", + "max_length": null, + "min_length": 2, + "multiple": false, + "nullable": false, + "persistence": "table_column", + "required": true, + "strip": true, + "lowercase": false, + "unique": false, + "values": null + }, + { + "default_string": null, + "type": "string", + "format": "attribute", + "helper_text": "Label", + "id": "label", + "is_primary": false, + "label": "Label", + "max_length": 200, + "min_length": 2, + "multiple": false, + "nullable": false, + "persistence": "arke_parameter", + "required": true, + "strip": false, + "lowercase": false, + "unique": false, + "values": null + }, + { + "default_string": "attribute", + "type": "string", + "format": "attribute", + "helper_text": "Format", + "id": "format", + "is_primary": false, + "label": "Format", + "max_length": null, + "min_length": 2, + "multiple": false, + "nullable": false, + "persistence": "arke_parameter", + "required": false, + "strip": false, + "lowercase": false, + "unique": false, + "values": null + }, + { + "default_string": "arke_parameter", + "type": "string", + "format": "attribute", + "helper_text": "Persistence", + "id": "persistence", + "is_primary": false, + "label": "Persistence", + "max_length": null, + "min_length": 2, + "multiple": false, + "nullable": false, + "persistence": "arke_parameter", + "required": false, + "strip": false, + "lowercase": false, + "unique": false, + "values": [ + { + "label": "Arke Parameter", + "value": "arke_parameter" + }, + { + "label": "Table Column", + "value": "table_column" + } + ] + }, + { + "default_string": null, + "type": "string", + "format": "attribute", + "helper_text": "Helper text", + "id": "helper_text", + "is_primary": false, + "label": "Helper text", + "max_length": null, + "min_length": 2, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "strip": false, + "lowercase": false, + "unique": false, + "values": null + }, + { + "default_string": null, + "type": "string", + "format": "attribute", + "helper_text": "Default", + "id": "default_string", + "is_primary": false, + "label": "Default", + "max_length": null, + "min_length": null, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "strip": false, + "lowercase": false, + "unique": false, + "values": null + }, + { + "default_string": null, + "type": "string", + "format": "attribute", + "helper_text": "Description", + "id": "description", + "is_primary": false, + "label": "Description", + "max_length": 500, + "min_length": 0, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "strip": false, + "lowercase": false, + "unique": false, + "values": null + }, + { + "default_string": null, + "type": "string", + "format": "attribute", + "helper_text": "Child Id", + "id": "child_id", + "is_primary": false, + "label": "Child Id", + "max_length": null, + "min_length": 2, + "multiple": false, + "nullable": true, + "persistence": "table_column", + "required": false, + "strip": true, + "lowercase": false, + "unique": false, + "values": null + }, + { + "default_string": null, + "type": "string", + "format": "attribute", + "helper_text": "Parent Id", + "id": "parent_id", + "is_primary": false, + "label": "Parent Id", + "max_length": null, + "min_length": 2, + "multiple": false, + "nullable": true, + "persistence": "table_column", + "required": false, + "strip": true, + "lowercase": false, + "unique": false, + "values": null + }, + { + "default_string": null, + "type": "string", + "format": "attribute", + "helper_text": "Type", + "id": "type", + "is_primary": false, + "label": "Type", + "max_length": null, + "min_length": 2, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "strip": true, + "lowercase": false, + "unique": false, + "values": null + }, + { + "default_string": null, + "type": "string", + "format": "attribute", + "helper_text": "Public Key", + "id": "public_key", + "is_primary": false, + "label": "Public Key", + "max_length": null, + "min_length": 2, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "strip": false, + "lowercase": false, + "unique": false, + "values": null + }, + { + "default_string": null, + "type": "string", + "format": "attribute", + "helper_text": "Vat", + "id": "vat", + "is_primary": false, + "label": "Vat", + "max_length": null, + "min_length": 2, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "strip": false, + "lowercase": false, + "unique": false, + "values": null + }, + { + "default_string": null, + "type": "string", + "format": "attribute", + "helper_text": "Environment", + "id": "environment", + "is_primary": false, + "label": "Environment", + "max_length": null, + "min_length": 2, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "strip": false, + "lowercase": false, + "unique": false, + "values": null + }, + { + "default_string": null, + "type": "string", + "format": "attribute", + "helper_text": "Fiscal code", + "id": "fiscal_code", + "is_primary": false, + "label": "Fiscal code", + "max_length": null, + "min_length": 3, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "strip": false, + "lowercase": false, + "unique": false, + "values": null + }, + { + "default_string": null, + "type": "string", + "format": "attribute", + "helper_text": "Birth date", + "id": "birth_date", + "is_primary": false, + "label": "Birth date", + "max_length": null, + "min_length": 1, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "strip": false, + "lowercase": false, + "unique": false, + "values": null + }, + { + "default_string": "link", + "type": "string", + "format": "attribute", + "helper_text": "Connection type", + "id": "connection_type", + "is_primary": false, + "label": "Connection type", + "max_length": null, + "min_length": 1, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "strip": true, + "lowercase": false, + "unique": false, + "values": null + }, + { + "default_string": "child", + "type": "string", + "format": "attribute", + "helper_text": "Direction", + "id": "direction", + "is_primary": false, + "label": "Direction", + "max_length": null, + "min_length": 1, + "multiple": false, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "strip": true, + "lowercase": false, + "unique": false, + "values": [ + { + "label": "Child", + "value": "child" + }, + { + "label": "Parent", + "value": "parent" + } + ] + }, + { + "default_string": null, + "type": "string", + "format": "attribute", + "helper_text": "Filter keys", + "id": "filter_keys", + "is_primary": false, + "label": "Filter keys", + "max_length": null, + "min_length": null, + "multiple": true, + "nullable": true, + "persistence": "arke_parameter", + "required": false, + "strip": false, + "lowercase": false, + "unique": false, + "values": null + } + ] } \ No newline at end of file diff --git a/mix.exs b/mix.exs index 09fc44a..7aabc1f 100644 --- a/mix.exs +++ b/mix.exs @@ -1,7 +1,7 @@ defmodule Arke.MixProject do use Mix.Project - @version "0.3.15" + @version "0.4.0-bulk.1" @scm_url "https://github.com/arkemishub/arke" @site_url "https://arkehub.com" @@ -61,7 +61,7 @@ defmodule Arke.MixProject do {:httpoison, "~> 2.0"}, {:calendar, "~> 1.0.0"}, {:xlsxir, "~> 1.6"}, - {:libcluster, "~> 3.3"}, + {:libcluster, "~> 3.3"} ] end