Current section
Files
Jump to
Current section
Files
lib/utils/rest.ex
defmodule StarkCore.Utils.Rest do
alias StarkCore.Utils.Request
alias StarkCore.Utils.Check
alias StarkCore.Utils.QueryGenerator
alias StarkCore.Utils.API
alias StarkCore.Utils.JSON
def get_page(
service,
{resource_name, resource_maker},
options \\ []
) do
case Request.fetch(
service,
:get,
"#{API.endpoint(resource_name)}",
query: Enum.into(options, %{})
|> Map.delete(:user)
|> API.cast_json_to_api_format(),
user: options[:user]
) do
{:ok, response} -> {:ok, process_page_response(resource_name, resource_maker, response)}
{:error, errors} -> {:error, errors}
end
end
def get_page!(
service,
{resource_name, resource_maker},
options \\ %{}
) do
case get_page(
service,
{resource_name, resource_maker},
options
) do
{:ok, response} -> response
{:error, err} -> raise API.errors_to_string(err)
end
end
def get_list(
service,
{resource_name, resource_maker},
options \\ []
) do
{getter, query} = get_list_parameters(service, resource_name, options |> Enum.into(%{}))
Stream.resource(
fn ->
{:ok, pid} =
QueryGenerator.start_query(
getter,
API.last_name_plural(resource_name),
query
)
pid
end,
fn pid ->
case QueryGenerator.get(pid) do
:halt -> {:halt, pid}
{:ok, element} -> {[{:ok, API.from_api_json(element, resource_maker)}], pid}
{:error, error} -> {[{:error, error}], pid}
end
end,
fn _pid ->
nil
end
)
end
def get_list!(
service,
{resource_name, resource_maker},
options \\ []
) do
{getter, query} = get_list_parameters(service, resource_name, options |> Enum.into(%{}))
Stream.resource(
fn ->
{:ok, pid} =
QueryGenerator.start_query(
getter,
API.last_name_plural(resource_name),
query
)
pid
end,
fn pid ->
case QueryGenerator.get(pid) do
:halt -> {:halt, pid}
{:ok, element} -> {[API.from_api_json(element, resource_maker)], pid}
{:error, errors} -> raise API.errors_to_string(errors)
end
end,
fn _pid -> nil end
)
end
defp get_list_parameters(
service,
resource_name,
options
) do
query = Enum.into(options |> Check.options(), %{})
{
make_getter(query[:user], resource_name, service),
query |> Map.delete(:user) |> Map.put(:limit, query[:limit])
}
end
defp make_getter(
user,
resource_name,
service
) do
fn query ->
Request.fetch(
service,
:get,
API.endpoint(resource_name),
query: query,
user: user
)
end
end
def get_id(
service,
{resource_name, resource_maker},
id,
options \\ %{}
) do
case Request.fetch(
service,
:get,
"#{API.endpoint(resource_name)}/#{id}",
options
) do
{:ok, response} -> {:ok, process_single_response(response, resource_name, resource_maker)}
{:error, errors} -> {:error, errors}
end
end
def get_id!(
service,
{resource_name, resource_maker},
id,
options \\ %{}
) do
case get_id(
service,
{resource_name, resource_maker},
id,
options
) do
{:ok, entity} -> entity
{:error, errors} -> raise API.errors_to_string(errors)
end
end
def get_content(
service,
resource_name,
id,
sub_resource_name,
options \\ %{}
) do
case Request.fetch(
service,
:get,
"#{API.endpoint(resource_name)}/#{id}/#{sub_resource_name}",
options
) do
{:ok, content} -> {:ok, content}
{:error, errors} -> {:error, errors}
end
end
def get_content!(
service,
resource_name,
id,
sub_resource_name,
options \\ %{}
) do
case get_content(
service,
resource_name,
id,
sub_resource_name,
options
) do
{:ok, content} -> content
{:error, errors} -> raise API.errors_to_string(errors)
end
end
def post(
service,
{resource_name, resource_maker},
options
) do
user = options[:user]
case Request.fetch(
service,
:post,
"#{API.endpoint(resource_name)}",
payload: prepare_payload(resource_name, options[:payload]),
user: user
) do
{:ok, response} -> {:ok, process_response(resource_name, resource_maker, response)}
{:error, errors} -> {:error, errors}
end
end
def post!(
service,
{resource_name, resource_maker},
options
) do
case post(
service,
{resource_name, resource_maker},
options
) do
{:ok, entities} -> entities
{:error, errors} -> raise API.errors_to_string(errors)
end
end
def post_single(
service,
{resource_name, resource_maker},
options
) do
case Request.fetch(
service,
:post,
"#{API.endpoint(resource_name)}",
options
) do
{:ok, response} -> {:ok, process_single_response(response, resource_name, resource_maker)}
{:error, errors} -> {:error, errors}
end
end
def post_single!(
service,
{resource_name, resource_maker},
options
) do
case post_single(
service,
{resource_name, resource_maker},
options
) do
{:ok, entity} -> entity
{:error, errors} -> raise API.errors_to_string(errors)
end
end
def delete_id(
service,
{resource_name, resource_maker},
id,
options \\ %{}
) do
case Request.fetch(
service,
:delete,
"#{API.endpoint(resource_name)}/#{id}",
options
) do
{:ok, response} -> {:ok, process_single_response(response, resource_name, resource_maker)}
{:error, errors} -> {:error, errors}
end
end
def delete_id!(
service,
{resource_name, resource_maker},
id,
options \\ %{}
) do
case delete_id(
service,
{resource_name, resource_maker},
id,
options
) do
{:ok, entity} -> entity
{:error, errors} -> raise API.errors_to_string(errors)
end
end
def patch_id(
service,
{resource_name, resource_maker},
id,
options \\ %{}
) do
case Request.fetch(
service,
:patch,
"#{API.endpoint(resource_name)}/#{id}",
options
) do
{:ok, response} -> {:ok, process_single_response(response, resource_name, resource_maker)}
{:error, errors} -> {:error, errors}
end
end
def patch_id!(
service,
{resource_name, resource_maker},
id,
options \\ %{}
) do
case patch_id(
service,
{resource_name, resource_maker},
id,
options
) do
{:ok, entity} -> entity
{:error, errors} -> raise API.errors_to_string(errors)
end
end
def get_sub_resource(
service,
resource_name,
{sub_resource_name, sub_resource_maker},
id,
options \\ []
) do
case Request.fetch(
service,
:get,
"#{API.endpoint(resource_name)}/#{id}/#{API.endpoint(sub_resource_name)}",
query: options |> Keyword.delete(:user) |> API.cast_json_to_api_format(),
user: options[:user]
) do
{:ok, response} -> {:ok, process_single_response(response, sub_resource_name, sub_resource_maker)}
{:error, errors} -> {:error, errors}
end
end
def get_sub_resource!(
service,
resource_name,
{sub_resource_name, sub_resource_maker},
id,
options \\ []
) do
case get_sub_resource(
service,
resource_name,
{sub_resource_name, sub_resource_maker},
id,
options
) do
{:ok, entity} -> entity
{:error, errors} -> raise API.errors_to_string(errors)
end
end
def prepare_payload(resource_name, entities) do
Map.put(
%{},
API.last_name_plural(resource_name),
Enum.map(entities, &API.api_json/1)
)
end
def post_sub_resource(
service,
resource_name,
{sub_resource_name, sub_resource_maker},
id,
options \\ %{}
) do
url = "#{API.endpoint(resource_name)}/#{id}/#{API.endpoint(sub_resource_name)}"
case Request.fetch(
service,
:post,
url,
options
) do
{:ok, response} -> {:ok, process_single_response(response, sub_resource_name, sub_resource_maker)}
{:error, errors} -> {:error, errors}
end
end
def post_sub_resource!(
service,
resource_name,
{sub_resource_name, sub_resource_maker},
id,
options \\ %{}
) do
case post_sub_resource(
service,
resource_name,
{sub_resource_name, sub_resource_maker},
id,
options
) do
{:ok, entity} -> entity
{:error, errors} -> raise API.errors_to_string(errors)
end
end
def get_raw(
service,
path,
options \\ %{}
) do
Request.fetch_raw(
service,
:get,
path,
options
)
end
def get_raw!(
service,
path,
options \\ %{}
) do
case get_raw(
service,
path,
options
) do
{:ok, %{headers: headers, content: content, status_code: status_code}} -> {:ok, %{headers: headers, content: content, status_code: status_code}}
{:error, %{headers: _headers, content: content, status_code: _status_code}} -> raise API.errors_to_string(content)
end
end
def post_raw(
service,
path,
options
) do
Request.fetch_raw(
service,
:post,
path,
options
)
end
def post_raw!(
service,
path,
options
) do
case post_raw(
service,
path,
options
) do
{:ok, %{headers: headers, content: content, status_code: status_code}} -> {:ok, %{headers: headers, content: content, status_code: status_code}}
{:error, %{headers: _headers, content: content, status_code: _status_code}} -> raise API.errors_to_string(content)
end
end
def patch_raw(
service,
resource_name,
id,
options \\ %{}
) do
Request.fetch_raw(
service,
:patch,
"#{resource_name}/#{id}",
options
)
end
def patch_raw!(
service,
resource_name,
id,
options \\ %{}
) do
case patch_raw(
service,
resource_name,
id,
options
) do
{:ok, %{headers: headers, content: content, status_code: status_code}} -> {:ok, %{headers: headers, content: content, status_code: status_code}}
{:error, %{headers: _headers, content: content, status_code: _status_code}} -> raise API.errors_to_string(content)
end
end
def delete_raw(
service,
resource_name,
id,
options \\ %{}
) do
Request.fetch_raw(
service,
:delete,
"#{API.endpoint(resource_name)}/#{id}",
options
)
end
def delete_raw!(
service,
resource_name,
id,
options \\ %{}
) do
case delete_raw(
service,
resource_name,
id,
options
) do
{:ok, %{headers: headers, content: content, status_code: status_code}} -> {:ok, %{headers: headers, content: content, status_code: status_code}}
{:error, %{headers: _headers, content: content, status_code: _status_code}} -> raise API.errors_to_string(content)
end
end
defp process_single_response(
response,
resource_name,
resource_maker
) do
JSON.decode!(response)[API.last_name(resource_name)]
|> API.from_api_json(resource_maker)
end
defp process_response(
resource_name,
resource_maker,
response
) do
JSON.decode!(response)[API.last_name_plural(resource_name)]
|> Enum.map(fn json -> API.from_api_json(json, resource_maker) end)
end
defp process_page_response(
resource_name,
resource_maker,
response
) do
decoded_response = JSON.decode!(response)
{
decoded_response["cursor"],
decoded_response[API.last_name_plural(resource_name)]
|> Enum.map(&(API.from_api_json(&1, resource_maker)))
}
end
end