diff --git a/lib/jsonapi/config.ex b/lib/jsonapi/config.ex index 0e7a3811..0f279790 100644 --- a/lib/jsonapi/config.ex +++ b/lib/jsonapi/config.ex @@ -9,8 +9,7 @@ defmodule JSONAPI.Config do include: [], opts: nil, sort: nil, - view: nil, - page: %{} + view: nil @type t :: %__MODULE__{ data: nil | map, @@ -19,7 +18,6 @@ defmodule JSONAPI.Config do include: [atom | {atom, any}], opts: nil | keyword, sort: nil | keyword, - view: any, - page: nil | map + view: any } end diff --git a/lib/jsonapi/paginator.ex b/lib/jsonapi/paginator.ex deleted file mode 100644 index 83bba4d9..00000000 --- a/lib/jsonapi/paginator.ex +++ /dev/null @@ -1,22 +0,0 @@ -defmodule JSONAPI.Paginator do - @moduledoc """ - Pagination strategy behaviour - """ - - alias Plug.Conn - - @type options :: Keyword.t() - - @type page :: map() - - @type params :: %{String.t() => String.t()} - - @type links :: %{ - first: String.t() | nil, - last: String.t() | nil, - next: String.t() | nil, - prev: String.t() | nil - } - - @callback paginate(data :: term, view :: atom, conn :: Conn.t(), page, options) :: links -end diff --git a/lib/jsonapi/plugs/query_parser.ex b/lib/jsonapi/plugs/query_parser.ex index ab12ccb2..78a80b3a 100644 --- a/lib/jsonapi/plugs/query_parser.ex +++ b/lib/jsonapi/plugs/query_parser.ex @@ -102,14 +102,15 @@ defmodule JSONAPI.QueryParser do |> parse_include(query_params_config_struct.include) |> parse_filter(query_params_config_struct.filter) |> parse_sort(query_params_config_struct.sort) - |> parse_pagination(query_params_config_struct.page) + + # |> parse_pagination(query_params_config_struct.page) Conn.assign(conn, :jsonapi_query, config) end def parse_pagination(config, map) when map_size(map) == 0, do: config - def parse_pagination(%Config{} = config, page), do: Map.put(config, :page, page) + # def parse_pagination(%Config{} = config, page), do: Map.put(config, :page, page) @spec parse_filter(Config.t(), keyword()) :: Config.t() def parse_filter(config, map) when map_size(map) == 0, do: config diff --git a/lib/jsonapi/serializer.ex b/lib/jsonapi/serializer.ex index 0ea777e8..82eaa0db 100644 --- a/lib/jsonapi/serializer.ex +++ b/lib/jsonapi/serializer.ex @@ -20,13 +20,13 @@ defmodule JSONAPI.Serializer do @spec serialize(View.t(), View.data(), Conn.t() | nil, View.meta() | nil, View.options()) :: document() def serialize(view, data, conn \\ nil, meta \\ nil, options \\ []) do - {query_includes, query_page} = + query_includes = case conn do - %Conn{assigns: %{jsonapi_query: %Config{include: include, page: page}}} -> - {include, page} + %Conn{assigns: %{jsonapi_query: %Config{include: include}}} -> + include _ -> - {[], nil} + [] end {to_include, encoded_data} = encode_data(view, data, conn, query_includes, options) @@ -43,7 +43,8 @@ defmodule JSONAPI.Serializer do encoded_data end - merge_links(encoded_data, data, view, conn, query_page, remove_links?(), options) + custom_merge_links(encoded_data, view.links(data, conn)) + # merge_links(encoded_data, data, view, conn, query_page, remove_links?(), options) end def encode_data(_view, nil, _conn, _query_includes, _options), do: {[], nil} @@ -65,7 +66,8 @@ defmodule JSONAPI.Serializer do relationships: %{} } - doc = merge_links(encoded_data, data, view, conn, nil, remove_links?(), options) + doc = custom_merge_links(encoded_data, view.links(data, conn)) + # doc = merge_links(encoded_data, data, view, conn, nil, remove_links?(), options) doc = case view.meta(data, conn) do @@ -98,8 +100,8 @@ defmodule JSONAPI.Serializer do ) do # Build the relationship url rel_key = transform_fields(relationship_name) - rel_url = parent_view.url_for_rel(parent_data, rel_key, conn) - + # rel_url = parent_view.url_for_rel(parent_data, rel_key, conn) + rel_url = nil # Build the relationship acc = put_in( @@ -204,42 +206,49 @@ defmodule JSONAPI.Serializer do data: encode_rel_data(rel_view, rel_data) } - merge_related_links(data, info, remove_links?()) + # merge_related_links(data, info, remove_links?()) end - defp merge_base_links(%{links: links} = doc, data, view, conn) do - view_links = Map.merge(view.links(data, conn), links) - Map.merge(doc, %{links: view_links}) + def custom_merge_links(encoded_data, nil), do: encoded_data + + def custom_merge_links(encoded_data, links) do + IO.inspect("BING BONG") + Map.merge(encoded_data, %{links: links}) end - defp merge_links(doc, data, view, conn, page, false, options) when is_list(data) do - links = - Map.merge(view.pagination_links(data, conn, page, options), %{ - self: view.url_for_pagination(data, conn, page) - }) + # defp merge_base_links(%{links: links} = doc, data, view, conn) do + # view_links = Map.merge(view.links(data, conn), links) + # Map.merge(doc, %{links: view_links}) + # end - doc - |> Map.merge(%{links: links}) - |> merge_base_links(data, view, conn) - end + # defp merge_links(doc, data, view, conn, page, false, options) when is_list(data) do + # links = + # Map.merge(view.pagination_links(data, conn, page, options), %{ + # self: view.url_for_pagination(data, conn, page) + # }) - defp merge_links(doc, data, view, conn, _page, false, _options) do - doc - |> Map.merge(%{links: %{self: view.url_for(data, conn)}}) - |> merge_base_links(data, view, conn) - end + # doc + # |> Map.merge(%{links: links}) + # |> merge_base_links(data, view, conn) + # end - defp merge_links(doc, _data, _view, _conn, _page, _remove_links, _options), do: doc + # defp merge_links(doc, data, view, conn, _page, false, _options) do + # doc + # |> Map.merge(%{links: %{self: view.url_for(data, conn)}}) + # |> merge_base_links(data, view, conn) + # end - defp merge_related_links( - encoded_data, - {rel_view, rel_data, rel_url, conn}, - false = _remove_links - ) do - Map.merge(encoded_data, %{links: %{self: rel_url, related: rel_view.url_for(rel_data, conn)}}) - end + # defp merge_links(doc, _data, _view, _conn, _page, _remove_links, _options), do: doc + + # defp merge_related_links( + # encoded_data, + # {rel_view, rel_data, rel_url, conn}, + # false = _remove_links + # ) do + # Map.merge(encoded_data, %{links: %{self: rel_url, related: rel_view.url_for(rel_data, conn)}}) + # end - defp merge_related_links(encoded_rel_data, _info, _remove_links), do: encoded_rel_data + # defp merge_related_links(encoded_rel_data, _info, _remove_links), do: encoded_rel_data @spec encode_rel_data(module(), map() | list()) :: map() | nil def encode_rel_data(_view, nil), do: nil @@ -296,7 +305,13 @@ defmodule JSONAPI.Serializer do |> List.flatten() end - defp remove_links?, do: Application.get_env(:jsonapi, :remove_links, false) + # defp remove_links?(options \\ []) do + # options + # |> Keyword.get( + # :remove_links, + # Application.get_env(:jsonapi, :remove_links, false) + # ) + # end defp transform_fields(fields) do case Utils.String.field_transformation() do diff --git a/lib/jsonapi/view.ex b/lib/jsonapi/view.ex index 5198ca2a..9579ab75 100644 --- a/lib/jsonapi/view.ex +++ b/lib/jsonapi/view.ex @@ -127,7 +127,6 @@ defmodule JSONAPI.View do default style for presentation in names is to be underscored and not dashed. """ - alias JSONAPI.{Paginator, Utils} alias Plug.Conn @type t :: module() @@ -144,28 +143,28 @@ defmodule JSONAPI.View do @callback fields() :: [field()] @callback get_field(field(), data(), Conn.t()) :: any() @callback hidden(data()) :: [field()] - @callback links(data(), Conn.t()) :: links() + @callback links(data(), Conn.t()) :: links() | nil @callback meta(data(), Conn.t()) :: meta() | nil - @callback namespace() :: String.t() - @callback pagination_links(data(), Conn.t(), Paginator.page(), Paginator.options()) :: - Paginator.links() - @callback path() :: String.t() | nil + # @callback namespace() :: String.t() + # @callback pagination_links(data(), Conn.t(), Paginator.page(), Paginator.options()) :: + # Paginator.links() + # @callback path() :: String.t() | nil @callback relationships() :: [ {atom(), t() | {t(), :include} | {atom(), t()} | {atom(), t(), :include}} ] @callback type() :: resource_type() - @callback url_for(data(), Conn.t() | nil) :: String.t() - @callback url_for_pagination(data(), Conn.t(), Paginator.params()) :: String.t() - @callback url_for_rel(term(), String.t(), Conn.t() | nil) :: String.t() + # @callback url_for(data(), Conn.t() | nil) :: String.t() + # @callback url_for_pagination(data(), Conn.t(), Paginator.params()) :: String.t() + # @callback url_for_rel(term(), String.t(), Conn.t() | nil) :: String.t() @callback visible_fields(data(), Conn.t() | nil) :: list(atom) @optional_callbacks [get_field: 3] defmacro __using__(opts \\ []) do - {type, opts} = Keyword.pop(opts, :type) - {namespace, opts} = Keyword.pop(opts, :namespace) - {path, opts} = Keyword.pop(opts, :path) - {paginator, _opts} = Keyword.pop(opts, :paginator) + type = Keyword.fetch!(opts, :type) + # {namespace, _opts} = Keyword.pop(opts, :namespace) + # {path, _opts} = Keyword.pop(opts, :path) + # {paginator, _opts} = Keyword.pop(opts, :paginator) quote do alias JSONAPI.{Serializer, View} @@ -173,9 +172,9 @@ defmodule JSONAPI.View do @behaviour View @resource_type unquote(type) - @namespace unquote(namespace) - @path unquote(path) - @paginator unquote(paginator) + # @namespace unquote(namespace) + # @path unquote(path) + # @paginator unquote(paginator) @impl View def id(nil), do: nil @@ -201,6 +200,7 @@ defmodule JSONAPI.View do Map.put(intermediate_map, field, value) end) + |> IO.inspect(label: "attributes") end @impl View @@ -210,31 +210,31 @@ defmodule JSONAPI.View do def hidden(_data), do: [] @impl View - def links(_data, _conn), do: %{} + def links(_data, _conn), do: nil @impl View def meta(_data, _conn), do: nil - @impl View - if @namespace do - def namespace, do: @namespace - else - def namespace, do: Application.get_env(:jsonapi, :namespace, "") - end + # @impl View + # if @namespace do + # def namespace, do: @namespace + # else + # def namespace, do: Application.get_env(:jsonapi, :namespace, "") + # end - @impl View - def pagination_links(data, conn, page, options) do - paginator = Application.get_env(:jsonapi, :paginator, @paginator) + # @impl View + # def pagination_links(data, conn, page, options) do + # paginator = Application.get_env(:jsonapi, :paginator, @paginator) - if Code.ensure_loaded?(paginator) && function_exported?(paginator, :paginate, 5) do - paginator.paginate(data, __MODULE__, conn, page, options) - else - %{} - end - end + # if Code.ensure_loaded?(paginator) && function_exported?(paginator, :paginate, 5) do + # paginator.paginate(data, __MODULE__, conn, page, options) + # else + # %{} + # end + # end - @impl View - def path, do: @path + # @impl View + # def path, do: @path @impl View def relationships, do: [] @@ -246,17 +246,17 @@ defmodule JSONAPI.View do def type, do: raise("Need to implement type/0") end - @impl View - def url_for(data, conn), - do: View.url_for(__MODULE__, data, conn) + # @impl View + # def url_for(data, conn), + # do: View.url_for(__MODULE__, data, conn) - @impl View - def url_for_pagination(data, conn, pagination_params), - do: View.url_for_pagination(__MODULE__, data, conn, pagination_params) + # @impl View + # def url_for_pagination(data, conn, pagination_params), + # do: View.url_for_pagination(__MODULE__, data, conn, pagination_params) - @impl View - def url_for_rel(data, rel_type, conn), - do: View.url_for_rel(__MODULE__, data, rel_type, conn) + # @impl View + # def url_for_rel(data, rel_type, conn), + # do: View.url_for_rel(__MODULE__, data, rel_type, conn) @impl View def visible_fields(data, conn), @@ -296,59 +296,59 @@ defmodule JSONAPI.View do end end - @spec url_for(t(), term(), Conn.t() | nil) :: String.t() - def url_for(view, data, nil = _conn) when is_nil(data) or is_list(data), - do: URI.to_string(%URI{path: Enum.join([view.namespace(), path_for(view)], "/")}) - - def url_for(view, data, nil = _conn) do - URI.to_string(%URI{ - path: Enum.join([view.namespace(), path_for(view), view.id(data)], "/") - }) - end - - def url_for(view, data, %Plug.Conn{} = conn) when is_nil(data) or is_list(data) do - URI.to_string(%URI{ - scheme: scheme(conn), - host: host(conn), - port: port(conn), - path: Enum.join([view.namespace(), path_for(view)], "/") - }) - end - - def url_for(view, data, %Plug.Conn{} = conn) do - URI.to_string(%URI{ - scheme: scheme(conn), - host: host(conn), - port: port(conn), - path: Enum.join([view.namespace(), path_for(view), view.id(data)], "/") - }) - end - - @spec url_for_rel(t(), data(), resource_type(), Conn.t() | nil) :: String.t() - def url_for_rel(view, data, rel_type, conn) do - "#{url_for(view, data, conn)}/relationships/#{rel_type}" - end - - @spec url_for_rel(t(), data(), Conn.query_params(), Paginator.params()) :: String.t() - def url_for_pagination( - view, - data, - %{query_params: query_params} = conn, - nil = _pagination_params - ) do - query = - query_params - |> Utils.List.to_list_of_query_string_components() - |> URI.encode_query() - - prepare_url(view, query, data, conn) - end - - def url_for_pagination(view, data, %{query_params: query_params} = conn, pagination_params) do - query_params = Map.put(query_params, "page", pagination_params) - - url_for_pagination(view, data, %{conn | query_params: query_params}, nil) - end + # @spec url_for(t(), term(), Conn.t() | nil) :: String.t() + # def url_for(view, data, nil = _conn) when is_nil(data) or is_list(data), + # do: URI.to_string(%URI{path: Enum.join([view.namespace(), path_for(view)], "/")}) + + # def url_for(view, data, nil = _conn) do + # URI.to_string(%URI{ + # path: Enum.join([view.namespace(), path_for(view), view.id(data)], "/") + # }) + # end + + # def url_for(view, data, %Plug.Conn{} = conn) when is_nil(data) or is_list(data) do + # URI.to_string(%URI{ + # scheme: scheme(conn), + # host: host(conn), + # port: port(conn), + # path: Enum.join([view.namespace(), path_for(view)], "/") + # }) + # end + + # def url_for(view, data, %Plug.Conn{} = conn) do + # URI.to_string(%URI{ + # scheme: scheme(conn), + # host: host(conn), + # port: port(conn), + # path: Enum.join([view.namespace(), path_for(view), view.id(data)], "/") + # }) + # end + + # @spec url_for_rel(t(), data(), resource_type(), Conn.t() | nil) :: String.t() + # def url_for_rel(view, data, rel_type, conn) do + # "#{url_for(view, data, conn)}/relationships/#{rel_type}" + # end + + # @spec url_for_rel(t(), data(), Conn.query_params(), Paginator.params()) :: String.t() + # def url_for_pagination( + # view, + # data, + # %{query_params: query_params} = conn, + # nil = _pagination_params + # ) do + # query = + # query_params + # |> Utils.List.to_list_of_query_string_components() + # |> URI.encode_query() + + # prepare_url(view, query, data, conn) + # end + + # def url_for_pagination(view, data, %{query_params: query_params} = conn, pagination_params) do + # query_params = Map.put(query_params, "page", pagination_params) + + # url_for_pagination(view, data, %{conn | query_params: query_params}, nil) + # end @spec visible_fields(t(), data(), Conn.t() | nil) :: list(atom) def visible_fields(view, data, conn) do @@ -372,15 +372,15 @@ defmodule JSONAPI.View do |> MapSet.to_list() end - defp prepare_url(view, "", data, conn), do: url_for(view, data, conn) + # defp prepare_url(view, "", data, conn), do: url_for(view, data, conn) - defp prepare_url(view, query, data, conn) do - view - |> url_for(data, conn) - |> URI.parse() - |> struct(query: query) - |> URI.to_string() - end + # defp prepare_url(view, query, data, conn) do + # view + # |> url_for(data, conn) + # |> URI.parse() + # |> struct(query: query) + # |> URI.to_string() + # end defp requested_fields_for_type(view, %Conn{assigns: %{jsonapi_query: %{fields: fields}}}) do fields[view.type()] @@ -388,17 +388,17 @@ defmodule JSONAPI.View do defp requested_fields_for_type(_view, _conn), do: nil - defp host(%Conn{host: host}), - do: Application.get_env(:jsonapi, :host, host) + # defp host(%Conn{host: host}), + # do: Application.get_env(:jsonapi, :host, host) - defp port(%Conn{port: 0} = conn), - do: port(%{conn | port: URI.default_port(scheme(conn))}) + # defp port(%Conn{port: 0} = conn), + # do: port(%{conn | port: URI.default_port(scheme(conn))}) - defp port(%Conn{port: port}), - do: Application.get_env(:jsonapi, :port, port) + # defp port(%Conn{port: port}), + # do: Application.get_env(:jsonapi, :port, port) - defp scheme(%Conn{scheme: scheme}), - do: Application.get_env(:jsonapi, :scheme, to_string(scheme)) + # defp scheme(%Conn{scheme: scheme}), + # do: Application.get_env(:jsonapi, :scheme, to_string(scheme)) - defp path_for(view), do: view.path() || view.type() + # defp path_for(view), do: view.path() || view.type() end