OuterfacesEctoApi.QueryEngine (Outerfaces Ecto API v0.2.9)

View Source

Runs index and show queries from a request's query param and returns them in one envelope:

{:ok, %{status: 200, results: %{data: [...], page_info: %{...}, schema: "..."}}}
{:error, %{status: 400 | 404 | 500, results: %{data: nil, ...}, debug: %{...}}}

Options

Both all/7 and get/5 take:

  • :base_queryable - the query to start from instead of the schema. Use it to scope what a caller may see (an owner, live rows only); a client can't override it the way it can override a filter default.
  • :include_schema - whether the envelope and every record carry a schema key naming the Elixir module (default true). Set false on an API the public can reach.
  • :include_debug - whether an error carries the debug block, which repeats the params and specs (default true).
  • Anything else is passed to the schemas' serializer hooks.

all/7 also takes:

  • :default_limit - the limit when the request sends none. Without it, an index with no limit returns every row.
  • :max_limit - the largest limit a request may ask for.
  • :search - opt-in text search: {module, function} or a 2-arity function called as (query, text) when the request's search text is a non-blank string, after filters and sorts. It returns the narrowed query, and may rank it or select_merge virtual fields (see QuerySerializer's serializer_virtual_fields/1). Without :search, the text is ignored.
  • :search_param - the key in the query JSON that holds the search text (default "q").

build/4 takes :search and :search_param too.

get/5 also takes:

  • :by - the field to look the record up by, such as :key or :slug, instead of the primary key.

Summary

Types

all_response()

@type all_response() :: {:ok, paginated_success()} | {:error, error_response()}

error_response()

@type error_response() :: %{
  :status => pos_integer(),
  :results => %{
    :data => nil,
    optional(:schema) => String.t(),
    optional(:page_info) => pagination_info() | nil,
    optional(:id) => term()
  },
  optional(:debug) => map()
}

filter_spec()

get_response()

@type get_response() :: {:ok, single_success()} | {:error, error_response()}

paginated_success()

@type paginated_success() :: %{
  status: pos_integer(),
  results: %{
    :data => [map()],
    :page_info => pagination_info(),
    optional(:schema) => String.t()
  }
}

pagination_info()

params()

@type params() :: map()

preload()

@type preload() :: atom() | {atom(), [preload()]}

repo()

@type repo() :: Ecto.Repo.t()

schema()

@type schema() :: module()

single_success()

@type single_success() :: %{
  status: pos_integer(),
  results: %{:data => map(), :id => term(), optional(:schema) => String.t()}
}

sort_spec()

Functions

all(repo, schema, preloads, filter_specs, sort_specs, params, opts \\ [])

@spec all(
  repo(),
  schema(),
  [preload()],
  [filter_spec()],
  [sort_spec()],
  params(),
  Keyword.t()
) ::
  all_response()

build(schema, filters, params, opts \\ [])

@spec build(
  schema(),
  [filter_spec()],
  params(),
  Keyword.t()
) :: {:ok, Ecto.Query.t()} | {:error, atom()}

get(repo, schema, id, preloads \\ [], opts \\ [])

@spec get(repo(), schema(), term(), [preload()], Keyword.t()) :: get_response()

Fetches one record by primary key, or by the field named in opts[:by].

A string id is cast to the field's type, so "42" finds integer id 42 and a UUID or key string finds its row. An id that can't be cast is a 404. results.id is the cast value (42 for "42", as before 0.2.9).