Current section

Files

Jump to
ept_sdk lib ept_sdk.ex
Raw

lib/ept_sdk.ex

defmodule EPTSDK do
@default_query_options %{
filter: %{},
include: [],
sort: [],
page: [],
fields: %{}
}
@enforce_keys [
:authorization,
:user_agent,
:location,
:http_client
]
@default_headers []
defstruct authorization: nil,
user_agent: nil,
location: %URI{scheme: "https", host: "api.tryedge.io"},
http_client: Req.new(),
response: nil,
links: nil,
meta: nil
@type t() :: %__MODULE__{
authorization: String.t(),
user_agent: String.t(),
location: URI.t() | String.t(),
http_client: Req.t()
}
def client(%{token: token, user_agent: user_agent} = properties) when is_map(properties) do
struct(
__MODULE__,
%{
authorization: "Bearer #{token}",
user_agent: user_agent
}
|> Map.merge(properties)
)
end
def get(%EPTSDK{location: location} = client, path, query \\ [])
when is_binary(path) do
client.http_client
|> Req.get(
url: encode_uri(location, path, with_query_defaults(query)),
headers:
default_headers(client, [
{"Accept", "application/vnd.api+json"}
])
)
|> response()
end
def delete(%EPTSDK{location: location} = client, path, query \\ [])
when is_binary(path) do
client.http_client
|> Req.delete(
url: encode_uri(location, path, with_query_defaults(query)),
headers: default_headers(client)
)
|> response()
end
def post(%EPTSDK{location: location} = client, path, data, query \\ [])
when is_binary(path) and is_map(data) do
client.http_client
|> Req.post(
url: encode_uri(location, path, with_query_defaults(query)),
headers:
default_headers(client, [
{"Content-Type", "application/vnd.api+json"},
{"Accept", "application/vnd.api+json"}
]),
json: dbg(data)
)
|> response()
end
def patch(%EPTSDK{location: location} = client, path, data, query \\ [])
when is_binary(path) and is_map(data) do
client.http_client
|> Req.patch(
url: encode_uri(location, path, with_query_defaults(query)),
headers:
default_headers(client, [
{"Content-Type", "application/vnd.api+json"},
{"Accept", "application/vnd.api+json"}
]),
json: data
)
|> response()
end
def put(%EPTSDK{location: location} = client, path, data, query \\ [])
when is_binary(path) and is_map(data) do
client.http_client
|> Req.put(
url: encode_uri(location, path, with_query_defaults(query)),
headers:
default_headers(client, [
{"Content-Type", "application/vnd.api+json"},
{"Accept", "application/vnd.api+json"}
]),
json: data
)
|> response()
end
defp encode_uri(location, path, nil)
when is_binary(location) and is_binary(path),
do: URI.append_path(%URI{host: location, scheme: "https"}, path)
defp encode_uri(uri, path, nil)
when is_struct(uri, URI) and is_binary(path),
do: URI.append_path(uri, path)
defp encode_uri(location, path, query)
when is_map(query),
do:
URI.append_query(
encode_uri(location, path, nil),
Plug.Conn.Query.encode(query)
)
defp default_headers(
%EPTSDK{user_agent: user_agent, authorization: authorization},
custom_headers \\ []
)
when is_binary(user_agent) and is_list(custom_headers) do
@default_headers
|> Enum.concat([
{"User-Agent", Enum.join(["Edge Payment Client/1.0", user_agent], " ")},
{"Authorization", authorization}
])
|> Enum.concat(custom_headers)
end
defp response({:ok, %Req.Response{status: 422, body: body} = response}) do
{:unprocessable_content, body, response}
end
defp response({:ok, %Req.Response{status: status} = response})
when status in 400..499 do
{:error, response}
end
defp response({:ok, %Req.Response{body: body} = response}) do
{:ok, body, response}
end
defp response({:error, error}) do
{:error, error}
end
defp with_query_defaults(nil), do: nil
defp with_query_defaults([]), do: nil
defp with_query_defaults(query) when is_list(query) do
%{
filter: query |> Keyword.get(:filter, @default_query_options[:filter]),
fields:
query
|> Keyword.get(:fields, @default_query_options[:fields])
|> encode_fields_query(),
sort: query |> Keyword.get(:sort, @default_query_options[:sort]) |> Enum.join(","),
page: query |> Keyword.get(:page, @default_query_options[:page]),
include: query |> Keyword.get(:include, @default_query_options[:include]) |> Enum.join(",")
}
|> Enum.filter(fn
{_key, ""} -> false
{_key, nil} -> false
{_key, _value} -> true
end)
|> Map.new()
end
defp with_query_defaults(%{}), do: %{}
defp encode_fields_query(fields) when is_map(fields) do
fields
|> Enum.map(fn {resource, fields} when is_list(fields) ->
{resource, Enum.join(fields, ",")}
end)
|> Map.new()
end
def update_client_from_request(
{:ok, payload, %Req.Response{} = response},
client
)
when is_struct(client, EPTSDK) and is_map(payload) do
{:ok, payload,
%__MODULE__{
client
| response: response,
links: payload["links"],
meta: payload["meta"]
}}
end
def update_client_from_request({:error, _exception} = error, _client), do: error
def update_client_from_request(
{:unprocessable_content, _exception, _response} = error,
_client
),
do: error
def update_client_from_request({:decoding_error, _exception, _response} = error, _client),
do: error
def update_client_from_request({:error, _exception, _response} = error, _client), do: error
end