| defmodule Plausible.Pagination do |
| @moduledoc """ |
| Cursor-based pagination. |
| """ |
|
|
| @limit 10 |
| @maximum_limit 100 |
|
|
| @spec paginate(Ecto.Queryable.t(), map(), Keyword.t(), Keyword.t()) :: Paginator.Page.t() |
| def paginate(queryable, params, opts, repo_opts \\ []) do |
| opts = Keyword.merge([limit: @limit, maximum_limit: @maximum_limit], opts) |
|
|
| Paginator.paginate( |
| queryable, |
| Keyword.merge(opts, to_pagination_opts(params)), |
| Plausible.Repo, |
| repo_opts |
| ) |
| end |
|
|
| defp to_pagination_opts(params) do |
| Enum.reduce(params, Keyword.new(), fn |
| {"after", cursor}, acc -> |
| Keyword.put(acc, :after, cursor) |
|
|
| {"before", cursor}, acc -> |
| Keyword.put(acc, :before, cursor) |
|
|
| {"limit", limit}, acc -> |
| limit = to_int(limit) |
|
|
| if limit > 0 and limit <= @maximum_limit do |
| Keyword.put(acc, :limit, limit) |
| else |
| acc |
| end |
|
|
| _, acc -> |
| acc |
| end) |
| end |
|
|
| defp to_int(x) when is_binary(x), do: String.to_integer(x) |
| defp to_int(x) when is_integer(x), do: x |
| end |
|
|