docs: documentation overhaul

This commit is contained in:
Zach Daniel 2024-05-01 15:59:26 -04:00
parent 7d1de87a3e
commit 0e79680681
15 changed files with 94 additions and 63 deletions

View file

@ -1,9 +1,30 @@
# AshGraphQL
![Logo](https://github.com/ash-project/ash/blob/main/logos/cropped-for-header-black-text.png?raw=true#gh-light-mode-only)
![Logo](https://github.com/ash-project/ash/blob/main/logos/cropped-for-header-white-text.png?raw=true#gh-dark-mode-only)
![Ash CI](https://github.com/ash-project/ash_graphql/workflows/Ash%20CI/badge.svg)
![Elixir CI](https://github.com/ash-project/ash_graphql/workflows/CI/badge.svg)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Hex version badge](https://img.shields.io/hexpm/v/ash_graphql.svg)](https://hex.pm/packages/ash_graphql)
[![Hexdocs badge](https://img.shields.io/badge/docs-hexdocs-purple)](https://hexdocs.pm/ash_graphql)
AshGraphQL is a [GraphQL](https://graphql.org/) extension for the [Ash framework](https://ash-hq.org/). It gives you an efficient way to expose your application resources over a GraphQL API. You configure what you want to expose and AshGraphQL will generate an [Absinthe](https://github.com/absinthe-graphql/absinthe) schema which will resolve data straight from your Ash resources.
# AshGraphql
See the [getting started guide](https://ash-hq.org/docs/guides/ash_graphql/latest/tutorials/getting-started-with-graphql.md) for information on setting it up, and see the `AshGraphql.Resource` documentation for docs on its DSL. See the [hexdocs](https://ash-hq.org/docs/dsl/ash_graphql/latest/ashgraphql-resource) for more information.
Welcome! This is the extension for building GraphQL APIs with Ash. The generated GraphQL APIs are powered by [Absinthe](http://hexdocs.pm/absinthe). Generate a powerful Graphql API in minutes!
## Tutorials
- [Getting Started with GraphQL](documentation/tutorials/getting-started-with-graphql.md)
## Topics
- [Authorize with GraphQL](documentation/topics/authorize-with-graphql.md)
- [Handle Errors](documentation/topics/handle-errors.md)
- [Monitoring](documentation/topics/monitoring.md)
- [Upgrade](documentation/topics/upgrade.md)
- [Use JSON with GraphQL](documentation/topics/use-json-with-graphql.md)
- [Use Subscriptions with GraphQL](documentation/topics/use-subscriptions-with-graphql.md)
- [GraphQL Generation](documentation/topics/graphql-generation.md)
- [Modifying the Resolution](documentation/topics/modifying-the-resolution.md)
- [Relay](documentation/topics/relay.md)
- [Use Enums with GraphQL](documentation/topics/use-enums-with-graphql.md)
- [Use Maps with GraphQL](documentation/topics/use-maps-with-graphql.md)
- [Use Unions with GraphQL](documentation/topics/use-unions-with-graphql.md)

View file

@ -2,9 +2,9 @@
AshGraphql uses three special keys in the `absinthe` context:
* `:actor` - the current actor, to be used for authorization/preparations/changes
* `:tenant` - a tenant when using [multitenancy](https://ash-hq.org/docs/guides/ash/latest/topics/multitenancy.md).
* `:ash_context` - a map of arbitrary context to be passed into the changeset/query. Accessible via `changeset.context` and `query.context`
- `:actor` - the current actor, to be used for authorization/preparations/changes
- `:tenant` - a tenant when using [multitenancy](https://hexdocs.pm/ash/multitenancy.html).
- `:ash_context` - a map of arbitrary context to be passed into the changeset/query. Accessible via `changeset.context` and `query.context`
By default, `authorize?` in the domain is set to true. To disable authorization for a given domain in graphql, use:
@ -17,9 +17,7 @@ end
If you are doing authorization, you'll need to provide an `actor`.
To set the `actor` for authorization, you'll need to add an `actor` key to the
absinthe context. Typically, you would have a plug that fetches the current user
and uses `Ash.PlugHelpers.set_actor/2` to set the actor in the `conn` (likewise
with `Ash.PlugHelpers.set_tenant/2`).
absinthe context. Typically, you would have a plug that fetches the current user and uses `Ash.PlugHelpers.set_actor/2` to set the actor in the `conn` (likewise with `Ash.PlugHelpers.set_tenant/2`).
Just add `AshGraphql.Plug` somewhere _after_ that in the pipeline and the your
GraphQL APIs will have the correct authorization.
@ -77,9 +75,7 @@ config :ash_graphql, :policies, show_policy_breakdowns?: true
}
],
"message": "MyApp.Authentication.User.read\n\n\n\n\nPolicy Breakdown\n Policy | ⛔:\n forbid unless: actor is active | ✓ | ⬇ \n authorize if: actor is Executive | ✘ | ⬇",
"path": [
"attendanceRecords"
],
"path": ["attendanceRecords"],
"short_message": "forbidden",
"vars": {}
}

View file

@ -1,9 +1,8 @@
# GraphQL Query Generation
## Fetch Data by ID
Following where we left off from [Getting Started with GraphQL](/documentation/tutorials/getting-started-with-graphql.md), this guide explores what the GraphQL requests and responses look like for different queries defined with the AshGraphql DSL.
Following where we left off from [Getting Started with GraphQL](/documentation/tutorials/getting-started-with-graphql.md), we'll explore what the GraphQL
requests and responses look like for different queries defined with the AshGraphql DSL.
## Fetch Data by ID
```elixir
defmodule Helpdesk.Support.Ticket do
@ -31,7 +30,7 @@ defmodule Helpdesk.Support.Ticket do
queries do
# create a field called `get_ticket` that uses the `read` read action to fetch a single ticket
get :get_ticket, :read
get :get_ticket, :read
end
end
end
@ -40,7 +39,7 @@ end
For the `get_ticket` query defined above, the corresponding GraphQL would look like this:
```graphql
query($id: ID!) {
query ($id: ID!) {
getTicket(id: $id) {
id
subject
@ -69,10 +68,10 @@ Let's look at an example of querying a list of things.
queries do
# create a field called `get_ticket` that uses the `read` read action to fetch a single ticket
get :get_ticket, :read
get :get_ticket, :read
# create a field called `list_tickets` that uses the `read` read action to fetch a list of tickets
list :list_tickets, :read
list :list_tickets, :read
end
end
```
@ -120,7 +119,7 @@ Consider `list :list_tickets, :read` and the `actions` section:
queries do
# create a field called `list_tickets` that uses the `read` read action to fetch a list of tickets
list :list_tickets, :read
list :list_tickets, :read
end
end
```
@ -134,7 +133,7 @@ We'll call this action `:query_tickets`:
```elixir
actions do
defaults [:read, :update, :destroy]
read :query_tickets do
argument :representative_id, :uuid
@ -161,7 +160,7 @@ In the `graphql` section, the `list/2` call has been changed, replacing the `:re
The GraphQL request would look something like this:
```graphql
query($representative_id: ID) {
query ($representative_id: ID) {
list_tickets(representative_id: $representative_id) {
id
representative_id
@ -199,9 +198,9 @@ defmodule Helpdesk.Support.Ticket do
type :ticket
queries do
get :get_ticket, :read
get :get_ticket, :read
end
mutations do
create :create_ticket, :create
end
@ -223,7 +222,7 @@ See [Use Enums with GraphQL](/documentation/guides/use-enums-with-graphql.md) fo
We can now create a ticket with the `createTicket` mutation:
```graphql
mutation($input: CreateTicketInput!) {
mutation ($input: CreateTicketInput!) {
createTicket(input: $input) {
result {
id
@ -279,20 +278,20 @@ Notice that the `status` attribute is set to `"OPEN"` and not `"open"`. It is im
This is required by GraphQL enums. AshGraphql will automatically convert the value to the correct case.
The response will look something like this:
```json
{
"data": {
"createTicket": {
"result": {
"id": "b771e433-0979-4d07-a280-4d12373849aa",
"subject": "My Ticket",
"status": "OPEN"
}
```json
{
"data": {
"createTicket": {
"result": {
"id": "b771e433-0979-4d07-a280-4d12373849aa",
"subject": "My Ticket",
"status": "OPEN"
}
}
}
```
}
```
Again, AshGraphql will automatically convert the `status` value from `:open` to `"OPEN"`.

View file

@ -1,10 +1,11 @@
# Modifying the Resolution
Using the `modify_resolution` option, you can alter the Absinthe resolution.
Using the `modify_resolution` option, you can alter the `Absinthe.Resolution`.
`modify_resoltion` is an MFA that will be called with the resolution, the query, and the result of the action as the first three arguments. Must return a new absinthe resolution.
`modify_resolution` is an MFA that will be called with the resolution, the query, and the result of the action as the first three arguments. Must return a new `Absinthe.Resolution`.
This can be used to implement things like setting cookies based on resource actions. A method of using resolution context
for that is documented here: https://hexdocs.pm/absinthe_plug/Absinthe.Plug.html#module-before-send
This can be used to implement things like setting cookies based on resource actions. A method of using resolution context for that is documented [in Absinthe.Plug](https://hexdocs.pm/absinthe_plug/Absinthe.Plug.html#module-before-send)
*Important* if you are modifying the context in a query, then you should also set `as_mutation?` to true and represent this in your graphql as a mutation. See `as_mutation?` for more.
> ### as_mutation? {: .warning}
>
> If you are modifying the context in a query, then you should also set `as_mutation?` to true and represent this in your graphql as a mutation. See `as_mutation?` for more.

View file

@ -1,18 +1,22 @@
# Relay
Enabling relay for a resource sets it up to follow the [relay specification](https://relay.dev/graphql/connections.htm).
Enabling Relay for a resource sets it up to follow the [Relay specification](https://relay.dev/graphql/connections.htm).
The two changes that are made currently are:
* the type for the resource will implement the `Node` interface
* pagination over that resource will behave as a Connection.
- the type for the resource will implement the `Node` interface
- pagination over that resource will behave as a `Connection`.
## Using with Absinthe.Relay
## Using Ash's built-in Relay support
Use the following option when calling `use AshGraphql`
Set `relay? true` on the resource:
```elixir
use AshGraphql, define_relay_types?: false
graphql do
relay? true
...
end
```
## Relay Global IDs
@ -56,3 +60,11 @@ mutations do
end
end
```
## Using with Absinthe.Relay instead of Ash's relay type
Use the following option when calling `use AshGraphql`
```elixir
use AshGraphql, define_relay_types?: false
```

View file

@ -123,7 +123,7 @@ 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.
> 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
@ -161,9 +161,9 @@ Topics:
How Tos:
- [Authorize With GraphQL](/documentation/how_to/authorize-with-graphql.md)
- [Handle Errors](/documentation/how_to/handle-errors.md)
- [Use Enums with GraphQL](/documentation/how_to/use-enums-with-graphql.md)
- [Use JSON with GraphQL](/documentation/how_to/use-json-with-graphql.md)
- [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)
[Monitoring](/documentation/monitoring.md)

View file

@ -58,7 +58,7 @@ defmodule AshGraphql.Type do
@doc """
Used for map/embedded types embedded in unions, to avoid nesting them in a key by their name.
See [the unions guide](/documentation/how_to/use-unions-with-graphql.md) for more.
See [the unions guide](/documentation/topics/use-unions-with-graphql.md) for more.
"""
@callback graphql_unnested_unions(Ash.Type.constraints()) :: [atom()]

20
mix.exs
View file

@ -2,7 +2,7 @@ defmodule AshGraphql.MixProject do
use Mix.Project
@description """
An absinthe-backed graphql extension for Ash
The extension for building GraphQL APIs with Ash
"""
@version "1.0.0-rc.5"
@ -35,7 +35,7 @@ defmodule AshGraphql.MixProject do
defp docs do
[
main: "getting-started-with-graphql",
main: "readme",
source_ref: "v#{@version}",
logo: "logos/small-logo.png",
extra_section: "GUIDES",
@ -55,18 +55,20 @@ defmodule AshGraphql.MixProject do
end
end,
extras: [
{"README.md", title: "Home"},
"documentation/tutorials/getting-started-with-graphql.md",
"documentation/how_to/authorize-with-graphql.md",
"documentation/how_to/handle-errors.md",
"documentation/how_to/use-enums-with-graphql.md",
"documentation/how_to/use-json-with-graphql.md",
"documentation/how_to/use-subscriptions-with-graphql.md",
"documentation/how_to/use-unions-with-graphql.md",
"documentation/how_to/use-maps-with-graphql.md",
"documentation/topics/authorize-with-graphql.md",
"documentation/topics/handle-errors.md",
"documentation/topics/use-enums-with-graphql.md",
"documentation/topics/use-json-with-graphql.md",
"documentation/topics/use-subscriptions-with-graphql.md",
"documentation/topics/use-unions-with-graphql.md",
"documentation/topics/use-maps-with-graphql.md",
"documentation/topics/monitoring.md",
"documentation/topics/graphql-generation.md",
"documentation/topics/modifying-the-resolution.md",
"documentation/topics/relay.md",
"documentation/topics/upgrade.md",
"documentation/dsls/DSL:-AshGraphql.Domain.md",
"documentation/dsls/DSL:-AshGraphql.Resource.md"
],