# `JSONAPIPlug.Plug`
[🔗](https://github.com/lucacorti/jsonapi_plug/blob/main/lib/jsonapi_plug/plug.ex#L1)

Implements validation and parsing of `JSON:API` requests

This plug handles the specification defined `JSON:API` request body and query parameters
(`fields`, `filter`, `include`, `page` and `sort`).

## Usage

Add this plug to your plug pipeline/controller like this:

```
plug JSONAPIPlug.Plug, api: MyApp.API, resource: MyApp.MyResource
```

If your connection receives a valid `JSON:API` request this plug will parse it into a
`JSONAPIPlug` struct that will be stored in the `Plug.Conn` private assign `:jsonapi_plug`.
The final `Plug.Conn` struct will look similar to the following:

```
%Plug.Conn{
  ...
  body_params: %{...},
  params: %{"data" => ...},
  private: %{
    ...
    jsonapi_plug: %JSONAPIPlug{
      api: MyApp.API,
      fields: ..., # Defaults to a map of field names by type.
      filter: ..., # Defaults to the query parameter value.
      include: ..., # Defaults to Ecto preload format.
      page: ..., # Defaults to the query parameter value.
      params: ..., # Defaults to Ecto normalized data.
      sort: ..., # Defaults to Ecto order_by format.
      resource: MyApp.MyResource
    }
    ...
  }
  ...
}
```

You can then use the contents of the struct to load data and call `JSONAPIPlug.render/4`
or the render function generated by `use JSONAPIPlug.Resource` to generate responses and render
them.

## Customizing default behaviour

### Body parameters

By default, body parameters are transformed into a format that is compatible with attrs for
`Ecto.Changeset` to perform inserts/updates of `Ecto.Schema` modules. However, you can transform
the `JSON:API` document in any format you want by writing your own module adopting the
`JSONAPIPlug.Normalizer` behaviour and configuring it through `JSONAPIPlug.API` configuration.

### Query parameters

The `JSON:API` `fields` and `include` query parameters format is defined by the specification.
The default implementation accepts the specification format and converts it to data usable as
`select` and `preload` options to `Ecto.Repo` functions.

The `JSON:API` `sort` query parameter format is not defined, however the specification suggests
to use a format for encoding sorting by attribute names with an optional `-` prefix to invert
ordering direction. The default implementation accepts the suggested format and converts it to
usable as `order_by` option to `Ecto.Repo` functions.

The `JSON:API` `filter` and `page` query parameters format is not defined by the JSON:API specification,
therefore the default implementation just copies the value of the query parameters in `JSONAPIPlug`.

You can transform data in any format you want for any of these parameters by implementing a module
adopting the `JSONAPIPlug.QueryParser` behaviour and configuring it through `JSONAPIPlug.API` configuration.

# `options`

```elixir
@type options() :: keyword()
```

Options:
* `:api` (`t:atom/0`) - Required. A module use-ing `JSONAPIPlug.API` to provide configuration

* `:includes` (`t:keyword/0`) - A nested keyword list of allowed includes for this endpoint. By default all includes are allowed. To disable all include, pass `[]`.

* `:normalizer` (`t:atom/0`) - Normalizer module. If unspecified, defaults to the API configured one.

* `:path` (`t:String.t/0`) - Resource path. The resource type is used unless speficied.

* `:resource` (`t:atom/0`) - Required. The `JSONAPIPlug.Resource` used to parse the request.

# `call`

---

*Consult [api-reference.md](api-reference.md) for complete listing*
