Skip to content

Adds support for schema constraints, type coercions, and other custom transformations

Notifications You must be signed in to change notification settings

surgeventures/absinthe_helpers

Repository files navigation

Absinthe Helpers

This package provides three key features:

  1. constraints: enforce validation rules (like min, max, etc.) on fields and arguments in your schema
  2. transforms: apply custom transformations (like Trim, ToInteger, etc.) to input fields and arguments
  3. error formatting: GraphQL specification compliant error formatting for validation and transform failures

Installation

Add absinthe_helpers to your list of dependencies in mix.exs:

def deps do
  [
    {:absinthe_helpers, "~> 0.1.0"}
  ]
end

Then, run:

mix deps.get

Setup: adding constraints, transforms, and error formatting to your Absinthe pipeline

Follow these steps:

  1. Add constraints, transforms, and error formatting to your Absinthe pipeline:
forward "/graphql",
    to: Absinthe.Plug,
    init_opts: [
      schema: MyProject.Schema,
      pipeline: {__MODULE__, :absinthe_pipeline},
    ]

def absinthe_pipeline(config, opts) do
  config
  |> Absinthe.Plug.default_pipeline(opts)
  |> AbsintheHelpers.Phases.ApplyConstraints.add_to_pipeline(opts)
  |> AbsintheHelpers.Phases.ApplyTransforms.add_to_pipeline(opts)
  |> AbsintheHelpers.Phases.ApplyErrorFormatting.add_to_pipeline(opts)
end
  1. Add constraints to your schema:
defmodule MyApp.Schema do
  use Absinthe.Schema
  @prototype_schema AbsintheHelpers.Directives.Constraints

  directive :constraints do
    on([:argument_definition, :field_definition, :input_field_definition])

    arg(:min, :integer, description: "Minimum value allowed")
    arg(:max, :integer, description: "Maximum value allowed")
    arg(:min_items, :integer, description: "Minimum number of items allowed in a list")
    arg(:max_items, :integer, description: "Maximum number of items allowed in a list")
    arg(:regex, :string, description: "Pattern to match for a string")
  end

  query do
  end

  mutation do
  end

  # ...
end

Constraints

The constraints directive allows you to enforce validation rules on fields and arguments in your GraphQL schema. Constraints are applied at the schema level and are visible in the GraphQL schema, making them accessible to the frontend.

Example: graphql schema with constraints

"Overrides for location-specific service pricing."
input LocationOverrideInput {
  duration: Int @constraints(min: 300, max: 43200)
  price: Decimal @constraints(min: 0, max: 100000000)
  priceType: ServicePriceType
  locationId: ID!
}

How to use constraints

  1. Apply constraints to a field or argument:
field :my_list, list_of(:integer) do
  directive(:constraints, [min_items: 2, max_items: 5, min: 1, max: 100])

  resolve(&MyResolver.resolve/3)
end

field :my_field, :integer do
  arg :my_arg, non_null(:string), directives: [constraints: [min: 10, regex: "^[a-zA-Z]+$"]]

  resolve(&MyResolver.resolve/3)
end

Transforms

Transforms allow you to modify or coerce input values at runtime. You can apply these transformations to individual fields, lists, or arguments in your Absinthe schema.

Example: applying transforms in your schema

  1. Apply transforms directly to a field:
alias AbsintheHelpers.Transforms.ToInteger
alias AbsintheHelpers.Transforms.Trim
alias AbsintheHelpers.Transforms.Increment

field :employee_id, :id do
  meta transforms: [Trim, ToInteger, {Increment, 3}]
end
  1. Apply transforms to a list of values:
field :employee_ids, non_null(list_of(non_null(:id))) do
  meta transforms: [Trim, ToInteger, {Increment, 3}]
end
  1. Apply transforms to an argument:
field(:create_booking, :string) do
  arg(:employee_id, non_null(:id),
    __private__: [meta: [transforms: [Trim, ToInteger, {Increment, 3}]]]
  )

  resolve(&TestResolver.run/3)
end

Error Formatting

The package includes GraphQL specification compliant error formatting. When enabled, validation errors from constraints or transform failures are formatted consistently.

For multiple related errors, they are grouped under a single error with BAD_USER_INPUT code:

{
  "errors": [
    {
      "message": "Invalid input",
      "extensions": {
        "code": "BAD_USER_INPUT",
        "details": {
          "fields": [
            {
              "message": "min_not_met",
              "path": ["description"],
              "details": {
                "min": 5
              },
              "locations": [
                {
                  "line": 6,
                  "column": 7
                }
              ],
              "custom_error_code": "min_not_met"
            },
            {
              "message": "max_exceeded",
              "path": ["title"],
              "details": {
                "max": 10
              },
              "locations": [
                {
                  "line": 7,
                  "column": 7
                }
              ],
              "custom_error_code": "max_exceeded"
            }
          ]
        }
      },
      "locations": []
    }
  ]
}

About

Adds support for schema constraints, type coercions, and other custom transformations

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages