2023-01-24 16:42:11 +13:00
# Getting Started With GraphQL
2020-08-14 10:55:34 +12:00
## Get familiar with Ash resources
2024-04-02 07:03:06 +13:00
If you haven't already, read the [Ash Getting Started Guide ](https://hexdocs.pm/ash/get-started.html ). This assumes that you already have resources set up, and only gives you the steps to _add_ AshGraphql to your resources/domains.
2020-08-14 10:55:34 +12:00
2024-07-16 06:25:40 +12:00
## Installation
<!-- tabs - open -->
### Using Igniter (recommended)
```elixir
mix igniter.install ash_graphql
```
### Manual
2024-07-16 07:54:47 +12:00
#### Bring in the `ash_graphql` dependency
```elixir
def deps()
[
...
2024-08-03 04:27:39 +12:00
{:ash_graphql, "~> 1.3.1"}
2024-07-16 07:54:47 +12:00
]
end
```
2024-07-16 06:25:40 +12:00
#### Setting up your schema
2024-08-17 06:35:21 +12:00
If you don't have an absinthe schema, you can create one just for ash.
Replace `helpdesk` in the examples with your own application name.
See [the SDL file guide ](/documentation/topics/sdl-file.md ) for more information on using the SDL file,
or remove the `generate_sdl_file` option to skip generating it on calls to `mix ash.codegen` .
2024-07-16 06:25:40 +12:00
in `lib/helpdesk/schema.ex`
```elixir
defmodule Helpdesk.GraphqlSchema do
use Absinthe.Schema
# Add your domains here
2024-08-17 06:35:21 +12:00
use AshGraphql,
2024-08-17 06:39:41 +12:00
domains: [Your.Domains]
2024-07-16 06:25:40 +12:00
query do
# Custom absinthe queries can be placed here
@desc "Remove me once you have a query of your own!"
field :remove_me, :string do
resolve fn _, _ , _ ->
{:ok, "Remove me!"}
end
end
end
mutation do
# Custom absinthe mutations can be placed here
end
end
```
#### Connect your schema
##### Using Phoenix
Add the following code to your Phoenix router. It's useful to set up the Absinthe playground for trying things out, but it's optional.
```elixir
pipeline :graphql do
plug AshGraphql.Plug
end
scope "/gql" do
pipe_through [:graphql]
forward "/",
Absinthe.Plug,
schema: Module.concat(["Helpdesk.GraphqlSchema"])
forward "/playground",
Absinthe.Plug.GraphiQL,
schema: Module.concat(["Helpdesk.GraphqlSchema"]),
interface: :playground
end
```
> ### Whats up with `Module.concat/1`? {: .info}
>
> This `Module.concat/1` prevents a [compile-time dependency](https://dashbit.co/blog/speeding-up-re-compilation-of-elixir-projects) from this router module to the schema module. It is an implementation detail of how `forward/2` works that you end up with a compile-time dependency on the schema, but there is no need for this dependency, and that dependency can have _drastic_ impacts on your compile times in certain scenarios.
If you started with `mix new ...` instead of `mix phx.new ...` and you want to
still use Phoenix, the fastest path that way is typically to just create a new
Phoenix application and copy your resources/config over.
##### Using Plug
If you are unfamiliar with how plug works, this [guide ](https://elixirschool.com/en/lessons/specifics/plug/#dependencies )
will be helpful for understanding it. It also guides you through adding plug to your application.
Then you can use a `Plug.Router` and [forward ](https://hexdocs.pm/plug/Plug.Router.html#forward/2 ) to your plugs similar to how it is done for phoenix:
```elixir
plug AshGraphql.Plug
forward "/gql",
to: Absinthe.Plug,
init_opts: [schema: Module.concat(["Helpdesk.GraphqlSchema"])]
forward "/playground",
to: Absinthe.Plug.GraphiQL,
init_opts: [
schema: Module.concat(["Helpdesk.GraphqlSchema"]),
interface: :playground
]
```
For information on why we are using `Module.concat/1` , see the note above in the Phoenix section.
<!-- tabs - close -->
2020-08-14 10:55:34 +12:00
2024-07-16 06:25:40 +12:00
## Select domains to show in your GraphQL
2023-01-30 13:03:59 +13:00
2024-07-16 06:25:40 +12:00
In the `use AshGraphql` call in your schema, you specify which domains you want to expose in your GraphQL API. Add any domains that will have `AshGraphql` queries/mutations to the `domains` list. For example:
2023-01-30 13:03:59 +13:00
2024-07-16 06:25:40 +12:00
```elixir
use AshGraphql, domains: [Your.Domain1, Your.Domain2]
2020-08-14 10:55:34 +12:00
```
2024-07-16 06:25:40 +12:00
## Adding Queries and Mutations
2020-08-14 10:55:34 +12:00
2023-01-30 13:03:59 +13:00
Some example queries/mutations are shown below. If no queries/mutations are added, nothing will show up in the GraphQL API, so be sure to set one up if you want to try it out.
2024-05-25 07:53:09 +12:00
### Queries & Mutations on the Resource
Here we show queries and mutations being added to the resource, but you can also define them on the _domain_ . See below for an equivalent definition
2020-08-14 10:55:34 +12:00
```elixir
2024-05-25 07:53:09 +12:00
defmodule Helpdesk.Support.Ticket do
2020-08-14 10:55:34 +12:00
use Ash.Resource,
2023-01-30 13:03:59 +13:00
...,
2020-08-14 10:55:34 +12:00
extensions: [
AshGraphql.Resource
]
2020-09-24 12:54:57 +12:00
2020-08-14 10:55:34 +12:00
graphql do
2023-01-30 13:03:59 +13:00
type :ticket
2020-09-24 12:54:57 +12:00
2020-08-14 10:55:34 +12:00
queries do
2023-01-30 13:03:59 +13:00
# Examples
# create a field called `get_ticket` that uses the `read` read action to fetch a single ticke
2023-10-13 04:24:47 +13:00
get :get_ticket, :read
2023-01-30 13:03:59 +13:00
# create a field called `most_important_ticket` that uses the `most_important` read action to fetch a single record
2023-10-13 04:24:47 +13:00
read_one :most_important_ticket, :most_important
2023-01-30 13:03:59 +13:00
# create a field called `list_tickets` that uses the `read` read action to fetch a list of tickets
2023-10-13 04:24:47 +13:00
list :list_tickets, :read
2020-08-14 10:55:34 +12:00
end
2020-09-24 12:54:57 +12:00
2020-08-14 10:55:34 +12:00
mutations do
2023-01-30 13:03:59 +13:00
# Examples
create :create_ticket, :create
update :update_ticket, :update
destroy :destroy_ticket, :destroy
2020-08-14 10:55:34 +12:00
end
end
2023-01-30 13:03:59 +13:00
...
2020-08-14 10:55:34 +12:00
end
```
2024-05-25 07:53:09 +12:00
### Queries & Mutations on the Domain
```elixir
defmodule Helpdesk.Support.Ticket do
use Ash.Resource,
...,
extensions: [
AshGraphql.Resource
]
# The resource still determines its type, and any other resource/type-based
# configuration
graphql do
type :ticket
end
...
end
defmodule Helpdesk.Support do
use Ash.Domain,
extensions: [
AshGraphql.Domain
]
2024-07-16 06:25:40 +12:00
2024-06-05 16:46:01 +12:00
...
2024-05-25 07:53:09 +12:00
graphql do
# equivalent queries and mutations, but the first argument
# is the resource because the domain can define queries for
# any of its resources
queries do
get Helpdesk.Support.Ticket, :get_ticket, :read
read_one Helpdesk.Support.Ticket, :most_important_ticket, :most_important
list Helpdesk.Support.Ticket, :list_tickets, :read
end
mutations do
create Helpdesk.Support.Ticket, :create_ticket, :create
update Helpdesk.Support.Ticket, :update_ticket, :update
destroy Helpdesk.Support.Ticket, :destroy_ticket, :destroy
end
end
```
2023-02-21 05:52:47 +13:00
## What's next?
Topics:
2024-04-02 09:02:30 +13:00
2023-02-21 05:52:47 +13:00
- [GraphQL Generation ](/documentation/topics/graphql-generation.md )
How Tos:
2024-04-02 09:02:30 +13:00
2024-05-02 07:59:26 +12:00
- [Authorize With GraphQL ](/documentation/topics/authorize-with-graphql.md )
- [Handle Errors ](/documentation/topics/handle-errors.md )
- [Use Enums with GraphQL ](/documentation/topics/use-enums-with-graphql.md )
- [Use JSON with GraphQL ](/documentation/topics/use-json-with-graphql.md )