Current section
Files
Jump to
Current section
Files
lib/carve.ex
defmodule Carve do
@moduledoc """
Carve simplifies JSON API development in Phoenix by automatically formatting endpoint outputs with associated links. Define resource relationships with a simple DSL, and let Carve handle link inclusion and query-based filtering, reducing boilerplate and ensuring consistent, flexible API responses.
It provides functionality for:
- Rendering JSON endpoints with links automatically
- Creating index/show methods for views from a DSL
- Retrieving links between different data types
- Encoding and decoding IDs using HashIds
- Configuring the application
"""
use Application
require Logger
@doc """
Starts the Carve application.
This function is called automatically by the OTP application behaviour.
It configures Carve using the configuration returned by `Carve.Config.get/0`.
## Returns
- `{:ok, pid}`: The pid is the process identifier of the started application.
"""
def start(_type, _args) do
Logger.info("Starting Carve")
configure(Carve.Config.get())
{:ok, self()}
end
@doc """
Configures Carve with the given arguments.
This function is typically called during application start, but can also be used
to reconfigure Carve at runtime.
## Parameters
- `args`: A keyword list of configuration options.
## Examples
iex> Carve.configure(salt: "my_salt", min_length: 8)
:ok
"""
def configure(args) do
Logger.info("Configuring Carve")
hash_ids_config = args
Carve.HashIds.configure(hash_ids_config)
end
@doc """
Retrieves links for a given module and data or ID(s).
This function supports various input types:
- Single integer ID
- List of integer IDs
- Single map (data structure)
- List of maps (data structures)
## Parameters
- `module`: The module to retrieve links for.
- `data_or_ids`: The data or ID(s) to retrieve links for.
## Returns
A list of link maps, each containing `:type`, `:id`, and `:data` keys.
## Examples
iex> Carve.links(PostJSON, 1)
[%{type: :user, id: "abc123", data: %{...}}, %{type: :comment, id: "def456", data: %{...}}]
iex> Carve.links(PostJSON, [1, 2, 3])
[%{type: :user, id: "abc123", data: %{...}}, %{type: :comment, id: "def456", data: %{...}}, ...]
iex> Carve.links(PostJSON, %{id: 1, title: "Test Post"})
[%{type: :user, id: "abc123", data: %{...}}, %{type: :comment, id: "def456", data: %{...}}]
"""
def links(module, data_or_ids) do
cond do
is_integer(data_or_ids) ->
Carve.Links.get_links_by_id(module, data_or_ids)
is_list(data_or_ids) and Enum.all?(data_or_ids, &is_integer/1) ->
Carve.Links.get_links_by_id(module, data_or_ids)
is_map(data_or_ids) ->
Carve.Links.get_links_by_data(module, data_or_ids)
is_list(data_or_ids) and Enum.all?(data_or_ids, &is_map/1) ->
Carve.Links.get_links_by_data(module, data_or_ids)
true ->
[]
end
end
@doc """
Encodes an ID for a given type using HashIds.
## Parameters
- `type`: The type of the ID (as an atom).
- `id`: The integer ID to encode.
## Returns
A string representing the encoded ID.
## Examples
iex> Carve.encode(:user, 123)
"abc123def"
"""
def encode(type, id) when is_atom(type) and is_integer(id) do
Carve.HashIds.encode(type, id)
end
@doc """
Decodes a hash with a given type using HashIds.
## Parameters
- `type`: The type of the ID (as an atom).
- `hash`: The string hash to decode.
## Returns
The decoded integer ID.
## Examples
iex> Carve.decode(:user, "abc123def")
{:ok, 123}
"""
def decode(type, hash) when is_atom(type) and is_binary(hash) do
Carve.HashIds.decode(type, hash)
end
@doc """
Decodes a hash without a type using HashIds.
This function attempts to decode the hash without knowing its type.
## Parameters
- `hash`: The string hash to decode.
## Returns
The decoded integer ID.
## Examples
iex> Carve.decode("abc123def")
{:ok, 123}
"""
def decode(hash) when is_binary(hash) do
Carve.HashIds.decode(hash)
end
end